diff --git a/main.js b/main.js index 3629403..0a8db65 100644 --- a/main.js +++ b/main.js @@ -2,10 +2,10 @@ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD Optimized for Phase 4 Performance */ -"use strict";var j=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var ht=Object.prototype.hasOwnProperty;var Ze=(o,e)=>()=>(o&&(e=o(o=0)),e);var je=(o,e)=>{for(var t in e)j(o,t,{get:e[t],enumerable:!0})},ft=(o,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of mt(e))!ht.call(o,i)&&i!==t&&j(o,i,{get:()=>e[i],enumerable:!(r=Ye(e,i))||r.enumerable});return o};var vt=o=>ft(j({},"__esModule",{value:!0}),o),Xe=(o,e,t,r)=>{for(var i=r>1?void 0:r?Ye(e,t):e,n=o.length-1,s;n>=0;n--)(s=o[n])&&(i=(r?s(e,t,i):s(i))||i);return r&&i&&j(e,t,i),i};var E,q,X,$,Y=Ze(()=>{"use strict";E=class extends Error{constructor(t,r,i,n=!1,s){super(t);this.code=r;this.provider=i;this.isRetryable=n;this.statusCode=s;this.name="TranscriptionError"}},q=class extends E{constructor(e,t="Invalid API key"){super(t,"AUTH_ERROR",e,!1,401)}},X=class extends E{constructor(t,r){super("Rate limit exceeded","RATE_LIMIT",t,!0,429);this.retryAfter=r}},$=class extends E{constructor(e){super("Provider temporarily unavailable","UNAVAILABLE",e,!0,503)}}});var Qe={};je(Qe,{DEFAULT_SETTINGS:()=>Pe});var Pe,Le=Ze(()=>{"use strict";Y();Pe={apiKey:"",model:"whisper-1",language:"auto",autoInsert:!0,insertPosition:"cursor",timestampFormat:"none",maxFileSize:25*1024*1024,enableCache:!0,cacheTTL:36e5,temperature:void 0,prompt:void 0,textFormat:"plain",addTimestamp:!1,showFormatOptions:!1,provider:"auto",selectionStrategy:"performance_optimized",fallbackStrategy:"auto",latencyWeight:40,successWeight:35,costWeight:25,budgetAlert:80,autoCostOptimization:!1,qualityThreshold:85,minConfidence:70,strictLanguage:!1,enablePostProcessing:!0,abTestEnabled:!1,abTestSplit:50,abTestDuration:7,abTestMetrics:"all",requestTimeout:3e4,maxParallelRequests:2,maxRetries:3,cacheDuration:24,circuitBreakerEnabled:!0,circuitBreakerThreshold:5,circuitBreakerTimeout:6e4,healthChecksEnabled:!1,gracefulDegradation:!0,debugMode:!1,metricsEnabled:!1,metricsRetentionDays:30,showMetrics:!1,autoValidateKeys:!1,useEnvVars:!1}});var St={};je(St,{default:()=>xe});module.exports=vt(St);var v=require("obsidian");Le();var Q=class{constructor(e,t,r,i,n,s){this.whisperService=e;this.audioProcessor=t;this.textFormatter=r;this.eventManager=i;this.logger=n;this.settings=s;this.status="idle"}async transcribe(e){var t,r,i,n,s,a,l;try{this.status="validating",this.eventManager.emit("transcription:start",{fileName:e.name});let c=await this.audioProcessor.validate(e);if(!c.valid)throw new Error(`File validation failed: ${(t=c.errors)==null?void 0:t.join(", ")}`);this.status="processing";let p=await this.audioProcessor.process(e);this.status="transcribing",this.logger.debug("Starting transcription with WhisperService");let u=typeof((r=this.settings)==null?void 0:r.language)=="string"?this.settings.language:void 0,h=typeof((i=this.settings)==null?void 0:i.model)=="string"?this.settings.model:void 0,f=!!(u||h);f&&this.logger.debug("Transcription options:",{language:u,model:h});let g=f?await this.whisperService.transcribe(p.buffer,{language:u,model:h}):await this.whisperService.transcribe(p.buffer);if(this.logger.debug("WhisperService response:",{hasResponse:!!g,hasText:!!(g!=null&&g.text),textLength:((n=g==null?void 0:g.text)==null?void 0:n.length)||0,textPreview:(s=g==null?void 0:g.text)==null?void 0:s.substring(0,100),language:g==null?void 0:g.language}),!g||g.text===void 0||g.text===null)throw this.logger.error("Empty or invalid response from WhisperService",void 0,{response:g}),new Error("Transcription service returned empty text");this.status="formatting";let D=this.textFormatter.format(g.text);this.logger.debug("Text formatted:",{originalLength:g.text.length,formattedLength:D.length,formattedPreview:D.substring(0,100)});let y={text:D,language:g.language,segments:(a=g.segments)==null?void 0:a.map((M,_)=>({id:_,start:M.start,end:M.end,text:M.text}))};return this.status="completed",this.logger.debug("Emitting transcription:complete event",{textLength:y.text.length,hasSegments:!!y.segments,segmentsCount:((l=y.segments)==null?void 0:l.length)||0}),this.eventManager.emit("transcription:complete",{result:y}),y}catch(c){this.status="error";let p=this.normalizeError(c);throw this.eventManager.emit("transcription:error",{error:p}),p}}cancel(){var e;(e=this.abortController)==null||e.abort(),this.status="cancelled",this.eventManager.emit("transcription:cancelled",{})}getStatus(){return this.status}normalizeError(e){var t;if(e instanceof Error){if(e.code==="MAX_RETRIES_EXCEEDED"&&e.message.includes(":")){let i=e.message.split(":"),n=(t=i[i.length-1])==null?void 0:t.trim();if(n)return new Error(n)}return e}return typeof e=="string"?new Error(e):new Error("Unknown error")}};var rt=require("obsidian");function Je(o){return new Promise(e=>setTimeout(e,o))}function et(o,e,t,r=!0){if(r){if(ot)return{valid:!1,error:`Value must be between ${e} and ${t} (inclusive)`}}else if(o<=e||o>=t)return{valid:!1,error:`Value must be between ${e} and ${t} (exclusive)`};return{valid:!0}}function tt(o,e,t="..."){if(e<=0)throw new Error("Max length must be positive");if(o.length<=e)return o;let r=e-t.length;return r<=0?t:o.substring(0,r)+t}var I=class extends Error{constructor(t,r,i,n=!1){super(t);this.code=r;this.status=i;this.isRetryable=n;this.name="WhisperAPIError"}},J=class extends I{constructor(e="Invalid API key"){super(e,"AUTH_ERROR",401,!1)}},ke=class extends I{constructor(t){super("Rate limit exceeded","RATE_LIMIT",429,!0);this.retryAfter=t}},ee=class extends I{constructor(){super("File size exceeds API limit (25MB)","FILE_TOO_LARGE",413,!1)}},Oe=class extends I{constructor(e,t){super(e,"SERVER_ERROR",t,!0)}},Re=class{constructor(e){this.logger=e;this.maxRetries=3;this.baseDelay=250;this.maxDelay=2e3}async execute(e){var r;let t;for(let i=0;i=this.nextAttemptTime?(this.state="HALF_OPEN",this.logger.info("Circuit breaker entering HALF_OPEN state"),!1):!0:!1}onSuccess(){this.failureCount=0,this.state==="HALF_OPEN"&&(this.successCount++,this.successCount>=this.successThreshold&&(this.state="CLOSED",this.successCount=0,this.logger.info("Circuit breaker closed")))}onFailure(){this.failureCount++,this.state==="HALF_OPEN"?(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn("Circuit breaker opened due to failure in HALF_OPEN state")):this.failureCount>=this.failureThreshold&&(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn(`Circuit breaker opened after ${this.failureCount} failures`))}reset(){this.state="CLOSED",this.failureCount=0,this.successCount=0,this.logger.info("Circuit breaker reset")}},H=class{constructor(e,t){this.apiKey=e;this.logger=t;this.API_ENDPOINT="https://api.openai.com/v1/audio/transcriptions";this.MAX_FILE_SIZE=25*1024*1024;this.TIMEOUT=3e4;this.requestQueue=Promise.resolve();this.pendingRequests=[];this.isProcessingQueue=!1;this.retryStrategy=new Re(t),this.circuitBreaker=new Fe(t)}async transcribe(e,t){return this.queueRequest(()=>this.executeTranscription(e,t))}async executeTranscription(e,t){if(e.byteLength>this.MAX_FILE_SIZE)throw new ee;return this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(e,t)))}async performTranscription(e,t){this.abortController=new AbortController;let r=Date.now();try{let i=this.buildFormData(e,t),n=this.buildRequestParams(i);this.logger.debug("Starting transcription request",this.sanitizeForLogging({fileSize:e.byteLength,options:t}));let s=await(0,rt.requestUrl)(n),a=Date.now()-r;if(this.logger.info(`Transcription completed in ${a}ms`,{status:s.status}),s.status===200)return this.parseResponse(s.json,a);throw await this.handleAPIError(s)}catch(i){throw i.name==="AbortError"?(this.logger.debug("Transcription cancelled by user"),new I("Transcription cancelled","CANCELLED",void 0,!1)):(this.logger.error("Transcription request failed",i),i)}finally{this.abortController=void 0}}buildFormData(e,t){let r=new FormData,i=this.getMimeType(t),n=new Blob([e],{type:i});if(r.append("file",n,"audio.m4a"),r.append("model",(t==null?void 0:t.model)||"whisper-1"),t!=null&&t.language&&t.language!=="auto"&&r.append("language",t.language),t!=null&&t.prompt){let s=this.truncatePrompt(t.prompt);r.append("prompt",s)}return(t==null?void 0:t.temperature)!==void 0&&(et(t.temperature,0,1).valid?r.append("temperature",t.temperature.toString()):this.logger.warn("Invalid temperature value, using default",{temperature:t.temperature})),t!=null&&t.responseFormat&&r.append("response_format",t.responseFormat),r}buildRequestParams(e){return{url:this.API_ENDPOINT,method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:e,timeout:this.TIMEOUT,throw:!1}}parseResponse(e,t){if(e==null)return{text:"",duration:Math.max(t/1e3,.001)};if(typeof e=="string"){let s=Math.max(t/1e3,.001);return{text:e,duration:s}}let r=Math.max(t/1e3,.001),i=e,n={text:typeof i.text=="string"?i.text:"",language:typeof i.language=="string"?i.language:void 0,duration:typeof i.duration=="number"?i.duration:r};return Array.isArray(i.segments)&&(n.segments=i.segments),n}async handleAPIError(e){var i,n;let t=e.json,r=((i=t==null?void 0:t.error)==null?void 0:i.message)||"Unknown error";switch(this.logger.error(`API Error: ${e.status} - ${r}`,void 0,this.sanitizeForLogging({status:e.status,errorBody:t})),e.status){case 400:throw new I(r||"Invalid request","BAD_REQUEST",400,!1);case 401:throw new J;case 429:let s=(n=e.headers)==null?void 0:n["retry-after"];throw new ke(s?parseInt(s):void 0);case 413:throw new ee;case 500:case 502:case 503:throw new Oe(`Server error: ${r}`,e.status);default:throw new I(`API error: ${r}`,"UNKNOWN_ERROR",e.status,!1)}}getMimeType(e){return"audio/m4a"}truncatePrompt(e,t=224){let r=t*4;return tt(e,r)}queueRequest(e){return new Promise((t,r)=>{let i=async()=>{try{let n=await e();t(n)}catch(n){r(n)}};this.pendingRequests.push(i),this.processQueue()})}async processQueue(){if(!this.isProcessingQueue){for(this.isProcessingQueue=!0;this.pendingRequests.length>0;){let e=this.pendingRequests.shift();e&&await e()}this.isProcessingQueue=!1}}async validateApiKey(e){let t=this.apiKey;this.apiKey=e;try{let r=new ArrayBuffer(1024);return await this.performTranscription(r,{responseFormat:"text"}),!0}catch(r){return r instanceof J?(this.logger.warn("API key validation failed: Invalid key"),!1):(this.logger.debug("API key validation encountered non-auth error",r),!0)}finally{this.apiKey=t}}cancel(){this.abortController&&!this.abortController.signal.aborted&&(this.abortController.abort(),this.logger.debug("Transcription cancelled by user"))}sanitizeForLogging(e){let t=["apikey","api_key","token","authorization","secret"],r=i=>{if(i==null||typeof i!="object")return i;if(i instanceof ArrayBuffer)return"[ArrayBuffer]";if(Array.isArray(i))return i.map(s=>r(s));let n={};for(let[s,a]of Object.entries(i)){let l=s.toLowerCase();t.some(c=>l.includes(c))?n[s]="***":n[s]=r(a)}return n};return r(e)}resetCircuitBreaker(){this.circuitBreaker.reset()}};Y();var te=class{constructor(e,t,r){this.whisperService=e;this.logger=t;this.config={enabled:!0,apiKey:"",model:"whisper-1",maxConcurrency:1,timeout:3e4,...r}}async transcribe(e,t){let r=Date.now();try{let i=this.convertOptions(t),n=await this.whisperService.transcribe(e,i),s=Date.now()-r;return this.convertResponse(n,s)}catch(i){throw this.logger.error("WhisperAdapter: Transcription failed",i),i}}convertOptions(e){let t={model:(e==null?void 0:e.model)||this.config.model||"whisper-1",language:e==null?void 0:e.language};if(e!=null&&e.whisper){let r=e.whisper;r.temperature!==void 0&&(t.temperature=r.temperature),r.prompt&&(t.prompt=r.prompt),r.responseFormat&&(t.responseFormat=r.responseFormat)}return t.responseFormat||(t.responseFormat="verbose_json"),t}convertResponse(e,t){var i;let r=e.text.split(/\s+/).filter(n=>n.length>0).length;return{text:e.text,language:e.language,duration:e.duration,segments:(i=e.segments)==null?void 0:i.map(n=>({id:n.id,start:n.start,end:n.end,text:n.text,confidence:n.no_speech_prob?1-n.no_speech_prob:void 0})),provider:"whisper",metadata:{model:"whisper-1",processingTime:t,wordCount:r}}}async validateApiKey(e){return this.whisperService.validateApiKey(e)}cancel(){this.whisperService.cancel()}getProviderName(){return"OpenAI Whisper"}getCapabilities(){return{streaming:!1,realtime:!1,languages:["en","zh","de","es","ru","ko","fr","ja","pt","tr","pl","ca","nl","ar","sv","it","id","hi","fi","vi","he","uk","el","ms","cs","ro","da","hu","ta","no","th","ur","hr","bg","lt","la","mi","ml","cy","sk","te","fa","lv","bn","sr","az","sl","kn","et","mk","br","eu","is","hy","ne","mn","bs","kk","sq","sw","gl","mr","pa","si","km","sn","yo","so","af","oc","ka","be","tg","sd","gu","am","yi","lo","uz","fo","ht","ps","tk","nn","mt","sa","lb","my","bo","tl","mg","as","tt","haw","ln","ha","ba","jw","su"],maxFileSize:25*1024*1024,audioFormats:["mp3","mp4","mpeg","mpga","m4a","wav","webm"],features:["transcription","translation","timestamps","language_detection","word_timestamps"],models:["whisper-1"]}}async isAvailable(){try{let e=new ArrayBuffer(1024);return await this.whisperService.transcribe(e,{responseFormat:"text"}),!0}catch(e){let t=e.message.toLowerCase();return!(t.includes("circuit")||t.includes("unavailable")||t.includes("timeout"))}}getConfig(){return{...this.config}}resetCircuitBreaker(){this.whisperService.resetCircuitBreaker()}updateConfig(e){this.config={...this.config,...e}}};var it=require("obsidian");Y();var re={ENDPOINT:"https://api.deepgram.com/v1/listen",MAX_FILE_SIZE:2147483648,DEFAULT_TIMEOUT:3e4,MAX_TIMEOUT:54e5,REQUESTS_PER_MINUTE:100,RECOMMENDED_MAX_SIZE:52428800},ie={MIN_HEADER_SIZE:44,SIZE_WARNING_THRESHOLD:1024,SIZE_WARNING_LARGE:100*1024*1024,SILENCE_THRESHOLD:327,SILENCE_PEAK_MULTIPLIER:5,SAMPLE_SIZE:8192},Nt={CIRCUIT_BREAKER:{FAILURE_THRESHOLD:5,SUCCESS_THRESHOLD:2,TIMEOUT:6e4},RETRY:{MAX_RETRIES:3,BASE_DELAY:1e3,MAX_DELAY:1e4,JITTER_MAX:1e3},TIMEOUT:{SIZE_MB_THRESHOLD:5,PROCESSING_TIME_PER_MB:30*1e3,BUFFER_MULTIPLIER:1.5}},Ne={CONSECUTIVE_THRESHOLD:.5,MIN_SEGMENT_LENGTH:1,WORDS_PER_SEGMENT:10,SPEAKER_LABELS:{PREFIX:"Speaker",NUMBERING:"numeric"}};var V={AUDIO_VALIDATION:{EMPTY:"Audio data is empty",TOO_SMALL:"Audio data too small to contain valid audio",TOO_LARGE:"Audio file exceeds maximum size limit (2GB)",VERY_SMALL_WARNING:"Audio file is very small, may not contain meaningful content",LARGE_WARNING:"Large audio file may take longer to process"},API:{INVALID_RESPONSE:"Invalid response from Deepgram API",NO_ALTERNATIVES:"No transcription alternatives found",EMPTY_TRANSCRIPT:"Transcription service returned empty text",SERVER_TIMEOUT:"Server timeout processing large audio file. This often happens with very large files (>50MB). Try: 1) Breaking the file into smaller chunks, 2) Reducing audio quality/bitrate, or 3) Using a different model like 'enhanced' which may be faster.",CANCELLED:"Transcription cancelled",MAX_RETRIES:"operation failed after {retries} attempts"},MIGRATION:{MODEL_NOT_FOUND:"Model not found. Please check model ID.",USER_APPROVAL_REQUIRED:"User approval required but not granted",INVALID_BACKUP:"Invalid backup data",ROLLBACK_FAILED:"Rollback failed"}};var se={enabled:!0,format:"speaker_prefix",speakerLabels:{prefix:"Speaker",numbering:"numeric"},merging:{consecutiveThreshold:Ne.CONSECUTIVE_THRESHOLD,minSegmentLength:Ne.MIN_SEGMENT_LENGTH},output:{includeTimestamps:!1,includeConfidence:!1,paragraphBreaks:!0,lineBreaksBetweenSpeakers:!0}},ne=class{constructor(e){this.logger=e}formatTranscript(e,t=se){let r=Date.now();if(this.logFormatStart(e,t),!this.hasSpeakerInformation(e))return this.logger.debug("No speaker information found, returning original text"),this.createFallbackResult(e);let i=this.processTranscriptWithSpeakers(e,t);return this.logFormatComplete(i,Date.now()-r),i}processTranscriptWithSpeakers(e,t){let r=this.buildSegments(e,t);this.logger.debug(`Created ${r.length} segments from ${e.length} words`);let i=this.calculateStatistics(r,e);return{formattedText:this.formatSegments(r,t),segments:r,speakerCount:i.totalSpeakers,statistics:i,originalWordCount:e.length}}logFormatStart(e,t){this.logger.debug("=== DiarizationFormatter.formatTranscript START ===",{wordCount:e.length,config:t})}logFormatComplete(e,t){this.logger.info("=== DiarizationFormatter.formatTranscript COMPLETE ===",{processingTime:t,speakerCount:e.speakerCount,segmentCount:e.segments.length,formattedTextLength:e.formattedText.length})}hasSpeakerInformation(e){return e.some(t=>t.speaker!==void 0&&t.speaker>=0)}createFallbackResult(e){var i,n;let t=e.map(s=>s.word).join(" "),r=e.length>0?e[e.length-1].end-e[0].start:0;return{formattedText:t,segments:[{id:0,text:t,speaker:0,start:((i=e[0])==null?void 0:i.start)||0,end:((n=e[e.length-1])==null?void 0:n.end)||0,confidence:e.reduce((s,a)=>s+a.confidence,0)/e.length||0,wordCount:e.length}],speakerCount:1,statistics:{totalSpeakers:1,totalSegments:1,averageSegmentLength:e.length,speakerDistribution:{0:1},totalDuration:r,averageConfidence:e.reduce((s,a)=>s+a.confidence,0)/e.length||0},originalWordCount:e.length}}buildSegments(e,t){if(e.length===0)return[];let r=[],i=null,n=0;for(let s=0;s0?e[s-1]:null)?(i&&this.isValidSegment(i,t)&&r.push(this.finalizeSegment(i,n++)),i=this.initializeSegment(a)):i&&this.appendToSegment(i,a)}return i&&this.isValidSegment(i,t)&&r.push(this.finalizeSegment(i,n)),r}shouldCreateNewSegment(e,t,r,i){return!!(!t||t.speaker!==e.speaker||i&&t.end!==void 0&&e.start-i.end>r.merging.consecutiveThreshold)}initializeSegment(e){return{text:e.word,speaker:e.speaker||0,start:e.start,end:e.end,confidence:e.confidence,wordCount:1}}appendToSegment(e,t){e.text=(e.text||"")+" "+t.word,e.end=t.end,e.wordCount=(e.wordCount||0)+1;let r=(e.confidence||0)*((e.wordCount||1)-1)+t.confidence;e.confidence=r/(e.wordCount||1)}isValidSegment(e,t){var r;return(e.wordCount||0)>=t.merging.minSegmentLength&&(((r=e.text)==null?void 0:r.trim().length)||0)>0}finalizeSegment(e,t){return{id:t,text:(e.text||"").trim(),speaker:e.speaker||0,start:e.start||0,end:e.end||0,confidence:e.confidence||0,wordCount:e.wordCount||0}}formatSegments(e,t){if(e.length===0)return"";let r=[];for(let i of e){let n=this.generateSpeakerLabel(i.speaker,t),s="";switch(t.format){case"speaker_prefix":s=`${n}: ${i.text}`;break;case"speaker_block":s=`${n} +"use strict";var j=Object.defineProperty;var Ye=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var ht=Object.prototype.hasOwnProperty;var Ze=(o,e)=>()=>(o&&(e=o(o=0)),e);var je=(o,e)=>{for(var t in e)j(o,t,{get:e[t],enumerable:!0})},ft=(o,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of mt(e))!ht.call(o,i)&&i!==t&&j(o,i,{get:()=>e[i],enumerable:!(r=Ye(e,i))||r.enumerable});return o};var vt=o=>ft(j({},"__esModule",{value:!0}),o),Xe=(o,e,t,r)=>{for(var i=r>1?void 0:r?Ye(e,t):e,n=o.length-1,s;n>=0;n--)(s=o[n])&&(i=(r?s(e,t,i):s(i))||i);return r&&i&&j(e,t,i),i};var E,q,X,$,Y=Ze(()=>{"use strict";E=class extends Error{constructor(t,r,i,n=!1,s){super(t);this.code=r;this.provider=i;this.isRetryable=n;this.statusCode=s;this.name="TranscriptionError"}},q=class extends E{constructor(e,t="Invalid API key"){super(t,"AUTH_ERROR",e,!1,401)}},X=class extends E{constructor(t,r){super("Rate limit exceeded","RATE_LIMIT",t,!0,429);this.retryAfter=r}},$=class extends E{constructor(e){super("Provider temporarily unavailable","UNAVAILABLE",e,!0,503)}}});var Qe={};je(Qe,{DEFAULT_SETTINGS:()=>Pe});var Pe,Le=Ze(()=>{"use strict";Y();Pe={apiKey:"",model:"whisper-1",language:"auto",autoInsert:!0,insertPosition:"cursor",timestampFormat:"none",maxFileSize:25*1024*1024,enableCache:!0,cacheTTL:36e5,temperature:void 0,prompt:void 0,textFormat:"plain",addTimestamp:!1,showFormatOptions:!1,provider:"auto",selectionStrategy:"performance_optimized",fallbackStrategy:"auto",latencyWeight:40,successWeight:35,costWeight:25,budgetAlert:80,autoCostOptimization:!1,qualityThreshold:85,minConfidence:70,strictLanguage:!1,enablePostProcessing:!0,abTestEnabled:!1,abTestSplit:50,abTestDuration:7,abTestMetrics:"all",requestTimeout:3e4,maxParallelRequests:2,maxRetries:3,cacheDuration:24,circuitBreakerEnabled:!0,circuitBreakerThreshold:5,circuitBreakerTimeout:6e4,healthChecksEnabled:!1,gracefulDegradation:!0,debugMode:!1,metricsEnabled:!1,metricsRetentionDays:30,showMetrics:!1,autoValidateKeys:!1,useEnvVars:!1}});var St={};je(St,{default:()=>Me});module.exports=vt(St);var v=require("obsidian");Le();var Q=class{constructor(e,t,r,i,n,s){this.whisperService=e;this.audioProcessor=t;this.textFormatter=r;this.eventManager=i;this.logger=n;this.settings=s;this.status="idle"}async transcribe(e){var t,r,i,n,s,a,l;try{this.status="validating",this.eventManager.emit("transcription:start",{fileName:e.name});let c=await this.audioProcessor.validate(e);if(!c.valid)throw new Error(`File validation failed: ${(t=c.errors)==null?void 0:t.join(", ")}`);this.status="processing";let p=await this.audioProcessor.process(e);this.status="transcribing",this.logger.debug("Starting transcription with WhisperService");let u=typeof((r=this.settings)==null?void 0:r.language)=="string"?this.settings.language:void 0,h=typeof((i=this.settings)==null?void 0:i.model)=="string"?this.settings.model:void 0,f=!!(u||h);f&&this.logger.debug("Transcription options:",{language:u,model:h});let g=f?await this.whisperService.transcribe(p.buffer,{language:u,model:h}):await this.whisperService.transcribe(p.buffer);if(this.logger.debug("WhisperService response:",{hasResponse:!!g,hasText:!!(g!=null&&g.text),textLength:((n=g==null?void 0:g.text)==null?void 0:n.length)||0,textPreview:(s=g==null?void 0:g.text)==null?void 0:s.substring(0,100),language:g==null?void 0:g.language}),!g||g.text===void 0||g.text===null)throw this.logger.error("Empty or invalid response from WhisperService",void 0,{response:g}),new Error("Transcription service returned empty text");this.status="formatting";let D=this.textFormatter.format(g.text);this.logger.debug("Text formatted:",{originalLength:g.text.length,formattedLength:D.length,formattedPreview:D.substring(0,100)});let y={text:D,language:g.language,segments:(a=g.segments)==null?void 0:a.map((x,_)=>({id:_,start:x.start,end:x.end,text:x.text}))};return this.status="completed",this.logger.debug("Emitting transcription:complete event",{textLength:y.text.length,hasSegments:!!y.segments,segmentsCount:((l=y.segments)==null?void 0:l.length)||0}),this.eventManager.emit("transcription:complete",{result:y}),y}catch(c){this.status="error";let p=this.normalizeError(c);throw this.eventManager.emit("transcription:error",{error:p}),p}}cancel(){var e;(e=this.abortController)==null||e.abort(),this.status="cancelled",this.eventManager.emit("transcription:cancelled",{})}getStatus(){return this.status}normalizeError(e){var t;if(e instanceof Error){if(e.code==="MAX_RETRIES_EXCEEDED"&&e.message.includes(":")){let i=e.message.split(":"),n=(t=i[i.length-1])==null?void 0:t.trim();if(n)return new Error(n)}return e}return typeof e=="string"?new Error(e):new Error("Unknown error")}};var rt=require("obsidian");function Je(o){return new Promise(e=>setTimeout(e,o))}function et(o,e,t,r=!0){if(r){if(ot)return{valid:!1,error:`Value must be between ${e} and ${t} (inclusive)`}}else if(o<=e||o>=t)return{valid:!1,error:`Value must be between ${e} and ${t} (exclusive)`};return{valid:!0}}function tt(o,e,t="..."){if(e<=0)throw new Error("Max length must be positive");if(o.length<=e)return o;let r=e-t.length;return r<=0?t:o.substring(0,r)+t}var I=class extends Error{constructor(t,r,i,n=!1){super(t);this.code=r;this.status=i;this.isRetryable=n;this.name="WhisperAPIError"}},J=class extends I{constructor(e="Invalid API key"){super(e,"AUTH_ERROR",401,!1)}},ke=class extends I{constructor(t){super("Rate limit exceeded","RATE_LIMIT",429,!0);this.retryAfter=t}},ee=class extends I{constructor(){super("File size exceeds API limit (25MB)","FILE_TOO_LARGE",413,!1)}},Oe=class extends I{constructor(e,t){super(e,"SERVER_ERROR",t,!0)}},Re=class{constructor(e){this.logger=e;this.maxRetries=3;this.baseDelay=250;this.maxDelay=2e3}async execute(e){var r;let t;for(let i=0;i=this.nextAttemptTime?(this.state="HALF_OPEN",this.logger.info("Circuit breaker entering HALF_OPEN state"),!1):!0:!1}onSuccess(){this.failureCount=0,this.state==="HALF_OPEN"&&(this.successCount++,this.successCount>=this.successThreshold&&(this.state="CLOSED",this.successCount=0,this.logger.info("Circuit breaker closed")))}onFailure(){this.failureCount++,this.state==="HALF_OPEN"?(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn("Circuit breaker opened due to failure in HALF_OPEN state")):this.failureCount>=this.failureThreshold&&(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn(`Circuit breaker opened after ${this.failureCount} failures`))}reset(){this.state="CLOSED",this.failureCount=0,this.successCount=0,this.logger.info("Circuit breaker reset")}},H=class{constructor(e,t){this.apiKey=e;this.logger=t;this.API_ENDPOINT="https://api.openai.com/v1/audio/transcriptions";this.MAX_FILE_SIZE=25*1024*1024;this.TIMEOUT=3e4;this.requestQueue=Promise.resolve();this.pendingRequests=[];this.isProcessingQueue=!1;this.retryStrategy=new Re(t),this.circuitBreaker=new Fe(t)}async transcribe(e,t){return this.queueRequest(()=>this.executeTranscription(e,t))}async executeTranscription(e,t){if(e.byteLength>this.MAX_FILE_SIZE)throw new ee;return this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(e,t)))}async performTranscription(e,t){this.abortController=new AbortController;let r=Date.now();try{let i=this.buildFormData(e,t),n=this.buildRequestParams(i);this.logger.debug("Starting transcription request",this.sanitizeForLogging({fileSize:e.byteLength,options:t}));let s=await(0,rt.requestUrl)(n),a=Date.now()-r;if(this.logger.info(`Transcription completed in ${a}ms`,{status:s.status}),s.status===200)return this.parseResponse(s.json,a);throw await this.handleAPIError(s)}catch(i){throw i.name==="AbortError"?(this.logger.debug("Transcription cancelled by user"),new I("Transcription cancelled","CANCELLED",void 0,!1)):(this.logger.error("Transcription request failed",i),i)}finally{this.abortController=void 0}}buildFormData(e,t){let r=new FormData,i=this.getMimeType(t),n=new Blob([e],{type:i});if(r.append("file",n,"audio.m4a"),r.append("model",(t==null?void 0:t.model)||"whisper-1"),t!=null&&t.language&&t.language!=="auto"&&r.append("language",t.language),t!=null&&t.prompt){let s=this.truncatePrompt(t.prompt);r.append("prompt",s)}return(t==null?void 0:t.temperature)!==void 0&&(et(t.temperature,0,1).valid?r.append("temperature",t.temperature.toString()):this.logger.warn("Invalid temperature value, using default",{temperature:t.temperature})),t!=null&&t.responseFormat&&r.append("response_format",t.responseFormat),r}buildRequestParams(e){return{url:this.API_ENDPOINT,method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:e,timeout:this.TIMEOUT,throw:!1}}parseResponse(e,t){if(e==null)return{text:"",duration:Math.max(t/1e3,.001)};if(typeof e=="string"){let s=Math.max(t/1e3,.001);return{text:e,duration:s}}let r=Math.max(t/1e3,.001),i=e,n={text:typeof i.text=="string"?i.text:"",language:typeof i.language=="string"?i.language:void 0,duration:typeof i.duration=="number"?i.duration:r};return Array.isArray(i.segments)&&(n.segments=i.segments),n}async handleAPIError(e){var i,n;let t=e.json,r=((i=t==null?void 0:t.error)==null?void 0:i.message)||"Unknown error";switch(this.logger.error(`API Error: ${e.status} - ${r}`,void 0,this.sanitizeForLogging({status:e.status,errorBody:t})),e.status){case 400:throw new I(r||"Invalid request","BAD_REQUEST",400,!1);case 401:throw new J;case 429:{let s=(n=e.headers)==null?void 0:n["retry-after"];throw new ke(s?parseInt(s):void 0)}case 413:throw new ee;case 500:case 502:case 503:throw new Oe(`Server error: ${r}`,e.status);default:throw new I(`API error: ${r}`,"UNKNOWN_ERROR",e.status,!1)}}getMimeType(e){return"audio/m4a"}truncatePrompt(e,t=224){let r=t*4;return tt(e,r)}queueRequest(e){return new Promise((t,r)=>{let i=async()=>{try{let n=await e();t(n)}catch(n){r(n)}};this.pendingRequests.push(i),this.processQueue()})}async processQueue(){if(!this.isProcessingQueue){for(this.isProcessingQueue=!0;this.pendingRequests.length>0;){let e=this.pendingRequests.shift();e&&await e()}this.isProcessingQueue=!1}}async validateApiKey(e){let t=this.apiKey;this.apiKey=e;try{let r=new ArrayBuffer(1024);return await this.performTranscription(r,{responseFormat:"text"}),!0}catch(r){return r instanceof J?(this.logger.warn("API key validation failed: Invalid key"),!1):(this.logger.debug("API key validation encountered non-auth error",r),!0)}finally{this.apiKey=t}}cancel(){this.abortController&&!this.abortController.signal.aborted&&(this.abortController.abort(),this.logger.debug("Transcription cancelled by user"))}sanitizeForLogging(e){let t=["apikey","api_key","token","authorization","secret"],r=i=>{if(i==null||typeof i!="object")return i;if(i instanceof ArrayBuffer)return"[ArrayBuffer]";if(Array.isArray(i))return i.map(s=>r(s));let n={};for(let[s,a]of Object.entries(i)){let l=s.toLowerCase();t.some(c=>l.includes(c))?n[s]="***":n[s]=r(a)}return n};return r(e)}resetCircuitBreaker(){this.circuitBreaker.reset()}};Y();var te=class{constructor(e,t,r){this.whisperService=e;this.logger=t;this.config={enabled:!0,apiKey:"",model:"whisper-1",maxConcurrency:1,timeout:3e4,...r}}async transcribe(e,t){let r=Date.now();try{let i=this.convertOptions(t),n=await this.whisperService.transcribe(e,i),s=Date.now()-r;return this.convertResponse(n,s)}catch(i){throw this.logger.error("WhisperAdapter: Transcription failed",i),i}}convertOptions(e){let t={model:(e==null?void 0:e.model)||this.config.model||"whisper-1",language:e==null?void 0:e.language};if(e!=null&&e.whisper){let r=e.whisper;r.temperature!==void 0&&(t.temperature=r.temperature),r.prompt&&(t.prompt=r.prompt),r.responseFormat&&(t.responseFormat=r.responseFormat)}return t.responseFormat||(t.responseFormat="verbose_json"),t}convertResponse(e,t){var i;let r=e.text.split(/\s+/).filter(n=>n.length>0).length;return{text:e.text,language:e.language,duration:e.duration,segments:(i=e.segments)==null?void 0:i.map(n=>({id:n.id,start:n.start,end:n.end,text:n.text,confidence:n.no_speech_prob?1-n.no_speech_prob:void 0})),provider:"whisper",metadata:{model:"whisper-1",processingTime:t,wordCount:r}}}async validateApiKey(e){return this.whisperService.validateApiKey(e)}cancel(){this.whisperService.cancel()}getProviderName(){return"OpenAI Whisper"}getCapabilities(){return{streaming:!1,realtime:!1,languages:["en","zh","de","es","ru","ko","fr","ja","pt","tr","pl","ca","nl","ar","sv","it","id","hi","fi","vi","he","uk","el","ms","cs","ro","da","hu","ta","no","th","ur","hr","bg","lt","la","mi","ml","cy","sk","te","fa","lv","bn","sr","az","sl","kn","et","mk","br","eu","is","hy","ne","mn","bs","kk","sq","sw","gl","mr","pa","si","km","sn","yo","so","af","oc","ka","be","tg","sd","gu","am","yi","lo","uz","fo","ht","ps","tk","nn","mt","sa","lb","my","bo","tl","mg","as","tt","haw","ln","ha","ba","jw","su"],maxFileSize:25*1024*1024,audioFormats:["mp3","mp4","mpeg","mpga","m4a","wav","webm"],features:["transcription","translation","timestamps","language_detection","word_timestamps"],models:["whisper-1"]}}async isAvailable(){try{let e=new ArrayBuffer(1024);return await this.whisperService.transcribe(e,{responseFormat:"text"}),!0}catch(e){let t=e.message.toLowerCase();return!(t.includes("circuit")||t.includes("unavailable")||t.includes("timeout"))}}getConfig(){return{...this.config}}resetCircuitBreaker(){this.whisperService.resetCircuitBreaker()}updateConfig(e){this.config={...this.config,...e}}};var it=require("obsidian");Y();var re={ENDPOINT:"https://api.deepgram.com/v1/listen",MAX_FILE_SIZE:2147483648,DEFAULT_TIMEOUT:3e4,MAX_TIMEOUT:54e5,REQUESTS_PER_MINUTE:100,RECOMMENDED_MAX_SIZE:52428800},ie={MIN_HEADER_SIZE:44,SIZE_WARNING_THRESHOLD:1024,SIZE_WARNING_LARGE:100*1024*1024,SILENCE_THRESHOLD:327,SILENCE_PEAK_MULTIPLIER:5,SAMPLE_SIZE:8192},Nt={CIRCUIT_BREAKER:{FAILURE_THRESHOLD:5,SUCCESS_THRESHOLD:2,TIMEOUT:6e4},RETRY:{MAX_RETRIES:3,BASE_DELAY:1e3,MAX_DELAY:1e4,JITTER_MAX:1e3},TIMEOUT:{SIZE_MB_THRESHOLD:5,PROCESSING_TIME_PER_MB:30*1e3,BUFFER_MULTIPLIER:1.5}},Ne={CONSECUTIVE_THRESHOLD:.5,MIN_SEGMENT_LENGTH:1,WORDS_PER_SEGMENT:10,SPEAKER_LABELS:{PREFIX:"Speaker",NUMBERING:"numeric"}};var V={AUDIO_VALIDATION:{EMPTY:"Audio data is empty",TOO_SMALL:"Audio data too small to contain valid audio",TOO_LARGE:"Audio file exceeds maximum size limit (2GB)",VERY_SMALL_WARNING:"Audio file is very small, may not contain meaningful content",LARGE_WARNING:"Large audio file may take longer to process"},API:{INVALID_RESPONSE:"Invalid response from Deepgram API",NO_ALTERNATIVES:"No transcription alternatives found",EMPTY_TRANSCRIPT:"Transcription service returned empty text",SERVER_TIMEOUT:"Server timeout processing large audio file. This often happens with very large files (>50MB). Try: 1) Breaking the file into smaller chunks, 2) Reducing audio quality/bitrate, or 3) Using a different model like 'enhanced' which may be faster.",CANCELLED:"Transcription cancelled",MAX_RETRIES:"operation failed after {retries} attempts"},MIGRATION:{MODEL_NOT_FOUND:"Model not found. Please check model ID.",USER_APPROVAL_REQUIRED:"User approval required but not granted",INVALID_BACKUP:"Invalid backup data",ROLLBACK_FAILED:"Rollback failed"}};var se={enabled:!0,format:"speaker_prefix",speakerLabels:{prefix:"Speaker",numbering:"numeric"},merging:{consecutiveThreshold:Ne.CONSECUTIVE_THRESHOLD,minSegmentLength:Ne.MIN_SEGMENT_LENGTH},output:{includeTimestamps:!1,includeConfidence:!1,paragraphBreaks:!0,lineBreaksBetweenSpeakers:!0}},ne=class{constructor(e){this.logger=e}formatTranscript(e,t=se){let r=Date.now();if(this.logFormatStart(e,t),!this.hasSpeakerInformation(e))return this.logger.debug("No speaker information found, returning original text"),this.createFallbackResult(e);let i=this.processTranscriptWithSpeakers(e,t);return this.logFormatComplete(i,Date.now()-r),i}processTranscriptWithSpeakers(e,t){let r=this.buildSegments(e,t);this.logger.debug(`Created ${r.length} segments from ${e.length} words`);let i=this.calculateStatistics(r,e);return{formattedText:this.formatSegments(r,t),segments:r,speakerCount:i.totalSpeakers,statistics:i,originalWordCount:e.length}}logFormatStart(e,t){this.logger.debug("=== DiarizationFormatter.formatTranscript START ===",{wordCount:e.length,config:t})}logFormatComplete(e,t){this.logger.info("=== DiarizationFormatter.formatTranscript COMPLETE ===",{processingTime:t,speakerCount:e.speakerCount,segmentCount:e.segments.length,formattedTextLength:e.formattedText.length})}hasSpeakerInformation(e){return e.some(t=>t.speaker!==void 0&&t.speaker>=0)}createFallbackResult(e){var i,n;let t=e.map(s=>s.word).join(" "),r=e.length>0?e[e.length-1].end-e[0].start:0;return{formattedText:t,segments:[{id:0,text:t,speaker:0,start:((i=e[0])==null?void 0:i.start)||0,end:((n=e[e.length-1])==null?void 0:n.end)||0,confidence:e.reduce((s,a)=>s+a.confidence,0)/e.length||0,wordCount:e.length}],speakerCount:1,statistics:{totalSpeakers:1,totalSegments:1,averageSegmentLength:e.length,speakerDistribution:{0:1},totalDuration:r,averageConfidence:e.reduce((s,a)=>s+a.confidence,0)/e.length||0},originalWordCount:e.length}}buildSegments(e,t){if(e.length===0)return[];let r=[],i=null,n=0;for(let s=0;s0?e[s-1]:null)?(i&&this.isValidSegment(i,t)&&r.push(this.finalizeSegment(i,n++)),i=this.initializeSegment(a)):i&&this.appendToSegment(i,a)}return i&&this.isValidSegment(i,t)&&r.push(this.finalizeSegment(i,n)),r}shouldCreateNewSegment(e,t,r,i){return!!(!t||t.speaker!==e.speaker||i&&t.end!==void 0&&e.start-i.end>r.merging.consecutiveThreshold)}initializeSegment(e){return{text:e.word,speaker:e.speaker||0,start:e.start,end:e.end,confidence:e.confidence,wordCount:1}}appendToSegment(e,t){e.text=(e.text||"")+" "+t.word,e.end=t.end,e.wordCount=(e.wordCount||0)+1;let r=(e.confidence||0)*((e.wordCount||1)-1)+t.confidence;e.confidence=r/(e.wordCount||1)}isValidSegment(e,t){var r;return(e.wordCount||0)>=t.merging.minSegmentLength&&(((r=e.text)==null?void 0:r.trim().length)||0)>0}finalizeSegment(e,t){return{id:t,text:(e.text||"").trim(),speaker:e.speaker||0,start:e.start||0,end:e.end||0,confidence:e.confidence||0,wordCount:e.wordCount||0}}formatSegments(e,t){if(e.length===0)return"";let r=[];for(let i of e){let n=this.generateSpeakerLabel(i.speaker,t),s="";switch(t.format){case"speaker_prefix":s=`${n}: ${i.text}`;break;case"speaker_block":s=`${n} ${i.text}`;break;case"custom":s=this.applyCustomFormat(i,n,t);break;default:s=`${n}: ${i.text}`}if(t.output.includeTimestamps&&(s=`${`[${this.formatTime(i.start)} - ${this.formatTime(i.end)}]`} ${s}`),t.output.includeConfidence){let a=`(${Math.round(i.confidence*100)}%)`;s=`${s} ${a}`}r.push(s)}return t.output.lineBreaksBetweenSpeakers?this.insertSpeakerBreaks(r,e):r.join(` -`)}generateSpeakerLabel(e,t){let{prefix:r,numbering:i,customLabels:n}=t.speakerLabels;if(n&&n[e])return n[e];switch(i){case"alphabetic":let s=String.fromCharCode(65+e%26);return`${r} ${s}`;case"numeric":default:return`${r} ${e+1}`}}applyCustomFormat(e,t,r){return`${t}: ${e.text}`}insertSpeakerBreaks(e,t){let r=[],i=null;for(let n=0;n0?t[t.length-1].end-t[0].start:0;return{totalSpeakers:Object.keys(r).length,totalSegments:e.length,averageSegmentLength:e.length>0?n/e.length:0,speakerDistribution:r,totalDuration:s,averageConfidence:e.length>0?i/e.length:0}}validateConfig(e){let t=[];return e.merging.consecutiveThreshold<0&&t.push("consecutiveThreshold must be non-negative"),e.merging.minSegmentLength<1&&t.push("minSegmentLength must be at least 1"),e.speakerLabels.prefix.trim()||t.push("speakerLabels.prefix cannot be empty"),{valid:t.length===0,errors:t}}};var _e=class{constructor(e){this.logger=e}validateAudio(e){let t=[],r=[],i={size:e.byteLength,isEmpty:e.byteLength===0,hasMinimumSize:e.byteLength>=ie.MIN_HEADER_SIZE,format:this.detectAudioFormat(e)};i.isEmpty&&r.push(V.AUDIO_VALIDATION.EMPTY),!i.hasMinimumSize&&!i.isEmpty&&r.push(V.AUDIO_VALIDATION.TOO_SMALL),i.size>re.MAX_FILE_SIZE&&r.push(V.AUDIO_VALIDATION.TOO_LARGE),i.sizeie.SIZE_WARNING_LARGE&&t.push(V.AUDIO_VALIDATION.LARGE_WARNING);let n=r.length===0;return this.logger.debug("Audio validation completed",{isValid:n,warnings:t.length,errors:r.length,metadata:i}),{isValid:n,warnings:t,errors:r,metadata:i}}detectAudioFormat(e){if(e.byteLength<12)return;let t=new Uint8Array(e,0,12);return t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70?"wav":t[0]===255&&(t[1]&224)===224||t[0]===73&&t[1]===68&&t[2]===51?"mp3":t[0]===102&&t[1]===76&&t[2]===97&&t[3]===67?"flac":t[0]===79&&t[1]===103&&t[2]===103&&t[3]===83?"ogg":t.length>=8&&t[4]===102&&t[5]===116&&t[6]===121&&t[7]===112?"m4a":t[0]===26&&t[1]===69&&t[2]===223&&t[3]===163?"webm":(this.logger.debug("Unknown audio format detected",{firstBytes:Array.from(t.slice(0,8)).map(r=>"0x"+r.toString(16).padStart(2,"0")).join(" ")}),"unknown")}checkForSilence(e){if(e.byteLength<44)return{isSilent:!0,averageAmplitude:0,peakAmplitude:0};let t=new Uint8Array(e,0,4);if(!(t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70))return{isSilent:!1,averageAmplitude:-1,peakAmplitude:-1};try{let i=Math.min(e.byteLength-44,8192),n=new Int16Array(e,44,i/2),s=0,a=0;for(let u=0;u0?s/n.length:0,c=327;return{isSilent:l{this.queue.push(e),this.processQueue()})}async processQueue(){if(this.processing||this.queue.length===0)return;this.processing=!0;let e=6e4/this.requestsPerMinute;for(;this.queue.length>0;){let r=Date.now()-this.lastRequestTime;if(rsetTimeout(t,e))}},Be=class{constructor(e){this.logger=e;this.state="CLOSED";this.failureCount=0;this.successCount=0;this.nextAttemptTime=0;this.failureThreshold=5;this.successThreshold=2;this.timeout=6e4}async execute(e){if(this.isOpen())throw new $("deepgram");try{let t=await e();return this.onSuccess(),t}catch(t){throw this.onFailure(),t}}isOpen(){return this.state==="OPEN"?Date.now()>=this.nextAttemptTime?(this.state="HALF_OPEN",this.logger.info("Deepgram Circuit breaker entering HALF_OPEN state"),!1):!0:!1}onSuccess(){this.failureCount=0,this.state==="HALF_OPEN"&&(this.successCount++,this.successCount>=this.successThreshold&&(this.state="CLOSED",this.successCount=0,this.logger.info("Deepgram Circuit breaker closed")))}onFailure(){this.failureCount++,this.state==="HALF_OPEN"?(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn("Deepgram Circuit breaker opened due to failure in HALF_OPEN state")):this.failureCount>=this.failureThreshold&&(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn(`Deepgram Circuit breaker opened after ${this.failureCount} failures`))}reset(){this.state="CLOSED",this.failureCount=0,this.successCount=0,this.logger.info("Deepgram Circuit breaker reset")}},Ke=class{constructor(e){this.logger=e;this.maxRetries=3;this.baseDelay=1e3;this.maxDelay=1e4}async execute(e){let t;for(let r=0;rsetTimeout(t,e))}},ae=class{constructor(e,t,r=100,i=3e4){this.apiKey=e;this.logger=t;this.API_ENDPOINT="https://api.deepgram.com/v1/listen";this.MAX_FILE_SIZE=2*1024*1024*1024;this.lastAudioSize=0;this.timeout=i,this.circuitBreaker=new Be(t),this.retryStrategy=new Ke(t),this.rateLimiter=new ze(r,t),this.audioValidator=new _e(t),this.diarizationFormatter=new ne(t)}async transcribe(e,t,r){return await this.rateLimiter.acquire(),this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(e,t,r)))}calculateDynamicTimeout(e){let t=e/1048576,r=this.timeout;if(t<=5)return r;let i;t<=10?i=t*30*1e3:t<=50?i=t*40*1e3*1.5:t<=100?i=t*45*1e3*1.8:i=t*50*1e3*2,t>=50&&(i=Math.max(i,40*60*1e3)),t>=100&&(i=Math.max(i,60*60*1e3));let n=90*60*1e3;return i=Math.min(i,n),this.logger.debug("Dynamic timeout calculation",{audioSizeMB:t,baseTimeout:r,finalTimeout:i,timeoutMinutes:Math.round(i/6e4)}),i}async performTranscription(e,t,r){var s,a,l,c,p,u,h,f,g,D;this.abortController=new AbortController;let i=Date.now();this.lastAudioSize=e.byteLength;let n=this.calculateDynamicTimeout(e.byteLength);try{let y=this.audioValidator.validateAudio(e);if(this.logger.debug("Audio validation results",{isValid:y.isValid,warnings:y.warnings,errors:y.errors,metadata:y.metadata}),!y.isValid)throw new E(`Audio validation failed: ${y.errors.join(", ")}`,"INVALID_AUDIO","deepgram",!1);if(y.warnings.forEach(m=>{this.logger.warn(`Audio validation warning: ${m}`)}),y.metadata.format==="wav"){let m=this.audioValidator.checkForSilence(e);this.logger.debug("Audio silence analysis",m),m.isSilent&&this.logger.warn("Audio appears to be silent or very quiet",{averageAmplitude:m.averageAmplitude,peakAmplitude:m.peakAmplitude})}let M=this.buildUrl(t,r),_=this.buildHeaders(y.metadata.format);this.logger.debug("Starting Deepgram transcription request",{fileSize:e.byteLength,detectedFormat:y.metadata.format,url:M,options:t,language:r});let K={url:M,method:"POST",headers:_,body:e,throw:!1},x=setTimeout(()=>{this.abortController&&(this.logger.warn(`Deepgram request timeout after ${n}ms for ${e.byteLength} byte file`),this.abortController.abort())},n),R;try{R=await(0,it.requestUrl)(K)}finally{clearTimeout(x)}let Z=Date.now()-i;if(this.logger.info(`Deepgram transcription completed in ${Z}ms`,{status:R.status,statusText:R.status>=200&&R.status<300?"OK":"ERROR"}),R.status===200){let m=R.json;if(this.logger.debug("=== Deepgram API Raw Response Analysis ===",{hasJson:!!m,responseKeys:m?Object.keys(m):[],hasMetadata:!!(m!=null&&m.metadata),hasResults:!!(m!=null&&m.results),metadataKeys:m!=null&&m.metadata?Object.keys(m.metadata):[],resultsKeys:m!=null&&m.results?Object.keys(m.results):[],channelsCount:((a=(s=m==null?void 0:m.results)==null?void 0:s.channels)==null?void 0:a.length)||0}),(c=(l=m==null?void 0:m.results)==null?void 0:l.channels)!=null&&c[0]){let w=m.results.channels[0];this.logger.debug("First channel analysis",{hasAlternatives:!!w.alternatives,alternativesCount:((p=w.alternatives)==null?void 0:p.length)||0,detectedLanguage:w.detected_language,firstAlternative:(u=w.alternatives)!=null&&u[0]?{hasTranscript:!!w.alternatives[0].transcript,transcriptLength:((h=w.alternatives[0].transcript)==null?void 0:h.length)||0,transcriptEmpty:!w.alternatives[0].transcript||w.alternatives[0].transcript.trim()==="",transcriptPreview:((f=w.alternatives[0].transcript)==null?void 0:f.substring(0,200))+(w.alternatives[0].transcript&&w.alternatives[0].transcript.length>200?"...":""),confidence:w.alternatives[0].confidence,hasWords:!!w.alternatives[0].words,wordsCount:((g=w.alternatives[0].words)==null?void 0:g.length)||0,firstFewWords:(D=w.alternatives[0].words)==null?void 0:D.slice(0,5).map(G=>({word:G.word,confidence:G.confidence}))}:null})}return m!=null&&m.metadata&&this.logger.debug("Metadata analysis",{duration:m.metadata.duration,channels:m.metadata.channels,models:m.metadata.models,modelInfo:m.metadata.model_info}),m}else throw await this.handleAPIError(R)}catch(y){throw y.name==="AbortError"?new E("Transcription cancelled","CANCELLED","deepgram",!1):y}finally{this.abortController=void 0}}buildUrl(e,t){let r=new URLSearchParams;if(((e==null?void 0:e.tier)||"").toString().toLowerCase().includes("nova")||t&&t.startsWith("ko"))r.append("model","2-general"),r.append("tier","nova");else{let s=(e==null?void 0:e.tier)||"nova-2";r.append("model",s)}return t&&t!=="auto"?r.append("language",t):e!=null&&e.detectLanguage&&r.append("detect_language","true"),(e==null?void 0:e.punctuate)!==!1&&r.append("punctuate","true"),e!=null&&e.smartFormat&&r.append("smart_format","true"),e!=null&&e.diarize&&r.append("diarize","true"),e!=null&&e.numerals&&r.append("numerals","true"),e!=null&&e.utterances&&r.append("utterances","true"),e!=null&&e.profanityFilter&&r.append("profanity_filter","true"),e!=null&&e.redact&&e.redact.length>0&&r.append("redact",e.redact.join(",")),e!=null&&e.keywords&&e.keywords.length>0&&r.append("keywords",e.keywords.join(",")),`${this.API_ENDPOINT}?${r.toString()}`}buildHeaders(e){let t={wav:"audio/wav",mp3:"audio/mpeg",flac:"audio/flac",ogg:"audio/ogg",m4a:"audio/mp4",webm:"audio/webm",opus:"audio/opus"},r=e&&t[e]?t[e]:"audio/wav";return this.logger.debug("Content-Type selected",{detectedFormat:e,contentType:r}),{Authorization:`Token ${this.apiKey}`,"Content-Type":r}}async handleAPIError(e){var s;let t=e.json,r=e.text,n=(t==null?void 0:t.message)||(t==null?void 0:t.error)||(typeof r=="string"&&r.length>0?r:"Unknown error");switch(this.logger.error(`Deepgram API Error: ${e.status} - ${n}`,void 0,{status:e.status,errorBody:t,rawText:r}),e.status){case 400:throw new E(n||"Invalid request","BAD_REQUEST","deepgram",!1,400);case 401:throw new q("deepgram");case 402:throw new E("Insufficient credits","INSUFFICIENT_CREDITS","deepgram",!1,402);case 429:let a=(s=e.headers)==null?void 0:s["retry-after"];throw new X("deepgram",a?parseInt(a):void 0);case 500:case 502:case 503:throw new $("deepgram");case 504:let l=this.lastAudioSize?` (${Math.round(this.lastAudioSize/(1024*1024))}MB)`:"";throw new E(`Server timeout processing large audio file${l}. This often happens with very large files (>50MB). Try: 1) Breaking the file into smaller chunks (recommended: <50MB per chunk), 2) Reducing audio quality/bitrate to 64-128 kbps, 3) Using the 'enhanced' model which may be faster, or 4) Converting to a more efficient format like MP3 or OGG.`,"SERVER_TIMEOUT","deepgram",!0,504);default:throw new E(`API error: ${n}`,"UNKNOWN_ERROR","deepgram",!1,e.status)}}async validateApiKey(e){let t=this.apiKey;this.apiKey=e;try{let r=new ArrayBuffer(1024);return await this.performTranscription(r),!0}catch(r){return r instanceof q?(this.logger.warn("Deepgram API key validation failed: Invalid key"),!1):(this.logger.debug("Deepgram API key validation encountered non-auth error",r),!0)}finally{this.apiKey=t}}cancel(){this.abortController&&(this.abortController.abort(),this.logger.debug("Deepgram transcription cancelled by user"))}resetCircuitBreaker(){this.circuitBreaker.reset()}parseResponse(e,t){var h,f,g,D,y,M,_,K,x,R,Z,m,w,G,qe;if(this.logger.debug("=== DeepgramService.parseResponse START ==="),this.logger.debug("Full response structure:",{hasMetadata:!!(e!=null&&e.metadata),hasResults:!!(e!=null&&e.results),channelsCount:((f=(h=e==null?void 0:e.results)==null?void 0:h.channels)==null?void 0:f.length)||0}),!e||!e.results||!e.results.channels||e.results.channels.length===0)throw this.logger.error("Invalid Deepgram response structure",void 0,{response:e}),new E("Invalid response from Deepgram API","INVALID_RESPONSE","deepgram",!1);let r=e.results.channels[0];if(this.logger.debug("Channel data:",{hasAlternatives:!!(r!=null&&r.alternatives),alternativesCount:((g=r==null?void 0:r.alternatives)==null?void 0:g.length)||0,detectedLanguage:r==null?void 0:r.detected_language}),!r.alternatives||r.alternatives.length===0)throw this.logger.error("No alternatives in Deepgram response",void 0,{channel:r}),new E("No transcription alternatives found","NO_ALTERNATIVES","deepgram",!1);let i=r.alternatives[0];if(this.logger.debug("Alternative data:",{hasTranscript:!!(i!=null&&i.transcript),transcriptLength:((D=i==null?void 0:i.transcript)==null?void 0:D.length)||0,transcriptPreview:(y=i==null?void 0:i.transcript)==null?void 0:y.substring(0,100),confidence:i==null?void 0:i.confidence,hasWords:!!(i!=null&&i.words),wordsCount:((M=i==null?void 0:i.words)==null?void 0:M.length)||0}),!i.transcript||i.transcript.trim().length===0){this.logger.warn("=== EMPTY TRANSCRIPT DETECTED ===",{transcript:i.transcript,transcriptType:typeof i.transcript,transcriptLength:((_=i.transcript)==null?void 0:_.length)||0,trimmedLength:((K=i.transcript)==null?void 0:K.trim().length)||0,confidence:i.confidence,hasWords:!!i.words,wordsCount:((x=i.words)==null?void 0:x.length)||0,detectedLanguage:r.detected_language,duration:e.metadata.duration,channels:e.metadata.channels,models:e.metadata.models});let S=[];i.confidence===0&&S.push("Zero confidence - possibly no speech detected"),!i.words||i.words.length===0?S.push("No word timestamps - indicates no speech recognition"):S.push(`${i.words.length} words detected but empty transcript`),e.metadata.duration<1&&S.push("Very short audio duration"),r.detected_language||S.push("No language detected"),this.logger.warn("Empty transcript diagnostic analysis",{possibleCauses:S,recommendations:["Check audio quality and volume","Verify audio contains actual speech","Consider adjusting language settings","Try different Deepgram model","Check for audio format compatibility issues"]});let P=S.length>0?` Possible causes: ${S.join(", ")}`:"";throw new E(`Transcription service returned empty text.${P}`,"EMPTY_TRANSCRIPT","deepgram",!1)}let s=i.transcript||"",a=[],l=1,c=null,p=i.words&&i.words.length>0&&i.words.some(S=>S.speaker!==void 0&&S.speaker>=0);if(this.logger.debug("Speaker information check:",{hasWords:!!i.words,wordCount:((R=i.words)==null?void 0:R.length)||0,hasSpeakerInfo:p,diarizationEnabled:t==null?void 0:t.enabled,firstWordSpeaker:(m=(Z=i.words)==null?void 0:Z[0])==null?void 0:m.speaker,sampleWords:(w=i.words)==null?void 0:w.slice(0,3).map(S=>({word:S.word,speaker:S.speaker,hasSpeaker:S.speaker!==void 0}))}),t!=null&&t.enabled&&p){this.logger.debug("Processing diarization with config:",t);try{let S=(i.words||[]).map(C=>({word:C.word,start:C.start,end:C.end,confidence:C.confidence,speaker:C.speaker!==void 0?C.speaker:0}));this.logger.debug("Converting to diarized words:",{originalWordCount:(i.words||[]).length,diarizedWordCount:S.length,speakersFound:[...new Set(S.map(C=>C.speaker))],firstFewWords:S.slice(0,5).map(C=>({word:C.word,speaker:C.speaker}))});let P=this.diarizationFormatter.formatTranscript(S,t);this.logger.info("Diarization result:",{speakerCount:P.speakerCount,segmentCount:P.segments.length,formattedTextLength:P.formattedText.length,originalWordCount:P.originalWordCount,textPreview:P.formattedText.substring(0,200)}),s=P.formattedText,l=P.speakerCount,c=P.statistics,a=P.segments.map(C=>({id:C.id,start:C.start,end:C.end,text:C.text,confidence:C.confidence,speaker:C.speaker.toString()}))}catch(S){this.logger.error("Diarization formatting failed, falling back to original transcript",S),s=i.transcript||"",a=this.createSegmentsFromWords(i.words||[])}}else t!=null&&t.enabled?this.logger.debug("Diarization enabled but no speaker information found"):this.logger.debug("Diarization disabled, using original transcript"),i.words&&i.words.length>0&&(a=this.createSegmentsFromWords(i.words),this.logger.debug(`Created ${a.length} segments from ${i.words.length} words`));let u={text:s,language:r.detected_language,confidence:i.confidence,duration:e.metadata.duration,segments:a,provider:"deepgram",metadata:{model:((G=e.metadata.models)==null?void 0:G[0])||"unknown",processingTime:e.metadata.duration,wordCount:i.transcript?i.transcript.split(/\s+/).length:0,...(t==null?void 0:t.enabled)&&{speakerCount:l,diarizationEnabled:!0,diarizationStats:c}}};return this.logger.info("=== DeepgramService.parseResponse COMPLETE ===",{textLength:u.text.length,textPreview:u.text.substring(0,100),language:u.language,confidence:u.confidence,segmentsCount:((qe=u.segments)==null?void 0:qe.length)||0}),u}createSegmentsFromWords(e){let t=[];for(let i=0;i0&&t.push({id:Math.floor(i/10),start:n[0].start,end:n[n.length-1].end,text:n.map(s=>s.word).join(" "),confidence:n.reduce((s,a)=>s+a.confidence,0)/n.length,speaker:n[0].speaker})}return t}};Y();var oe=class{constructor(e){this.logger=e;this.CHUNK_SIZE=re.RECOMMENDED_MAX_SIZE;this.WAV_HEADER_SIZE=44}needsChunking(e){return e>this.CHUNK_SIZE}async splitAudio(e){let t=e.byteLength;return this.needsChunking(t)?(this.logger.info("Splitting large audio file into chunks",{originalSizeMB:Math.round(t/(1024*1024)),chunkSizeMB:Math.round(this.CHUNK_SIZE/(1024*1024)),estimatedChunks:Math.ceil(t/this.CHUNK_SIZE)}),this.isWavFile(e)?this.splitWavAudio(e):this.splitByteArray(e)):[e]}isWavFile(e){if(e.byteLength<12)return!1;let t=new Uint8Array(e,0,4);return t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70}splitWavAudio(e){let t=[],r=e.slice(0,this.WAV_HEADER_SIZE),i=e.slice(this.WAV_HEADER_SIZE),n=i.byteLength,s=this.CHUNK_SIZE-this.WAV_HEADER_SIZE,a=Math.ceil(n/s);for(let l=0;lt&&t.trim()).join(" ")}getRecommendedSettings(e){let t=e/1048576;return t<=50?{needsChunking:!1,recommendedModel:"nova-2"}:t<=100?{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"128 kbps",estimatedChunks:Math.ceil(e/this.CHUNK_SIZE)}:{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"64 kbps",estimatedChunks:Math.ceil(e/this.CHUNK_SIZE)}}};var W=class W{constructor(e,t,r,i){this.deepgramService=e;this.logger=t;this.settingsManager=r;this.audioChunker=new oe(t),this.config={enabled:!0,apiKey:"",model:"nova-3",maxConcurrency:5,timeout:3e4,rateLimit:{requests:100,window:6e4},...i}}async transcribe(e,t){var i,n;let r=e.byteLength/1048576;this.logger.debug("=== DeepgramAdapter.transcribe START ===",this.sanitizeForLogging({audioSize:e.byteLength,audioSizeMB:r,options:t}));try{return((n=(i=this.settingsManager)==null?void 0:i.get("autoChunking"))!=null?n:!0)&&this.audioChunker.needsChunking(e.byteLength)?(this.logger.info("Large file detected, using chunked processing",{sizeMB:r,recommendedSettings:this.audioChunker.getRecommendedSettings(e.byteLength)}),r>100&&this.logger.warn(`Very large audio file (${Math.round(r)}MB). Processing may take significant time. Consider reducing file size or bitrate for better performance.`),await this.transcribeWithChunking(e,t)):await this.transcribeStandard(e,t)}catch(s){let a=s;if(a instanceof E&&a.code==="SERVER_TIMEOUT"){let c=this.audioChunker.getRecommendedSettings(e.byteLength);this.logger.error("Timeout error - providing chunking recommendations",a,{audioSizeMB:r,recommendations:c});let p=`Transcription timeout for ${Math.round(r)}MB file. +`)}generateSpeakerLabel(e,t){let{prefix:r,numbering:i,customLabels:n}=t.speakerLabels;if(n&&n[e])return n[e];switch(i){case"alphabetic":{let s=String.fromCharCode(65+e%26);return`${r} ${s}`}case"numeric":default:return`${r} ${e+1}`}}applyCustomFormat(e,t,r){return`${t}: ${e.text}`}insertSpeakerBreaks(e,t){let r=[],i=null;for(let n=0;n0?t[t.length-1].end-t[0].start:0;return{totalSpeakers:Object.keys(r).length,totalSegments:e.length,averageSegmentLength:e.length>0?n/e.length:0,speakerDistribution:r,totalDuration:s,averageConfidence:e.length>0?i/e.length:0}}validateConfig(e){let t=[];return e.merging.consecutiveThreshold<0&&t.push("consecutiveThreshold must be non-negative"),e.merging.minSegmentLength<1&&t.push("minSegmentLength must be at least 1"),e.speakerLabels.prefix.trim()||t.push("speakerLabels.prefix cannot be empty"),{valid:t.length===0,errors:t}}};var _e=class{constructor(e){this.logger=e}validateAudio(e){let t=[],r=[],i={size:e.byteLength,isEmpty:e.byteLength===0,hasMinimumSize:e.byteLength>=ie.MIN_HEADER_SIZE,format:this.detectAudioFormat(e)};i.isEmpty&&r.push(V.AUDIO_VALIDATION.EMPTY),!i.hasMinimumSize&&!i.isEmpty&&r.push(V.AUDIO_VALIDATION.TOO_SMALL),i.size>re.MAX_FILE_SIZE&&r.push(V.AUDIO_VALIDATION.TOO_LARGE),i.sizeie.SIZE_WARNING_LARGE&&t.push(V.AUDIO_VALIDATION.LARGE_WARNING);let n=r.length===0;return this.logger.debug("Audio validation completed",{isValid:n,warnings:t.length,errors:r.length,metadata:i}),{isValid:n,warnings:t,errors:r,metadata:i}}detectAudioFormat(e){if(e.byteLength<12)return;let t=new Uint8Array(e,0,12);return t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70?"wav":t[0]===255&&(t[1]&224)===224||t[0]===73&&t[1]===68&&t[2]===51?"mp3":t[0]===102&&t[1]===76&&t[2]===97&&t[3]===67?"flac":t[0]===79&&t[1]===103&&t[2]===103&&t[3]===83?"ogg":t.length>=8&&t[4]===102&&t[5]===116&&t[6]===121&&t[7]===112?"m4a":t[0]===26&&t[1]===69&&t[2]===223&&t[3]===163?"webm":(this.logger.debug("Unknown audio format detected",{firstBytes:Array.from(t.slice(0,8)).map(r=>"0x"+r.toString(16).padStart(2,"0")).join(" ")}),"unknown")}checkForSilence(e){if(e.byteLength<44)return{isSilent:!0,averageAmplitude:0,peakAmplitude:0};let t=new Uint8Array(e,0,4);if(!(t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70))return{isSilent:!1,averageAmplitude:-1,peakAmplitude:-1};try{let i=Math.min(e.byteLength-44,8192),n=new Int16Array(e,44,i/2),s=0,a=0;for(let u=0;u0?s/n.length:0,c=327;return{isSilent:l{this.queue.push(e),this.processQueue()})}async processQueue(){if(this.processing||this.queue.length===0)return;this.processing=!0;let e=6e4/this.requestsPerMinute;for(;this.queue.length>0;){let r=Date.now()-this.lastRequestTime;if(rsetTimeout(t,e))}},Be=class{constructor(e){this.logger=e;this.state="CLOSED";this.failureCount=0;this.successCount=0;this.nextAttemptTime=0;this.failureThreshold=5;this.successThreshold=2;this.timeout=6e4}async execute(e){if(this.isOpen())throw new $("deepgram");try{let t=await e();return this.onSuccess(),t}catch(t){throw this.onFailure(),t}}isOpen(){return this.state==="OPEN"?Date.now()>=this.nextAttemptTime?(this.state="HALF_OPEN",this.logger.info("Deepgram Circuit breaker entering HALF_OPEN state"),!1):!0:!1}onSuccess(){this.failureCount=0,this.state==="HALF_OPEN"&&(this.successCount++,this.successCount>=this.successThreshold&&(this.state="CLOSED",this.successCount=0,this.logger.info("Deepgram Circuit breaker closed")))}onFailure(){this.failureCount++,this.state==="HALF_OPEN"?(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn("Deepgram Circuit breaker opened due to failure in HALF_OPEN state")):this.failureCount>=this.failureThreshold&&(this.state="OPEN",this.nextAttemptTime=Date.now()+this.timeout,this.logger.warn(`Deepgram Circuit breaker opened after ${this.failureCount} failures`))}reset(){this.state="CLOSED",this.failureCount=0,this.successCount=0,this.logger.info("Deepgram Circuit breaker reset")}},Ke=class{constructor(e){this.logger=e;this.maxRetries=3;this.baseDelay=1e3;this.maxDelay=1e4}async execute(e){let t;for(let r=0;rsetTimeout(t,e))}},ae=class{constructor(e,t,r=100,i=3e4){this.apiKey=e;this.logger=t;this.API_ENDPOINT="https://api.deepgram.com/v1/listen";this.MAX_FILE_SIZE=2*1024*1024*1024;this.lastAudioSize=0;this.timeout=i,this.circuitBreaker=new Be(t),this.retryStrategy=new Ke(t),this.rateLimiter=new ze(r,t),this.audioValidator=new _e(t),this.diarizationFormatter=new ne(t)}async transcribe(e,t,r){return await this.rateLimiter.acquire(),this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(e,t,r)))}calculateDynamicTimeout(e){let t=e/1048576,r=this.timeout;if(t<=5)return r;let i;t<=10?i=t*30*1e3:t<=50?i=t*40*1e3*1.5:t<=100?i=t*45*1e3*1.8:i=t*50*1e3*2,t>=50&&(i=Math.max(i,40*60*1e3)),t>=100&&(i=Math.max(i,60*60*1e3));let n=90*60*1e3;return i=Math.min(i,n),this.logger.debug("Dynamic timeout calculation",{audioSizeMB:t,baseTimeout:r,finalTimeout:i,timeoutMinutes:Math.round(i/6e4)}),i}async performTranscription(e,t,r){var s,a,l,c,p,u,h,f,g,D;this.abortController=new AbortController;let i=Date.now();this.lastAudioSize=e.byteLength;let n=this.calculateDynamicTimeout(e.byteLength);try{let y=this.audioValidator.validateAudio(e);if(this.logger.debug("Audio validation results",{isValid:y.isValid,warnings:y.warnings,errors:y.errors,metadata:y.metadata}),!y.isValid)throw new E(`Audio validation failed: ${y.errors.join(", ")}`,"INVALID_AUDIO","deepgram",!1);if(y.warnings.forEach(m=>{this.logger.warn(`Audio validation warning: ${m}`)}),y.metadata.format==="wav"){let m=this.audioValidator.checkForSilence(e);this.logger.debug("Audio silence analysis",m),m.isSilent&&this.logger.warn("Audio appears to be silent or very quiet",{averageAmplitude:m.averageAmplitude,peakAmplitude:m.peakAmplitude})}let x=this.buildUrl(t,r),_=this.buildHeaders(y.metadata.format);this.logger.debug("Starting Deepgram transcription request",{fileSize:e.byteLength,detectedFormat:y.metadata.format,url:x,options:t,language:r});let K={url:x,method:"POST",headers:_,body:e,throw:!1},M=setTimeout(()=>{this.abortController&&(this.logger.warn(`Deepgram request timeout after ${n}ms for ${e.byteLength} byte file`),this.abortController.abort())},n),R;try{R=await(0,it.requestUrl)(K)}finally{clearTimeout(M)}let Z=Date.now()-i;if(this.logger.info(`Deepgram transcription completed in ${Z}ms`,{status:R.status,statusText:R.status>=200&&R.status<300?"OK":"ERROR"}),R.status===200){let m=R.json;if(this.logger.debug("=== Deepgram API Raw Response Analysis ===",{hasJson:!!m,responseKeys:m?Object.keys(m):[],hasMetadata:!!(m!=null&&m.metadata),hasResults:!!(m!=null&&m.results),metadataKeys:m!=null&&m.metadata?Object.keys(m.metadata):[],resultsKeys:m!=null&&m.results?Object.keys(m.results):[],channelsCount:((a=(s=m==null?void 0:m.results)==null?void 0:s.channels)==null?void 0:a.length)||0}),(c=(l=m==null?void 0:m.results)==null?void 0:l.channels)!=null&&c[0]){let w=m.results.channels[0];this.logger.debug("First channel analysis",{hasAlternatives:!!w.alternatives,alternativesCount:((p=w.alternatives)==null?void 0:p.length)||0,detectedLanguage:w.detected_language,firstAlternative:(u=w.alternatives)!=null&&u[0]?{hasTranscript:!!w.alternatives[0].transcript,transcriptLength:((h=w.alternatives[0].transcript)==null?void 0:h.length)||0,transcriptEmpty:!w.alternatives[0].transcript||w.alternatives[0].transcript.trim()==="",transcriptPreview:((f=w.alternatives[0].transcript)==null?void 0:f.substring(0,200))+(w.alternatives[0].transcript&&w.alternatives[0].transcript.length>200?"...":""),confidence:w.alternatives[0].confidence,hasWords:!!w.alternatives[0].words,wordsCount:((g=w.alternatives[0].words)==null?void 0:g.length)||0,firstFewWords:(D=w.alternatives[0].words)==null?void 0:D.slice(0,5).map(G=>({word:G.word,confidence:G.confidence}))}:null})}return m!=null&&m.metadata&&this.logger.debug("Metadata analysis",{duration:m.metadata.duration,channels:m.metadata.channels,models:m.metadata.models,modelInfo:m.metadata.model_info}),m}else throw await this.handleAPIError(R)}catch(y){throw y.name==="AbortError"?new E("Transcription cancelled","CANCELLED","deepgram",!1):y}finally{this.abortController=void 0}}buildUrl(e,t){let r=new URLSearchParams;if(((e==null?void 0:e.tier)||"").toString().toLowerCase().includes("nova")||t&&t.startsWith("ko"))r.append("model","2-general"),r.append("tier","nova");else{let s=(e==null?void 0:e.tier)||"nova-2";r.append("model",s)}return t&&t!=="auto"?r.append("language",t):e!=null&&e.detectLanguage&&r.append("detect_language","true"),(e==null?void 0:e.punctuate)!==!1&&r.append("punctuate","true"),e!=null&&e.smartFormat&&r.append("smart_format","true"),e!=null&&e.diarize&&r.append("diarize","true"),e!=null&&e.numerals&&r.append("numerals","true"),e!=null&&e.utterances&&r.append("utterances","true"),e!=null&&e.profanityFilter&&r.append("profanity_filter","true"),e!=null&&e.redact&&e.redact.length>0&&r.append("redact",e.redact.join(",")),e!=null&&e.keywords&&e.keywords.length>0&&r.append("keywords",e.keywords.join(",")),`${this.API_ENDPOINT}?${r.toString()}`}buildHeaders(e){let t={wav:"audio/wav",mp3:"audio/mpeg",flac:"audio/flac",ogg:"audio/ogg",m4a:"audio/mp4",webm:"audio/webm",opus:"audio/opus"},r=e&&t[e]?t[e]:"audio/wav";return this.logger.debug("Content-Type selected",{detectedFormat:e,contentType:r}),{Authorization:`Token ${this.apiKey}`,"Content-Type":r}}async handleAPIError(e){var s;let t=e.json,r=e.text,n=(t==null?void 0:t.message)||(t==null?void 0:t.error)||(typeof r=="string"&&r.length>0?r:"Unknown error");switch(this.logger.error(`Deepgram API Error: ${e.status} - ${n}`,void 0,{status:e.status,errorBody:t,rawText:r}),e.status){case 400:throw new E(n||"Invalid request","BAD_REQUEST","deepgram",!1,400);case 401:throw new q("deepgram");case 402:throw new E("Insufficient credits","INSUFFICIENT_CREDITS","deepgram",!1,402);case 429:{let a=(s=e.headers)==null?void 0:s["retry-after"];throw new X("deepgram",a?parseInt(a):void 0)}case 500:case 502:case 503:throw new $("deepgram");case 504:{let a=this.lastAudioSize?` (${Math.round(this.lastAudioSize/1048576)}MB)`:"";throw new E(`Server timeout processing large audio file${a}. This often happens with very large files (>50MB). Try: 1) Breaking the file into smaller chunks (recommended: <50MB per chunk), 2) Reducing audio quality/bitrate to 64-128 kbps, 3) Using the 'enhanced' model which may be faster, or 4) Converting to a more efficient format like MP3 or OGG.`,"SERVER_TIMEOUT","deepgram",!0,504)}default:throw new E(`API error: ${n}`,"UNKNOWN_ERROR","deepgram",!1,e.status)}}async validateApiKey(e){let t=this.apiKey;this.apiKey=e;try{let r=new ArrayBuffer(1024);return await this.performTranscription(r),!0}catch(r){return r instanceof q?(this.logger.warn("Deepgram API key validation failed: Invalid key"),!1):(this.logger.debug("Deepgram API key validation encountered non-auth error",r),!0)}finally{this.apiKey=t}}cancel(){this.abortController&&(this.abortController.abort(),this.logger.debug("Deepgram transcription cancelled by user"))}resetCircuitBreaker(){this.circuitBreaker.reset()}parseResponse(e,t){var h,f,g,D,y,x,_,K,M,R,Z,m,w,G,qe;if(this.logger.debug("=== DeepgramService.parseResponse START ==="),this.logger.debug("Full response structure:",{hasMetadata:!!(e!=null&&e.metadata),hasResults:!!(e!=null&&e.results),channelsCount:((f=(h=e==null?void 0:e.results)==null?void 0:h.channels)==null?void 0:f.length)||0}),!e||!e.results||!e.results.channels||e.results.channels.length===0)throw this.logger.error("Invalid Deepgram response structure",void 0,{response:e}),new E("Invalid response from Deepgram API","INVALID_RESPONSE","deepgram",!1);let r=e.results.channels[0];if(this.logger.debug("Channel data:",{hasAlternatives:!!(r!=null&&r.alternatives),alternativesCount:((g=r==null?void 0:r.alternatives)==null?void 0:g.length)||0,detectedLanguage:r==null?void 0:r.detected_language}),!r.alternatives||r.alternatives.length===0)throw this.logger.error("No alternatives in Deepgram response",void 0,{channel:r}),new E("No transcription alternatives found","NO_ALTERNATIVES","deepgram",!1);let i=r.alternatives[0];if(this.logger.debug("Alternative data:",{hasTranscript:!!(i!=null&&i.transcript),transcriptLength:((D=i==null?void 0:i.transcript)==null?void 0:D.length)||0,transcriptPreview:(y=i==null?void 0:i.transcript)==null?void 0:y.substring(0,100),confidence:i==null?void 0:i.confidence,hasWords:!!(i!=null&&i.words),wordsCount:((x=i==null?void 0:i.words)==null?void 0:x.length)||0}),!i.transcript||i.transcript.trim().length===0){this.logger.warn("=== EMPTY TRANSCRIPT DETECTED ===",{transcript:i.transcript,transcriptType:typeof i.transcript,transcriptLength:((_=i.transcript)==null?void 0:_.length)||0,trimmedLength:((K=i.transcript)==null?void 0:K.trim().length)||0,confidence:i.confidence,hasWords:!!i.words,wordsCount:((M=i.words)==null?void 0:M.length)||0,detectedLanguage:r.detected_language,duration:e.metadata.duration,channels:e.metadata.channels,models:e.metadata.models});let S=[];i.confidence===0&&S.push("Zero confidence - possibly no speech detected"),!i.words||i.words.length===0?S.push("No word timestamps - indicates no speech recognition"):S.push(`${i.words.length} words detected but empty transcript`),e.metadata.duration<1&&S.push("Very short audio duration"),r.detected_language||S.push("No language detected"),this.logger.warn("Empty transcript diagnostic analysis",{possibleCauses:S,recommendations:["Check audio quality and volume","Verify audio contains actual speech","Consider adjusting language settings","Try different Deepgram model","Check for audio format compatibility issues"]});let P=S.length>0?` Possible causes: ${S.join(", ")}`:"";throw new E(`Transcription service returned empty text.${P}`,"EMPTY_TRANSCRIPT","deepgram",!1)}let s=i.transcript||"",a=[],l=1,c=null,p=i.words&&i.words.length>0&&i.words.some(S=>S.speaker!==void 0&&S.speaker>=0);if(this.logger.debug("Speaker information check:",{hasWords:!!i.words,wordCount:((R=i.words)==null?void 0:R.length)||0,hasSpeakerInfo:p,diarizationEnabled:t==null?void 0:t.enabled,firstWordSpeaker:(m=(Z=i.words)==null?void 0:Z[0])==null?void 0:m.speaker,sampleWords:(w=i.words)==null?void 0:w.slice(0,3).map(S=>({word:S.word,speaker:S.speaker,hasSpeaker:S.speaker!==void 0}))}),t!=null&&t.enabled&&p){this.logger.debug("Processing diarization with config:",t);try{let S=(i.words||[]).map(C=>({word:C.word,start:C.start,end:C.end,confidence:C.confidence,speaker:C.speaker!==void 0?C.speaker:0}));this.logger.debug("Converting to diarized words:",{originalWordCount:(i.words||[]).length,diarizedWordCount:S.length,speakersFound:[...new Set(S.map(C=>C.speaker))],firstFewWords:S.slice(0,5).map(C=>({word:C.word,speaker:C.speaker}))});let P=this.diarizationFormatter.formatTranscript(S,t);this.logger.info("Diarization result:",{speakerCount:P.speakerCount,segmentCount:P.segments.length,formattedTextLength:P.formattedText.length,originalWordCount:P.originalWordCount,textPreview:P.formattedText.substring(0,200)}),s=P.formattedText,l=P.speakerCount,c=P.statistics,a=P.segments.map(C=>({id:C.id,start:C.start,end:C.end,text:C.text,confidence:C.confidence,speaker:C.speaker.toString()}))}catch(S){this.logger.error("Diarization formatting failed, falling back to original transcript",S),s=i.transcript||"",a=this.createSegmentsFromWords(i.words||[])}}else t!=null&&t.enabled?this.logger.debug("Diarization enabled but no speaker information found"):this.logger.debug("Diarization disabled, using original transcript"),i.words&&i.words.length>0&&(a=this.createSegmentsFromWords(i.words),this.logger.debug(`Created ${a.length} segments from ${i.words.length} words`));let u={text:s,language:r.detected_language,confidence:i.confidence,duration:e.metadata.duration,segments:a,provider:"deepgram",metadata:{model:((G=e.metadata.models)==null?void 0:G[0])||"unknown",processingTime:e.metadata.duration,wordCount:i.transcript?i.transcript.split(/\s+/).length:0,...(t==null?void 0:t.enabled)&&{speakerCount:l,diarizationEnabled:!0,diarizationStats:c}}};return this.logger.info("=== DeepgramService.parseResponse COMPLETE ===",{textLength:u.text.length,textPreview:u.text.substring(0,100),language:u.language,confidence:u.confidence,segmentsCount:((qe=u.segments)==null?void 0:qe.length)||0}),u}createSegmentsFromWords(e){let t=[];for(let i=0;i0&&t.push({id:Math.floor(i/10),start:n[0].start,end:n[n.length-1].end,text:n.map(s=>s.word).join(" "),confidence:n.reduce((s,a)=>s+a.confidence,0)/n.length,speaker:n[0].speaker})}return t}};Y();var oe=class{constructor(e){this.logger=e;this.CHUNK_SIZE=re.RECOMMENDED_MAX_SIZE;this.WAV_HEADER_SIZE=44}needsChunking(e){return e>this.CHUNK_SIZE}async splitAudio(e){let t=e.byteLength;return this.needsChunking(t)?(this.logger.info("Splitting large audio file into chunks",{originalSizeMB:Math.round(t/(1024*1024)),chunkSizeMB:Math.round(this.CHUNK_SIZE/(1024*1024)),estimatedChunks:Math.ceil(t/this.CHUNK_SIZE)}),this.isWavFile(e)?this.splitWavAudio(e):this.splitByteArray(e)):[e]}isWavFile(e){if(e.byteLength<12)return!1;let t=new Uint8Array(e,0,4);return t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70}splitWavAudio(e){let t=[],r=e.slice(0,this.WAV_HEADER_SIZE),i=e.slice(this.WAV_HEADER_SIZE),n=i.byteLength,s=this.CHUNK_SIZE-this.WAV_HEADER_SIZE,a=Math.ceil(n/s);for(let l=0;lt&&t.trim()).join(" ")}getRecommendedSettings(e){let t=e/1048576;return t<=50?{needsChunking:!1,recommendedModel:"nova-2"}:t<=100?{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"128 kbps",estimatedChunks:Math.ceil(e/this.CHUNK_SIZE)}:{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"64 kbps",estimatedChunks:Math.ceil(e/this.CHUNK_SIZE)}}};var W=class W{constructor(e,t,r,i){this.deepgramService=e;this.logger=t;this.settingsManager=r;this.audioChunker=new oe(t),this.config={enabled:!0,apiKey:"",model:"nova-3",maxConcurrency:5,timeout:3e4,rateLimit:{requests:100,window:6e4},...i}}async transcribe(e,t){var i,n;let r=e.byteLength/1048576;this.logger.debug("=== DeepgramAdapter.transcribe START ===",this.sanitizeForLogging({audioSize:e.byteLength,audioSizeMB:r,options:t}));try{return((n=(i=this.settingsManager)==null?void 0:i.get("autoChunking"))!=null?n:!0)&&this.audioChunker.needsChunking(e.byteLength)?(this.logger.info("Large file detected, using chunked processing",{sizeMB:r,recommendedSettings:this.audioChunker.getRecommendedSettings(e.byteLength)}),r>100&&this.logger.warn(`Very large audio file (${Math.round(r)}MB). Processing may take significant time. Consider reducing file size or bitrate for better performance.`),await this.transcribeWithChunking(e,t)):await this.transcribeStandard(e,t)}catch(s){let a=s;if(a instanceof E&&a.code==="SERVER_TIMEOUT"){let c=this.audioChunker.getRecommendedSettings(e.byteLength);this.logger.error("Timeout error - providing chunking recommendations",a,{audioSizeMB:r,recommendations:c});let p=`Transcription timeout for ${Math.round(r)}MB file. Recommended solutions: - Enable automatic chunking (files will be split into ${c.estimatedChunks||"multiple"} chunks) @@ -42,8 +42,8 @@ ${e} \`\`\``}applyCalloutFormat(e,t){let r=t.calloutType||"info",i=t.calloutTitle||"",n=t.calloutFoldable?"+":"";return`> [!${r}]${n} ${i} > ${e.replace(/\n/g,` > `)}`}addTimestamp(e,t){let r=new Date;return`[${t?this.formatDate(r,t):r.toISOString()}] -${e}`}formatDate(e,t){let r={YYYY:e.getFullYear().toString(),MM:(e.getMonth()+1).toString().padStart(2,"0"),DD:e.getDate().toString().padStart(2,"0"),HH:e.getHours().toString().padStart(2,"0"),mm:e.getMinutes().toString().padStart(2,"0"),ss:e.getSeconds().toString().padStart(2,"0")},i=t;for(let[n,s]of Object.entries(r))i=i.replace(new RegExp(n,"g"),s);return i}applyTemplate(e,t){return t.replace("{{content}}",e).replace("{{date}}",new Date().toLocaleDateString()).replace("{{time}}",new Date().toLocaleTimeString()).replace("{{datetime}}",new Date().toLocaleString())}processLanguageSpecific(e,t){switch(t){case"ko":return this.processKoreanText(e);case"ja":return this.processJapaneseText(e);case"zh":return this.processChineseText(e);default:return e}}processKoreanText(e){return e.replace(/\s+([.,!?])/g,"$1").replace(/([.,!?])\s*/g,"$1 ").trim()}processJapaneseText(e){return e}processChineseText(e){return e}async executeInsertion(e,t){switch(t.mode){case"cursor":return await this.editorService.insertAtCursor(e);case"replace":return await this.editorService.replaceSelection(e);case"append":return await this.editorService.appendToDocument(e,!0);case"prepend":return await this.editorService.prependToDocument(e,!0);case"line-end":let r=this.editorService.getCurrentLineNumber();return r!==null?await this.editorService.appendToLine(r,e):!1;case"new-line":let i=this.editorService.getCursorPosition();return i?await this.editorService.insertAtPosition(` -${e}`,i):!1;default:return await this.editorService.insertAtCursor(e)}}async showPreview(e,t){return await Promise.resolve(),new ye.Notice(`Preview: +${e}`}formatDate(e,t){let r={YYYY:e.getFullYear().toString(),MM:(e.getMonth()+1).toString().padStart(2,"0"),DD:e.getDate().toString().padStart(2,"0"),HH:e.getHours().toString().padStart(2,"0"),mm:e.getMinutes().toString().padStart(2,"0"),ss:e.getSeconds().toString().padStart(2,"0")},i=t;for(let[n,s]of Object.entries(r))i=i.replace(new RegExp(n,"g"),s);return i}applyTemplate(e,t){return t.replace("{{content}}",e).replace("{{date}}",new Date().toLocaleDateString()).replace("{{time}}",new Date().toLocaleTimeString()).replace("{{datetime}}",new Date().toLocaleString())}processLanguageSpecific(e,t){switch(t){case"ko":return this.processKoreanText(e);case"ja":return this.processJapaneseText(e);case"zh":return this.processChineseText(e);default:return e}}processKoreanText(e){return e.replace(/\s+([.,!?])/g,"$1").replace(/([.,!?])\s*/g,"$1 ").trim()}processJapaneseText(e){return e}processChineseText(e){return e}async executeInsertion(e,t){switch(t.mode){case"cursor":return await this.editorService.insertAtCursor(e);case"replace":return await this.editorService.replaceSelection(e);case"append":return await this.editorService.appendToDocument(e,!0);case"prepend":return await this.editorService.prependToDocument(e,!0);case"line-end":{let r=this.editorService.getCurrentLineNumber();return r!==null?await this.editorService.appendToLine(r,e):!1}case"new-line":{let r=this.editorService.getCursorPosition();return r?await this.editorService.insertAtPosition(` +${e}`,r):!1}default:return await this.editorService.insertAtCursor(e)}}async showPreview(e,t){return await Promise.resolve(),new ye.Notice(`Preview: ${e.substring(0,100)}...`),this.eventManager.emit("text:preview",{text:e,options:t}),!0}async createNewNoteWithText(e,t){let r=new Date().toISOString().replace(/[:.]/g,"-"),i=t.noteTitle||`Transcription-${r}.md`,n=t.noteFolder||"",s=await this.formatText(e,t);return await this.editorService.createAndOpenNote(i,s,n)}recordInsertion(e){this.insertionHistory.push(e),this.insertionHistory.length>this.maxHistorySize&&this.insertionHistory.shift(),this.lastInsertedText=e.text}getLastInsertedText(){return this.lastInsertedText}getInsertionHistory(){return[...this.insertionHistory]}setPreviewMode(e){this.previewMode=e,this.logger.debug("Preview mode changed",{enabled:e})}isPreviewMode(){return this.previewMode}clearHistory(){this.insertionHistory=[],this.lastInsertedText="",this.logger.debug("Insertion history cleared")}destroy(){this.clearHistory(),this.logger.debug("TextInsertionHandler destroyed")}};var T=require("obsidian"),Te=class extends T.Modal{constructor(t,r,i,n){super(t);this.previewContainer=null;this.templates=[];this.onConfirm=i,this.onCancel=n,this.options={mode:"cursor",format:"plain",addTimestamp:!1,timestampFormat:"YYYY-MM-DD HH:mm:ss",...r},this.loadDefaultTemplates()}onOpen(){let{contentEl:t}=this;t.empty(),t.addClass("format-options-modal"),t.createEl("h2",{text:"Text Formatting Options"});let r=t.createDiv("format-tabs"),i=["Basic","Format","Advanced","Templates"],n=[];i.forEach((s,a)=>{let l=r.createEl("button",{text:s,cls:"format-tab"}),c=t.createDiv({cls:"format-tab-content"});a===0?(l.addClass("active"),c.addClass("active")):c.addClass("sn-hidden"),n.push(c),l.onclick=()=>{r.querySelectorAll(".format-tab").forEach(p=>{p.removeClass("active")}),n.forEach(p=>{p.removeClass("active"),p.addClass("sn-hidden")}),l.addClass("active"),c.addClass("active"),c.removeClass("sn-hidden")}}),this.createBasicTab(n[0]),this.createFormatTab(n[1]),this.createAdvancedTab(n[2]),this.createTemplatesTab(n[3]),this.createPreviewSection(t),this.createButtonSection(t)}createBasicTab(t){new T.Setting(t).setName("Insertion Mode").setDesc("Where to insert the text").addDropdown(r=>{r.addOption("cursor","At Cursor").addOption("replace","Replace Selection").addOption("append","End of Document").addOption("prepend","Beginning of Document").addOption("line-end","End of Current Line").addOption("new-line","New Line Below").setValue(this.options.mode).onChange(i=>{this.options.mode=i,this.updatePreview()})}),new T.Setting(t).setName("Text Format").setDesc("How to format the inserted text").addDropdown(r=>{r.addOption("plain","Plain Text").addOption("markdown","Markdown").addOption("quote","Quote Block").addOption("bullet","Bullet List").addOption("heading","Heading").addOption("code","Code Block").addOption("callout","Callout Block").setValue(this.options.format).onChange(i=>{this.options.format=i,this.updateFormatSpecificOptions(),this.updatePreview()})}),new T.Setting(t).setName("Add Timestamp").setDesc("Add timestamp before the text").addToggle(r=>{r.setValue(this.options.addTimestamp||!1).onChange(i=>{this.options.addTimestamp=i,this.updatePreview()})}),this.options.addTimestamp&&new T.Setting(t).setName("Timestamp Format").setDesc("Format for the timestamp (YYYY-MM-DD HH:mm:ss)").addText(r=>{r.setPlaceholder("YYYY-MM-DD HH:mm:ss").setValue(this.options.timestampFormat||"").onChange(i=>{this.options.timestampFormat=i,this.updatePreview()})})}createFormatTab(t){let r=t.createDiv("format-specific-options");this.updateFormatSpecificOptions(r)}updateFormatSpecificOptions(t){let r=t||document.querySelector(".format-specific-options");if(r)switch(r.empty(),this.options.format){case"quote":new T.Setting(r).setName("Quote Author").setDesc("Author attribution for the quote").addText(i=>{i.setPlaceholder("Author name").setValue(this.options.quoteAuthor||"").onChange(n=>{this.options.quoteAuthor=n,this.updatePreview()})});break;case"bullet":new T.Setting(r).setName("Bullet Character").setDesc("Character to use for bullets").addDropdown(i=>{i.addOption("-","- (Dash)").addOption("*","* (Asterisk)").addOption("+","+ (Plus)").addOption("\u2022","\u2022 (Bullet)").setValue(this.options.bulletChar||"-").onChange(n=>{this.options.bulletChar=n,this.updatePreview()})});break;case"heading":new T.Setting(r).setName("Heading Level").setDesc("Level of the heading (1-6)").addDropdown(i=>{for(let n=1;n<=6;n++)i.addOption(String(n),`H${n}`);i.setValue(String(this.options.headingLevel||2)).onChange(n=>{this.options.headingLevel=parseInt(n),this.updatePreview()})});break;case"code":new T.Setting(r).setName("Language").setDesc("Programming language for syntax highlighting").addText(i=>{i.setPlaceholder("javascript, python, etc.").setValue(this.options.codeLanguage||"").onChange(n=>{this.options.codeLanguage=n,this.updatePreview()})});break;case"callout":new T.Setting(r).setName("Callout Type").setDesc("Type of callout block").addDropdown(i=>{i.addOption("info","Info").addOption("tip","Tip").addOption("warning","Warning").addOption("danger","Danger").addOption("note","Note").addOption("abstract","Abstract").addOption("success","Success").addOption("question","Question").addOption("failure","Failure").addOption("example","Example").addOption("quote","Quote").setValue(this.options.calloutType||"info").onChange(n=>{this.options.calloutType=n,this.updatePreview()})}),new T.Setting(r).setName("Callout Title").setDesc("Title for the callout").addText(i=>{i.setPlaceholder("Title").setValue(this.options.calloutTitle||"").onChange(n=>{this.options.calloutTitle=n,this.updatePreview()})}),new T.Setting(r).setName("Foldable").setDesc("Make callout foldable").addToggle(i=>{i.setValue(this.options.calloutFoldable||!1).onChange(n=>{this.options.calloutFoldable=n,this.updatePreview()})});break}}createAdvancedTab(t){new T.Setting(t).setName("Language").setDesc("Language for special processing").addDropdown(r=>{r.addOption("","Auto Detect").addOption("en","English").addOption("ko","Korean").addOption("ja","Japanese").addOption("zh","Chinese").addOption("es","Spanish").addOption("fr","French").addOption("de","German").setValue(this.options.language||"").onChange(i=>{this.options.language=i,this.updatePreview()})}),new T.Setting(t).setName("Paragraph Breaks").setDesc("Add paragraph breaks between sentences").addToggle(r=>{r.setValue(this.options.paragraphBreaks||!1).onChange(i=>{this.options.paragraphBreaks=i,this.updatePreview()})}),new T.Setting(t).setName("Create New Note").setDesc("Create a new note for the text").addToggle(r=>{r.setValue(this.options.createNewNote||!1).onChange(i=>{this.options.createNewNote=i,this.updateNewNoteOptions()})}),this.options.createNewNote&&(new T.Setting(t).setName("Note Title").setDesc("Title for the new note").addText(r=>{r.setPlaceholder("Transcription-YYYY-MM-DD").setValue(this.options.noteTitle||"").onChange(i=>{this.options.noteTitle=i})}),new T.Setting(t).setName("Note Folder").setDesc("Folder for the new note").addText(r=>{r.setPlaceholder("Transcriptions").setValue(this.options.noteFolder||"").onChange(i=>{this.options.noteFolder=i})})),new T.Setting(t).setName("Preview Before Insert").setDesc("Show preview before inserting text").addToggle(r=>{r.setValue(this.options.preview||!1).onChange(i=>{this.options.preview=i})})}createTemplatesTab(t){let r=new T.Setting(t).setName("Template").setDesc("Select a template to apply"),i=new T.DropdownComponent(r.controlEl);i.addOption("","None"),this.templates.forEach(l=>{i.addOption(l.id,l.name)}),i.onChange(l=>{let c=this.templates.find(p=>p.id===l);c?(this.options.template=c.content,this.updatePreview()):(this.options.template=void 0,this.updatePreview())}),new T.Setting(t).setName("Custom Template").setDesc("Use {{content}} for the text placeholder").addTextArea(l=>{l.setPlaceholder(`## {{date}} {{content}} @@ -114,8 +114,8 @@ ${r}`),this.options.template&&(r=this.options.template.replace("{{content}}",r). - --- -*Transcribed at {{datetime}}*`}]}onClose(){let{contentEl:t}=this;t.empty()}};var b=require("obsidian");var A=require("obsidian");var F="[Deepgram]",N={DEBUG:"debug",INFO:"info",WARN:"warn",ERROR:"error"},d={CLASSES:{API_KEY_INPUT:"deepgram-api-key-input",MODEL_INFO:"deepgram-model-info",MODEL_DESCRIPTION:"model-description",MODEL_METRICS:"model-metrics",SUPPORTED_LANGUAGES:"supported-languages",FEATURES_CONTAINER:"deepgram-features",ADVANCED_CONTAINER:"deepgram-advanced",COST_ESTIMATION:"deepgram-cost-estimation",COST_DETAILS:"cost-details",WARNING:"mod-warning",ERROR_DETAILS:"error-details",SETTING_DESCRIPTION:"setting-item-description"},MESSAGES:{HEADER:"Deepgram Configuration",DESCRIPTION:"Configure Deepgram for advanced speech recognition with multiple language support and AI features.",REGISTRY_WARNING:"\u26A0\uFE0F Model registry not available. Using default configuration.",API_KEY_LABEL:"Deepgram API Key",API_KEY_DESC:"Enter your Deepgram API key for transcription",API_KEY_PLACEHOLDER:"Enter API key...",API_KEY_SAVED:"Deepgram API key saved",API_KEY_REQUIRED:"Please enter your Deepgram API key first",MODEL_LABEL:"Deepgram Model",MODEL_DESC:"Select the Deepgram model for transcription",MODEL_PLACEHOLDER:"Select a model...",FEATURES_HEADER:"Features",ADVANCED_HEADER:"Advanced Settings",COST_HEADER:"Cost Estimation",VALIDATION_LABEL:"Validate Configuration",VALIDATION_DESC:"Test your Deepgram API key and settings",VALIDATION_BUTTON:"Validate",VALIDATING:"Validating...",VALIDATION_SUCCESS:"\u2705 Deepgram configuration is valid",VALIDATION_ERROR:"\u274C Invalid Deepgram API key or configuration",FALLBACK_ERROR_TITLE:"\u26A0\uFE0F Deepgram Settings Error",FALLBACK_ERROR_DESC:"Unable to load full configuration. Basic settings are available below.",CRITICAL_ERROR:"Deepgram settings could not be loaded. Please check the console for errors."},STYLES:{WARNING_BOX:"deepgram-warning-box",INFO_CONTAINER:"deepgram-info-container",METRICS_ROW:"deepgram-metrics-row",LANGUAGES_ROW:"deepgram-languages-row",COST_CONTAINER:"deepgram-cost-container",ERROR_CONTAINER:"deepgram-error-container",ERROR_DETAILS:"deepgram-error-details",DESCRIPTION_MARGIN:"deepgram-description"}},U={ENDPOINTS:{VALIDATION:"https://api.deepgram.com/v1/projects"},HEADERS:{AUTHORIZATION_PREFIX:"Token",CONTENT_TYPE:"application/json"},METHODS:{GET:"GET",POST:"POST"},MASK:{VISIBLE_START:8,VISIBLE_END:4,CHAR:"*"},TIMEOUT:{MIN:5e3,MAX:12e4}},k={TIMEOUT:{MIN:5e3,MAX:12e4,DEFAULT:3e4},RETRIES:{MIN:0,MAX:3,DEFAULT:3},COST_ESTIMATION:{DAILY_MINUTES:10,DAYS_PER_MONTH:30},VALIDATION_RESET_DELAY:3e3},ot=[{value:"auto",label:"Auto-detect"},{value:"en",label:"English"},{value:"es",label:"Spanish"},{value:"fr",label:"French"},{value:"de",label:"German"},{value:"pt",label:"Portuguese"},{value:"nl",label:"Dutch"},{value:"it",label:"Italian"},{value:"pl",label:"Polish"},{value:"ru",label:"Russian"},{value:"zh",label:"Chinese"},{value:"ja",label:"Japanese"},{value:"ko",label:"Korean"},{value:"ar",label:"Arabic"},{value:"hi",label:"Hindi"}],lt=[{id:"nova-3",name:"Nova 3",tier:"Premium",price:.0043},{id:"nova-2",name:"Nova 2",tier:"Premium",price:.0059},{id:"nova",name:"Nova",tier:"Standard",price:.0025},{id:"enhanced",name:"Enhanced",tier:"Standard",price:.0145},{id:"base",name:"Base",tier:"Economy",price:.0125}],ct=[{key:"punctuation",name:"Punctuation",description:"Add punctuation to transcript",default:!0},{key:"smartFormat",name:"Smart Format",description:"Format numbers, dates, etc.",default:!0},{key:"diarization",name:"Speaker Diarization",description:"Identify different speakers",default:!0},{key:"numerals",name:"Numerals",description:"Convert numbers to digits",default:!1}];var O=class o{constructor(){this.enabled=!0;this.minLevel=N.INFO}static getInstance(){return o.instance||(o.instance=new o),o.instance}setEnabled(e){this.enabled=e}setMinLevel(e){this.minLevel=e}debug(e,...t){this.shouldLog(N.DEBUG)&&(`${F}${e}`,[...t])}info(e,...t){this.shouldLog(N.INFO)&&console.info(`${F} ${e}`,...t)}warn(e,...t){this.shouldLog(N.WARN)&&console.warn(`${F} ${e}`,...t)}error(e,t){this.shouldLog(N.ERROR)&&(console.error(`${F} ${e}`),t&&(t instanceof Error?console.error(`${F} Error details:`,{message:t.message,stack:t.stack}):console.error(`${F} Error details:`,t)))}group(e){this.enabled&&console.group(`${F} ${e}`)}groupEnd(){this.enabled&&console.groupEnd()}shouldLog(e){if(!this.enabled)return!1;let t=[N.DEBUG,N.INFO,N.WARN,N.ERROR],r=t.indexOf(e),i=t.indexOf(this.minLevel);return r>=i}time(e){this.enabled&&console.time(`${F} ${e}`)}timeEnd(e){this.enabled&&console.timeEnd(`${F} ${e}`)}};var dt={models:{"nova-3":{id:"nova-3",name:"Nova-3",description:"Next-generation model with state-of-the-art accuracy and enhanced diarization",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0,advancedDiarization:!0,emotionDetection:!0,speakerIdentification:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi","tr","sv","da","no","fi","cs","hu","bg"],performance:{accuracy:98,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"},isDefault:!0,migrationPath:{from:["nova-2","nova"],autoMigrate:!0,backwardCompatible:!0}},"nova-2":{id:"nova-2",name:"Nova-2",description:"Latest and most powerful model with best accuracy",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi","tr","sv","da","no","fi"],performance:{accuracy:95,speed:"fast",latency:"low"},pricing:{perMinute:.0145,currency:"USD"}},nova:{id:"nova",name:"Nova",description:"High-quality model with excellent accuracy",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!1,utterances:!0,summarization:!1},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko"],performance:{accuracy:90,speed:"fast",latency:"low"},pricing:{perMinute:.0125,currency:"USD"}},enhanced:{id:"enhanced",name:"Enhanced",description:"Balanced model for general use",tier:"basic",features:{punctuation:!0,smartFormat:!0,diarization:!1,numerals:!0,profanityFilter:!0,redaction:!1,utterances:!1,summarization:!1},languages:["en","es","fr","de","pt"],performance:{accuracy:85,speed:"moderate",latency:"medium"},pricing:{perMinute:.0085,currency:"USD"}},base:{id:"base",name:"Base",description:"Basic model for simple transcription",tier:"economy",features:{punctuation:!0,smartFormat:!1,diarization:!1,numerals:!1,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:80,speed:"moderate",latency:"medium"},pricing:{perMinute:.0059,currency:"USD"}}},features:{punctuation:{name:"Punctuation",description:"Add punctuation marks to transcript",default:!0},smartFormat:{name:"Smart Format",description:"Apply intelligent formatting (numbers, dates, etc.)",default:!0},diarization:{name:"Speaker Diarization",description:"Identify different speakers in audio",default:!0,requiresPremium:!0},numerals:{name:"Numerals",description:"Convert number words to digits",default:!0},profanityFilter:{name:"Profanity Filter",description:"Filter profane words",default:!1},redaction:{name:"Redaction",description:"Redact sensitive information (SSN, credit cards)",default:!1,requiresPremium:!0},utterances:{name:"Utterances",description:"Split transcript by natural speech boundaries",default:!1},summarization:{name:"Summarization",description:"Generate summary of transcript",default:!1,requiresPremium:!0}}};var Se={models:{"nova-3":{id:"nova-3",name:"Nova 3",description:"Latest premium model with higher accuracy and improved diarization",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi"],performance:{accuracy:98,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"}},"nova-2":{id:"nova-2",name:"Nova 2",description:"Most accurate and powerful model with advanced features",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi"],performance:{accuracy:95,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"}},nova:{id:"nova",name:"Nova",description:"Balanced model with good accuracy and speed",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!1,utterances:!0,summarization:!1},languages:["en","es","fr","de","pt","nl","it"],performance:{accuracy:90,speed:"fast",latency:"low"},pricing:{perMinute:.0025,currency:"USD"}},enhanced:{id:"enhanced",name:"Enhanced",description:"Enhanced accuracy for challenging audio",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!1,numerals:!0,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:85,speed:"moderate",latency:"medium"},pricing:{perMinute:.0145,currency:"USD"}},base:{id:"base",name:"Base",description:"Cost-effective option for simple transcription",tier:"economy",features:{punctuation:!0,smartFormat:!1,diarization:!1,numerals:!1,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:80,speed:"moderate",latency:"medium"},pricing:{perMinute:.0125,currency:"USD"}}},features:{punctuation:{name:"Punctuation",description:"Add punctuation marks to transcript",default:!0,requiresPremium:!1},smartFormat:{name:"Smart Format",description:"Format numbers, dates, and other entities",default:!0,requiresPremium:!1},diarization:{name:"Speaker Diarization",description:"Identify different speakers",default:!1,requiresPremium:!1},numerals:{name:"Numerals",description:"Convert numbers to digits",default:!1,requiresPremium:!1},profanityFilter:{name:"Profanity Filter",description:"Filter out profanity from transcript",default:!1,requiresPremium:!1},redaction:{name:"Redaction",description:"Redact sensitive information",default:!1,requiresPremium:!0},utterances:{name:"Utterances",description:"Split transcript into utterances",default:!1,requiresPremium:!1},summarization:{name:"Summarization",description:"Generate summary of transcript",default:!1,requiresPremium:!0}}},ut,Et=(ut=dt)!=null?ut:Se,Ae=class o{constructor(){this.models=new Map,this.features=new Map,this.logger=O.getInstance();try{this.loadConfiguration(),this.logger.info("Constructor completed successfully")}catch(e){this.logger.error("Error during initialization",e)}}static getInstance(){try{return o.instance||(o.instance=new o),o.instance}catch(e){if(!o.instance){let t=Object.create(o.prototype);t.models=new Map,t.features=new Map,t.logger=O.getInstance(),t.logger.error("Failed to create instance, using fallback",e),o.instance=t}return o.instance}}loadConfiguration(){try{let e=Et||Se;this.loadModels(e),this.loadFeatures(e),this.models.size===0&&this.features.size===0&&(this.logger.warn("No data loaded, loading fallback configuration"),this.loadFallbackConfiguration())}catch(e){this.logger.error("Error loading configuration",e),this.loadFallbackConfiguration()}}loadModels(e){if(!e.models||typeof e.models!="object"){this.logger.warn("No models in configuration");return}Object.entries(e.models).forEach(([t,r])=>{try{this.isValidModel(r)?this.models.set(t,r):this.logger.warn(`Invalid model structure for ${t}`)}catch(i){this.logger.error(`Failed to load model ${t}`,i)}}),this.logger.info(`Loaded ${this.models.size} models`)}loadFeatures(e){if(!e.features||typeof e.features!="object"){this.logger.warn("No features in configuration");return}Object.entries(e.features).forEach(([t,r])=>{try{this.isValidFeature(r)?this.features.set(t,r):this.logger.warn(`Invalid feature structure for ${t}`)}catch(i){this.logger.error(`Failed to load feature ${t}`,i)}}),this.logger.info(`Loaded ${this.features.size} features`)}loadFallbackConfiguration(){try{Object.entries(Se.models).forEach(([e,t])=>{this.models.set(e,t)}),Object.entries(Se.features).forEach(([e,t])=>{this.features.set(e,t)}),this.logger.info("Fallback configuration loaded")}catch(e){this.logger.error("Failed to load fallback configuration",e)}}isValidModel(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.id=="string"&&typeof t.name=="string"&&t.features!==void 0&&Array.isArray(t.languages)&&typeof t.performance=="object"&&typeof t.pricing=="object"}isValidFeature(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.name=="string"&&typeof t.description=="string"&&typeof t.default=="boolean"}getAllModels(){try{return Array.from(this.models.values())}catch(e){return this.logger.error("Error getting all models",e),[]}}getModel(e){return this.models.get(e)}getAllFeatures(){try{return this.features}catch(e){return this.logger.error("Error getting all features",e),new Map}}getFeature(e){return this.features.get(e)}isLanguageSupported(e,t){let r=this.models.get(e);return r?r.languages.includes(t):!1}isFeatureSupported(e,t){let r=this.models.get(e);return r?r.features[t]===!0:!1}getModelsByLanguage(e){return Array.from(this.models.values()).filter(t=>t.languages.includes(e))}getModelsByTier(e){return Array.from(this.models.values()).filter(t=>t.tier===e)}getModelsByPriceRange(e){return Array.from(this.models.values()).filter(t=>t.pricing.perMinute<=e)}calculateCost(e,t){let r=this.models.get(e);return r?r.pricing.perMinute*t:0}getPerformanceScore(e){let t=this.models.get(e);if(!t)return 0;let r=t.performance.accuracy;return t.performance.speed==="fast"?r+=5:t.performance.speed==="moderate"&&(r+=2),t.performance.latency==="high"?r-=5:t.performance.latency==="medium"&&(r-=2),Math.min(100,Math.max(0,r))}getRecommendedModel(e){let t=Array.from(this.models.values()),{language:r,maxPrice:i,minAccuracy:n,requiredFeatures:s}=e;return r&&(t=t.filter(a=>a.languages.includes(r))),i!==void 0&&(t=t.filter(a=>a.pricing.perMinute<=i)),n!==void 0&&(t=t.filter(a=>a.performance.accuracy>=n)),s&&s.length>0&&(t=t.filter(a=>s.every(l=>a.features[l]===!0))),t.length>0?(t.sort((a,l)=>this.getPerformanceScore(l.id)-this.getPerformanceScore(a.id)),t[0]):null}validateModel(e){let t=[],r=this.models.get(e);return r?(r.id||t.push("Model ID is missing"),r.name||t.push("Model name is missing"),r.tier||t.push("Model tier is missing"),(!r.languages||r.languages.length===0)&&t.push("Model must support at least one language"),r.pricing.perMinute<0&&t.push("Model pricing cannot be negative"),(r.performance.accuracy<0||r.performance.accuracy>100)&&t.push("Model accuracy must be between 0 and 100"),{valid:t.length===0,errors:t}):(t.push(`Model '${e}' not found`),{valid:!1,errors:t})}};var we=class{constructor(e){this.containerEl=e}createHeader(e){return this.containerEl.createEl("h4",{text:e})}createDescription(e){let t=this.containerEl.createEl("p",{text:e,cls:d.CLASSES.SETTING_DESCRIPTION});return t.addClass(d.STYLES.DESCRIPTION_MARGIN),t}createWarning(e){let t=this.containerEl.createEl("div",{cls:d.CLASSES.WARNING,text:e});return t.addClass(d.STYLES.WARNING_BOX),t}createModelInfoCard(e){this.removeElement(`.${d.CLASSES.MODEL_INFO}`);let t=this.containerEl.createEl("div",{cls:d.CLASSES.MODEL_INFO});return t.addClass(d.STYLES.INFO_CONTAINER),t.createEl("p",{text:e.description,cls:d.CLASSES.MODEL_DESCRIPTION}),this.createMetricsRow(t,e),this.createLanguagesRow(t,e),t}createMetricsRow(e,t){let r=e.createEl("div",{cls:d.CLASSES.MODEL_METRICS});r.addClass(d.STYLES.METRICS_ROW),r.createEl("span",{text:`Accuracy: ${t.performance.accuracy}%`}),r.createEl("span",{text:`Speed: ${t.performance.speed}`}),r.createEl("span",{text:`Latency: ${t.performance.latency}`})}createLanguagesRow(e,t){let r=e.createEl("div",{cls:d.CLASSES.SUPPORTED_LANGUAGES});r.addClass(d.STYLES.LANGUAGES_ROW),r.createEl("span",{text:`Supported languages: ${t.languages.join(", ")}`})}createCostEstimationContainer(){let e=this.containerEl.createEl("div",{cls:d.CLASSES.COST_ESTIMATION});return e.addClass(d.STYLES.COST_CONTAINER),e.createEl("h5",{text:d.MESSAGES.COST_HEADER}),e}updateCostDetails(e,t,r){let i=e.querySelector(`.${d.CLASSES.COST_DETAILS}`)||e.createEl("div",{cls:d.CLASSES.COST_DETAILS});if(i.empty(),!t){i.createEl("p",{text:"Select a model to see cost estimation",cls:d.CLASSES.WARNING});return}let n=i.createEl("div");if(n.createEl("p",{text:`Cost per minute: $${t.pricing.perMinute}`}),r!==void 0){let s=k.COST_ESTIMATION.DAILY_MINUTES;n.createEl("p",{text:`Estimated monthly cost (${s} min/day): $${r.toFixed(2)}`})}}addBudgetWarning(e,t,r){if(t>r){let i=e.querySelector(".budget-warning")||e.createEl("p",{cls:"budget-warning"});i.textContent=`\u26A0\uFE0F Exceeds monthly budget of $${r}`,i.classList.add(d.CLASSES.WARNING)}}createErrorContainer(e){let t=this.containerEl.createEl("div",{cls:d.CLASSES.WARNING});if(t.addClass(d.STYLES.ERROR_CONTAINER),t.createEl("h5",{text:d.MESSAGES.FALLBACK_ERROR_TITLE}),t.createEl("p",{text:d.MESSAGES.FALLBACK_ERROR_DESC}),e instanceof Error){let r=t.createEl("details");r.createEl("summary",{text:"Error details"}),r.createEl("pre",{text:e.message,cls:d.CLASSES.ERROR_DETAILS}).addClass(d.STYLES.ERROR_DETAILS)}return t}createSection(e,t){let r=this.containerEl.createEl("div",{cls:e});return t&&r.createEl("h5",{text:t}),r}removeElement(e){let t=this.containerEl.querySelector(e);t&&t.remove()}clearContainer(){this.containerEl.empty()}};var gt=require("obsidian");var Ce=class{constructor(){this.logger=O.getInstance()}async validateApiKey(e){if(!e)return this.logger.warn("API key validation failed: No key provided"),!1;try{this.logger.info("Validating API key via Obsidian requestUrl...");let t={url:U.ENDPOINTS.VALIDATION,method:U.METHODS.GET,headers:{Authorization:`${U.HEADERS.AUTHORIZATION_PREFIX} ${e}`,"Content-Type":U.HEADERS.CONTENT_TYPE},throw:!1},r=await(0,gt.requestUrl)(t),i=r.status===200;return i?this.logger.info("API key validation successful"):this.logger.warn(`API key validation failed with status: ${r.status}`),i}catch(t){return this.logger.error("API validation error (requestUrl)",t),!1}}maskApiKey(e){if(!e||e.length<10)return"";let{VISIBLE_START:t,VISIBLE_END:r,CHAR:i}=U.MASK;if(e.length<=t+r)return e;let n=i.repeat(e.length-t-r);return e.substring(0,t)+n+e.substring(e.length-r)}validateTimeout(e){let t=parseInt(e)*1e3,{MIN:r,MAX:i}=U.TIMEOUT;return isNaN(t)||ti?(this.logger.warn(`Invalid timeout value: ${e}`),null):t}validateRetries(e){let t=parseInt(e),{MIN:r,MAX:i}=k.RETRIES;return isNaN(t)||ti?(this.logger.warn(`Invalid retries value: ${e}`),null):t}};var Ie=class{constructor(){this.logger=O.getInstance()}calculateEstimation(e,t){if(!e)return this.logger.debug("No model selected for cost calculation"),null;let{DAILY_MINUTES:r,DAYS_PER_MONTH:i}=k.COST_ESTIMATION,n=e.pricing.perMinute,s=n*r,a=s*i,l=t?a>t:!1;return this.logger.debug(`Cost calculated for ${e.name}:`,{perMinute:n,daily:s,monthly:a,exceeedsBudget:l}),{perMinute:n,daily:s,monthly:a,exceeedsBudget:l}}calculateCostByUsage(e,t){let r=e.pricing.perMinute*t;return this.logger.debug(`Usage cost calculated: ${t} minutes = $${r}`),r}calculateAvailableMinutes(e,t){let r=t/e.pricing.perMinute;return this.logger.debug(`Available minutes for budget $${t}: ${r.toFixed(2)}`),r}compareModelCosts(e,t){let r=new Map;return e.forEach(i=>{let n=this.calculateCostByUsage(i,t);r.set(i.id,n)}),r}calculateEfficiencyScore(e,t){if(e.pricing.perMinute>t)return 0;let r=1-e.pricing.perMinute/t,n=(e.performance.accuracy/100*.7+r*.3)*100;return this.logger.debug(`Efficiency score for ${e.name}: ${n.toFixed(2)}`),Math.round(n)}};var De=class{constructor(e,t){this.registry=null;this.selectedModel=null;this.estimatedCostEl=null;this.plugin=e,this.containerEl=t,this.logger=O.getInstance(),this.uiBuilder=new we(t),this.validator=new Ce,this.costCalculator=new Ie,this.initializeRegistry()}initializeRegistry(){try{this.logger.info("Attempting to initialize DeepgramModelRegistry..."),this.registry=Ae.getInstance();let e=this.registry.getAllModels();this.logger.info(`Registry initialized successfully with ${e.length} models`),e.length===0&&(this.logger.warn("Registry has no models, will use fallback"),this.registry=null)}catch(e){this.logger.error("Failed to initialize registry",e),this.registry=null,this.logger.info("Will continue with fallback UI")}}render(){this.logger.group("render()"),this.logRenderState();try{this.uiBuilder.clearContainer(),this.renderHeader(),this.renderSections(),this.logger.info(`Total elements created: ${this.containerEl.children.length}`),this.logger.groupEnd()}catch(e){this.logger.error("Critical error in render()",e),this.renderFallbackUI(e)}}logRenderState(){this.logger.debug("Container element:",this.containerEl),this.logger.debug("Container is connected:",this.containerEl.isConnected),this.logger.debug("Registry available:",!!this.registry),this.logger.debug("API key exists:",!!this.plugin.settings.deepgramApiKey),this.containerEl.isConnected||this.logger.warn("Container is not connected to DOM, attempting to render anyway"),this.registry||this.logger.warn("Registry not available, using fallback UI")}renderHeader(){this.uiBuilder.createHeader(d.MESSAGES.HEADER),this.uiBuilder.createDescription(d.MESSAGES.DESCRIPTION),this.registry||this.uiBuilder.createWarning(d.MESSAGES.REGISTRY_WARNING)}renderSections(){this.logger.info("Rendering API key section..."),this.renderApiKeySection(),this.logger.info("Rendering model selection..."),this.renderModelSelection(),this.logger.info("Rendering feature toggles..."),this.renderFeatureToggles(),this.logger.info("Rendering advanced settings..."),this.renderAdvancedSettings(),this.logger.info("Rendering cost estimation..."),this.renderCostEstimation(),this.logger.info("Rendering validation button..."),this.renderValidationButton()}renderApiKeySection(){new A.Setting(this.containerEl).setName(d.MESSAGES.API_KEY_LABEL).setDesc(d.MESSAGES.API_KEY_DESC).addText(e=>{this.setupApiKeyInput(e)})}setupApiKeyInput(e){let t=this.plugin.settings.deepgramApiKey||"";e.setPlaceholder(d.MESSAGES.API_KEY_PLACEHOLDER).setValue(this.validator.maskApiKey(t)).onChange(async r=>{await this.handleApiKeyChange(r,e)}),e.inputEl.type="password",e.inputEl.addClass(d.CLASSES.API_KEY_INPUT),this.attachApiKeyEventListeners(e)}async handleApiKeyChange(e,t){e&&!e.includes("*")&&(this.plugin.settings.deepgramApiKey=e,await this.plugin.saveSettings(),t.setValue(this.validator.maskApiKey(e)),new A.Notice(d.MESSAGES.API_KEY_SAVED),this.updateUIState())}attachApiKeyEventListeners(e){e.inputEl.addEventListener("focus",()=>{this.plugin.settings.deepgramApiKey&&e.setValue(this.plugin.settings.deepgramApiKey)}),e.inputEl.addEventListener("blur",()=>{this.plugin.settings.deepgramApiKey&&e.setValue(this.validator.maskApiKey(this.plugin.settings.deepgramApiKey))})}renderModelSelection(){let e=new A.Setting(this.containerEl).setName(d.MESSAGES.MODEL_LABEL).setDesc(d.MESSAGES.MODEL_DESC),t=e.addDropdown(r=>(this.populateModelDropdown(r),this.setupModelDropdownHandlers(r),r));this.disableIfNoApiKey(e)}populateModelDropdown(e){if(e.addOption("",d.MESSAGES.MODEL_PLACEHOLDER),!this.registry){this.logger.warn("Registry not available, using default models"),this.addDefaultModelOptions(e);return}try{let t=this.registry.getAllModels();t.length===0?(this.logger.warn("No models in registry, using defaults"),this.addDefaultModelOptions(e)):(this.addModelOptions(e,t),this.logger.info(`Added ${t.length} models to dropdown`))}catch(t){this.logger.error("Error loading models",t),this.addDefaultModelOptions(e)}}addModelOptions(e,t){t.forEach(r=>{let i=this.formatModelOption(r);e.addOption(r.id,i)})}formatModelOption(e){return`${e.name} (${e.tier}) - $${e.pricing.perMinute}/min`}setupModelDropdownHandlers(e){var r,i;let t=((i=(r=this.plugin.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.model)||"";e.setValue(t),e.onChange(async n=>{await this.handleModelChange(n)})}async handleModelChange(e){var t;if(!e){this.selectedModel=null;return}this.selectedModel=((t=this.registry)==null?void 0:t.getModel(e))||null,await this.saveModelSelection(e),this.updateUIAfterModelChange(),this.selectedModel&&new A.Notice(`Selected model: ${this.selectedModel.name}`)}async saveModelSelection(e){this.plugin.settings.transcription||(this.plugin.settings.transcription={}),this.plugin.settings.transcription.deepgram?this.plugin.settings.transcription.deepgram.model=e:this.plugin.settings.transcription.deepgram={enabled:!0,model:e},await this.plugin.saveSettings()}updateUIAfterModelChange(){this.updateModelInfo(),this.updateFeatureAvailability(),this.updateCostEstimation()}disableIfNoApiKey(e){if(!this.plugin.settings.deepgramApiKey){let t=e.settingEl.querySelector("select");t&&(t.disabled=!0),e.setDesc(d.MESSAGES.API_KEY_REQUIRED)}}updateModelInfo(){this.selectedModel&&this.uiBuilder.createModelInfoCard(this.selectedModel)}renderFeatureToggles(){let e=this.uiBuilder.createSection(d.CLASSES.FEATURES_CONTAINER,d.MESSAGES.FEATURES_HEADER);if(!this.registry){this.renderDefaultFeatures(e);return}this.registry.getAllFeatures().forEach((r,i)=>{this.renderFeatureToggle(e,r,i)})}renderFeatureToggle(e,t,r){let i=new A.Setting(e).setName(t.name).setDesc(this.getFeatureDescription(t));i.addToggle(n=>{let s=this.getFeatureValue(r,t.default);return n.setValue(s).onChange(async a=>{await this.saveFeatureSetting(r,a),this.updateCostEstimation()}),this.updateFeatureAvailabilityForToggle(n,i,t,r),n})}getFeatureDescription(e){return e.requiresPremium?`${e.description} (Premium feature)`:e.description}getFeatureValue(e,t){var i,n,s;let r=(n=(i=this.plugin.settings.transcription)==null?void 0:i.deepgram)==null?void 0:n.features;return(s=r==null?void 0:r[e])!=null?s:t}async saveFeatureSetting(e,t){this.ensureTranscriptionSettings(),this.plugin.settings.transcription.deepgram.features||(this.plugin.settings.transcription.deepgram.features={});let r=this.plugin.settings.transcription.deepgram.features;r[e]=t,await this.plugin.saveSettings()}ensureTranscriptionSettings(){this.plugin.settings.transcription||(this.plugin.settings.transcription={}),this.plugin.settings.transcription.deepgram||(this.plugin.settings.transcription.deepgram={enabled:!0})}updateFeatureAvailabilityForToggle(e,t,r,i){this.selectedModel&&this.registry&&!this.registry.isFeatureSupported(this.selectedModel.id,i)&&(e.setDisabled(!0),t.setDesc(`${r.description} (Not supported by selected model)`))}renderAdvancedSettings(){let e=this.uiBuilder.createSection(d.CLASSES.ADVANCED_CONTAINER,d.MESSAGES.ADVANCED_HEADER);this.renderLanguagePreference(e),this.renderTimeoutSetting(e),this.renderRetrySetting(e),this.renderChunkingSettings(e)}renderLanguagePreference(e){new A.Setting(e).setName("Preferred Language").setDesc("Set preferred language for better accuracy").addDropdown(t=>{ot.forEach(r=>{t.addOption(r.value,r.label)}),t.setValue(this.plugin.settings.language||"auto"),t.onChange(async r=>{this.plugin.settings.language=r,await this.plugin.saveSettings()})})}renderTimeoutSetting(e){new A.Setting(e).setName("Request Timeout").setDesc("Maximum time to wait for transcription (in seconds)").addText(t=>{let r=this.plugin.settings.requestTimeout||k.TIMEOUT.DEFAULT;t.setPlaceholder("30").setValue(String(r/1e3)).onChange(async i=>{let n=this.validator.validateTimeout(i);n!==null&&(this.plugin.settings.requestTimeout=n,await this.plugin.saveSettings())})})}renderRetrySetting(e){new A.Setting(e).setName("Max Retries").setDesc("Number of retry attempts on failure").addDropdown(t=>{for(let i=0;i<=k.RETRIES.MAX;i++){let n=i===0?"No retries":`${i} ${i===1?"retry":"retries"}`;t.addOption(String(i),n)}let r=this.plugin.settings.maxRetries||k.RETRIES.DEFAULT;t.setValue(String(r)),t.onChange(async i=>{this.plugin.settings.maxRetries=parseInt(i),await this.plugin.saveSettings()})})}renderChunkingSettings(e){new A.Setting(e).setName("Automatic File Chunking").setDesc("Automatically split large audio files (>50MB) into smaller chunks for reliable processing").addToggle(s=>{var a;s.setValue((a=this.plugin.settings.autoChunking)!=null?a:!0).onChange(async l=>{this.plugin.settings.autoChunking=l,await this.plugin.saveSettings();let c=e.querySelector(".chunk-size-setting");c&&c.classList.toggle("sn-hidden",!l)})});let t=new A.Setting(e).setName("Maximum Chunk Size").setDesc("Maximum size per chunk in MB (recommended: 50MB)").addSlider(s=>{var a;s.setLimits(10,100,10).setValue((a=this.plugin.settings.maxChunkSizeMB)!=null?a:50).setDynamicTooltip().onChange(async l=>{this.plugin.settings.maxChunkSizeMB=l,await this.plugin.saveSettings()})});t.settingEl.addClass("chunk-size-setting"),this.plugin.settings.autoChunking||t.settingEl.addClass("sn-hidden");let r=e.createDiv();r.addClass("setting-item-description"),r.addClass("deepgram-note"),r.createEl("strong",{text:"Note on Large Files:"});let i=r.createEl("ul");["Files larger than 50MB may experience timeout errors","Auto-chunking splits files into manageable pieces","Each chunk is processed separately and results are merged"].forEach(s=>{i.createEl("li",{text:s})}),r.createEl("p",{text:"For best results with very large files (>100MB), consider:"});let n=r.createEl("ul");["Using the 'enhanced' model for faster processing","Reducing audio bitrate to 64-128 kbps","Converting to efficient formats (MP3, OGG)"].forEach(s=>{n.createEl("li",{text:s})})}renderCostEstimation(){let e=this.uiBuilder.createCostEstimationContainer();this.estimatedCostEl=e.createEl("div",{cls:d.CLASSES.COST_DETAILS}),this.updateCostEstimation()}updateCostEstimation(){if(!this.estimatedCostEl)return;let e=this.costCalculator.calculateEstimation(this.selectedModel,this.plugin.settings.monthlyBudget);if(!e){this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,null);return}this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,this.selectedModel,e.monthly),e.exceeedsBudget&&this.plugin.settings.monthlyBudget&&this.uiBuilder.addBudgetWarning(this.estimatedCostEl.parentElement,e.monthly,this.plugin.settings.monthlyBudget)}renderValidationButton(){new A.Setting(this.containerEl).setName(d.MESSAGES.VALIDATION_LABEL).setDesc(d.MESSAGES.VALIDATION_DESC).addButton(e=>{this.setupValidationButton(e)})}setupValidationButton(e){e.setButtonText(d.MESSAGES.VALIDATION_BUTTON).setCta().onClick(async()=>{await this.handleValidation(e)})}async handleValidation(e){e.setDisabled(!0),e.setButtonText(d.MESSAGES.VALIDATING);try{if(await this.validator.validateApiKey(this.plugin.settings.deepgramApiKey||""))this.handleValidationSuccess(e);else throw new Error("Invalid API key")}catch(t){this.handleValidationError(e,t)}}handleValidationSuccess(e){new A.Notice(d.MESSAGES.VALIDATION_SUCCESS),e.setButtonText("Valid \u2713"),e.removeCta(),setTimeout(()=>{e.setButtonText(d.MESSAGES.VALIDATION_BUTTON),e.setCta(),e.setDisabled(!1)},k.VALIDATION_RESET_DELAY)}handleValidationError(e,t){this.logger.error("Validation error",t),new A.Notice(d.MESSAGES.VALIDATION_ERROR),e.setButtonText(d.MESSAGES.VALIDATION_BUTTON),e.setWarning(),e.setDisabled(!1)}updateUIState(){let e=!!this.plugin.settings.deepgramApiKey,t=this.containerEl.querySelector("select");t&&(t.disabled=!e),this.containerEl.querySelectorAll(".checkbox-container input").forEach(i=>{i.disabled=!e||!this.selectedModel})}renderDefaultFeatures(e){ct.forEach(t=>{new A.Setting(e).setName(t.name).setDesc(t.description).addToggle(r=>{let i=this.getFeatureValue(t.key,t.default);r.setValue(i).onChange(async n=>{await this.saveFeatureSetting(t.key,n)})})})}updateFeatureAvailability(){if(!this.selectedModel||!this.registry)return;this.registry.getAllFeatures().forEach((t,r)=>{this.updateFeatureToggleState(r)})}updateFeatureToggleState(e){let t=this.containerEl.querySelector(`[data-feature="${e}"]`);if(!t||!this.selectedModel||!this.registry)return;let r=this.registry.isFeatureSupported(this.selectedModel.id,e);t.disabled=!r,!r&&t.checked&&(t.checked=!1,t.dispatchEvent(new Event("change")))}addDefaultModelOptions(e){lt.forEach(t=>{let r=`${t.name} (${t.tier}) - $${t.price}/min`;e.addOption(t.id,r)}),this.logger.info("Added default model options")}renderFallbackUI(e){this.logger.info("Rendering fallback UI due to error");try{this.uiBuilder.clearContainer(),this.uiBuilder.createErrorContainer(e),this.renderMinimalSettings(),this.logger.info("Fallback UI rendered successfully")}catch(t){this.logger.error("Failed to render fallback UI",t),this.renderCriticalError()}}renderMinimalSettings(){new A.Setting(this.containerEl).setName(d.MESSAGES.API_KEY_LABEL).setDesc(d.MESSAGES.API_KEY_DESC).addText(e=>{e.setPlaceholder(d.MESSAGES.API_KEY_PLACEHOLDER).setValue(this.plugin.settings.deepgramApiKey||"").onChange(async t=>{this.plugin.settings.deepgramApiKey=t,await this.plugin.saveSettings(),new A.Notice(d.MESSAGES.API_KEY_SAVED)}),e.inputEl.type="password"}),new A.Setting(this.containerEl).setName(d.MESSAGES.MODEL_LABEL).setDesc(d.MESSAGES.MODEL_DESC).addDropdown(e=>{var r,i;e.addOption("",d.MESSAGES.MODEL_PLACEHOLDER),this.addDefaultModelOptions(e);let t=((i=(r=this.plugin.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.model)||"";e.setValue(t),e.onChange(async n=>{await this.saveModelSelection(n)})})}renderCriticalError(){this.uiBuilder.clearContainer(),this.containerEl.createEl("p",{text:d.MESSAGES.CRITICAL_ERROR,cls:d.CLASSES.WARNING})}};var Me=class extends b.PluginSettingTab{constructor(e,t){super(e,t),this.plugin=t}display(){var s,a,l,c,p,u,h,f,g,D,y,M,_,K;let{containerEl:e}=this;if(!e){this.debug("SettingsTab display called without container element");return}this.debug("=== SettingsTab display() called ==="),this.debug("Container element:",e),this.debug("Container element exists:",!!e),this.debug("Container element type:",(s=e==null?void 0:e.constructor)==null?void 0:s.name),this.debug("Plugin instance:",this.plugin),this.debug("Plugin instance exists:",!!this.plugin),this.debug("Plugin settings object:",(a=this.plugin)==null?void 0:a.settings),this.debug("Plugin settings keys:",(l=this.plugin)!=null&&l.settings?Object.keys(this.plugin.settings):"N/A"),e&&(this.debug("Container parent element:",e.parentElement),this.debug("Container is connected to DOM:",e.isConnected),this.debug("Container display style:",window.getComputedStyle(e).display)),e.empty();let t=e.createEl("h2",{text:"Speech to Text Settings"});this.debug("Title element created:",t);let r=e.createEl("details",{cls:"speech-to-text-debug"}),i=r.createEl("summary",{text:"Debug Information"}),n=r.createEl("pre",{text:JSON.stringify({pluginExists:!!this.plugin,settingsExists:!!((c=this.plugin)!=null&&c.settings),apiKey:(u=(p=this.plugin)==null?void 0:p.settings)!=null&&u.apiKey?"Set (hidden)":"Not set",language:((f=(h=this.plugin)==null?void 0:h.settings)==null?void 0:f.language)||"Not set",autoInsert:(D=(g=this.plugin)==null?void 0:g.settings)==null?void 0:D.autoInsert,insertPosition:(M=(y=this.plugin)==null?void 0:y.settings)==null?void 0:M.insertPosition,model:(K=(_=this.plugin)==null?void 0:_.settings)==null?void 0:K.model,timestamp:new Date().toISOString()},null,2)});this.debug("Debug section added");try{this.debug("Creating API section..."),this.createApiSection(e),this.debug("API section created"),this.debug("Creating General section..."),this.createGeneralSection(e),this.debug("General section created"),this.debug("Creating Audio section..."),this.createAudioSection(e),this.debug("Audio section created"),this.debug("Creating Advanced section..."),this.createAdvancedSection(e),this.debug("Advanced section created"),this.debug("Creating Support section..."),this.createSupportSection(e),this.debug("Support section created"),this.debug("=== Settings tab rendered successfully ==="),this.debug("Total child elements:",e.children.length)}catch(x){console.error("=== Error displaying settings ==="),console.error("Error details:",x),console.error("Error stack:",x instanceof Error?x.stack:"N/A"),e.empty(),e.createEl("h2",{text:"Settings Error"}),e.createEl("p",{text:"Error loading settings. Please reload the plugin.",cls:"mod-warning"}),e.createEl("pre",{text:`Error: ${x instanceof Error?x.message:String(x)}`,cls:"error-details"})}}createApiSection(e){e.createEl("h3",{text:"API Configuration"});let t=e.createEl("div",{cls:"provider-selection"});this.createProviderSelection(t);let r=e.createEl("div",{cls:"provider-settings"}),i=this.plugin.settings.provider||"auto";this.renderProviderSettings(r,i)}createProviderSelection(e){var r;this.debug("=== createProviderSelection called ==="),this.debug("Creating Setting instance...");try{let i=new b.Setting(e);this.debug("Setting instance created:",i),this.debug("Setting element:",i.settingEl),this.debug("Setting element in DOM:",(r=i.settingEl)==null?void 0:r.isConnected),i.setName("Transcription Provider").setDesc("Select the speech-to-text provider").addDropdown(n=>{var s;this.debug("Dropdown callback called"),this.debug("Dropdown component:",n),n.addOption("auto","Auto (Intelligent Selection)").addOption("whisper","OpenAI Whisper").addOption("deepgram","Deepgram").setValue(this.plugin.settings.provider||"auto").onChange(async a=>{var p;this.debug("Provider dropdown changed to:",a),this.plugin.settings.provider=a,await this.plugin.saveSettings();let l=(p=e.parentElement)==null?void 0:p.querySelector(".provider-settings");this.debug("Settings container found:",!!l),l?(this.debug("Updating provider settings UI for:",a),this.renderProviderSettings(l,a)):console.error("Could not find .provider-settings container");let c=e.querySelector(".provider-info");c&&this.updateProviderInfo(c,a),new b.Notice(`Provider changed to: ${a}`)}),this.debug("Dropdown setup complete"),this.debug("Dropdown element:",n.selectEl),this.debug("Dropdown options:",(s=n.selectEl)==null?void 0:s.options.length)}),this.debug("Provider selection setting created successfully"),this.debug("=== createProviderSelection completed ===")}catch(i){console.error("Error creating provider selection:",i),console.error("Error stack:",i instanceof Error?i.stack:"N/A")}let t=e.createEl("div",{cls:"provider-info"});t.addClass("sn-info-box"),this.updateProviderInfo(t,this.plugin.settings.provider||"auto")}renderProviderSettings(e,t){this.debug("=== renderProviderSettings called ==="),this.debug("Provider:",t),this.debug("Container element:",e);let r=e.isConnected;e.empty(),this.debug("Container cleared, still connected:",r);try{switch(t){case"auto":this.debug("Rendering auto provider settings"),this.renderAutoProviderSettings(e);break;case"whisper":this.debug("Rendering whisper settings"),this.renderWhisperSettings(e);break;case"deepgram":this.debug("Rendering deepgram settings"),this.renderDeepgramSettings(e);break;default:console.warn("Unknown provider:",t),e.createEl("p",{text:`Unknown provider: ${t}`,cls:"mod-warning"})}}catch(i){console.error("Error rendering provider settings:",i),e.createEl("p",{text:"Error loading provider settings",cls:"mod-warning"})}this.debug("Final container children:",e.children.length),this.debug("=== renderProviderSettings completed ===")}renderAutoProviderSettings(e){e.createEl("h4",{text:"Automatic Provider Selection"}),new b.Setting(e).setName("Selection Strategy").setDesc("How to choose between available providers").addDropdown(t=>{t.addOption("cost_optimized","Cost Optimized").addOption("performance_optimized","Performance Optimized").addOption("quality_optimized","Quality Optimized").addOption("balanced","Balanced").setValue(this.plugin.settings.selectionStrategy||"performance_optimized").onChange(async r=>{this.plugin.settings.selectionStrategy=r,await this.plugin.saveSettings()})}),new b.Setting(e).setName("Fallback Strategy").setDesc("What to do when primary provider fails").addDropdown(t=>{t.addOption("auto","Automatic Fallback").addOption("manual","Ask User").addOption("none","No Fallback").setValue(this.plugin.settings.fallbackStrategy||"auto").onChange(async r=>{this.plugin.settings.fallbackStrategy=r,await this.plugin.saveSettings()})}),e.createEl("h5",{text:"Provider API Keys"}),e.createEl("p",{text:"Configure API keys for each provider to enable automatic selection",cls:"setting-item-description"}),this.renderWhisperApiKey(e),this.renderDeepgramApiKey(e)}renderWhisperSettings(e){e.createEl("h4",{text:"OpenAI Whisper Configuration"}),this.renderWhisperApiKey(e),new b.Setting(e).setName("API Endpoint").setDesc("OpenAI API endpoint (leave default unless using custom endpoint)").addText(t=>t.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.apiEndpoint||"https://api.openai.com/v1").onChange(async r=>{this.plugin.settings.apiEndpoint=r||"https://api.openai.com/v1",await this.plugin.saveSettings()}))}renderDeepgramSettings(e){this.debug("=== renderDeepgramSettings called ==="),this.debug("Container element:",e),this.debug("Container is connected:",e.isConnected),this.debug("Container children before:",e.children.length),e.empty();let t=e.createEl("div",{cls:"deepgram-settings-container"});this.debug("Deepgram container created:",t);try{let r=new De(this.plugin,t);this.debug("DeepgramSettings instance created"),r.render(),this.debug("DeepgramSettings.render() completed")}catch(r){console.error("Error rendering Deepgram settings:",r),t.createEl("p",{text:"Error loading Deepgram settings",cls:"mod-warning"})}this.debug("Container children after:",e.children.length),this.debug("=== renderDeepgramSettings completed ===")}renderWhisperApiKey(e){new b.Setting(e).setName("OpenAI API Key").setDesc("Enter your OpenAI API key for Whisper transcription").addText(t=>{t.setPlaceholder("sk-...").setValue(this.maskApiKey(this.plugin.settings.apiKey||"")).onChange(async r=>{r&&!r.includes("*")&&(this.plugin.settings.apiKey=r,this.plugin.settings.whisperApiKey=r,await this.plugin.saveSettings(),t.setValue(this.maskApiKey(r)),new b.Notice("OpenAI API key saved"))}),t.inputEl.type="password",t.inputEl.addEventListener("focus",()=>{this.plugin.settings.apiKey&&t.setValue(this.plugin.settings.apiKey)}),t.inputEl.addEventListener("blur",()=>{this.plugin.settings.apiKey&&t.setValue(this.maskApiKey(this.plugin.settings.apiKey))})})}renderDeepgramApiKey(e){new b.Setting(e).setName("Deepgram API Key").setDesc("Enter your Deepgram API key for transcription").addText(t=>{t.setPlaceholder("Enter Deepgram API key...").setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey||"")).onChange(async r=>{r&&!r.includes("*")&&(this.plugin.settings.deepgramApiKey=r,await this.plugin.saveSettings(),t.setValue(this.maskApiKey(r)),new b.Notice("Deepgram API key saved"))}),t.inputEl.type="password",t.inputEl.addEventListener("focus",()=>{this.plugin.settings.deepgramApiKey&&t.setValue(this.plugin.settings.deepgramApiKey)}),t.inputEl.addEventListener("blur",()=>{this.plugin.settings.deepgramApiKey&&t.setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey))})})}updateProviderInfo(e,t){e.empty();let r={auto:"\u{1F916} Intelligent selection between providers based on your configured strategy. Automatically chooses the best provider for each request.",whisper:"\u{1F3AF} OpenAI Whisper - High-quality transcription with support for multiple languages. Best for general-purpose transcription.",deepgram:"\u26A1 Deepgram - Fast, accurate transcription with advanced AI features. Best for real-time processing and speaker diarization."};e.createEl("p",{text:r[t]})}createGeneralSection(e){e.createEl("h3",{text:"General Settings"}),new b.Setting(e).setName("Language").setDesc("Primary language for transcription").addDropdown(t=>t.addOption("auto","Auto-detect").addOption("en","English").addOption("ko","\uD55C\uAD6D\uC5B4").addOption("ja","\u65E5\u672C\u8A9E").addOption("zh","\u4E2D\u6587").addOption("es","Espa\xF1ol").addOption("fr","Fran\xE7ais").addOption("de","Deutsch").setValue(this.plugin.settings.language||"auto").onChange(async r=>{this.plugin.settings.language=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Auto-insert transcription").setDesc("Automatically insert transcribed text into the active note").addToggle(t=>t.setValue(this.plugin.settings.autoInsert||!1).onChange(async r=>{this.plugin.settings.autoInsert=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Insert position").setDesc("Where to insert transcribed text").addDropdown(t=>t.addOption("cursor","At cursor position").addOption("end","At end of note").addOption("beginning","At beginning of note").setValue(this.plugin.settings.insertPosition||"cursor").onChange(async r=>{this.plugin.settings.insertPosition=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Show format options").setDesc("Show formatting options before inserting text").addToggle(t=>t.setValue(this.plugin.settings.showFormatOptions||!1).onChange(async r=>{this.plugin.settings.showFormatOptions=r,await this.plugin.saveSettings()}))}createAudioSection(e){e.createEl("h3",{text:"Audio Settings"});let t=this.plugin.settings.provider||"auto";(t==="whisper"||t==="auto")&&new b.Setting(e).setName("Whisper Model").setDesc("Select the Whisper model to use").addDropdown(r=>r.addOption("whisper-1","Whisper v1 (Default)").setValue(this.plugin.settings.model||"whisper-1").onChange(async i=>{this.plugin.settings.model=i,await this.plugin.saveSettings()})),new b.Setting(e).setName("Temperature").setDesc("Sampling temperature (0-1). Lower values make output more focused and deterministic").addText(r=>r.setPlaceholder("0.0").setValue(String(this.plugin.settings.temperature||0)).onChange(async i=>{let n=parseFloat(i);!isNaN(n)&&n>=0&&n<=1&&(this.plugin.settings.temperature=n,await this.plugin.saveSettings())})),new b.Setting(e).setName("Add timestamp").setDesc("Add timestamp to transcribed text").addToggle(r=>r.setValue(this.plugin.settings.addTimestamp||!1).onChange(async i=>{this.plugin.settings.addTimestamp=i,await this.plugin.saveSettings()}))}createAdvancedSection(e){e.createEl("h3",{text:"Advanced Settings"}),new b.Setting(e).setName("Enable cache").setDesc("Cache transcription results to avoid re-processing").addToggle(t=>t.setValue(this.plugin.settings.enableCache!==!1).onChange(async r=>{this.plugin.settings.enableCache=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Debug mode").setDesc("Enable debug logging in console").addToggle(t=>t.setValue(this.plugin.settings.debugMode||!1).onChange(async r=>{this.plugin.settings.debugMode=r,await this.plugin.saveSettings(),r&&new b.Notice("Debug mode enabled. Check console for logs.")})),new b.Setting(e).setName("Reset to defaults").setDesc("Reset all settings to their default values").addButton(t=>t.setButtonText("Reset").setWarning().onClick(async()=>{if(confirm("Are you sure you want to reset all settings to defaults?")){let{DEFAULT_SETTINGS:i}=await Promise.resolve().then(()=>(Le(),Qe));this.plugin.settings={...i},await this.plugin.saveSettings(),this.display(),new b.Notice("Settings reset to defaults")}}))}createSupportSection(e){e.createEl("hr",{cls:"speech-to-text-separator"}),e.createEl("h3",{text:"Support"}),e.createEl("p",{text:"Thank you for using Speech to Text! Your support helps keep this plugin free and actively maintained.",cls:"setting-item-description"}),new b.Setting(e).setName("Support Development").setDesc("If you find this plugin helpful, consider buying me a coffee \u2615").addButton(t=>t.setButtonText("\u2615 Buy me a coffee").setCta().onClick(()=>{window.open("https://buymeacoffee.com/asyouplz","_blank")}))}debug(...e){var t;(t=this.plugin.settings)!=null&&t.debugMode&&[...e]}maskApiKey(e){if(!e||e.length<10)return"";let t=7,r=4;if(e.length<=t+r)return e;let i="*".repeat(e.length-t-r);return e.substring(0,t)+i+e.substring(e.length-r)}};var We=require("obsidian");function Tt(o){return o instanceof We.TFile}function pt(o,e){if(!Tt(o)){let t=e?`[${e}] `:"";throw new Error(`${t}Expected a TFile instance.`)}}var xe=class extends v.Plugin{async onload(){this.logger=new z("SpeechToText"),this.logger.info("Loading Speech-to-Text plugin");try{await this.initializeServices(),this.registerCommands(),this.registerContextMenu(),this.addSettingTab(new Me(this.app,this)),this.logger.debug("SettingsTab added"),this.registerEventHandlers(),this.app.workspace.onLayoutReady(()=>{this.createStatusBarItem()}),new v.Notice("Speech-to-Text plugin loaded successfully")}catch(e){console.error("Failed to load Speech-to-Text plugin:",e),new v.Notice("Failed to load Speech-to-Text plugin. Check console for details.")}}onunload(){var e;(e=this.logger)==null||e.info("Unloading Speech-to-Text plugin"),this.cleanupEventHandlers(),this.cancelPendingOperations(),this.editorService&&this.editorService.destroy(),this.textInsertionHandler&&this.textInsertionHandler.destroy()}async initializeServices(){await this.loadSettings(),this.logger=new z("SpeechToText"),this.errorHandler=new me(this.logger),this.settingsManager=new pe(this),this.stateManager=new he,this.eventManager=new L,this.editorService=new ve(this.app,this.eventManager,this.logger),this.textInsertionHandler=new Ee(this.editorService,this.eventManager,this.logger),this.initializeTranscriberFactory(),this.initializeTranscriptionService()}initializeTranscriberFactory(){let e={load:async()=>(await this.loadSettings(),this.settings),save:async t=>{this.settings=t,await this.saveSettings()},get:t=>{var r,i;return t==="transcription"?{defaultProvider:this.settings.provider||"whisper",autoSelect:this.settings.provider==="auto",selectionStrategy:this.settings.selectionStrategy,fallbackEnabled:this.settings.fallbackStrategy!=="none",whisper:{enabled:!!this.settings.apiKey||!!this.settings.whisperApiKey,apiKey:this.settings.whisperApiKey||this.settings.apiKey},deepgram:{enabled:!!this.settings.deepgramApiKey,apiKey:this.settings.deepgramApiKey,model:this.settings.deepgramModel||"nova-2",features:(i=(r=this.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.features},abTest:{enabled:this.settings.abTestEnabled,trafficSplit:this.settings.abTestSplit},monitoring:{enabled:this.settings.metricsEnabled}}:t==="apiKey"?this.settings.apiKey:this.settings[t]},set:async(t,r)=>{var i,n;t==="transcription"?(r.defaultProvider&&(this.settings.provider=r.defaultProvider),(i=r.whisper)!=null&&i.apiKey&&(this.settings.whisperApiKey=r.whisper.apiKey),(n=r.deepgram)!=null&&n.apiKey&&(this.settings.deepgramApiKey=r.deepgram.apiKey)):this.settings[t]=r,await this.saveSettings()}};this.transcriberFactory=new ce(e,this.logger)}initializeTranscriptionService(){let e=this.settings.provider||"whisper",t;try{let r=this.transcriberFactory.getProvider(e==="auto"?"auto":e);t=new de(r,this.logger),this.logger.info(`Initialized transcription service with provider: ${r.getProviderName()}`)}catch(r){this.logger.warn("Failed to initialize transcriber from factory, using fallback",r);let i=this.settings.whisperApiKey||this.settings.apiKey;i?(t=new H(i,this.logger),this.logger.info("Initialized fallback WhisperService")):(t=null,this.logger.warn("No transcription service initialized - API key missing"))}if(t){let r=new ue(this.app.vault,this.logger);try{let n=this.transcriberFactory.getProvider(e==="auto"?"auto":e),s=n.getCapabilities();r.setProviderCapabilities({maxFileSize:s.maxFileSize}),this.logger.info("AudioProcessor configured with provider capabilities",{provider:n.getProviderName(),maxFileSize:s.maxFileSize/1024/1024+"MB"})}catch(n){this.logger.warn("Failed to get provider capabilities, using default limits",n)}let i=new ge(this.settings);this.transcriptionService=new Q(t,r,i,this.eventManager,this.logger,this.settings),this.logger.debug("TranscriptionService initialized successfully")}}registerContextMenu(){this.registerEvent(this.app.workspace.on("file-menu",(e,t)=>{if(!t||!(t instanceof v.TFile))return;["m4a","mp3","wav","mp4","webm","ogg"].includes(t.extension.toLowerCase())&&e.addItem(i=>{i.setTitle("Transcribe audio file").setIcon("microphone").onClick(async()=>{await this.transcribeFile(t)})})}))}registerCommands(){this.addCommand({id:"transcribe-audio-file",name:"Transcribe audio file",callback:()=>{this.showAudioFilePicker()}}),this.addCommand({id:"transcribe-from-clipboard",name:"Transcribe audio from clipboard",callback:async()=>{new v.Notice("Clipboard transcription not yet implemented")}}),this.addCommand({id:"show-format-options",name:"Show text formatting options",callback:()=>{this.showFormatOptions()}}),this.addCommand({id:"show-transcription-history",name:"Show transcription history",callback:()=>{new v.Notice("Transcription history not yet implemented")}}),this.addCommand({id:"cancel-transcription",name:"Cancel current transcription",callback:()=>{this.transcriptionService.cancel(),new v.Notice("Transcription cancelled")}}),this.addCommand({id:"undo-insertion",name:"Undo last text insertion",callback:async()=>{await this.editorService.undo()?new v.Notice("Text insertion undone"):new v.Notice("Nothing to undo")}}),this.addCommand({id:"redo-insertion",name:"Redo last text insertion",callback:async()=>{await this.editorService.redo()?new v.Notice("Text insertion redone"):new v.Notice("Nothing to redo")}})}registerEventHandlers(){this.eventManager.on("transcription:start",e=>{this.stateManager.setState({status:"processing"}),new v.Notice(`Transcribing: ${e.fileName}`)}),this.eventManager.on("transcription:complete",async e=>{var r;this.logger.debug("=== Transcription complete event received ===",{hasData:!!e,hasText:!!(e!=null&&e.text),textLength:((r=e==null?void 0:e.text)==null?void 0:r.length)||0,autoInsert:this.settings.autoInsert}),this.stateManager.setState({status:"completed"}),new v.Notice("Transcription completed successfully");let t=e.text;if(!t){this.logger.error("No text found in transcription complete event",void 0,{data:e}),new v.Notice("Transcription completed but no text was returned");return}this.settings.autoInsert?(this.logger.debug("Auto-inserting transcribed text",{textLength:t.length,textPreview:t.substring(0,100)}),await this.insertTranscriptionWithOptions(t)):this.logger.debug("Auto-insert disabled, text not inserted")}),this.eventManager.on("transcription:error",e=>{this.stateManager.setState({status:"error",error:e.error}),new v.Notice(`Transcription failed: ${e.error.message}`)}),this.eventManager.on("transcription:progress",e=>{this.stateManager.setState({progress:e.progress})}),this.eventManager.on("editor:text-inserted",e=>{this.logger.debug("Text inserted into editor",e)}),this.eventManager.on("editor:text-replaced",e=>{this.logger.debug("Text replaced in editor",e)})}cleanupEventHandlers(){this.eventManager.removeAllListeners()}cancelPendingOperations(){this.transcriptionService&&this.transcriptionService.cancel()}createStatusBarItem(){var e;try{if(!this.app.workspace){console.warn("Workspace not ready, skipping status bar creation");return}let t=this.addStatusBarItem();if(!t){console.warn("Failed to create status bar item");return}t.textContent="";let r=i=>{if(t)try{let n=i?String(i):"";t.textContent=n}catch(n){console.warn("Failed to update status bar text:",n)}};this.stateManager.subscribe(i=>{if(t)switch(i.status){case"idle":r("");break;case"processing":r("\u{1F399}\uFE0F Transcribing...");break;case"completed":r("\u2705 Transcription complete"),setTimeout(()=>{this.stateManager.getState().status==="completed"&&r("")},3e3);break;case"error":r("\u274C Transcription failed"),setTimeout(()=>{this.stateManager.getState().status==="error"&&r("")},3e3);break;default:r("");break}}),(e=this.logger)==null||e.debug("Status bar item created successfully")}catch(t){console.error("Error creating status bar item:",t)}}async showAudioFilePicker(){let e=this.app.vault.getFiles().filter(t=>t.extension==="m4a"||t.extension==="mp3"||t.extension==="wav"||t.extension==="mp4");if(e.length===0){new v.Notice("No audio files found in vault");return}new Ge(this.app,e,async t=>{await this.transcribeFile(t)}).open()}async transcribeFile(e){var t,r;pt(e,"SpeechToTextPlugin.transcribeFile");try{let i=this.settings.provider||"whisper",n=!1,s="";if(i==="whisper"?(n=!!(this.settings.apiKey||this.settings.whisperApiKey),s="Please configure your OpenAI API key in settings"):i==="deepgram"?(n=!!this.settings.deepgramApiKey,s="Please configure your Deepgram API key in settings"):i==="auto"&&(n=!!(this.settings.apiKey||this.settings.whisperApiKey||this.settings.deepgramApiKey),s="Please configure at least one API key (OpenAI or Deepgram) in settings"),!n){new v.Notice(s);return}if(!this.transcriptionService&&(this.initializeTranscriptionService(),!this.transcriptionService)){new v.Notice("Failed to initialize transcription service. Please check your API keys.");return}this.logger.debug("Starting transcription for file:",{fileName:e.name});let a=await this.transcriptionService.transcribe(e);if(this.logger.debug("Transcription result received:",{hasResult:!!a,hasText:!!(a!=null&&a.text),textLength:((t=a==null?void 0:a.text)==null?void 0:t.length)||0,textPreview:(r=a==null?void 0:a.text)==null?void 0:r.substring(0,100)}),!a||!a.text){this.logger.error("Transcription returned no text",void 0,{result:a}),new v.Notice("Transcription completed but no text was returned");return}this.settings.showFormatOptions?(this.logger.debug("Showing format options with text"),this.showFormatOptionsWithText(a.text)):(this.logger.debug("Inserting text directly without format options"),await this.insertTranscriptionWithOptions(a.text))}catch(i){this.errorHandler.handle(i)}}async insertTranscriptionWithOptions(e){this.logger.debug("=== insertTranscriptionWithOptions START ===",{textLength:(e==null?void 0:e.length)||0,textPreview:e==null?void 0:e.substring(0,100),insertPosition:this.settings.insertPosition,autoInsert:this.settings.autoInsert});let t={mode:this.settings.insertPosition==="cursor"?"cursor":this.settings.insertPosition==="end"?"append":this.settings.insertPosition==="beginning"?"prepend":"cursor",format:this.settings.textFormat||"plain",addTimestamp:this.settings.addTimestamp||!1,timestampFormat:this.settings.timestampFormat,language:this.settings.language,createNewNote:!this.editorService.hasActiveEditor()};this.logger.debug("Inserting text with options:",t),await this.textInsertionHandler.insertText(e,t)?(this.logger.info("Text successfully inserted"),new v.Notice("Transcription inserted successfully")):(this.logger.warn("TextInsertionHandler failed, using legacy method"),await this.insertTranscriptionLegacy(e))}async insertTranscriptionLegacy(e){let t=this.app.workspace.getActiveViewOfType(v.MarkdownView);if(!t){new v.Notice("No active editor found. Opening new note...");let n=await this.app.vault.create(`Transcription ${new Date().toISOString()}.md`,e);await this.app.workspace.openLinkText(n.path,"",!0);return}let r=t.editor;switch(this.settings.insertPosition){case"cursor":r.replaceSelection(e);break;case"end":let n=r.lastLine(),s=r.getLine(n);r.setLine(n,s+` +*Transcribed at {{datetime}}*`}]}onClose(){let{contentEl:t}=this;t.empty()}};var b=require("obsidian");var A=require("obsidian");var F="[Deepgram]",N={DEBUG:"debug",INFO:"info",WARN:"warn",ERROR:"error"},d={CLASSES:{API_KEY_INPUT:"deepgram-api-key-input",MODEL_INFO:"deepgram-model-info",MODEL_DESCRIPTION:"model-description",MODEL_METRICS:"model-metrics",SUPPORTED_LANGUAGES:"supported-languages",FEATURES_CONTAINER:"deepgram-features",ADVANCED_CONTAINER:"deepgram-advanced",COST_ESTIMATION:"deepgram-cost-estimation",COST_DETAILS:"cost-details",WARNING:"mod-warning",ERROR_DETAILS:"error-details",SETTING_DESCRIPTION:"setting-item-description"},MESSAGES:{HEADER:"Deepgram Configuration",DESCRIPTION:"Configure Deepgram for advanced speech recognition with multiple language support and AI features.",REGISTRY_WARNING:"\u26A0\uFE0F Model registry not available. Using default configuration.",API_KEY_LABEL:"Deepgram API Key",API_KEY_DESC:"Enter your Deepgram API key for transcription",API_KEY_PLACEHOLDER:"Enter API key...",API_KEY_SAVED:"Deepgram API key saved",API_KEY_REQUIRED:"Please enter your Deepgram API key first",MODEL_LABEL:"Deepgram Model",MODEL_DESC:"Select the Deepgram model for transcription",MODEL_PLACEHOLDER:"Select a model...",FEATURES_HEADER:"Features",ADVANCED_HEADER:"Advanced Settings",COST_HEADER:"Cost Estimation",VALIDATION_LABEL:"Validate Configuration",VALIDATION_DESC:"Test your Deepgram API key and settings",VALIDATION_BUTTON:"Validate",VALIDATING:"Validating...",VALIDATION_SUCCESS:"\u2705 Deepgram configuration is valid",VALIDATION_ERROR:"\u274C Invalid Deepgram API key or configuration",FALLBACK_ERROR_TITLE:"\u26A0\uFE0F Deepgram Settings Error",FALLBACK_ERROR_DESC:"Unable to load full configuration. Basic settings are available below.",CRITICAL_ERROR:"Deepgram settings could not be loaded. Please check the console for errors."},STYLES:{WARNING_BOX:"deepgram-warning-box",INFO_CONTAINER:"deepgram-info-container",METRICS_ROW:"deepgram-metrics-row",LANGUAGES_ROW:"deepgram-languages-row",COST_CONTAINER:"deepgram-cost-container",ERROR_CONTAINER:"deepgram-error-container",ERROR_DETAILS:"deepgram-error-details",DESCRIPTION_MARGIN:"deepgram-description"}},U={ENDPOINTS:{VALIDATION:"https://api.deepgram.com/v1/projects"},HEADERS:{AUTHORIZATION_PREFIX:"Token",CONTENT_TYPE:"application/json"},METHODS:{GET:"GET",POST:"POST"},MASK:{VISIBLE_START:8,VISIBLE_END:4,CHAR:"*"},TIMEOUT:{MIN:5e3,MAX:12e4}},k={TIMEOUT:{MIN:5e3,MAX:12e4,DEFAULT:3e4},RETRIES:{MIN:0,MAX:3,DEFAULT:3},COST_ESTIMATION:{DAILY_MINUTES:10,DAYS_PER_MONTH:30},VALIDATION_RESET_DELAY:3e3},ot=[{value:"auto",label:"Auto-detect"},{value:"en",label:"English"},{value:"es",label:"Spanish"},{value:"fr",label:"French"},{value:"de",label:"German"},{value:"pt",label:"Portuguese"},{value:"nl",label:"Dutch"},{value:"it",label:"Italian"},{value:"pl",label:"Polish"},{value:"ru",label:"Russian"},{value:"zh",label:"Chinese"},{value:"ja",label:"Japanese"},{value:"ko",label:"Korean"},{value:"ar",label:"Arabic"},{value:"hi",label:"Hindi"}],lt=[{id:"nova-3",name:"Nova 3",tier:"Premium",price:.0043},{id:"nova-2",name:"Nova 2",tier:"Premium",price:.0059},{id:"nova",name:"Nova",tier:"Standard",price:.0025},{id:"enhanced",name:"Enhanced",tier:"Standard",price:.0145},{id:"base",name:"Base",tier:"Economy",price:.0125}],ct=[{key:"punctuation",name:"Punctuation",description:"Add punctuation to transcript",default:!0},{key:"smartFormat",name:"Smart Format",description:"Format numbers, dates, etc.",default:!0},{key:"diarization",name:"Speaker Diarization",description:"Identify different speakers",default:!0},{key:"numerals",name:"Numerals",description:"Convert numbers to digits",default:!1}];var O=class o{constructor(){this.enabled=!0;this.minLevel=N.INFO}static getInstance(){return o.instance||(o.instance=new o),o.instance}setEnabled(e){this.enabled=e}setMinLevel(e){this.minLevel=e}debug(e,...t){this.shouldLog(N.DEBUG)&&(`${F}${e}`,[...t])}info(e,...t){this.shouldLog(N.INFO)&&console.info(`${F} ${e}`,...t)}warn(e,...t){this.shouldLog(N.WARN)&&console.warn(`${F} ${e}`,...t)}error(e,t){this.shouldLog(N.ERROR)&&(console.error(`${F} ${e}`),t&&(t instanceof Error?console.error(`${F} Error details:`,{message:t.message,stack:t.stack}):console.error(`${F} Error details:`,t)))}group(e){this.enabled&&console.group(`${F} ${e}`)}groupEnd(){this.enabled&&console.groupEnd()}shouldLog(e){if(!this.enabled)return!1;let t=[N.DEBUG,N.INFO,N.WARN,N.ERROR],r=t.indexOf(e),i=t.indexOf(this.minLevel);return r>=i}time(e){this.enabled&&console.time(`${F} ${e}`)}timeEnd(e){this.enabled&&console.timeEnd(`${F} ${e}`)}};var dt={models:{"nova-3":{id:"nova-3",name:"Nova-3",description:"Next-generation model with state-of-the-art accuracy and enhanced diarization",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0,advancedDiarization:!0,emotionDetection:!0,speakerIdentification:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi","tr","sv","da","no","fi","cs","hu","bg"],performance:{accuracy:98,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"},isDefault:!0,migrationPath:{from:["nova-2","nova"],autoMigrate:!0,backwardCompatible:!0}},"nova-2":{id:"nova-2",name:"Nova-2",description:"Latest and most powerful model with best accuracy",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi","tr","sv","da","no","fi"],performance:{accuracy:95,speed:"fast",latency:"low"},pricing:{perMinute:.0145,currency:"USD"}},nova:{id:"nova",name:"Nova",description:"High-quality model with excellent accuracy",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!1,utterances:!0,summarization:!1},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko"],performance:{accuracy:90,speed:"fast",latency:"low"},pricing:{perMinute:.0125,currency:"USD"}},enhanced:{id:"enhanced",name:"Enhanced",description:"Balanced model for general use",tier:"basic",features:{punctuation:!0,smartFormat:!0,diarization:!1,numerals:!0,profanityFilter:!0,redaction:!1,utterances:!1,summarization:!1},languages:["en","es","fr","de","pt"],performance:{accuracy:85,speed:"moderate",latency:"medium"},pricing:{perMinute:.0085,currency:"USD"}},base:{id:"base",name:"Base",description:"Basic model for simple transcription",tier:"economy",features:{punctuation:!0,smartFormat:!1,diarization:!1,numerals:!1,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:80,speed:"moderate",latency:"medium"},pricing:{perMinute:.0059,currency:"USD"}}},features:{punctuation:{name:"Punctuation",description:"Add punctuation marks to transcript",default:!0},smartFormat:{name:"Smart Format",description:"Apply intelligent formatting (numbers, dates, etc.)",default:!0},diarization:{name:"Speaker Diarization",description:"Identify different speakers in audio",default:!0,requiresPremium:!0},numerals:{name:"Numerals",description:"Convert number words to digits",default:!0},profanityFilter:{name:"Profanity Filter",description:"Filter profane words",default:!1},redaction:{name:"Redaction",description:"Redact sensitive information (SSN, credit cards)",default:!1,requiresPremium:!0},utterances:{name:"Utterances",description:"Split transcript by natural speech boundaries",default:!1},summarization:{name:"Summarization",description:"Generate summary of transcript",default:!1,requiresPremium:!0}}};var Se={models:{"nova-3":{id:"nova-3",name:"Nova 3",description:"Latest premium model with higher accuracy and improved diarization",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi"],performance:{accuracy:98,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"}},"nova-2":{id:"nova-2",name:"Nova 2",description:"Most accurate and powerful model with advanced features",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi"],performance:{accuracy:95,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"}},nova:{id:"nova",name:"Nova",description:"Balanced model with good accuracy and speed",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!1,utterances:!0,summarization:!1},languages:["en","es","fr","de","pt","nl","it"],performance:{accuracy:90,speed:"fast",latency:"low"},pricing:{perMinute:.0025,currency:"USD"}},enhanced:{id:"enhanced",name:"Enhanced",description:"Enhanced accuracy for challenging audio",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!1,numerals:!0,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:85,speed:"moderate",latency:"medium"},pricing:{perMinute:.0145,currency:"USD"}},base:{id:"base",name:"Base",description:"Cost-effective option for simple transcription",tier:"economy",features:{punctuation:!0,smartFormat:!1,diarization:!1,numerals:!1,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:80,speed:"moderate",latency:"medium"},pricing:{perMinute:.0125,currency:"USD"}}},features:{punctuation:{name:"Punctuation",description:"Add punctuation marks to transcript",default:!0,requiresPremium:!1},smartFormat:{name:"Smart Format",description:"Format numbers, dates, and other entities",default:!0,requiresPremium:!1},diarization:{name:"Speaker Diarization",description:"Identify different speakers",default:!1,requiresPremium:!1},numerals:{name:"Numerals",description:"Convert numbers to digits",default:!1,requiresPremium:!1},profanityFilter:{name:"Profanity Filter",description:"Filter out profanity from transcript",default:!1,requiresPremium:!1},redaction:{name:"Redaction",description:"Redact sensitive information",default:!1,requiresPremium:!0},utterances:{name:"Utterances",description:"Split transcript into utterances",default:!1,requiresPremium:!1},summarization:{name:"Summarization",description:"Generate summary of transcript",default:!1,requiresPremium:!0}}},ut,Et=(ut=dt)!=null?ut:Se,Ae=class o{constructor(){this.models=new Map,this.features=new Map,this.logger=O.getInstance();try{this.loadConfiguration(),this.logger.info("Constructor completed successfully")}catch(e){this.logger.error("Error during initialization",e)}}static getInstance(){try{return o.instance||(o.instance=new o),o.instance}catch(e){if(!o.instance){let t=Object.create(o.prototype);t.models=new Map,t.features=new Map,t.logger=O.getInstance(),t.logger.error("Failed to create instance, using fallback",e),o.instance=t}return o.instance}}loadConfiguration(){try{let e=Et||Se;this.loadModels(e),this.loadFeatures(e),this.models.size===0&&this.features.size===0&&(this.logger.warn("No data loaded, loading fallback configuration"),this.loadFallbackConfiguration())}catch(e){this.logger.error("Error loading configuration",e),this.loadFallbackConfiguration()}}loadModels(e){if(!e.models||typeof e.models!="object"){this.logger.warn("No models in configuration");return}Object.entries(e.models).forEach(([t,r])=>{try{this.isValidModel(r)?this.models.set(t,r):this.logger.warn(`Invalid model structure for ${t}`)}catch(i){this.logger.error(`Failed to load model ${t}`,i)}}),this.logger.info(`Loaded ${this.models.size} models`)}loadFeatures(e){if(!e.features||typeof e.features!="object"){this.logger.warn("No features in configuration");return}Object.entries(e.features).forEach(([t,r])=>{try{this.isValidFeature(r)?this.features.set(t,r):this.logger.warn(`Invalid feature structure for ${t}`)}catch(i){this.logger.error(`Failed to load feature ${t}`,i)}}),this.logger.info(`Loaded ${this.features.size} features`)}loadFallbackConfiguration(){try{Object.entries(Se.models).forEach(([e,t])=>{this.models.set(e,t)}),Object.entries(Se.features).forEach(([e,t])=>{this.features.set(e,t)}),this.logger.info("Fallback configuration loaded")}catch(e){this.logger.error("Failed to load fallback configuration",e)}}isValidModel(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.id=="string"&&typeof t.name=="string"&&t.features!==void 0&&Array.isArray(t.languages)&&typeof t.performance=="object"&&typeof t.pricing=="object"}isValidFeature(e){if(!e||typeof e!="object")return!1;let t=e;return typeof t.name=="string"&&typeof t.description=="string"&&typeof t.default=="boolean"}getAllModels(){try{return Array.from(this.models.values())}catch(e){return this.logger.error("Error getting all models",e),[]}}getModel(e){return this.models.get(e)}getAllFeatures(){try{return this.features}catch(e){return this.logger.error("Error getting all features",e),new Map}}getFeature(e){return this.features.get(e)}isLanguageSupported(e,t){let r=this.models.get(e);return r?r.languages.includes(t):!1}isFeatureSupported(e,t){let r=this.models.get(e);return r?r.features[t]===!0:!1}getModelsByLanguage(e){return Array.from(this.models.values()).filter(t=>t.languages.includes(e))}getModelsByTier(e){return Array.from(this.models.values()).filter(t=>t.tier===e)}getModelsByPriceRange(e){return Array.from(this.models.values()).filter(t=>t.pricing.perMinute<=e)}calculateCost(e,t){let r=this.models.get(e);return r?r.pricing.perMinute*t:0}getPerformanceScore(e){let t=this.models.get(e);if(!t)return 0;let r=t.performance.accuracy;return t.performance.speed==="fast"?r+=5:t.performance.speed==="moderate"&&(r+=2),t.performance.latency==="high"?r-=5:t.performance.latency==="medium"&&(r-=2),Math.min(100,Math.max(0,r))}getRecommendedModel(e){let t=Array.from(this.models.values()),{language:r,maxPrice:i,minAccuracy:n,requiredFeatures:s}=e;return r&&(t=t.filter(a=>a.languages.includes(r))),i!==void 0&&(t=t.filter(a=>a.pricing.perMinute<=i)),n!==void 0&&(t=t.filter(a=>a.performance.accuracy>=n)),s&&s.length>0&&(t=t.filter(a=>s.every(l=>a.features[l]===!0))),t.length>0?(t.sort((a,l)=>this.getPerformanceScore(l.id)-this.getPerformanceScore(a.id)),t[0]):null}validateModel(e){let t=[],r=this.models.get(e);return r?(r.id||t.push("Model ID is missing"),r.name||t.push("Model name is missing"),r.tier||t.push("Model tier is missing"),(!r.languages||r.languages.length===0)&&t.push("Model must support at least one language"),r.pricing.perMinute<0&&t.push("Model pricing cannot be negative"),(r.performance.accuracy<0||r.performance.accuracy>100)&&t.push("Model accuracy must be between 0 and 100"),{valid:t.length===0,errors:t}):(t.push(`Model '${e}' not found`),{valid:!1,errors:t})}};var we=class{constructor(e){this.containerEl=e}createHeader(e){return this.containerEl.createEl("h4",{text:e})}createDescription(e){let t=this.containerEl.createEl("p",{text:e,cls:d.CLASSES.SETTING_DESCRIPTION});return t.addClass(d.STYLES.DESCRIPTION_MARGIN),t}createWarning(e){let t=this.containerEl.createEl("div",{cls:d.CLASSES.WARNING,text:e});return t.addClass(d.STYLES.WARNING_BOX),t}createModelInfoCard(e){this.removeElement(`.${d.CLASSES.MODEL_INFO}`);let t=this.containerEl.createEl("div",{cls:d.CLASSES.MODEL_INFO});return t.addClass(d.STYLES.INFO_CONTAINER),t.createEl("p",{text:e.description,cls:d.CLASSES.MODEL_DESCRIPTION}),this.createMetricsRow(t,e),this.createLanguagesRow(t,e),t}createMetricsRow(e,t){let r=e.createEl("div",{cls:d.CLASSES.MODEL_METRICS});r.addClass(d.STYLES.METRICS_ROW),r.createEl("span",{text:`Accuracy: ${t.performance.accuracy}%`}),r.createEl("span",{text:`Speed: ${t.performance.speed}`}),r.createEl("span",{text:`Latency: ${t.performance.latency}`})}createLanguagesRow(e,t){let r=e.createEl("div",{cls:d.CLASSES.SUPPORTED_LANGUAGES});r.addClass(d.STYLES.LANGUAGES_ROW),r.createEl("span",{text:`Supported languages: ${t.languages.join(", ")}`})}createCostEstimationContainer(){let e=this.containerEl.createEl("div",{cls:d.CLASSES.COST_ESTIMATION});return e.addClass(d.STYLES.COST_CONTAINER),e.createEl("h5",{text:d.MESSAGES.COST_HEADER}),e}updateCostDetails(e,t,r){let i=e.querySelector(`.${d.CLASSES.COST_DETAILS}`)||e.createEl("div",{cls:d.CLASSES.COST_DETAILS});if(i.empty(),!t){i.createEl("p",{text:"Select a model to see cost estimation",cls:d.CLASSES.WARNING});return}let n=i.createEl("div");if(n.createEl("p",{text:`Cost per minute: $${t.pricing.perMinute}`}),r!==void 0){let s=k.COST_ESTIMATION.DAILY_MINUTES;n.createEl("p",{text:`Estimated monthly cost (${s} min/day): $${r.toFixed(2)}`})}}addBudgetWarning(e,t,r){if(t>r){let i=e.querySelector(".budget-warning")||e.createEl("p",{cls:"budget-warning"});i.textContent=`\u26A0\uFE0F Exceeds monthly budget of $${r}`,i.classList.add(d.CLASSES.WARNING)}}createErrorContainer(e){let t=this.containerEl.createEl("div",{cls:d.CLASSES.WARNING});if(t.addClass(d.STYLES.ERROR_CONTAINER),t.createEl("h5",{text:d.MESSAGES.FALLBACK_ERROR_TITLE}),t.createEl("p",{text:d.MESSAGES.FALLBACK_ERROR_DESC}),e instanceof Error){let r=t.createEl("details");r.createEl("summary",{text:"Error details"}),r.createEl("pre",{text:e.message,cls:d.CLASSES.ERROR_DETAILS}).addClass(d.STYLES.ERROR_DETAILS)}return t}createSection(e,t){let r=this.containerEl.createEl("div",{cls:e});return t&&r.createEl("h5",{text:t}),r}removeElement(e){let t=this.containerEl.querySelector(e);t&&t.remove()}clearContainer(){this.containerEl.empty()}};var gt=require("obsidian");var Ce=class{constructor(){this.logger=O.getInstance()}async validateApiKey(e){if(!e)return this.logger.warn("API key validation failed: No key provided"),!1;try{this.logger.info("Validating API key via Obsidian requestUrl...");let t={url:U.ENDPOINTS.VALIDATION,method:U.METHODS.GET,headers:{Authorization:`${U.HEADERS.AUTHORIZATION_PREFIX} ${e}`,"Content-Type":U.HEADERS.CONTENT_TYPE},throw:!1},r=await(0,gt.requestUrl)(t),i=r.status===200;return i?this.logger.info("API key validation successful"):this.logger.warn(`API key validation failed with status: ${r.status}`),i}catch(t){return this.logger.error("API validation error (requestUrl)",t),!1}}maskApiKey(e){if(!e||e.length<10)return"";let{VISIBLE_START:t,VISIBLE_END:r,CHAR:i}=U.MASK;if(e.length<=t+r)return e;let n=i.repeat(e.length-t-r);return e.substring(0,t)+n+e.substring(e.length-r)}validateTimeout(e){let t=parseInt(e)*1e3,{MIN:r,MAX:i}=U.TIMEOUT;return isNaN(t)||ti?(this.logger.warn(`Invalid timeout value: ${e}`),null):t}validateRetries(e){let t=parseInt(e),{MIN:r,MAX:i}=k.RETRIES;return isNaN(t)||ti?(this.logger.warn(`Invalid retries value: ${e}`),null):t}};var Ie=class{constructor(){this.logger=O.getInstance()}calculateEstimation(e,t){if(!e)return this.logger.debug("No model selected for cost calculation"),null;let{DAILY_MINUTES:r,DAYS_PER_MONTH:i}=k.COST_ESTIMATION,n=e.pricing.perMinute,s=n*r,a=s*i,l=t?a>t:!1;return this.logger.debug(`Cost calculated for ${e.name}:`,{perMinute:n,daily:s,monthly:a,exceeedsBudget:l}),{perMinute:n,daily:s,monthly:a,exceeedsBudget:l}}calculateCostByUsage(e,t){let r=e.pricing.perMinute*t;return this.logger.debug(`Usage cost calculated: ${t} minutes = $${r}`),r}calculateAvailableMinutes(e,t){let r=t/e.pricing.perMinute;return this.logger.debug(`Available minutes for budget $${t}: ${r.toFixed(2)}`),r}compareModelCosts(e,t){let r=new Map;return e.forEach(i=>{let n=this.calculateCostByUsage(i,t);r.set(i.id,n)}),r}calculateEfficiencyScore(e,t){if(e.pricing.perMinute>t)return 0;let r=1-e.pricing.perMinute/t,n=(e.performance.accuracy/100*.7+r*.3)*100;return this.logger.debug(`Efficiency score for ${e.name}: ${n.toFixed(2)}`),Math.round(n)}};var De=class{constructor(e,t){this.registry=null;this.selectedModel=null;this.estimatedCostEl=null;this.plugin=e,this.containerEl=t,this.logger=O.getInstance(),this.uiBuilder=new we(t),this.validator=new Ce,this.costCalculator=new Ie,this.initializeRegistry()}initializeRegistry(){try{this.logger.info("Attempting to initialize DeepgramModelRegistry..."),this.registry=Ae.getInstance();let e=this.registry.getAllModels();this.logger.info(`Registry initialized successfully with ${e.length} models`),e.length===0&&(this.logger.warn("Registry has no models, will use fallback"),this.registry=null)}catch(e){this.logger.error("Failed to initialize registry",e),this.registry=null,this.logger.info("Will continue with fallback UI")}}render(){this.logger.group("render()"),this.logRenderState();try{this.uiBuilder.clearContainer(),this.renderHeader(),this.renderSections(),this.logger.info(`Total elements created: ${this.containerEl.children.length}`),this.logger.groupEnd()}catch(e){this.logger.error("Critical error in render()",e),this.renderFallbackUI(e)}}logRenderState(){this.logger.debug("Container element:",this.containerEl),this.logger.debug("Container is connected:",this.containerEl.isConnected),this.logger.debug("Registry available:",!!this.registry),this.logger.debug("API key exists:",!!this.plugin.settings.deepgramApiKey),this.containerEl.isConnected||this.logger.warn("Container is not connected to DOM, attempting to render anyway"),this.registry||this.logger.warn("Registry not available, using fallback UI")}renderHeader(){this.uiBuilder.createHeader(d.MESSAGES.HEADER),this.uiBuilder.createDescription(d.MESSAGES.DESCRIPTION),this.registry||this.uiBuilder.createWarning(d.MESSAGES.REGISTRY_WARNING)}renderSections(){this.logger.info("Rendering API key section..."),this.renderApiKeySection(),this.logger.info("Rendering model selection..."),this.renderModelSelection(),this.logger.info("Rendering feature toggles..."),this.renderFeatureToggles(),this.logger.info("Rendering advanced settings..."),this.renderAdvancedSettings(),this.logger.info("Rendering cost estimation..."),this.renderCostEstimation(),this.logger.info("Rendering validation button..."),this.renderValidationButton()}renderApiKeySection(){new A.Setting(this.containerEl).setName(d.MESSAGES.API_KEY_LABEL).setDesc(d.MESSAGES.API_KEY_DESC).addText(e=>{this.setupApiKeyInput(e)})}setupApiKeyInput(e){let t=this.plugin.settings.deepgramApiKey||"";e.setPlaceholder(d.MESSAGES.API_KEY_PLACEHOLDER).setValue(this.validator.maskApiKey(t)).onChange(async r=>{await this.handleApiKeyChange(r,e)}),e.inputEl.type="password",e.inputEl.addClass(d.CLASSES.API_KEY_INPUT),this.attachApiKeyEventListeners(e)}async handleApiKeyChange(e,t){e&&!e.includes("*")&&(this.plugin.settings.deepgramApiKey=e,await this.plugin.saveSettings(),t.setValue(this.validator.maskApiKey(e)),new A.Notice(d.MESSAGES.API_KEY_SAVED),this.updateUIState())}attachApiKeyEventListeners(e){e.inputEl.addEventListener("focus",()=>{this.plugin.settings.deepgramApiKey&&e.setValue(this.plugin.settings.deepgramApiKey)}),e.inputEl.addEventListener("blur",()=>{this.plugin.settings.deepgramApiKey&&e.setValue(this.validator.maskApiKey(this.plugin.settings.deepgramApiKey))})}renderModelSelection(){let e=new A.Setting(this.containerEl).setName(d.MESSAGES.MODEL_LABEL).setDesc(d.MESSAGES.MODEL_DESC),t=e.addDropdown(r=>(this.populateModelDropdown(r),this.setupModelDropdownHandlers(r),r));this.disableIfNoApiKey(e)}populateModelDropdown(e){if(e.addOption("",d.MESSAGES.MODEL_PLACEHOLDER),!this.registry){this.logger.warn("Registry not available, using default models"),this.addDefaultModelOptions(e);return}try{let t=this.registry.getAllModels();t.length===0?(this.logger.warn("No models in registry, using defaults"),this.addDefaultModelOptions(e)):(this.addModelOptions(e,t),this.logger.info(`Added ${t.length} models to dropdown`))}catch(t){this.logger.error("Error loading models",t),this.addDefaultModelOptions(e)}}addModelOptions(e,t){t.forEach(r=>{let i=this.formatModelOption(r);e.addOption(r.id,i)})}formatModelOption(e){return`${e.name} (${e.tier}) - $${e.pricing.perMinute}/min`}setupModelDropdownHandlers(e){var r,i;let t=((i=(r=this.plugin.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.model)||"";e.setValue(t),e.onChange(async n=>{await this.handleModelChange(n)})}async handleModelChange(e){var t;if(!e){this.selectedModel=null;return}this.selectedModel=((t=this.registry)==null?void 0:t.getModel(e))||null,await this.saveModelSelection(e),this.updateUIAfterModelChange(),this.selectedModel&&new A.Notice(`Selected model: ${this.selectedModel.name}`)}async saveModelSelection(e){this.plugin.settings.transcription||(this.plugin.settings.transcription={}),this.plugin.settings.transcription.deepgram?this.plugin.settings.transcription.deepgram.model=e:this.plugin.settings.transcription.deepgram={enabled:!0,model:e},await this.plugin.saveSettings()}updateUIAfterModelChange(){this.updateModelInfo(),this.updateFeatureAvailability(),this.updateCostEstimation()}disableIfNoApiKey(e){if(!this.plugin.settings.deepgramApiKey){let t=e.settingEl.querySelector("select");t&&(t.disabled=!0),e.setDesc(d.MESSAGES.API_KEY_REQUIRED)}}updateModelInfo(){this.selectedModel&&this.uiBuilder.createModelInfoCard(this.selectedModel)}renderFeatureToggles(){let e=this.uiBuilder.createSection(d.CLASSES.FEATURES_CONTAINER,d.MESSAGES.FEATURES_HEADER);if(!this.registry){this.renderDefaultFeatures(e);return}this.registry.getAllFeatures().forEach((r,i)=>{this.renderFeatureToggle(e,r,i)})}renderFeatureToggle(e,t,r){let i=new A.Setting(e).setName(t.name).setDesc(this.getFeatureDescription(t));i.addToggle(n=>{let s=this.getFeatureValue(r,t.default);return n.setValue(s).onChange(async a=>{await this.saveFeatureSetting(r,a),this.updateCostEstimation()}),this.updateFeatureAvailabilityForToggle(n,i,t,r),n})}getFeatureDescription(e){return e.requiresPremium?`${e.description} (Premium feature)`:e.description}getFeatureValue(e,t){var i,n,s;let r=(n=(i=this.plugin.settings.transcription)==null?void 0:i.deepgram)==null?void 0:n.features;return(s=r==null?void 0:r[e])!=null?s:t}async saveFeatureSetting(e,t){this.ensureTranscriptionSettings(),this.plugin.settings.transcription.deepgram.features||(this.plugin.settings.transcription.deepgram.features={});let r=this.plugin.settings.transcription.deepgram.features;r[e]=t,await this.plugin.saveSettings()}ensureTranscriptionSettings(){this.plugin.settings.transcription||(this.plugin.settings.transcription={}),this.plugin.settings.transcription.deepgram||(this.plugin.settings.transcription.deepgram={enabled:!0})}updateFeatureAvailabilityForToggle(e,t,r,i){this.selectedModel&&this.registry&&!this.registry.isFeatureSupported(this.selectedModel.id,i)&&(e.setDisabled(!0),t.setDesc(`${r.description} (Not supported by selected model)`))}renderAdvancedSettings(){let e=this.uiBuilder.createSection(d.CLASSES.ADVANCED_CONTAINER,d.MESSAGES.ADVANCED_HEADER);this.renderLanguagePreference(e),this.renderTimeoutSetting(e),this.renderRetrySetting(e),this.renderChunkingSettings(e)}renderLanguagePreference(e){new A.Setting(e).setName("Preferred Language").setDesc("Set preferred language for better accuracy").addDropdown(t=>{ot.forEach(r=>{t.addOption(r.value,r.label)}),t.setValue(this.plugin.settings.language||"auto"),t.onChange(async r=>{this.plugin.settings.language=r,await this.plugin.saveSettings()})})}renderTimeoutSetting(e){new A.Setting(e).setName("Request Timeout").setDesc("Maximum time to wait for transcription (in seconds)").addText(t=>{let r=this.plugin.settings.requestTimeout||k.TIMEOUT.DEFAULT;t.setPlaceholder("30").setValue(String(r/1e3)).onChange(async i=>{let n=this.validator.validateTimeout(i);n!==null&&(this.plugin.settings.requestTimeout=n,await this.plugin.saveSettings())})})}renderRetrySetting(e){new A.Setting(e).setName("Max Retries").setDesc("Number of retry attempts on failure").addDropdown(t=>{for(let i=0;i<=k.RETRIES.MAX;i++){let n=i===0?"No retries":`${i} ${i===1?"retry":"retries"}`;t.addOption(String(i),n)}let r=this.plugin.settings.maxRetries||k.RETRIES.DEFAULT;t.setValue(String(r)),t.onChange(async i=>{this.plugin.settings.maxRetries=parseInt(i),await this.plugin.saveSettings()})})}renderChunkingSettings(e){new A.Setting(e).setName("Automatic File Chunking").setDesc("Automatically split large audio files (>50MB) into smaller chunks for reliable processing").addToggle(s=>{var a;s.setValue((a=this.plugin.settings.autoChunking)!=null?a:!0).onChange(async l=>{this.plugin.settings.autoChunking=l,await this.plugin.saveSettings();let c=e.querySelector(".chunk-size-setting");c&&c.classList.toggle("sn-hidden",!l)})});let t=new A.Setting(e).setName("Maximum Chunk Size").setDesc("Maximum size per chunk in MB (recommended: 50MB)").addSlider(s=>{var a;s.setLimits(10,100,10).setValue((a=this.plugin.settings.maxChunkSizeMB)!=null?a:50).setDynamicTooltip().onChange(async l=>{this.plugin.settings.maxChunkSizeMB=l,await this.plugin.saveSettings()})});t.settingEl.addClass("chunk-size-setting"),this.plugin.settings.autoChunking||t.settingEl.addClass("sn-hidden");let r=e.createDiv();r.addClass("setting-item-description"),r.addClass("deepgram-note"),r.createEl("strong",{text:"Note on Large Files:"});let i=r.createEl("ul");["Files larger than 50MB may experience timeout errors","Auto-chunking splits files into manageable pieces","Each chunk is processed separately and results are merged"].forEach(s=>{i.createEl("li",{text:s})}),r.createEl("p",{text:"For best results with very large files (>100MB), consider:"});let n=r.createEl("ul");["Using the 'enhanced' model for faster processing","Reducing audio bitrate to 64-128 kbps","Converting to efficient formats (MP3, OGG)"].forEach(s=>{n.createEl("li",{text:s})})}renderCostEstimation(){let e=this.uiBuilder.createCostEstimationContainer();this.estimatedCostEl=e.createEl("div",{cls:d.CLASSES.COST_DETAILS}),this.updateCostEstimation()}updateCostEstimation(){if(!this.estimatedCostEl)return;let e=this.costCalculator.calculateEstimation(this.selectedModel,this.plugin.settings.monthlyBudget);if(!e){this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,null);return}this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,this.selectedModel,e.monthly),e.exceeedsBudget&&this.plugin.settings.monthlyBudget&&this.uiBuilder.addBudgetWarning(this.estimatedCostEl.parentElement,e.monthly,this.plugin.settings.monthlyBudget)}renderValidationButton(){new A.Setting(this.containerEl).setName(d.MESSAGES.VALIDATION_LABEL).setDesc(d.MESSAGES.VALIDATION_DESC).addButton(e=>{this.setupValidationButton(e)})}setupValidationButton(e){e.setButtonText(d.MESSAGES.VALIDATION_BUTTON).setCta().onClick(async()=>{await this.handleValidation(e)})}async handleValidation(e){e.setDisabled(!0),e.setButtonText(d.MESSAGES.VALIDATING);try{if(await this.validator.validateApiKey(this.plugin.settings.deepgramApiKey||""))this.handleValidationSuccess(e);else throw new Error("Invalid API key")}catch(t){this.handleValidationError(e,t)}}handleValidationSuccess(e){new A.Notice(d.MESSAGES.VALIDATION_SUCCESS),e.setButtonText("Valid \u2713"),e.removeCta(),setTimeout(()=>{e.setButtonText(d.MESSAGES.VALIDATION_BUTTON),e.setCta(),e.setDisabled(!1)},k.VALIDATION_RESET_DELAY)}handleValidationError(e,t){this.logger.error("Validation error",t),new A.Notice(d.MESSAGES.VALIDATION_ERROR),e.setButtonText(d.MESSAGES.VALIDATION_BUTTON),e.setWarning(),e.setDisabled(!1)}updateUIState(){let e=!!this.plugin.settings.deepgramApiKey,t=this.containerEl.querySelector("select");t&&(t.disabled=!e),this.containerEl.querySelectorAll(".checkbox-container input").forEach(i=>{i.disabled=!e||!this.selectedModel})}renderDefaultFeatures(e){ct.forEach(t=>{new A.Setting(e).setName(t.name).setDesc(t.description).addToggle(r=>{let i=this.getFeatureValue(t.key,t.default);r.setValue(i).onChange(async n=>{await this.saveFeatureSetting(t.key,n)})})})}updateFeatureAvailability(){if(!this.selectedModel||!this.registry)return;this.registry.getAllFeatures().forEach((t,r)=>{this.updateFeatureToggleState(r)})}updateFeatureToggleState(e){let t=this.containerEl.querySelector(`[data-feature="${e}"]`);if(!t||!this.selectedModel||!this.registry)return;let r=this.registry.isFeatureSupported(this.selectedModel.id,e);t.disabled=!r,!r&&t.checked&&(t.checked=!1,t.dispatchEvent(new Event("change")))}addDefaultModelOptions(e){lt.forEach(t=>{let r=`${t.name} (${t.tier}) - $${t.price}/min`;e.addOption(t.id,r)}),this.logger.info("Added default model options")}renderFallbackUI(e){this.logger.info("Rendering fallback UI due to error");try{this.uiBuilder.clearContainer(),this.uiBuilder.createErrorContainer(e),this.renderMinimalSettings(),this.logger.info("Fallback UI rendered successfully")}catch(t){this.logger.error("Failed to render fallback UI",t),this.renderCriticalError()}}renderMinimalSettings(){new A.Setting(this.containerEl).setName(d.MESSAGES.API_KEY_LABEL).setDesc(d.MESSAGES.API_KEY_DESC).addText(e=>{e.setPlaceholder(d.MESSAGES.API_KEY_PLACEHOLDER).setValue(this.plugin.settings.deepgramApiKey||"").onChange(async t=>{this.plugin.settings.deepgramApiKey=t,await this.plugin.saveSettings(),new A.Notice(d.MESSAGES.API_KEY_SAVED)}),e.inputEl.type="password"}),new A.Setting(this.containerEl).setName(d.MESSAGES.MODEL_LABEL).setDesc(d.MESSAGES.MODEL_DESC).addDropdown(e=>{var r,i;e.addOption("",d.MESSAGES.MODEL_PLACEHOLDER),this.addDefaultModelOptions(e);let t=((i=(r=this.plugin.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.model)||"";e.setValue(t),e.onChange(async n=>{await this.saveModelSelection(n)})})}renderCriticalError(){this.uiBuilder.clearContainer(),this.containerEl.createEl("p",{text:d.MESSAGES.CRITICAL_ERROR,cls:d.CLASSES.WARNING})}};var xe=class extends b.PluginSettingTab{constructor(e,t){super(e,t),this.plugin=t}display(){var s,a,l,c,p,u,h,f,g,D,y,x,_,K;let{containerEl:e}=this;if(!e){this.debug("SettingsTab display called without container element");return}this.debug("=== SettingsTab display() called ==="),this.debug("Container element:",e),this.debug("Container element exists:",!!e),this.debug("Container element type:",(s=e==null?void 0:e.constructor)==null?void 0:s.name),this.debug("Plugin instance:",this.plugin),this.debug("Plugin instance exists:",!!this.plugin),this.debug("Plugin settings object:",(a=this.plugin)==null?void 0:a.settings),this.debug("Plugin settings keys:",(l=this.plugin)!=null&&l.settings?Object.keys(this.plugin.settings):"N/A"),e&&(this.debug("Container parent element:",e.parentElement),this.debug("Container is connected to DOM:",e.isConnected),this.debug("Container display style:",window.getComputedStyle(e).display)),e.empty();let t=e.createEl("h2",{text:"Speech to Text Settings"});this.debug("Title element created:",t);let r=e.createEl("details",{cls:"speech-to-text-debug"}),i=r.createEl("summary",{text:"Debug Information"}),n=r.createEl("pre",{text:JSON.stringify({pluginExists:!!this.plugin,settingsExists:!!((c=this.plugin)!=null&&c.settings),apiKey:(u=(p=this.plugin)==null?void 0:p.settings)!=null&&u.apiKey?"Set (hidden)":"Not set",language:((f=(h=this.plugin)==null?void 0:h.settings)==null?void 0:f.language)||"Not set",autoInsert:(D=(g=this.plugin)==null?void 0:g.settings)==null?void 0:D.autoInsert,insertPosition:(x=(y=this.plugin)==null?void 0:y.settings)==null?void 0:x.insertPosition,model:(K=(_=this.plugin)==null?void 0:_.settings)==null?void 0:K.model,timestamp:new Date().toISOString()},null,2)});this.debug("Debug section added");try{this.debug("Creating API section..."),this.createApiSection(e),this.debug("API section created"),this.debug("Creating General section..."),this.createGeneralSection(e),this.debug("General section created"),this.debug("Creating Audio section..."),this.createAudioSection(e),this.debug("Audio section created"),this.debug("Creating Advanced section..."),this.createAdvancedSection(e),this.debug("Advanced section created"),this.debug("Creating Support section..."),this.createSupportSection(e),this.debug("Support section created"),this.debug("=== Settings tab rendered successfully ==="),this.debug("Total child elements:",e.children.length)}catch(M){console.error("=== Error displaying settings ==="),console.error("Error details:",M),console.error("Error stack:",M instanceof Error?M.stack:"N/A"),e.empty(),e.createEl("h2",{text:"Settings Error"}),e.createEl("p",{text:"Error loading settings. Please reload the plugin.",cls:"mod-warning"}),e.createEl("pre",{text:`Error: ${M instanceof Error?M.message:String(M)}`,cls:"error-details"})}}createApiSection(e){e.createEl("h3",{text:"API Configuration"});let t=e.createEl("div",{cls:"provider-selection"});this.createProviderSelection(t);let r=e.createEl("div",{cls:"provider-settings"}),i=this.plugin.settings.provider||"auto";this.renderProviderSettings(r,i)}createProviderSelection(e){var r;this.debug("=== createProviderSelection called ==="),this.debug("Creating Setting instance...");try{let i=new b.Setting(e);this.debug("Setting instance created:",i),this.debug("Setting element:",i.settingEl),this.debug("Setting element in DOM:",(r=i.settingEl)==null?void 0:r.isConnected),i.setName("Transcription Provider").setDesc("Select the speech-to-text provider").addDropdown(n=>{var s;this.debug("Dropdown callback called"),this.debug("Dropdown component:",n),n.addOption("auto","Auto (Intelligent Selection)").addOption("whisper","OpenAI Whisper").addOption("deepgram","Deepgram").setValue(this.plugin.settings.provider||"auto").onChange(async a=>{var p;this.debug("Provider dropdown changed to:",a),this.plugin.settings.provider=a,await this.plugin.saveSettings();let l=(p=e.parentElement)==null?void 0:p.querySelector(".provider-settings");this.debug("Settings container found:",!!l),l?(this.debug("Updating provider settings UI for:",a),this.renderProviderSettings(l,a)):console.error("Could not find .provider-settings container");let c=e.querySelector(".provider-info");c&&this.updateProviderInfo(c,a),new b.Notice(`Provider changed to: ${a}`)}),this.debug("Dropdown setup complete"),this.debug("Dropdown element:",n.selectEl),this.debug("Dropdown options:",(s=n.selectEl)==null?void 0:s.options.length)}),this.debug("Provider selection setting created successfully"),this.debug("=== createProviderSelection completed ===")}catch(i){console.error("Error creating provider selection:",i),console.error("Error stack:",i instanceof Error?i.stack:"N/A")}let t=e.createEl("div",{cls:"provider-info"});t.addClass("sn-info-box"),this.updateProviderInfo(t,this.plugin.settings.provider||"auto")}renderProviderSettings(e,t){this.debug("=== renderProviderSettings called ==="),this.debug("Provider:",t),this.debug("Container element:",e);let r=e.isConnected;e.empty(),this.debug("Container cleared, still connected:",r);try{switch(t){case"auto":this.debug("Rendering auto provider settings"),this.renderAutoProviderSettings(e);break;case"whisper":this.debug("Rendering whisper settings"),this.renderWhisperSettings(e);break;case"deepgram":this.debug("Rendering deepgram settings"),this.renderDeepgramSettings(e);break;default:console.warn("Unknown provider:",t),e.createEl("p",{text:`Unknown provider: ${String(t)}`,cls:"mod-warning"})}}catch(i){console.error("Error rendering provider settings:",i),e.createEl("p",{text:"Error loading provider settings",cls:"mod-warning"})}this.debug("Final container children:",e.children.length),this.debug("=== renderProviderSettings completed ===")}renderAutoProviderSettings(e){e.createEl("h4",{text:"Automatic Provider Selection"}),new b.Setting(e).setName("Selection Strategy").setDesc("How to choose between available providers").addDropdown(t=>{t.addOption("cost_optimized","Cost Optimized").addOption("performance_optimized","Performance Optimized").addOption("quality_optimized","Quality Optimized").addOption("balanced","Balanced").setValue(this.plugin.settings.selectionStrategy||"performance_optimized").onChange(async r=>{this.plugin.settings.selectionStrategy=r,await this.plugin.saveSettings()})}),new b.Setting(e).setName("Fallback Strategy").setDesc("What to do when primary provider fails").addDropdown(t=>{t.addOption("auto","Automatic Fallback").addOption("manual","Ask User").addOption("none","No Fallback").setValue(this.plugin.settings.fallbackStrategy||"auto").onChange(async r=>{this.plugin.settings.fallbackStrategy=r,await this.plugin.saveSettings()})}),e.createEl("h5",{text:"Provider API Keys"}),e.createEl("p",{text:"Configure API keys for each provider to enable automatic selection",cls:"setting-item-description"}),this.renderWhisperApiKey(e),this.renderDeepgramApiKey(e)}renderWhisperSettings(e){e.createEl("h4",{text:"OpenAI Whisper Configuration"}),this.renderWhisperApiKey(e),new b.Setting(e).setName("API Endpoint").setDesc("OpenAI API endpoint (leave default unless using custom endpoint)").addText(t=>t.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.apiEndpoint||"https://api.openai.com/v1").onChange(async r=>{this.plugin.settings.apiEndpoint=r||"https://api.openai.com/v1",await this.plugin.saveSettings()}))}renderDeepgramSettings(e){this.debug("=== renderDeepgramSettings called ==="),this.debug("Container element:",e),this.debug("Container is connected:",e.isConnected),this.debug("Container children before:",e.children.length),e.empty();let t=e.createEl("div",{cls:"deepgram-settings-container"});this.debug("Deepgram container created:",t);try{let r=new De(this.plugin,t);this.debug("DeepgramSettings instance created"),r.render(),this.debug("DeepgramSettings.render() completed")}catch(r){console.error("Error rendering Deepgram settings:",r),t.createEl("p",{text:"Error loading Deepgram settings",cls:"mod-warning"})}this.debug("Container children after:",e.children.length),this.debug("=== renderDeepgramSettings completed ===")}renderWhisperApiKey(e){new b.Setting(e).setName("OpenAI API Key").setDesc("Enter your OpenAI API key for Whisper transcription").addText(t=>{t.setPlaceholder("sk-...").setValue(this.maskApiKey(this.plugin.settings.apiKey||"")).onChange(async r=>{r&&!r.includes("*")&&(this.plugin.settings.apiKey=r,this.plugin.settings.whisperApiKey=r,await this.plugin.saveSettings(),t.setValue(this.maskApiKey(r)),new b.Notice("OpenAI API key saved"))}),t.inputEl.type="password",t.inputEl.addEventListener("focus",()=>{this.plugin.settings.apiKey&&t.setValue(this.plugin.settings.apiKey)}),t.inputEl.addEventListener("blur",()=>{this.plugin.settings.apiKey&&t.setValue(this.maskApiKey(this.plugin.settings.apiKey))})})}renderDeepgramApiKey(e){new b.Setting(e).setName("Deepgram API Key").setDesc("Enter your Deepgram API key for transcription").addText(t=>{t.setPlaceholder("Enter Deepgram API key...").setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey||"")).onChange(async r=>{r&&!r.includes("*")&&(this.plugin.settings.deepgramApiKey=r,await this.plugin.saveSettings(),t.setValue(this.maskApiKey(r)),new b.Notice("Deepgram API key saved"))}),t.inputEl.type="password",t.inputEl.addEventListener("focus",()=>{this.plugin.settings.deepgramApiKey&&t.setValue(this.plugin.settings.deepgramApiKey)}),t.inputEl.addEventListener("blur",()=>{this.plugin.settings.deepgramApiKey&&t.setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey))})})}updateProviderInfo(e,t){e.empty();let r={auto:"\u{1F916} Intelligent selection between providers based on your configured strategy. Automatically chooses the best provider for each request.",whisper:"\u{1F3AF} OpenAI Whisper - High-quality transcription with support for multiple languages. Best for general-purpose transcription.",deepgram:"\u26A1 Deepgram - Fast, accurate transcription with advanced AI features. Best for real-time processing and speaker diarization."};e.createEl("p",{text:r[t]})}createGeneralSection(e){e.createEl("h3",{text:"General Settings"}),new b.Setting(e).setName("Language").setDesc("Primary language for transcription").addDropdown(t=>t.addOption("auto","Auto-detect").addOption("en","English").addOption("ko","\uD55C\uAD6D\uC5B4").addOption("ja","\u65E5\u672C\u8A9E").addOption("zh","\u4E2D\u6587").addOption("es","Espa\xF1ol").addOption("fr","Fran\xE7ais").addOption("de","Deutsch").setValue(this.plugin.settings.language||"auto").onChange(async r=>{this.plugin.settings.language=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Auto-insert transcription").setDesc("Automatically insert transcribed text into the active note").addToggle(t=>t.setValue(this.plugin.settings.autoInsert||!1).onChange(async r=>{this.plugin.settings.autoInsert=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Insert position").setDesc("Where to insert transcribed text").addDropdown(t=>t.addOption("cursor","At cursor position").addOption("end","At end of note").addOption("beginning","At beginning of note").setValue(this.plugin.settings.insertPosition||"cursor").onChange(async r=>{this.plugin.settings.insertPosition=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Show format options").setDesc("Show formatting options before inserting text").addToggle(t=>t.setValue(this.plugin.settings.showFormatOptions||!1).onChange(async r=>{this.plugin.settings.showFormatOptions=r,await this.plugin.saveSettings()}))}createAudioSection(e){e.createEl("h3",{text:"Audio Settings"});let t=this.plugin.settings.provider||"auto";(t==="whisper"||t==="auto")&&new b.Setting(e).setName("Whisper Model").setDesc("Select the Whisper model to use").addDropdown(r=>r.addOption("whisper-1","Whisper v1 (Default)").setValue(this.plugin.settings.model||"whisper-1").onChange(async i=>{this.plugin.settings.model=i,await this.plugin.saveSettings()})),new b.Setting(e).setName("Temperature").setDesc("Sampling temperature (0-1). Lower values make output more focused and deterministic").addText(r=>r.setPlaceholder("0.0").setValue(String(this.plugin.settings.temperature||0)).onChange(async i=>{let n=parseFloat(i);!isNaN(n)&&n>=0&&n<=1&&(this.plugin.settings.temperature=n,await this.plugin.saveSettings())})),new b.Setting(e).setName("Add timestamp").setDesc("Add timestamp to transcribed text").addToggle(r=>r.setValue(this.plugin.settings.addTimestamp||!1).onChange(async i=>{this.plugin.settings.addTimestamp=i,await this.plugin.saveSettings()}))}createAdvancedSection(e){e.createEl("h3",{text:"Advanced Settings"}),new b.Setting(e).setName("Enable cache").setDesc("Cache transcription results to avoid re-processing").addToggle(t=>t.setValue(this.plugin.settings.enableCache!==!1).onChange(async r=>{this.plugin.settings.enableCache=r,await this.plugin.saveSettings()})),new b.Setting(e).setName("Debug mode").setDesc("Enable debug logging in console").addToggle(t=>t.setValue(this.plugin.settings.debugMode||!1).onChange(async r=>{this.plugin.settings.debugMode=r,await this.plugin.saveSettings(),r&&new b.Notice("Debug mode enabled. Check console for logs.")})),new b.Setting(e).setName("Reset to defaults").setDesc("Reset all settings to their default values").addButton(t=>t.setButtonText("Reset").setWarning().onClick(async()=>{if(confirm("Are you sure you want to reset all settings to defaults?")){let{DEFAULT_SETTINGS:i}=await Promise.resolve().then(()=>(Le(),Qe));this.plugin.settings={...i},await this.plugin.saveSettings(),this.display(),new b.Notice("Settings reset to defaults")}}))}createSupportSection(e){e.createEl("hr",{cls:"speech-to-text-separator"}),e.createEl("h3",{text:"Support"}),e.createEl("p",{text:"Thank you for using Speech to Text! Your support helps keep this plugin free and actively maintained.",cls:"setting-item-description"}),new b.Setting(e).setName("Support Development").setDesc("If you find this plugin helpful, consider buying me a coffee \u2615").addButton(t=>t.setButtonText("\u2615 Buy me a coffee").setCta().onClick(()=>{window.open("https://buymeacoffee.com/asyouplz","_blank")}))}debug(...e){var t;(t=this.plugin.settings)!=null&&t.debugMode&&[...e]}maskApiKey(e){if(!e||e.length<10)return"";let t=7,r=4;if(e.length<=t+r)return e;let i="*".repeat(e.length-t-r);return e.substring(0,t)+i+e.substring(e.length-r)}};var We=require("obsidian");function Tt(o){return o instanceof We.TFile}function pt(o,e){if(!Tt(o)){let t=e?`[${e}] `:"";throw new Error(`${t}Expected a TFile instance.`)}}var Me=class extends v.Plugin{async onload(){this.logger=new z("SpeechToText"),this.logger.info("Loading Speech-to-Text plugin");try{await this.initializeServices(),this.registerCommands(),this.registerContextMenu(),this.addSettingTab(new xe(this.app,this)),this.logger.debug("SettingsTab added"),this.registerEventHandlers(),this.app.workspace.onLayoutReady(()=>{this.createStatusBarItem()}),new v.Notice("Speech-to-Text plugin loaded successfully")}catch(e){console.error("Failed to load Speech-to-Text plugin:",e),new v.Notice("Failed to load Speech-to-Text plugin. Check console for details.")}}onunload(){var e;(e=this.logger)==null||e.info("Unloading Speech-to-Text plugin"),this.cleanupEventHandlers(),this.cancelPendingOperations(),this.editorService&&this.editorService.destroy(),this.textInsertionHandler&&this.textInsertionHandler.destroy()}async initializeServices(){await this.loadSettings(),this.logger=new z("SpeechToText"),this.errorHandler=new me(this.logger),this.settingsManager=new pe(this),this.stateManager=new he,this.eventManager=new L,this.editorService=new ve(this.app,this.eventManager,this.logger),this.textInsertionHandler=new Ee(this.editorService,this.eventManager,this.logger),this.initializeTranscriberFactory(),this.initializeTranscriptionService()}initializeTranscriberFactory(){let e={load:async()=>(await this.loadSettings(),this.settings),save:async t=>{this.settings=t,await this.saveSettings()},get:t=>{var r,i;return t==="transcription"?{defaultProvider:this.settings.provider||"whisper",autoSelect:this.settings.provider==="auto",selectionStrategy:this.settings.selectionStrategy,fallbackEnabled:this.settings.fallbackStrategy!=="none",whisper:{enabled:!!this.settings.apiKey||!!this.settings.whisperApiKey,apiKey:this.settings.whisperApiKey||this.settings.apiKey},deepgram:{enabled:!!this.settings.deepgramApiKey,apiKey:this.settings.deepgramApiKey,model:this.settings.deepgramModel||"nova-2",features:(i=(r=this.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.features},abTest:{enabled:this.settings.abTestEnabled,trafficSplit:this.settings.abTestSplit},monitoring:{enabled:this.settings.metricsEnabled}}:t==="apiKey"?this.settings.apiKey:this.settings[t]},set:async(t,r)=>{var i,n;t==="transcription"?(r.defaultProvider&&(this.settings.provider=r.defaultProvider),(i=r.whisper)!=null&&i.apiKey&&(this.settings.whisperApiKey=r.whisper.apiKey),(n=r.deepgram)!=null&&n.apiKey&&(this.settings.deepgramApiKey=r.deepgram.apiKey)):this.settings[t]=r,await this.saveSettings()}};this.transcriberFactory=new ce(e,this.logger)}initializeTranscriptionService(){let e=this.settings.provider||"whisper",t;try{let r=this.transcriberFactory.getProvider(e==="auto"?"auto":e);t=new de(r,this.logger),this.logger.info(`Initialized transcription service with provider: ${r.getProviderName()}`)}catch(r){this.logger.warn("Failed to initialize transcriber from factory, using fallback",r);let i=this.settings.whisperApiKey||this.settings.apiKey;i?(t=new H(i,this.logger),this.logger.info("Initialized fallback WhisperService")):(t=null,this.logger.warn("No transcription service initialized - API key missing"))}if(t){let r=new ue(this.app.vault,this.logger);try{let n=this.transcriberFactory.getProvider(e==="auto"?"auto":e),s=n.getCapabilities();r.setProviderCapabilities({maxFileSize:s.maxFileSize}),this.logger.info("AudioProcessor configured with provider capabilities",{provider:n.getProviderName(),maxFileSize:s.maxFileSize/1024/1024+"MB"})}catch(n){this.logger.warn("Failed to get provider capabilities, using default limits",n)}let i=new ge(this.settings);this.transcriptionService=new Q(t,r,i,this.eventManager,this.logger,this.settings),this.logger.debug("TranscriptionService initialized successfully")}}registerContextMenu(){this.registerEvent(this.app.workspace.on("file-menu",(e,t)=>{if(!t||!(t instanceof v.TFile))return;["m4a","mp3","wav","mp4","webm","ogg"].includes(t.extension.toLowerCase())&&e.addItem(i=>{i.setTitle("Transcribe audio file").setIcon("microphone").onClick(async()=>{await this.transcribeFile(t)})})}))}registerCommands(){this.addCommand({id:"transcribe-audio-file",name:"Transcribe audio file",callback:()=>{this.showAudioFilePicker()}}),this.addCommand({id:"transcribe-from-clipboard",name:"Transcribe audio from clipboard",callback:async()=>{new v.Notice("Clipboard transcription not yet implemented")}}),this.addCommand({id:"show-format-options",name:"Show text formatting options",callback:()=>{this.showFormatOptions()}}),this.addCommand({id:"show-transcription-history",name:"Show transcription history",callback:()=>{new v.Notice("Transcription history not yet implemented")}}),this.addCommand({id:"cancel-transcription",name:"Cancel current transcription",callback:()=>{this.transcriptionService.cancel(),new v.Notice("Transcription cancelled")}}),this.addCommand({id:"undo-insertion",name:"Undo last text insertion",callback:async()=>{await this.editorService.undo()?new v.Notice("Text insertion undone"):new v.Notice("Nothing to undo")}}),this.addCommand({id:"redo-insertion",name:"Redo last text insertion",callback:async()=>{await this.editorService.redo()?new v.Notice("Text insertion redone"):new v.Notice("Nothing to redo")}})}registerEventHandlers(){this.eventManager.on("transcription:start",e=>{this.stateManager.setState({status:"processing"}),new v.Notice(`Transcribing: ${e.fileName}`)}),this.eventManager.on("transcription:complete",async e=>{var r;this.logger.debug("=== Transcription complete event received ===",{hasData:!!e,hasText:!!(e!=null&&e.text),textLength:((r=e==null?void 0:e.text)==null?void 0:r.length)||0,autoInsert:this.settings.autoInsert}),this.stateManager.setState({status:"completed"}),new v.Notice("Transcription completed successfully");let t=e.text;if(!t){this.logger.error("No text found in transcription complete event",void 0,{data:e}),new v.Notice("Transcription completed but no text was returned");return}this.settings.autoInsert?(this.logger.debug("Auto-inserting transcribed text",{textLength:t.length,textPreview:t.substring(0,100)}),await this.insertTranscriptionWithOptions(t)):this.logger.debug("Auto-insert disabled, text not inserted")}),this.eventManager.on("transcription:error",e=>{this.stateManager.setState({status:"error",error:e.error}),new v.Notice(`Transcription failed: ${e.error.message}`)}),this.eventManager.on("transcription:progress",e=>{this.stateManager.setState({progress:e.progress})}),this.eventManager.on("editor:text-inserted",e=>{this.logger.debug("Text inserted into editor",e)}),this.eventManager.on("editor:text-replaced",e=>{this.logger.debug("Text replaced in editor",e)})}cleanupEventHandlers(){this.eventManager.removeAllListeners()}cancelPendingOperations(){this.transcriptionService&&this.transcriptionService.cancel()}createStatusBarItem(){var e;try{if(!this.app.workspace){console.warn("Workspace not ready, skipping status bar creation");return}let t=this.addStatusBarItem();if(!t){console.warn("Failed to create status bar item");return}t.textContent="";let r=i=>{if(t)try{let n=i?String(i):"";t.textContent=n}catch(n){console.warn("Failed to update status bar text:",n)}};this.stateManager.subscribe(i=>{if(t)switch(i.status){case"idle":r("");break;case"processing":r("\u{1F399}\uFE0F Transcribing...");break;case"completed":r("\u2705 Transcription complete"),setTimeout(()=>{this.stateManager.getState().status==="completed"&&r("")},3e3);break;case"error":r("\u274C Transcription failed"),setTimeout(()=>{this.stateManager.getState().status==="error"&&r("")},3e3);break;default:r("");break}}),(e=this.logger)==null||e.debug("Status bar item created successfully")}catch(t){console.error("Error creating status bar item:",t)}}async showAudioFilePicker(){let e=this.app.vault.getFiles().filter(t=>t.extension==="m4a"||t.extension==="mp3"||t.extension==="wav"||t.extension==="mp4");if(e.length===0){new v.Notice("No audio files found in vault");return}new Ge(this.app,e,async t=>{await this.transcribeFile(t)}).open()}async transcribeFile(e){var t,r;pt(e,"SpeechToTextPlugin.transcribeFile");try{let i=this.settings.provider||"whisper",n=!1,s="";if(i==="whisper"?(n=!!(this.settings.apiKey||this.settings.whisperApiKey),s="Please configure your OpenAI API key in settings"):i==="deepgram"?(n=!!this.settings.deepgramApiKey,s="Please configure your Deepgram API key in settings"):i==="auto"&&(n=!!(this.settings.apiKey||this.settings.whisperApiKey||this.settings.deepgramApiKey),s="Please configure at least one API key (OpenAI or Deepgram) in settings"),!n){new v.Notice(s);return}if(!this.transcriptionService&&(this.initializeTranscriptionService(),!this.transcriptionService)){new v.Notice("Failed to initialize transcription service. Please check your API keys.");return}this.logger.debug("Starting transcription for file:",{fileName:e.name});let a=await this.transcriptionService.transcribe(e);if(this.logger.debug("Transcription result received:",{hasResult:!!a,hasText:!!(a!=null&&a.text),textLength:((t=a==null?void 0:a.text)==null?void 0:t.length)||0,textPreview:(r=a==null?void 0:a.text)==null?void 0:r.substring(0,100)}),!a||!a.text){this.logger.error("Transcription returned no text",void 0,{result:a}),new v.Notice("Transcription completed but no text was returned");return}this.settings.showFormatOptions?(this.logger.debug("Showing format options with text"),this.showFormatOptionsWithText(a.text)):(this.logger.debug("Inserting text directly without format options"),await this.insertTranscriptionWithOptions(a.text))}catch(i){this.errorHandler.handle(i)}}async insertTranscriptionWithOptions(e){this.logger.debug("=== insertTranscriptionWithOptions START ===",{textLength:(e==null?void 0:e.length)||0,textPreview:e==null?void 0:e.substring(0,100),insertPosition:this.settings.insertPosition,autoInsert:this.settings.autoInsert});let t={mode:this.settings.insertPosition==="cursor"?"cursor":this.settings.insertPosition==="end"?"append":this.settings.insertPosition==="beginning"?"prepend":"cursor",format:this.settings.textFormat||"plain",addTimestamp:this.settings.addTimestamp||!1,timestampFormat:this.settings.timestampFormat,language:this.settings.language,createNewNote:!this.editorService.hasActiveEditor()};this.logger.debug("Inserting text with options:",t),await this.textInsertionHandler.insertText(e,t)?(this.logger.info("Text successfully inserted"),new v.Notice("Transcription inserted successfully")):(this.logger.warn("TextInsertionHandler failed, using legacy method"),await this.insertTranscriptionLegacy(e))}async insertTranscriptionLegacy(e){let t=this.app.workspace.getActiveViewOfType(v.MarkdownView);if(!t){new v.Notice("No active editor found. Opening new note...");let n=await this.app.vault.create(`Transcription ${new Date().toISOString()}.md`,e);await this.app.workspace.openLinkText(n.path,"",!0);return}let r=t.editor;switch(this.settings.insertPosition){case"cursor":r.replaceSelection(e);break;case"end":{let n=r.lastLine(),s=r.getLine(n);r.setLine(n,s+` -`+e);break;case"beginning":let a=r.getLine(0);r.setLine(0,e+` +`+e);break}case"beginning":{let n=r.getLine(0);r.setLine(0,e+` -`+a);break}}showFormatOptions(){this.showFormatOptionsWithText("")}showFormatOptionsWithText(e){new Te(this.app,{mode:"cursor",format:this.settings.textFormat||"plain",addTimestamp:this.settings.addTimestamp||!1,language:this.settings.language},async r=>{e?await this.textInsertionHandler.insertText(e,r):new v.Notice("No text to insert")},()=>{this.logger.debug("Format options cancelled")}).open()}async loadSettings(){this.settings=Object.assign({},Pe,await this.loadData())}async saveSettings(){await this.saveData(this.settings)}async saveSettingsAndReinitialize(){await this.saveData(this.settings),this.transcriberFactory&&(this.initializeTranscriberFactory(),this.initializeTranscriptionService())}},Ge=class extends v.Modal{constructor(e,t,r){super(e),this.files=t,this.onChoose=r}onOpen(){let{contentEl:e}=this;e.createEl("h2",{text:"Select an audio file to transcribe"});let t=e.createEl("div",{cls:"speech-to-text-file-list"});this.files.forEach(r=>{t.createEl("div",{cls:"speech-to-text-file-item",text:r.path}).addEventListener("click",()=>{this.onChoose(r),this.close()})})}onClose(){let{contentEl:e}=this;e.empty()}}; +`+n);break}}}showFormatOptions(){this.showFormatOptionsWithText("")}showFormatOptionsWithText(e){new Te(this.app,{mode:"cursor",format:this.settings.textFormat||"plain",addTimestamp:this.settings.addTimestamp||!1,language:this.settings.language},async r=>{e?await this.textInsertionHandler.insertText(e,r):new v.Notice("No text to insert")},()=>{this.logger.debug("Format options cancelled")}).open()}async loadSettings(){this.settings=Object.assign({},Pe,await this.loadData())}async saveSettings(){await this.saveData(this.settings)}async saveSettingsAndReinitialize(){await this.saveData(this.settings),this.transcriberFactory&&(this.initializeTranscriberFactory(),this.initializeTranscriptionService())}},Ge=class extends v.Modal{constructor(e,t,r){super(e),this.files=t,this.onChoose=r}onOpen(){let{contentEl:e}=this;e.createEl("h2",{text:"Select an audio file to transcribe"});let t=e.createEl("div",{cls:"speech-to-text-file-list"});this.files.forEach(r=>{t.createEl("div",{cls:"speech-to-text-file-item",text:r.path}).addEventListener("click",()=>{this.onChoose(r),this.close()})})}onClose(){let{contentEl:e}=this;e.empty()}}; diff --git a/manifest.json b/manifest.json index d0fbe73..fd3c8fb 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "speech-to-text", "name": "Speech to Text", - "version": "3.0.4", + "version": "3.0.5", "minAppVersion": "0.15.0", "description": "Convert audio recordings to text using multiple AI providers (OpenAI Whisper, Deepgram)", "author": "Taesun Lee", diff --git a/package-lock.json b/package-lock.json index a5383e2..3e33d2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-speech-to-text", - "version": "3.0.4", + "version": "3.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "obsidian-speech-to-text", - "version": "3.0.4", + "version": "3.0.5", "license": "MIT", "dependencies": { "@deepgram/sdk": "^3.9.0" diff --git a/package.json b/package.json index 7135138..0929be3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-speech-to-text", - "version": "3.0.4", + "version": "3.0.5", "description": "Convert audio recordings to text in Obsidian using multiple AI providers (OpenAI Whisper, Deepgram)", "main": "main.js", "scripts": { diff --git a/versions.json b/versions.json index 1901585..3b30f41 100644 --- a/versions.json +++ b/versions.json @@ -5,5 +5,6 @@ "3.0.1": "0.15.0", "3.0.2": "0.15.0", "3.0.3": "0.15.0", - "3.0.4": "0.15.0" + "3.0.4": "0.15.0", + "3.0.5": "0.15.0" } \ No newline at end of file