From d7b86645a8e817ea1d3dcbe566355447f885cda8 Mon Sep 17 00:00:00 2001 From: Taesun Lee Date: Wed, 1 Oct 2025 13:14:30 +0900 Subject: [PATCH] fix(deepgram): differentiate auth failures during key validation --- main.js | 14 ++++++------- .../api/providers/deepgram/DeepgramAdapter.ts | 20 ++++++++++++++++--- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/main.js b/main.js index 8f50649..adeac92 100644 --- a/main.js +++ b/main.js @@ -2,18 +2,18 @@ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD Optimized for Phase 4 Performance */ -"use strict";var Q=Object.defineProperty;var Ze=Object.getOwnPropertyDescriptor;var pt=Object.getOwnPropertyNames;var mt=Object.prototype.hasOwnProperty;var je=(l,t)=>()=>(l&&(t=l(l=0)),t);var ht=(l,t)=>()=>(t||l((t={exports:{}}).exports,t),t.exports),Xe=(l,t)=>{for(var e in t)Q(l,e,{get:t[e],enumerable:!0})},ft=(l,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of pt(t))!mt.call(l,i)&&i!==e&&Q(l,i,{get:()=>t[i],enumerable:!(r=Ze(t,i))||r.enumerable});return l};var vt=l=>ft(Q({},"__esModule",{value:!0}),l),Qe=(l,t,e,r)=>{for(var i=r>1?void 0:r?Ze(t,e):t,n=l.length-1,s;n>=0;n--)(s=l[n])&&(i=(r?s(t,e,i):s(i))||i);return r&&i&&Q(t,e,i),i};var b,q,J,U,Y=je(()=>{"use strict";b=class extends Error{constructor(e,r,i,n=!1,s){super(e);this.code=r;this.provider=i;this.isRetryable=n;this.statusCode=s;this.name="TranscriptionError"}},q=class extends b{constructor(t,e="Invalid API key"){super(e,"AUTH_ERROR",t,!1,401)}},J=class extends b{constructor(e,r){super("Rate limit exceeded","RATE_LIMIT",e,!0,429);this.retryAfter=r}},U=class extends b{constructor(t){super("Provider temporarily unavailable","UNAVAILABLE",t,!0,503)}}});var Je={};Xe(Je,{DEFAULT_SETTINGS:()=>Pe});var Pe,Le=je(()=>{"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 dt=ht((si,bt)=>{bt.exports={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 Tt={};Xe(Tt,{default:()=>Me});module.exports=vt(Tt);var f=require("obsidian");Le();var ee=class{constructor(t,e,r,i,n,s){this.whisperService=t;this.audioProcessor=e;this.textFormatter=r;this.eventManager=i;this.logger=n;this.settings=s;this.status="idle"}async transcribe(t){var e,r,i,n,s,a,o;try{this.status="validating",this.eventManager.emit("transcription:start",{fileName:t.name});let d=await this.audioProcessor.validate(t);if(!d.valid)throw new Error(`File validation failed: ${(e=d.errors)==null?void 0:e.join(", ")}`);this.status="processing";let m=await this.audioProcessor.process(t);this.status="transcribing",this.logger.debug("Starting transcription with WhisperService");let u={language:(r=this.settings)==null?void 0:r.language,model:(i=this.settings)==null?void 0:i.model};this.logger.debug("Transcription options:",u);let g=await this.whisperService.transcribe(m.buffer,u);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)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 v=this.textFormatter.format(g.text);this.logger.debug("Text formatted:",{originalLength:g.text.length,formattedLength:v.length,formattedPreview:v.substring(0,100)});let h={text:v,language:g.language,segments:(a=g.segments)==null?void 0:a.map((M,S)=>({id:S,start:M.start,end:M.end,text:M.text}))};return this.status="completed",this.logger.debug("Emitting transcription:complete event",{textLength:h.text.length,hasSegments:!!h.segments,segmentsCount:((o=h.segments)==null?void 0:o.length)||0}),this.eventManager.emit("transcription:complete",{result:h,text:h.text}),h}catch(d){throw this.status="error",this.eventManager.emit("transcription:error",{error:d}),d}}cancel(){var t;(t=this.abortController)==null||t.abort(),this.status="cancelled",this.eventManager.emit("transcription:cancelled",{})}getStatus(){return this.status}};var it=require("obsidian");function et(l){return new Promise(t=>setTimeout(t,l))}function tt(l,t,e,r=!0){if(r){if(le)return{valid:!1,error:`Value must be between ${t} and ${e} (inclusive)`}}else if(l<=t||l>=e)return{valid:!1,error:`Value must be between ${t} and ${e} (exclusive)`};return{valid:!0}}function rt(l,t,e="..."){if(t<=0)throw new Error("Max length must be positive");if(l.length<=t)return l;let r=t-e.length;return r<=0?e:l.substring(0,r)+e}var P=class extends Error{constructor(e,r,i,n=!1){super(e);this.code=r;this.status=i;this.isRetryable=n;this.name="WhisperAPIError"}},te=class extends P{constructor(t="Invalid API key"){super(t,"AUTH_ERROR",401,!1)}},Oe=class extends P{constructor(e){super("Rate limit exceeded","RATE_LIMIT",429,!0);this.retryAfter=e}},re=class extends P{constructor(){super("File size exceeds API limit (25MB)","FILE_TOO_LARGE",413,!1)}},ke=class extends P{constructor(t,e){super(t,"SERVER_ERROR",e,!0)}},Re=class{constructor(t){this.logger=t;this.maxRetries=3;this.baseDelay=1e3;this.maxDelay=1e4}async execute(t){let e;for(let r=0;r=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")}},V=class{constructor(t,e){this.apiKey=t;this.logger=e;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.retryStrategy=new Re(e),this.circuitBreaker=new Ne(e)}async transcribe(t,e){return this.queueRequest(()=>this.executeTranscription(t,e))}async executeTranscription(t,e){if(t.byteLength>this.MAX_FILE_SIZE)throw new re;return this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(t,e)))}async performTranscription(t,e){this.abortController=new AbortController;let r=Date.now();try{let i=this.buildFormData(t,e),n=await this.buildRequestParams(i);this.logger.debug("Starting transcription request",{fileSize:t.byteLength,options:e});let s=await(0,it.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"?new P("Transcription cancelled","CANCELLED",void 0,!1):i}finally{this.abortController=void 0}}buildFormData(t,e){let r=new FormData,i=this.getMimeType(e),n=new Blob([t],{type:i});if(r.append("file",n,"audio.m4a"),r.append("model",(e==null?void 0:e.model)||"whisper-1"),e!=null&&e.language&&e.language!=="auto"&&r.append("language",e.language),e!=null&&e.prompt){let s=this.truncatePrompt(e.prompt);r.append("prompt",s)}return(e==null?void 0:e.temperature)!==void 0&&(tt(e.temperature,0,1).valid?r.append("temperature",e.temperature.toString()):this.logger.warn("Invalid temperature value, using default",{temperature:e.temperature})),e!=null&&e.responseFormat&&r.append("response_format",e.responseFormat),r}async buildRequestParams(t){let e=new Uint8Array(await new Response(t).arrayBuffer());return{url:this.API_ENDPOINT,method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:e.buffer,throw:!1}}parseResponse(t,e){if(typeof t=="string")return{text:t,duration:e/1e3};let r={text:t.text||"",language:t.language,duration:t.duration||e/1e3};return t.segments&&(r.segments=t.segments),r}async handleAPIError(t){var i,n;let e=t.json,r=((i=e==null?void 0:e.error)==null?void 0:i.message)||"Unknown error";switch(this.logger.error(`API Error: ${t.status} - ${r}`,void 0,{status:t.status,errorBody:e}),t.status){case 400:throw new P(r||"Invalid request","BAD_REQUEST",400,!1);case 401:throw new te;case 429:let s=(n=t.headers)==null?void 0:n["retry-after"];throw new Oe(s?parseInt(s):void 0);case 413:throw new re;case 500:case 502:case 503:throw new ke(`Server error: ${r}`,t.status);default:throw new P(`API error: ${r}`,"UNKNOWN_ERROR",t.status,!1)}}getMimeType(t){return"audio/m4a"}truncatePrompt(t,e=224){let r=e*4;return rt(t,r)}async queueRequest(t){let e=this.requestQueue.then(t,t);return this.requestQueue=e.catch(()=>{}),e}async validateApiKey(t){let e=this.apiKey;this.apiKey=t;try{let r=new ArrayBuffer(1024);return await this.performTranscription(r,{responseFormat:"text"}),!0}catch(r){return r instanceof te?(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=e}}cancel(){this.abortController&&(this.abortController.abort(),this.logger.debug("Transcription cancelled by user"))}resetCircuitBreaker(){this.circuitBreaker.reset()}};Y();var ie=class{constructor(t,e,r){this.whisperService=t;this.logger=e;this.config={enabled:!0,apiKey:"",model:"whisper-1",maxConcurrency:1,timeout:3e4,...r}}async transcribe(t,e){let r=Date.now();try{let i=this.convertOptions(e),n=await this.whisperService.transcribe(t,i),s=Date.now()-r;return this.convertResponse(n,s)}catch(i){throw this.logger.error("WhisperAdapter: Transcription failed",i),i}}convertOptions(t){let e={model:(t==null?void 0:t.model)||this.config.model||"whisper-1",language:t==null?void 0:t.language};if(t!=null&&t.whisper){let r=t.whisper;r.temperature!==void 0&&(e.temperature=r.temperature),r.prompt&&(e.prompt=r.prompt),r.responseFormat&&(e.responseFormat=r.responseFormat)}return e.responseFormat||(e.responseFormat="verbose_json"),e}convertResponse(t,e){var i;let r=t.text.split(/\s+/).filter(n=>n.length>0).length;return{text:t.text,language:t.language,duration:t.duration,segments:(i=t.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:e,wordCount:r}}}async validateApiKey(t){return this.whisperService.validateApiKey(t)}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 t=new ArrayBuffer(1024);return await this.whisperService.transcribe(t,{responseFormat:"text"}),!0}catch(t){let e=t.message.toLowerCase();return!(e.includes("circuit")||e.includes("unavailable")||e.includes("timeout"))}}getConfig(){return{...this.config}}resetCircuitBreaker(){this.whisperService.resetCircuitBreaker()}updateConfig(t){this.config={...this.config,...t}}};var nt=require("obsidian");Y();var ne={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},se={MIN_HEADER_SIZE:44,SIZE_WARNING_THRESHOLD:1024,SIZE_WARNING_LARGE:100*1024*1024,SILENCE_THRESHOLD:327,SILENCE_PEAK_MULTIPLIER:5,SAMPLE_SIZE:8192},zt={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}},Fe={CONSECUTIVE_THRESHOLD:.5,MIN_SEGMENT_LENGTH:1,WORDS_PER_SEGMENT:10,SPEAKER_LABELS:{PREFIX:"Speaker",NUMBERING:"numeric"}};var W={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 oe={enabled:!0,format:"speaker_prefix",speakerLabels:{prefix:"Speaker",numbering:"numeric"},merging:{consecutiveThreshold:Fe.CONSECUTIVE_THRESHOLD,minSegmentLength:Fe.MIN_SEGMENT_LENGTH},output:{includeTimestamps:!1,includeConfidence:!1,paragraphBreaks:!0,lineBreaksBetweenSpeakers:!0}},ae=class{constructor(t){this.logger=t}formatTranscript(t,e=oe){let r=Date.now();if(this.logFormatStart(t,e),!this.hasSpeakerInformation(t))return this.logger.debug("No speaker information found, returning original text"),this.createFallbackResult(t);let i=this.processTranscriptWithSpeakers(t,e);return this.logFormatComplete(i,Date.now()-r),i}processTranscriptWithSpeakers(t,e){let r=this.buildSegments(t,e);this.logger.debug(`Created ${r.length} segments from ${t.length} words`);let i=this.calculateStatistics(r,t);return{formattedText:this.formatSegments(r,e),segments:r,speakerCount:i.totalSpeakers,statistics:i,originalWordCount:t.length}}logFormatStart(t,e){this.logger.debug("=== DiarizationFormatter.formatTranscript START ===",{wordCount:t.length,config:e})}logFormatComplete(t,e){this.logger.info("=== DiarizationFormatter.formatTranscript COMPLETE ===",{processingTime:e,speakerCount:t.speakerCount,segmentCount:t.segments.length,formattedTextLength:t.formattedText.length})}hasSpeakerInformation(t){return t.some(e=>e.speaker!==void 0&&e.speaker>=0)}createFallbackResult(t){var i,n;let e=t.map(s=>s.word).join(" "),r=t.length>0?t[t.length-1].end-t[0].start:0;return{formattedText:e,segments:[{id:0,text:e,speaker:0,start:((i=t[0])==null?void 0:i.start)||0,end:((n=t[t.length-1])==null?void 0:n.end)||0,confidence:t.reduce((s,a)=>s+a.confidence,0)/t.length||0,wordCount:t.length}],speakerCount:1,statistics:{totalSpeakers:1,totalSegments:1,averageSegmentLength:t.length,speakerDistribution:{0:1},totalDuration:r,averageConfidence:t.reduce((s,a)=>s+a.confidence,0)/t.length||0},originalWordCount:t.length}}buildSegments(t,e){if(t.length===0)return[];let r=[],i=null,n=0;for(let s=0;s0?t[s-1]:null)?(i&&this.isValidSegment(i,e)&&r.push(this.finalizeSegment(i,n++)),i=this.initializeSegment(a)):i&&this.appendToSegment(i,a)}return i&&this.isValidSegment(i,e)&&r.push(this.finalizeSegment(i,n)),r}shouldCreateNewSegment(t,e,r,i){return!!(!e||e.speaker!==t.speaker||i&&e.end!==void 0&&t.start-i.end>r.merging.consecutiveThreshold)}initializeSegment(t){return{text:t.word,speaker:t.speaker||0,start:t.start,end:t.end,confidence:t.confidence,wordCount:1}}appendToSegment(t,e){t.text=(t.text||"")+" "+e.word,t.end=e.end,t.wordCount=(t.wordCount||0)+1;let r=(t.confidence||0)*((t.wordCount||1)-1)+e.confidence;t.confidence=r/(t.wordCount||1)}isValidSegment(t,e){var r;return(t.wordCount||0)>=e.merging.minSegmentLength&&(((r=t.text)==null?void 0:r.trim().length)||0)>0}finalizeSegment(t,e){return{id:e,text:(t.text||"").trim(),speaker:t.speaker||0,start:t.start||0,end:t.end||0,confidence:t.confidence||0,wordCount:t.wordCount||0}}formatSegments(t,e){if(t.length===0)return"";let r=[];for(let i of t){let n=this.generateSpeakerLabel(i.speaker,e),s="";switch(e.format){case"speaker_prefix":s=`${n}: ${i.text}`;break;case"speaker_block":s=`${n} +"use strict";var Q=Object.defineProperty;var Ze=Object.getOwnPropertyDescriptor;var pt=Object.getOwnPropertyNames;var mt=Object.prototype.hasOwnProperty;var je=(l,t)=>()=>(l&&(t=l(l=0)),t);var ht=(l,t)=>()=>(t||l((t={exports:{}}).exports,t),t.exports),Xe=(l,t)=>{for(var e in t)Q(l,e,{get:t[e],enumerable:!0})},ft=(l,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of pt(t))!mt.call(l,i)&&i!==e&&Q(l,i,{get:()=>t[i],enumerable:!(r=Ze(t,i))||r.enumerable});return l};var vt=l=>ft(Q({},"__esModule",{value:!0}),l),Qe=(l,t,e,r)=>{for(var i=r>1?void 0:r?Ze(t,e):t,n=l.length-1,s;n>=0;n--)(s=l[n])&&(i=(r?s(t,e,i):s(i))||i);return r&&i&&Q(t,e,i),i};var y,q,J,U,Y=je(()=>{"use strict";y=class extends Error{constructor(e,r,i,n=!1,s){super(e);this.code=r;this.provider=i;this.isRetryable=n;this.statusCode=s;this.name="TranscriptionError"}},q=class extends y{constructor(t,e="Invalid API key"){super(e,"AUTH_ERROR",t,!1,401)}},J=class extends y{constructor(e,r){super("Rate limit exceeded","RATE_LIMIT",e,!0,429);this.retryAfter=r}},U=class extends y{constructor(t){super("Provider temporarily unavailable","UNAVAILABLE",t,!0,503)}}});var Je={};Xe(Je,{DEFAULT_SETTINGS:()=>Pe});var Pe,Le=je(()=>{"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 dt=ht((si,bt)=>{bt.exports={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 Tt={};Xe(Tt,{default:()=>Me});module.exports=vt(Tt);var f=require("obsidian");Le();var ee=class{constructor(t,e,r,i,n,s){this.whisperService=t;this.audioProcessor=e;this.textFormatter=r;this.eventManager=i;this.logger=n;this.settings=s;this.status="idle"}async transcribe(t){var e,r,i,n,s,a,o;try{this.status="validating",this.eventManager.emit("transcription:start",{fileName:t.name});let d=await this.audioProcessor.validate(t);if(!d.valid)throw new Error(`File validation failed: ${(e=d.errors)==null?void 0:e.join(", ")}`);this.status="processing";let m=await this.audioProcessor.process(t);this.status="transcribing",this.logger.debug("Starting transcription with WhisperService");let u={language:(r=this.settings)==null?void 0:r.language,model:(i=this.settings)==null?void 0:i.model};this.logger.debug("Transcription options:",u);let g=await this.whisperService.transcribe(m.buffer,u);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)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 v=this.textFormatter.format(g.text);this.logger.debug("Text formatted:",{originalLength:g.text.length,formattedLength:v.length,formattedPreview:v.substring(0,100)});let h={text:v,language:g.language,segments:(a=g.segments)==null?void 0:a.map((M,S)=>({id:S,start:M.start,end:M.end,text:M.text}))};return this.status="completed",this.logger.debug("Emitting transcription:complete event",{textLength:h.text.length,hasSegments:!!h.segments,segmentsCount:((o=h.segments)==null?void 0:o.length)||0}),this.eventManager.emit("transcription:complete",{result:h,text:h.text}),h}catch(d){throw this.status="error",this.eventManager.emit("transcription:error",{error:d}),d}}cancel(){var t;(t=this.abortController)==null||t.abort(),this.status="cancelled",this.eventManager.emit("transcription:cancelled",{})}getStatus(){return this.status}};var it=require("obsidian");function et(l){return new Promise(t=>setTimeout(t,l))}function tt(l,t,e,r=!0){if(r){if(le)return{valid:!1,error:`Value must be between ${t} and ${e} (inclusive)`}}else if(l<=t||l>=e)return{valid:!1,error:`Value must be between ${t} and ${e} (exclusive)`};return{valid:!0}}function rt(l,t,e="..."){if(t<=0)throw new Error("Max length must be positive");if(l.length<=t)return l;let r=t-e.length;return r<=0?e:l.substring(0,r)+e}var P=class extends Error{constructor(e,r,i,n=!1){super(e);this.code=r;this.status=i;this.isRetryable=n;this.name="WhisperAPIError"}},te=class extends P{constructor(t="Invalid API key"){super(t,"AUTH_ERROR",401,!1)}},Oe=class extends P{constructor(e){super("Rate limit exceeded","RATE_LIMIT",429,!0);this.retryAfter=e}},re=class extends P{constructor(){super("File size exceeds API limit (25MB)","FILE_TOO_LARGE",413,!1)}},ke=class extends P{constructor(t,e){super(t,"SERVER_ERROR",e,!0)}},Re=class{constructor(t){this.logger=t;this.maxRetries=3;this.baseDelay=1e3;this.maxDelay=1e4}async execute(t){let e;for(let r=0;r=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")}},V=class{constructor(t,e){this.apiKey=t;this.logger=e;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.retryStrategy=new Re(e),this.circuitBreaker=new Ne(e)}async transcribe(t,e){return this.queueRequest(()=>this.executeTranscription(t,e))}async executeTranscription(t,e){if(t.byteLength>this.MAX_FILE_SIZE)throw new re;return this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(t,e)))}async performTranscription(t,e){this.abortController=new AbortController;let r=Date.now();try{let i=this.buildFormData(t,e),n=await this.buildRequestParams(i);this.logger.debug("Starting transcription request",{fileSize:t.byteLength,options:e});let s=await(0,it.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"?new P("Transcription cancelled","CANCELLED",void 0,!1):i}finally{this.abortController=void 0}}buildFormData(t,e){let r=new FormData,i=this.getMimeType(e),n=new Blob([t],{type:i});if(r.append("file",n,"audio.m4a"),r.append("model",(e==null?void 0:e.model)||"whisper-1"),e!=null&&e.language&&e.language!=="auto"&&r.append("language",e.language),e!=null&&e.prompt){let s=this.truncatePrompt(e.prompt);r.append("prompt",s)}return(e==null?void 0:e.temperature)!==void 0&&(tt(e.temperature,0,1).valid?r.append("temperature",e.temperature.toString()):this.logger.warn("Invalid temperature value, using default",{temperature:e.temperature})),e!=null&&e.responseFormat&&r.append("response_format",e.responseFormat),r}async buildRequestParams(t){let e=new Uint8Array(await new Response(t).arrayBuffer());return{url:this.API_ENDPOINT,method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`},body:e.buffer,throw:!1}}parseResponse(t,e){if(typeof t=="string")return{text:t,duration:e/1e3};let r={text:t.text||"",language:t.language,duration:t.duration||e/1e3};return t.segments&&(r.segments=t.segments),r}async handleAPIError(t){var i,n;let e=t.json,r=((i=e==null?void 0:e.error)==null?void 0:i.message)||"Unknown error";switch(this.logger.error(`API Error: ${t.status} - ${r}`,void 0,{status:t.status,errorBody:e}),t.status){case 400:throw new P(r||"Invalid request","BAD_REQUEST",400,!1);case 401:throw new te;case 429:let s=(n=t.headers)==null?void 0:n["retry-after"];throw new Oe(s?parseInt(s):void 0);case 413:throw new re;case 500:case 502:case 503:throw new ke(`Server error: ${r}`,t.status);default:throw new P(`API error: ${r}`,"UNKNOWN_ERROR",t.status,!1)}}getMimeType(t){return"audio/m4a"}truncatePrompt(t,e=224){let r=e*4;return rt(t,r)}async queueRequest(t){let e=this.requestQueue.then(t,t);return this.requestQueue=e.catch(()=>{}),e}async validateApiKey(t){let e=this.apiKey;this.apiKey=t;try{let r=new ArrayBuffer(1024);return await this.performTranscription(r,{responseFormat:"text"}),!0}catch(r){return r instanceof te?(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=e}}cancel(){this.abortController&&(this.abortController.abort(),this.logger.debug("Transcription cancelled by user"))}resetCircuitBreaker(){this.circuitBreaker.reset()}};Y();var ie=class{constructor(t,e,r){this.whisperService=t;this.logger=e;this.config={enabled:!0,apiKey:"",model:"whisper-1",maxConcurrency:1,timeout:3e4,...r}}async transcribe(t,e){let r=Date.now();try{let i=this.convertOptions(e),n=await this.whisperService.transcribe(t,i),s=Date.now()-r;return this.convertResponse(n,s)}catch(i){throw this.logger.error("WhisperAdapter: Transcription failed",i),i}}convertOptions(t){let e={model:(t==null?void 0:t.model)||this.config.model||"whisper-1",language:t==null?void 0:t.language};if(t!=null&&t.whisper){let r=t.whisper;r.temperature!==void 0&&(e.temperature=r.temperature),r.prompt&&(e.prompt=r.prompt),r.responseFormat&&(e.responseFormat=r.responseFormat)}return e.responseFormat||(e.responseFormat="verbose_json"),e}convertResponse(t,e){var i;let r=t.text.split(/\s+/).filter(n=>n.length>0).length;return{text:t.text,language:t.language,duration:t.duration,segments:(i=t.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:e,wordCount:r}}}async validateApiKey(t){return this.whisperService.validateApiKey(t)}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 t=new ArrayBuffer(1024);return await this.whisperService.transcribe(t,{responseFormat:"text"}),!0}catch(t){let e=t.message.toLowerCase();return!(e.includes("circuit")||e.includes("unavailable")||e.includes("timeout"))}}getConfig(){return{...this.config}}resetCircuitBreaker(){this.whisperService.resetCircuitBreaker()}updateConfig(t){this.config={...this.config,...t}}};var nt=require("obsidian");Y();var ne={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},se={MIN_HEADER_SIZE:44,SIZE_WARNING_THRESHOLD:1024,SIZE_WARNING_LARGE:100*1024*1024,SILENCE_THRESHOLD:327,SILENCE_PEAK_MULTIPLIER:5,SAMPLE_SIZE:8192},zt={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}},Fe={CONSECUTIVE_THRESHOLD:.5,MIN_SEGMENT_LENGTH:1,WORDS_PER_SEGMENT:10,SPEAKER_LABELS:{PREFIX:"Speaker",NUMBERING:"numeric"}};var W={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 oe={enabled:!0,format:"speaker_prefix",speakerLabels:{prefix:"Speaker",numbering:"numeric"},merging:{consecutiveThreshold:Fe.CONSECUTIVE_THRESHOLD,minSegmentLength:Fe.MIN_SEGMENT_LENGTH},output:{includeTimestamps:!1,includeConfidence:!1,paragraphBreaks:!0,lineBreaksBetweenSpeakers:!0}},ae=class{constructor(t){this.logger=t}formatTranscript(t,e=oe){let r=Date.now();if(this.logFormatStart(t,e),!this.hasSpeakerInformation(t))return this.logger.debug("No speaker information found, returning original text"),this.createFallbackResult(t);let i=this.processTranscriptWithSpeakers(t,e);return this.logFormatComplete(i,Date.now()-r),i}processTranscriptWithSpeakers(t,e){let r=this.buildSegments(t,e);this.logger.debug(`Created ${r.length} segments from ${t.length} words`);let i=this.calculateStatistics(r,t);return{formattedText:this.formatSegments(r,e),segments:r,speakerCount:i.totalSpeakers,statistics:i,originalWordCount:t.length}}logFormatStart(t,e){this.logger.debug("=== DiarizationFormatter.formatTranscript START ===",{wordCount:t.length,config:e})}logFormatComplete(t,e){this.logger.info("=== DiarizationFormatter.formatTranscript COMPLETE ===",{processingTime:e,speakerCount:t.speakerCount,segmentCount:t.segments.length,formattedTextLength:t.formattedText.length})}hasSpeakerInformation(t){return t.some(e=>e.speaker!==void 0&&e.speaker>=0)}createFallbackResult(t){var i,n;let e=t.map(s=>s.word).join(" "),r=t.length>0?t[t.length-1].end-t[0].start:0;return{formattedText:e,segments:[{id:0,text:e,speaker:0,start:((i=t[0])==null?void 0:i.start)||0,end:((n=t[t.length-1])==null?void 0:n.end)||0,confidence:t.reduce((s,a)=>s+a.confidence,0)/t.length||0,wordCount:t.length}],speakerCount:1,statistics:{totalSpeakers:1,totalSegments:1,averageSegmentLength:t.length,speakerDistribution:{0:1},totalDuration:r,averageConfidence:t.reduce((s,a)=>s+a.confidence,0)/t.length||0},originalWordCount:t.length}}buildSegments(t,e){if(t.length===0)return[];let r=[],i=null,n=0;for(let s=0;s0?t[s-1]:null)?(i&&this.isValidSegment(i,e)&&r.push(this.finalizeSegment(i,n++)),i=this.initializeSegment(a)):i&&this.appendToSegment(i,a)}return i&&this.isValidSegment(i,e)&&r.push(this.finalizeSegment(i,n)),r}shouldCreateNewSegment(t,e,r,i){return!!(!e||e.speaker!==t.speaker||i&&e.end!==void 0&&t.start-i.end>r.merging.consecutiveThreshold)}initializeSegment(t){return{text:t.word,speaker:t.speaker||0,start:t.start,end:t.end,confidence:t.confidence,wordCount:1}}appendToSegment(t,e){t.text=(t.text||"")+" "+e.word,t.end=e.end,t.wordCount=(t.wordCount||0)+1;let r=(t.confidence||0)*((t.wordCount||1)-1)+e.confidence;t.confidence=r/(t.wordCount||1)}isValidSegment(t,e){var r;return(t.wordCount||0)>=e.merging.minSegmentLength&&(((r=t.text)==null?void 0:r.trim().length)||0)>0}finalizeSegment(t,e){return{id:e,text:(t.text||"").trim(),speaker:t.speaker||0,start:t.start||0,end:t.end||0,confidence:t.confidence||0,wordCount:t.wordCount||0}}formatSegments(t,e){if(t.length===0)return"";let r=[];for(let i of t){let n=this.generateSpeakerLabel(i.speaker,e),s="";switch(e.format){case"speaker_prefix":s=`${n}: ${i.text}`;break;case"speaker_block":s=`${n} ${i.text}`;break;case"custom":s=this.applyCustomFormat(i,n,e);break;default:s=`${n}: ${i.text}`}if(e.output.includeTimestamps&&(s=`${`[${this.formatTime(i.start)} - ${this.formatTime(i.end)}]`} ${s}`),e.output.includeConfidence){let a=`(${Math.round(i.confidence*100)}%)`;s=`${s} ${a}`}r.push(s)}return e.output.lineBreaksBetweenSpeakers?this.insertSpeakerBreaks(r,t):r.join(` `)}generateSpeakerLabel(t,e){let{prefix:r,numbering:i,customLabels:n}=e.speakerLabels;if(n&&n[t])return n[t];switch(i){case"alphabetic":let s=String.fromCharCode(65+t%26);return`${r} ${s}`;case"numeric":default:return`${r} ${t+1}`}}applyCustomFormat(t,e,r){return`${e}: ${t.text}`}insertSpeakerBreaks(t,e){let r=[],i=null;for(let n=0;n0?e[e.length-1].end-e[0].start:0;return{totalSpeakers:Object.keys(r).length,totalSegments:t.length,averageSegmentLength:t.length>0?n/t.length:0,speakerDistribution:r,totalDuration:s,averageConfidence:t.length>0?i/t.length:0}}validateConfig(t){let e=[];return t.merging.consecutiveThreshold<0&&e.push("consecutiveThreshold must be non-negative"),t.merging.minSegmentLength<1&&e.push("minSegmentLength must be at least 1"),t.speakerLabels.prefix.trim()||e.push("speakerLabels.prefix cannot be empty"),{valid:e.length===0,errors:e}}};var _e=class{constructor(t){this.logger=t}validateAudio(t){let e=[],r=[],i={size:t.byteLength,isEmpty:t.byteLength===0,hasMinimumSize:t.byteLength>=se.MIN_HEADER_SIZE,format:this.detectAudioFormat(t)};i.isEmpty&&r.push(W.AUDIO_VALIDATION.EMPTY),!i.hasMinimumSize&&!i.isEmpty&&r.push(W.AUDIO_VALIDATION.TOO_SMALL),i.size>ne.MAX_FILE_SIZE&&r.push(W.AUDIO_VALIDATION.TOO_LARGE),i.sizese.SIZE_WARNING_LARGE&&e.push(W.AUDIO_VALIDATION.LARGE_WARNING);let n=r.length===0;return this.logger.debug("Audio validation completed",{isValid:n,warnings:e.length,errors:r.length,metadata:i}),{isValid:n,warnings:e,errors:r,metadata:i}}detectAudioFormat(t){if(t.byteLength<12)return;let e=new Uint8Array(t,0,12);return e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70?"wav":e[0]===255&&(e[1]&224)===224||e[0]===73&&e[1]===68&&e[2]===51?"mp3":e[0]===102&&e[1]===76&&e[2]===97&&e[3]===67?"flac":e[0]===79&&e[1]===103&&e[2]===103&&e[3]===83?"ogg":e.length>=8&&e[4]===102&&e[5]===116&&e[6]===121&&e[7]===112?"m4a":e[0]===26&&e[1]===69&&e[2]===223&&e[3]===163?"webm":(this.logger.debug("Unknown audio format detected",{firstBytes:Array.from(e.slice(0,8)).map(r=>"0x"+r.toString(16).padStart(2,"0")).join(" ")}),"unknown")}checkForSilence(t){if(t.byteLength<44)return{isSilent:!0,averageAmplitude:0,peakAmplitude:0};let e=new Uint8Array(t,0,4);if(!(e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70))return{isSilent:!1,averageAmplitude:-1,peakAmplitude:-1};try{let i=Math.min(t.byteLength-44,8192),n=new Int16Array(t,44,i/2),s=0,a=0;for(let u=0;u0?s/n.length:0,d=327;return{isSilent:o{this.queue.push(t),this.processQueue()})}async processQueue(){if(this.processing||this.queue.length===0)return;this.processing=!0;let t=6e4/this.requestsPerMinute;for(;this.queue.length>0;){let r=Date.now()-this.lastRequestTime;if(rsetTimeout(e,t))}},Ke=class{constructor(t){this.logger=t;this.state="CLOSED";this.failureCount=0;this.successCount=0;this.nextAttemptTime=0;this.failureThreshold=5;this.successThreshold=2;this.timeout=6e4}async execute(t){if(this.isOpen())throw new U("deepgram");try{let e=await t();return this.onSuccess(),e}catch(e){throw this.onFailure(),e}}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")}},Be=class{constructor(t){this.logger=t;this.maxRetries=3;this.baseDelay=1e3;this.maxDelay=1e4}async execute(t){let e;for(let r=0;rsetTimeout(e,t))}},le=class{constructor(t,e,r=100,i=3e4){this.apiKey=t;this.logger=e;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 Ke(e),this.retryStrategy=new Be(e),this.rateLimiter=new ze(r,e),this.audioValidator=new _e(e),this.diarizationFormatter=new ae(e)}async transcribe(t,e,r){return await this.rateLimiter.acquire(),this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(t,e,r)))}calculateDynamicTimeout(t){let e=t/1048576,r=this.timeout;if(e<=5)return r;let i;e<=10?i=e*30*1e3:e<=50?i=e*40*1e3*1.5:e<=100?i=e*45*1e3*1.8:i=e*50*1e3*2,e>=50&&(i=Math.max(i,40*60*1e3)),e>=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:e,baseTimeout:r,finalTimeout:i,timeoutMinutes:Math.round(i/6e4)}),i}async performTranscription(t,e,r){var s,a,o,d,m,u,g,v,h,M;this.abortController=new AbortController;let i=Date.now();this.lastAudioSize=t.byteLength;let n=this.calculateDynamicTimeout(t.byteLength);try{let S=this.audioValidator.validateAudio(t);if(this.logger.debug("Audio validation results",{isValid:S.isValid,warnings:S.warnings,errors:S.errors,metadata:S.metadata}),!S.isValid)throw new b(`Audio validation failed: ${S.errors.join(", ")}`,"INVALID_AUDIO","deepgram",!1);if(S.warnings.forEach(p=>{this.logger.warn(`Audio validation warning: ${p}`)}),S.metadata.format==="wav"){let p=this.audioValidator.checkForSilence(t);this.logger.debug("Audio silence analysis",p),p.isSilent&&this.logger.warn("Audio appears to be silent or very quiet",{averageAmplitude:p.averageAmplitude,peakAmplitude:p.peakAmplitude})}let F=this.buildUrl(e,r),K=this.buildHeaders(S.metadata.format);this.logger.debug("Starting Deepgram transcription request",{fileSize:t.byteLength,detectedFormat:S.metadata.format,url:F,options:e,language:r});let B={url:F,method:"POST",headers:K,body:t,throw:!1},$=setTimeout(()=>{this.abortController&&(this.logger.warn(`Deepgram request timeout after ${n}ms for ${t.byteLength} byte file`),this.abortController.abort())},n),C;try{C=await(0,nt.requestUrl)(B)}finally{clearTimeout($)}let X=Date.now()-i;if(this.logger.info(`Deepgram transcription completed in ${X}ms`,{status:C.status,statusText:C.status>=200&&C.status<300?"OK":"ERROR"}),C.status===200){let p=C.json;if(this.logger.debug("=== Deepgram API Raw Response Analysis ===",{hasJson:!!p,responseKeys:p?Object.keys(p):[],hasMetadata:!!(p!=null&&p.metadata),hasResults:!!(p!=null&&p.results),metadataKeys:p!=null&&p.metadata?Object.keys(p.metadata):[],resultsKeys:p!=null&&p.results?Object.keys(p.results):[],channelsCount:((a=(s=p==null?void 0:p.results)==null?void 0:s.channels)==null?void 0:a.length)||0}),(d=(o=p==null?void 0:p.results)==null?void 0:o.channels)!=null&&d[0]){let w=p.results.channels[0];this.logger.debug("First channel analysis",{hasAlternatives:!!w.alternatives,alternativesCount:((m=w.alternatives)==null?void 0:m.length)||0,detectedLanguage:w.detected_language,firstAlternative:(u=w.alternatives)!=null&&u[0]?{hasTranscript:!!w.alternatives[0].transcript,transcriptLength:((g=w.alternatives[0].transcript)==null?void 0:g.length)||0,transcriptEmpty:!w.alternatives[0].transcript||w.alternatives[0].transcript.trim()==="",transcriptPreview:((v=w.alternatives[0].transcript)==null?void 0:v.substring(0,200))+(w.alternatives[0].transcript&&w.alternatives[0].transcript.length>200?"...":""),confidence:w.alternatives[0].confidence,hasWords:!!w.alternatives[0].words,wordsCount:((h=w.alternatives[0].words)==null?void 0:h.length)||0,firstFewWords:(M=w.alternatives[0].words)==null?void 0:M.slice(0,5).map(G=>({word:G.word,confidence:G.confidence}))}:null})}return p!=null&&p.metadata&&this.logger.debug("Metadata analysis",{duration:p.metadata.duration,channels:p.metadata.channels,models:p.metadata.models,modelInfo:p.metadata.model_info}),p}else throw await this.handleAPIError(C)}catch(S){throw S.name==="AbortError"?new b("Transcription cancelled","CANCELLED","deepgram",!1):S}finally{this.abortController=void 0}}buildUrl(t,e){let r=new URLSearchParams;if(((t==null?void 0:t.tier)||"").toString().toLowerCase().includes("nova")||e&&e.startsWith("ko"))r.append("model","2-general"),r.append("tier","nova");else{let s=(t==null?void 0:t.tier)||"nova-2";r.append("model",s)}return e&&e!=="auto"?r.append("language",e):t!=null&&t.detectLanguage&&r.append("detect_language","true"),(t==null?void 0:t.punctuate)!==!1&&r.append("punctuate","true"),t!=null&&t.smartFormat&&r.append("smart_format","true"),t!=null&&t.diarize&&r.append("diarize","true"),t!=null&&t.numerals&&r.append("numerals","true"),t!=null&&t.utterances&&r.append("utterances","true"),t!=null&&t.profanityFilter&&r.append("profanity_filter","true"),t!=null&&t.redact&&t.redact.length>0&&r.append("redact",t.redact.join(",")),t!=null&&t.keywords&&t.keywords.length>0&&r.append("keywords",t.keywords.join(",")),`${this.API_ENDPOINT}?${r.toString()}`}buildHeaders(t){let e={wav:"audio/wav",mp3:"audio/mpeg",flac:"audio/flac",ogg:"audio/ogg",m4a:"audio/mp4",webm:"audio/webm",opus:"audio/opus"},r=t&&e[t]?e[t]:"audio/wav";return this.logger.debug("Content-Type selected",{detectedFormat:t,contentType:r}),{Authorization:`Token ${this.apiKey}`,"Content-Type":r}}async handleAPIError(t){var s;let e=t.json,r=t.text,n=(e==null?void 0:e.message)||(e==null?void 0:e.error)||(typeof r=="string"&&r.length>0?r:"Unknown error");switch(this.logger.error(`Deepgram API Error: ${t.status} - ${n}`,void 0,{status:t.status,errorBody:e,rawText:r}),t.status){case 400:throw new b(n||"Invalid request","BAD_REQUEST","deepgram",!1,400);case 401:throw new q("deepgram");case 402:throw new b("Insufficient credits","INSUFFICIENT_CREDITS","deepgram",!1,402);case 429:let a=(s=t.headers)==null?void 0:s["retry-after"];throw new J("deepgram",a?parseInt(a):void 0);case 500:case 502:case 503:throw new U("deepgram");case 504:let o=this.lastAudioSize?` (${Math.round(this.lastAudioSize/(1024*1024))}MB)`:"";throw new b(`Server timeout processing large audio file${o}. 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 b(`API error: ${n}`,"UNKNOWN_ERROR","deepgram",!1,t.status)}}async validateApiKey(t){let e=this.apiKey;this.apiKey=t;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=e}}cancel(){this.abortController&&(this.abortController.abort(),this.logger.debug("Deepgram transcription cancelled by user"))}resetCircuitBreaker(){this.circuitBreaker.reset()}parseResponse(t,e){var g,v,h,M,S,F,K,B,$,C,X,p,w,G,Ye;if(this.logger.debug("=== DeepgramService.parseResponse START ==="),this.logger.debug("Full response structure:",{hasMetadata:!!(t!=null&&t.metadata),hasResults:!!(t!=null&&t.results),channelsCount:((v=(g=t==null?void 0:t.results)==null?void 0:g.channels)==null?void 0:v.length)||0}),!t||!t.results||!t.results.channels||t.results.channels.length===0)throw this.logger.error("Invalid Deepgram response structure",void 0,{response:t}),new b("Invalid response from Deepgram API","INVALID_RESPONSE","deepgram",!1);let r=t.results.channels[0];if(this.logger.debug("Channel data:",{hasAlternatives:!!(r!=null&&r.alternatives),alternativesCount:((h=r==null?void 0:r.alternatives)==null?void 0:h.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 b("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:((M=i==null?void 0:i.transcript)==null?void 0:M.length)||0,transcriptPreview:(S=i==null?void 0:i.transcript)==null?void 0:S.substring(0,100),confidence:i==null?void 0:i.confidence,hasWords:!!(i!=null&&i.words),wordsCount:((F=i==null?void 0:i.words)==null?void 0:F.length)||0}),!i.transcript||i.transcript.trim().length===0){this.logger.warn("=== EMPTY TRANSCRIPT DETECTED ===",{transcript:i.transcript,transcriptType:typeof i.transcript,transcriptLength:((K=i.transcript)==null?void 0:K.length)||0,trimmedLength:((B=i.transcript)==null?void 0:B.trim().length)||0,confidence:i.confidence,hasWords:!!i.words,wordsCount:(($=i.words)==null?void 0:$.length)||0,detectedLanguage:r.detected_language,duration:t.metadata.duration,channels:t.metadata.channels,models:t.metadata.models});let E=[];i.confidence===0&&E.push("Zero confidence - possibly no speech detected"),!i.words||i.words.length===0?E.push("No word timestamps - indicates no speech recognition"):E.push(`${i.words.length} words detected but empty transcript`),t.metadata.duration<1&&E.push("Very short audio duration"),r.detected_language||E.push("No language detected"),this.logger.warn("Empty transcript diagnostic analysis",{possibleCauses:E,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 L=E.length>0?` Possible causes: ${E.join(", ")}`:"";throw new b(`Transcription service returned empty text.${L}`,"EMPTY_TRANSCRIPT","deepgram",!1)}let s=i.transcript||"",a=[],o=1,d=null,m=i.words&&i.words.length>0&&i.words.some(E=>E.speaker!==void 0&&E.speaker>=0);if(this.logger.debug("Speaker information check:",{hasWords:!!i.words,wordCount:((C=i.words)==null?void 0:C.length)||0,hasSpeakerInfo:m,diarizationEnabled:e==null?void 0:e.enabled,firstWordSpeaker:(p=(X=i.words)==null?void 0:X[0])==null?void 0:p.speaker,sampleWords:(w=i.words)==null?void 0:w.slice(0,3).map(E=>({word:E.word,speaker:E.speaker,hasSpeaker:E.speaker!==void 0}))}),e!=null&&e.enabled&&m){this.logger.debug("Processing diarization with config:",e);try{let E=(i.words||[]).map(I=>({word:I.word,start:I.start,end:I.end,confidence:I.confidence,speaker:I.speaker!==void 0?I.speaker:0}));this.logger.debug("Converting to diarized words:",{originalWordCount:(i.words||[]).length,diarizedWordCount:E.length,speakersFound:[...new Set(E.map(I=>I.speaker))],firstFewWords:E.slice(0,5).map(I=>({word:I.word,speaker:I.speaker}))});let L=this.diarizationFormatter.formatTranscript(E,e);this.logger.info("Diarization result:",{speakerCount:L.speakerCount,segmentCount:L.segments.length,formattedTextLength:L.formattedText.length,originalWordCount:L.originalWordCount,textPreview:L.formattedText.substring(0,200)}),s=L.formattedText,o=L.speakerCount,d=L.statistics,a=L.segments.map(I=>({id:I.id,start:I.start,end:I.end,text:I.text,confidence:I.confidence,speaker:I.speaker.toString()}))}catch(E){this.logger.error("Diarization formatting failed, falling back to original transcript",E),s=i.transcript||"",a=this.createSegmentsFromWords(i.words||[])}}else e!=null&&e.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:t.metadata.duration,segments:a,provider:"deepgram",metadata:{model:((G=t.metadata.models)==null?void 0:G[0])||"unknown",processingTime:t.metadata.duration,wordCount:i.transcript?i.transcript.split(/\s+/).length:0,...(e==null?void 0:e.enabled)&&{speakerCount:o,diarizationEnabled:!0,diarizationStats:d}}};return this.logger.info("=== DeepgramService.parseResponse COMPLETE ===",{textLength:u.text.length,textPreview:u.text.substring(0,100),language:u.language,confidence:u.confidence,segmentsCount:((Ye=u.segments)==null?void 0:Ye.length)||0}),u}createSegmentsFromWords(t){let e=[];for(let i=0;i0&&e.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 e}};Y();var ce=class{constructor(t){this.logger=t;this.CHUNK_SIZE=ne.RECOMMENDED_MAX_SIZE;this.WAV_HEADER_SIZE=44}needsChunking(t){return t>this.CHUNK_SIZE}async splitAudio(t){let e=t.byteLength;return this.needsChunking(e)?(this.logger.info("Splitting large audio file into chunks",{originalSizeMB:Math.round(e/(1024*1024)),chunkSizeMB:Math.round(this.CHUNK_SIZE/(1024*1024)),estimatedChunks:Math.ceil(e/this.CHUNK_SIZE)}),this.isWavFile(t)?this.splitWavAudio(t):this.splitByteArray(t)):[t]}isWavFile(t){if(t.byteLength<12)return!1;let e=new Uint8Array(t,0,4);return e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}splitWavAudio(t){let e=[],r=t.slice(0,this.WAV_HEADER_SIZE),i=t.slice(this.WAV_HEADER_SIZE),n=i.byteLength,s=this.CHUNK_SIZE-this.WAV_HEADER_SIZE,a=Math.ceil(n/s);for(let o=0;oe&&e.trim()).join(" ")}getRecommendedSettings(t){let e=t/1048576;return e<=50?{needsChunking:!1,recommendedModel:"nova-2"}:e<=100?{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"128 kbps",estimatedChunks:Math.ceil(t/this.CHUNK_SIZE)}:{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"64 kbps",estimatedChunks:Math.ceil(t/this.CHUNK_SIZE)}}};var j=class{constructor(t,e,r,i){this.deepgramService=t;this.logger=e;this.settingsManager=r;this.audioChunker=new ce(e),this.config={enabled:!0,apiKey:"",model:"nova-3",maxConcurrency:5,timeout:3e4,rateLimit:{requests:100,window:6e4},...i}}async transcribe(t,e){var n,s;let r=Date.now(),i=t.byteLength/(1024*1024);this.logger.debug("=== DeepgramAdapter.transcribe START ===",this.sanitizeForLogging({audioSize:t.byteLength,audioSizeMB:i,options:e}));try{return((s=(n=this.settingsManager)==null?void 0:n.get("autoChunking"))!=null?s:!0)&&this.audioChunker.needsChunking(t.byteLength)?(this.logger.info("Large file detected, using chunked processing",{sizeMB:i,recommendedSettings:this.audioChunker.getRecommendedSettings(t.byteLength)}),i>100&&this.logger.warn(`Very large audio file (${Math.round(i)}MB). Processing may take significant time. Consider reducing file size or bitrate for better performance.`),await this.transcribeWithChunking(t,e)):await this.transcribeStandard(t,e)}catch(a){let o=a;if(o instanceof b&&o.code==="SERVER_TIMEOUT"){let m=this.audioChunker.getRecommendedSettings(t.byteLength);this.logger.error("Timeout error - providing chunking recommendations",o,{audioSizeMB:i,recommendations:m});let u=`Transcription timeout for ${Math.round(i)}MB file. +`)}formatTime(t){let e=Math.floor(t/60),r=Math.floor(t%60);return`${e.toString().padStart(2,"0")}:${r.toString().padStart(2,"0")}`}calculateStatistics(t,e){if(t.length===0)return{totalSpeakers:0,totalSegments:0,averageSegmentLength:0,speakerDistribution:{},totalDuration:0,averageConfidence:0};let r={},i=0,n=0;for(let a of t)r[a.speaker]=(r[a.speaker]||0)+1,i+=a.confidence,n+=a.wordCount;let s=e.length>0?e[e.length-1].end-e[0].start:0;return{totalSpeakers:Object.keys(r).length,totalSegments:t.length,averageSegmentLength:t.length>0?n/t.length:0,speakerDistribution:r,totalDuration:s,averageConfidence:t.length>0?i/t.length:0}}validateConfig(t){let e=[];return t.merging.consecutiveThreshold<0&&e.push("consecutiveThreshold must be non-negative"),t.merging.minSegmentLength<1&&e.push("minSegmentLength must be at least 1"),t.speakerLabels.prefix.trim()||e.push("speakerLabels.prefix cannot be empty"),{valid:e.length===0,errors:e}}};var _e=class{constructor(t){this.logger=t}validateAudio(t){let e=[],r=[],i={size:t.byteLength,isEmpty:t.byteLength===0,hasMinimumSize:t.byteLength>=se.MIN_HEADER_SIZE,format:this.detectAudioFormat(t)};i.isEmpty&&r.push(W.AUDIO_VALIDATION.EMPTY),!i.hasMinimumSize&&!i.isEmpty&&r.push(W.AUDIO_VALIDATION.TOO_SMALL),i.size>ne.MAX_FILE_SIZE&&r.push(W.AUDIO_VALIDATION.TOO_LARGE),i.sizese.SIZE_WARNING_LARGE&&e.push(W.AUDIO_VALIDATION.LARGE_WARNING);let n=r.length===0;return this.logger.debug("Audio validation completed",{isValid:n,warnings:e.length,errors:r.length,metadata:i}),{isValid:n,warnings:e,errors:r,metadata:i}}detectAudioFormat(t){if(t.byteLength<12)return;let e=new Uint8Array(t,0,12);return e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70?"wav":e[0]===255&&(e[1]&224)===224||e[0]===73&&e[1]===68&&e[2]===51?"mp3":e[0]===102&&e[1]===76&&e[2]===97&&e[3]===67?"flac":e[0]===79&&e[1]===103&&e[2]===103&&e[3]===83?"ogg":e.length>=8&&e[4]===102&&e[5]===116&&e[6]===121&&e[7]===112?"m4a":e[0]===26&&e[1]===69&&e[2]===223&&e[3]===163?"webm":(this.logger.debug("Unknown audio format detected",{firstBytes:Array.from(e.slice(0,8)).map(r=>"0x"+r.toString(16).padStart(2,"0")).join(" ")}),"unknown")}checkForSilence(t){if(t.byteLength<44)return{isSilent:!0,averageAmplitude:0,peakAmplitude:0};let e=new Uint8Array(t,0,4);if(!(e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70))return{isSilent:!1,averageAmplitude:-1,peakAmplitude:-1};try{let i=Math.min(t.byteLength-44,8192),n=new Int16Array(t,44,i/2),s=0,a=0;for(let u=0;u0?s/n.length:0,d=327;return{isSilent:o{this.queue.push(t),this.processQueue()})}async processQueue(){if(this.processing||this.queue.length===0)return;this.processing=!0;let t=6e4/this.requestsPerMinute;for(;this.queue.length>0;){let r=Date.now()-this.lastRequestTime;if(rsetTimeout(e,t))}},Ke=class{constructor(t){this.logger=t;this.state="CLOSED";this.failureCount=0;this.successCount=0;this.nextAttemptTime=0;this.failureThreshold=5;this.successThreshold=2;this.timeout=6e4}async execute(t){if(this.isOpen())throw new U("deepgram");try{let e=await t();return this.onSuccess(),e}catch(e){throw this.onFailure(),e}}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")}},Be=class{constructor(t){this.logger=t;this.maxRetries=3;this.baseDelay=1e3;this.maxDelay=1e4}async execute(t){let e;for(let r=0;rsetTimeout(e,t))}},le=class{constructor(t,e,r=100,i=3e4){this.apiKey=t;this.logger=e;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 Ke(e),this.retryStrategy=new Be(e),this.rateLimiter=new ze(r,e),this.audioValidator=new _e(e),this.diarizationFormatter=new ae(e)}async transcribe(t,e,r){return await this.rateLimiter.acquire(),this.circuitBreaker.execute(()=>this.retryStrategy.execute(()=>this.performTranscription(t,e,r)))}calculateDynamicTimeout(t){let e=t/1048576,r=this.timeout;if(e<=5)return r;let i;e<=10?i=e*30*1e3:e<=50?i=e*40*1e3*1.5:e<=100?i=e*45*1e3*1.8:i=e*50*1e3*2,e>=50&&(i=Math.max(i,40*60*1e3)),e>=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:e,baseTimeout:r,finalTimeout:i,timeoutMinutes:Math.round(i/6e4)}),i}async performTranscription(t,e,r){var s,a,o,d,m,u,g,v,h,M;this.abortController=new AbortController;let i=Date.now();this.lastAudioSize=t.byteLength;let n=this.calculateDynamicTimeout(t.byteLength);try{let S=this.audioValidator.validateAudio(t);if(this.logger.debug("Audio validation results",{isValid:S.isValid,warnings:S.warnings,errors:S.errors,metadata:S.metadata}),!S.isValid)throw new y(`Audio validation failed: ${S.errors.join(", ")}`,"INVALID_AUDIO","deepgram",!1);if(S.warnings.forEach(p=>{this.logger.warn(`Audio validation warning: ${p}`)}),S.metadata.format==="wav"){let p=this.audioValidator.checkForSilence(t);this.logger.debug("Audio silence analysis",p),p.isSilent&&this.logger.warn("Audio appears to be silent or very quiet",{averageAmplitude:p.averageAmplitude,peakAmplitude:p.peakAmplitude})}let F=this.buildUrl(e,r),K=this.buildHeaders(S.metadata.format);this.logger.debug("Starting Deepgram transcription request",{fileSize:t.byteLength,detectedFormat:S.metadata.format,url:F,options:e,language:r});let B={url:F,method:"POST",headers:K,body:t,throw:!1},$=setTimeout(()=>{this.abortController&&(this.logger.warn(`Deepgram request timeout after ${n}ms for ${t.byteLength} byte file`),this.abortController.abort())},n),C;try{C=await(0,nt.requestUrl)(B)}finally{clearTimeout($)}let X=Date.now()-i;if(this.logger.info(`Deepgram transcription completed in ${X}ms`,{status:C.status,statusText:C.status>=200&&C.status<300?"OK":"ERROR"}),C.status===200){let p=C.json;if(this.logger.debug("=== Deepgram API Raw Response Analysis ===",{hasJson:!!p,responseKeys:p?Object.keys(p):[],hasMetadata:!!(p!=null&&p.metadata),hasResults:!!(p!=null&&p.results),metadataKeys:p!=null&&p.metadata?Object.keys(p.metadata):[],resultsKeys:p!=null&&p.results?Object.keys(p.results):[],channelsCount:((a=(s=p==null?void 0:p.results)==null?void 0:s.channels)==null?void 0:a.length)||0}),(d=(o=p==null?void 0:p.results)==null?void 0:o.channels)!=null&&d[0]){let w=p.results.channels[0];this.logger.debug("First channel analysis",{hasAlternatives:!!w.alternatives,alternativesCount:((m=w.alternatives)==null?void 0:m.length)||0,detectedLanguage:w.detected_language,firstAlternative:(u=w.alternatives)!=null&&u[0]?{hasTranscript:!!w.alternatives[0].transcript,transcriptLength:((g=w.alternatives[0].transcript)==null?void 0:g.length)||0,transcriptEmpty:!w.alternatives[0].transcript||w.alternatives[0].transcript.trim()==="",transcriptPreview:((v=w.alternatives[0].transcript)==null?void 0:v.substring(0,200))+(w.alternatives[0].transcript&&w.alternatives[0].transcript.length>200?"...":""),confidence:w.alternatives[0].confidence,hasWords:!!w.alternatives[0].words,wordsCount:((h=w.alternatives[0].words)==null?void 0:h.length)||0,firstFewWords:(M=w.alternatives[0].words)==null?void 0:M.slice(0,5).map(G=>({word:G.word,confidence:G.confidence}))}:null})}return p!=null&&p.metadata&&this.logger.debug("Metadata analysis",{duration:p.metadata.duration,channels:p.metadata.channels,models:p.metadata.models,modelInfo:p.metadata.model_info}),p}else throw await this.handleAPIError(C)}catch(S){throw S.name==="AbortError"?new y("Transcription cancelled","CANCELLED","deepgram",!1):S}finally{this.abortController=void 0}}buildUrl(t,e){let r=new URLSearchParams;if(((t==null?void 0:t.tier)||"").toString().toLowerCase().includes("nova")||e&&e.startsWith("ko"))r.append("model","2-general"),r.append("tier","nova");else{let s=(t==null?void 0:t.tier)||"nova-2";r.append("model",s)}return e&&e!=="auto"?r.append("language",e):t!=null&&t.detectLanguage&&r.append("detect_language","true"),(t==null?void 0:t.punctuate)!==!1&&r.append("punctuate","true"),t!=null&&t.smartFormat&&r.append("smart_format","true"),t!=null&&t.diarize&&r.append("diarize","true"),t!=null&&t.numerals&&r.append("numerals","true"),t!=null&&t.utterances&&r.append("utterances","true"),t!=null&&t.profanityFilter&&r.append("profanity_filter","true"),t!=null&&t.redact&&t.redact.length>0&&r.append("redact",t.redact.join(",")),t!=null&&t.keywords&&t.keywords.length>0&&r.append("keywords",t.keywords.join(",")),`${this.API_ENDPOINT}?${r.toString()}`}buildHeaders(t){let e={wav:"audio/wav",mp3:"audio/mpeg",flac:"audio/flac",ogg:"audio/ogg",m4a:"audio/mp4",webm:"audio/webm",opus:"audio/opus"},r=t&&e[t]?e[t]:"audio/wav";return this.logger.debug("Content-Type selected",{detectedFormat:t,contentType:r}),{Authorization:`Token ${this.apiKey}`,"Content-Type":r}}async handleAPIError(t){var s;let e=t.json,r=t.text,n=(e==null?void 0:e.message)||(e==null?void 0:e.error)||(typeof r=="string"&&r.length>0?r:"Unknown error");switch(this.logger.error(`Deepgram API Error: ${t.status} - ${n}`,void 0,{status:t.status,errorBody:e,rawText:r}),t.status){case 400:throw new y(n||"Invalid request","BAD_REQUEST","deepgram",!1,400);case 401:throw new q("deepgram");case 402:throw new y("Insufficient credits","INSUFFICIENT_CREDITS","deepgram",!1,402);case 429:let a=(s=t.headers)==null?void 0:s["retry-after"];throw new J("deepgram",a?parseInt(a):void 0);case 500:case 502:case 503:throw new U("deepgram");case 504:let o=this.lastAudioSize?` (${Math.round(this.lastAudioSize/(1024*1024))}MB)`:"";throw new y(`Server timeout processing large audio file${o}. 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 y(`API error: ${n}`,"UNKNOWN_ERROR","deepgram",!1,t.status)}}async validateApiKey(t){let e=this.apiKey;this.apiKey=t;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=e}}cancel(){this.abortController&&(this.abortController.abort(),this.logger.debug("Deepgram transcription cancelled by user"))}resetCircuitBreaker(){this.circuitBreaker.reset()}parseResponse(t,e){var g,v,h,M,S,F,K,B,$,C,X,p,w,G,Ye;if(this.logger.debug("=== DeepgramService.parseResponse START ==="),this.logger.debug("Full response structure:",{hasMetadata:!!(t!=null&&t.metadata),hasResults:!!(t!=null&&t.results),channelsCount:((v=(g=t==null?void 0:t.results)==null?void 0:g.channels)==null?void 0:v.length)||0}),!t||!t.results||!t.results.channels||t.results.channels.length===0)throw this.logger.error("Invalid Deepgram response structure",void 0,{response:t}),new y("Invalid response from Deepgram API","INVALID_RESPONSE","deepgram",!1);let r=t.results.channels[0];if(this.logger.debug("Channel data:",{hasAlternatives:!!(r!=null&&r.alternatives),alternativesCount:((h=r==null?void 0:r.alternatives)==null?void 0:h.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 y("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:((M=i==null?void 0:i.transcript)==null?void 0:M.length)||0,transcriptPreview:(S=i==null?void 0:i.transcript)==null?void 0:S.substring(0,100),confidence:i==null?void 0:i.confidence,hasWords:!!(i!=null&&i.words),wordsCount:((F=i==null?void 0:i.words)==null?void 0:F.length)||0}),!i.transcript||i.transcript.trim().length===0){this.logger.warn("=== EMPTY TRANSCRIPT DETECTED ===",{transcript:i.transcript,transcriptType:typeof i.transcript,transcriptLength:((K=i.transcript)==null?void 0:K.length)||0,trimmedLength:((B=i.transcript)==null?void 0:B.trim().length)||0,confidence:i.confidence,hasWords:!!i.words,wordsCount:(($=i.words)==null?void 0:$.length)||0,detectedLanguage:r.detected_language,duration:t.metadata.duration,channels:t.metadata.channels,models:t.metadata.models});let E=[];i.confidence===0&&E.push("Zero confidence - possibly no speech detected"),!i.words||i.words.length===0?E.push("No word timestamps - indicates no speech recognition"):E.push(`${i.words.length} words detected but empty transcript`),t.metadata.duration<1&&E.push("Very short audio duration"),r.detected_language||E.push("No language detected"),this.logger.warn("Empty transcript diagnostic analysis",{possibleCauses:E,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 L=E.length>0?` Possible causes: ${E.join(", ")}`:"";throw new y(`Transcription service returned empty text.${L}`,"EMPTY_TRANSCRIPT","deepgram",!1)}let s=i.transcript||"",a=[],o=1,d=null,m=i.words&&i.words.length>0&&i.words.some(E=>E.speaker!==void 0&&E.speaker>=0);if(this.logger.debug("Speaker information check:",{hasWords:!!i.words,wordCount:((C=i.words)==null?void 0:C.length)||0,hasSpeakerInfo:m,diarizationEnabled:e==null?void 0:e.enabled,firstWordSpeaker:(p=(X=i.words)==null?void 0:X[0])==null?void 0:p.speaker,sampleWords:(w=i.words)==null?void 0:w.slice(0,3).map(E=>({word:E.word,speaker:E.speaker,hasSpeaker:E.speaker!==void 0}))}),e!=null&&e.enabled&&m){this.logger.debug("Processing diarization with config:",e);try{let E=(i.words||[]).map(I=>({word:I.word,start:I.start,end:I.end,confidence:I.confidence,speaker:I.speaker!==void 0?I.speaker:0}));this.logger.debug("Converting to diarized words:",{originalWordCount:(i.words||[]).length,diarizedWordCount:E.length,speakersFound:[...new Set(E.map(I=>I.speaker))],firstFewWords:E.slice(0,5).map(I=>({word:I.word,speaker:I.speaker}))});let L=this.diarizationFormatter.formatTranscript(E,e);this.logger.info("Diarization result:",{speakerCount:L.speakerCount,segmentCount:L.segments.length,formattedTextLength:L.formattedText.length,originalWordCount:L.originalWordCount,textPreview:L.formattedText.substring(0,200)}),s=L.formattedText,o=L.speakerCount,d=L.statistics,a=L.segments.map(I=>({id:I.id,start:I.start,end:I.end,text:I.text,confidence:I.confidence,speaker:I.speaker.toString()}))}catch(E){this.logger.error("Diarization formatting failed, falling back to original transcript",E),s=i.transcript||"",a=this.createSegmentsFromWords(i.words||[])}}else e!=null&&e.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:t.metadata.duration,segments:a,provider:"deepgram",metadata:{model:((G=t.metadata.models)==null?void 0:G[0])||"unknown",processingTime:t.metadata.duration,wordCount:i.transcript?i.transcript.split(/\s+/).length:0,...(e==null?void 0:e.enabled)&&{speakerCount:o,diarizationEnabled:!0,diarizationStats:d}}};return this.logger.info("=== DeepgramService.parseResponse COMPLETE ===",{textLength:u.text.length,textPreview:u.text.substring(0,100),language:u.language,confidence:u.confidence,segmentsCount:((Ye=u.segments)==null?void 0:Ye.length)||0}),u}createSegmentsFromWords(t){let e=[];for(let i=0;i0&&e.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 e}};Y();var ce=class{constructor(t){this.logger=t;this.CHUNK_SIZE=ne.RECOMMENDED_MAX_SIZE;this.WAV_HEADER_SIZE=44}needsChunking(t){return t>this.CHUNK_SIZE}async splitAudio(t){let e=t.byteLength;return this.needsChunking(e)?(this.logger.info("Splitting large audio file into chunks",{originalSizeMB:Math.round(e/(1024*1024)),chunkSizeMB:Math.round(this.CHUNK_SIZE/(1024*1024)),estimatedChunks:Math.ceil(e/this.CHUNK_SIZE)}),this.isWavFile(t)?this.splitWavAudio(t):this.splitByteArray(t)):[t]}isWavFile(t){if(t.byteLength<12)return!1;let e=new Uint8Array(t,0,4);return e[0]===82&&e[1]===73&&e[2]===70&&e[3]===70}splitWavAudio(t){let e=[],r=t.slice(0,this.WAV_HEADER_SIZE),i=t.slice(this.WAV_HEADER_SIZE),n=i.byteLength,s=this.CHUNK_SIZE-this.WAV_HEADER_SIZE,a=Math.ceil(n/s);for(let o=0;oe&&e.trim()).join(" ")}getRecommendedSettings(t){let e=t/1048576;return e<=50?{needsChunking:!1,recommendedModel:"nova-2"}:e<=100?{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"128 kbps",estimatedChunks:Math.ceil(t/this.CHUNK_SIZE)}:{needsChunking:!0,recommendedModel:"enhanced",recommendedBitrate:"64 kbps",estimatedChunks:Math.ceil(t/this.CHUNK_SIZE)}}};var j=class{constructor(t,e,r,i){this.deepgramService=t;this.logger=e;this.settingsManager=r;this.audioChunker=new ce(e),this.config={enabled:!0,apiKey:"",model:"nova-3",maxConcurrency:5,timeout:3e4,rateLimit:{requests:100,window:6e4},...i}}async transcribe(t,e){var n,s;let r=Date.now(),i=t.byteLength/(1024*1024);this.logger.debug("=== DeepgramAdapter.transcribe START ===",this.sanitizeForLogging({audioSize:t.byteLength,audioSizeMB:i,options:e}));try{return((s=(n=this.settingsManager)==null?void 0:n.get("autoChunking"))!=null?s:!0)&&this.audioChunker.needsChunking(t.byteLength)?(this.logger.info("Large file detected, using chunked processing",{sizeMB:i,recommendedSettings:this.audioChunker.getRecommendedSettings(t.byteLength)}),i>100&&this.logger.warn(`Very large audio file (${Math.round(i)}MB). Processing may take significant time. Consider reducing file size or bitrate for better performance.`),await this.transcribeWithChunking(t,e)):await this.transcribeStandard(t,e)}catch(a){let o=a;if(o instanceof y&&o.code==="SERVER_TIMEOUT"){let m=this.audioChunker.getRecommendedSettings(t.byteLength);this.logger.error("Timeout error - providing chunking recommendations",o,{audioSizeMB:i,recommendations:m});let u=`Transcription timeout for ${Math.round(i)}MB file. Recommended solutions: - Enable automatic chunking (files will be split into ${m.estimatedChunks||"multiple"} chunks) - Use '${m.recommendedModel}' model for faster processing - Reduce audio bitrate to ${m.recommendedBitrate||"128 kbps"} -- Convert to MP3 or OGG format for smaller file size`;throw new b(u,o.code,o.provider,o.isRetryable,o.statusCode)}throw this.enhanceTranscriptionError(o,t,e)}}async transcribeStandard(t,e){var i,n,s;let r=Date.now();try{let a=this.convertOptions(e),o=e==null?void 0:e.language;this.logger.debug("Calling Deepgram API with options:",this.sanitizeForLogging({deepgramOptions:a,language:o}));let d=await this.deepgramService.transcribe(t,a,o);this.logger.debug("Deepgram API response received:",{hasResponse:!!d,responseType:typeof d,hasResults:!!(d!=null&&d.results)});let m=this.createDiarizationConfig(a),u=this.deepgramService.parseResponse(d,m);return this.logger.debug("Parsed response:",{hasText:!!(u!=null&&u.text),textLength:((i=u==null?void 0:u.text)==null?void 0:i.length)||0,textPreview:(n=u==null?void 0:u.text)==null?void 0:n.substring(0,100)}),u.metadata={...u.metadata,processingTime:Date.now()-r},this.logger.info("=== DeepgramAdapter.transcribe COMPLETE ===",{processingTime:u.metadata.processingTime,textLength:((s=u.text)==null?void 0:s.length)||0,language:u.language}),u}finally{}}async transcribeWithChunking(t,e){var i,n;let r=Date.now();try{let s=await this.audioChunker.splitAudio(t);this.logger.info(`Processing ${s.length} audio chunks`);let a=[],o=0,d;for(let v=0;v0?o/a.length:0;if(!m||m.trim().length===0)throw new b("All chunks failed to produce transcription","CHUNKING_FAILED","deepgram",!1);let g={text:m,language:d,confidence:u,provider:"deepgram",metadata:{processingTime:Date.now()-r,chunksProcessed:s.length,chunksSuccessful:a.length,isPartial:a.length{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 o=s.toLowerCase();e.some(d=>o.includes(d))?n[s]="***":n[s]=r(a)}return n};return r(t)}estimateCost(t,e){let r=e||this.config.model||j.DEFAULT_TIER,i={"nova-3":.0043,"nova-2":.0145,nova:.0125,enhanced:.0085,base:.0059},n=t/60,s=i[r]||i[j.DEFAULT_TIER];return n*s}},Z=j;Z.DEFAULT_TIER="nova-3";var $e=class{constructor(t){this.logger=t;this.metrics=new Map;this.initializeMetrics()}initializeMetrics(){["whisper","deepgram"].forEach(e=>{this.metrics.set(e,{provider:e,totalRequests:0,successfulRequests:0,failedRequests:0,averageLatency:0,averageCost:0})})}recordRequest(t,e,r,i,n){let s=this.metrics.get(t);s&&(s.totalRequests++,e?(s.successfulRequests++,r!==void 0&&(s.averageLatency=(s.averageLatency*(s.successfulRequests-1)+r)/s.successfulRequests),i!==void 0&&(s.averageCost=(s.averageCost*(s.successfulRequests-1)+i)/s.successfulRequests)):(s.failedRequests++,n&&(s.lastError={message:n.message,timestamp:new Date})),this.logger.debug(`Metrics updated for ${t}`,s))}getMetrics(t){return this.metrics.get(t)}getAllMetrics(){return Array.from(this.metrics.values())}getSuccessRate(t){let e=this.metrics.get(t);return!e||e.totalRequests===0?0:e.successfulRequests/e.totalRequests}},Ue=class{constructor(t,e){this.logger=t;this.metricsTracker=e;this.roundRobinIndex=0}select(t,e,r){let i=Array.from(t.entries()).filter(([n,s])=>s.getConfig().enabled);if(i.length===0)throw new Error("No transcription providers available");switch(e){case"cost_optimized":return this.selectByCost(i);case"performance_optimized":return this.selectByPerformance(i);case"quality_optimized":return this.selectByQuality(i);case"round_robin":return this.selectRoundRobin(i);case"ab_test":return this.selectForABTest(i,r);case"manual":default:return i[0][1]}}selectByCost(t){let e=t.find(([r])=>r==="deepgram");return e?e[1]:t[0][1]}selectByPerformance(t){let e=t[0],r=1/0;for(let[i,n]of t){let s=this.metricsTracker.getMetrics(i);s&&s.averageLatencyr&&(r=s,e=[i,n])}return e[1]}selectRoundRobin(t){let e=t[this.roundRobinIndex%t.length];return this.roundRobinIndex++,e[1]}selectForABTest(t,e){if(!e)return this.selectRoundRobin(t);if(this.hashString(e)<.5){let n=t.find(([s])=>s==="whisper");return n?n[1]:t[0][1]}else{let n=t.find(([s])=>s==="deepgram");return n?n[1]:t[0][1]}}hashString(t){let e=0;for(let r=0;re.getConfig().enabled).map(([t])=>t)}recordMetrics(t,e,r,i,n){var s;this.metricsTracker.recordRequest(t,e,r,i,n),(s=this.config.monitoring)!=null&&s.enabled&&this.config.monitoring.metricsEndpoint&&this.sendMetricsToEndpoint(t)}getMetrics(t){if(t){let e=this.metricsTracker.getMetrics(t);if(!e)throw new Error(`No metrics found for provider: ${t}`);return e}return this.metricsTracker.getAllMetrics()}async sendMetricsToEndpoint(t){let e=this.metricsTracker.getMetrics(t);this.logger.debug("Sending metrics to monitoring endpoint",e)}async updateConfig(t){this.config={...this.config,...t},await this.settingsManager.set("transcription",this.config),this.reinitializeProviders()}reinitializeProviders(){this.providers.clear(),this.initializeProviders(),this.logger.info("Providers reinitialized with new configuration")}async toggleProvider(t,e){let r=t==="whisper"?this.config.whisper:this.config.deepgram;r&&(r.enabled=e,await this.updateConfig(this.config))}async setDefaultProvider(t){this.config.defaultProvider=t,await this.updateConfig(this.config)}};var ue=class{constructor(t,e){this.transcriber=t;this.logger=e}async transcribe(t,e){var s,a,o,d,m,u,g,v;(s=this.logger)==null||s.debug("=== TranscriberToWhisperAdapter.transcribe START ===",{audioSize:t.byteLength,provider:this.transcriber.getProviderName(),options:e});let r={language:e==null?void 0:e.language,model:e==null?void 0:e.model,whisper:{temperature:e==null?void 0:e.temperature,prompt:e==null?void 0:e.prompt,responseFormat:e==null?void 0:e.responseFormat}},i=await this.transcriber.transcribe(t,r);(m=this.logger)==null||m.debug("Transcriber response received:",{hasText:!!(i!=null&&i.text),textLength:((a=i==null?void 0:i.text)==null?void 0:a.length)||0,textPreview:(o=i==null?void 0:i.text)==null?void 0:o.substring(0,100),language:i==null?void 0:i.language,segmentsCount:((d=i==null?void 0:i.segments)==null?void 0:d.length)||0});let n={text:i.text||"",language:i.language,duration:i.duration,segments:(u=i.segments)==null?void 0:u.map(h=>({id:h.id,seek:0,start:h.start,end:h.end,text:h.text,tokens:[],temperature:0,avg_logprob:0,compression_ratio:0,no_speech_prob:0}))};return(v=this.logger)==null||v.info("=== TranscriberToWhisperAdapter.transcribe COMPLETE ===",{textLength:((g=n.text)==null?void 0:g.length)||0,language:n.language}),n}async validateApiKey(t){return this.transcriber.validateApiKey(t)}cancel(){this.transcriber.cancel()}getTranscriber(){return this.transcriber}getProviderName(){return this.transcriber.getProviderName()}};var ge=class{constructor(t,e){this.vault=t;this.logger=e;this.DEFAULT_MAX_FILE_SIZE=25*1024*1024;this.SUPPORTED_FORMATS=[".m4a",".mp3",".wav",".mp4"];this.maxFileSize=this.DEFAULT_MAX_FILE_SIZE}setProviderCapabilities(t){this.maxFileSize=t.maxFileSize,this.logger.debug("AudioProcessor capabilities updated",{previousLimit:this.DEFAULT_MAX_FILE_SIZE/1024/1024,newLimit:t.maxFileSize/1024/1024,provider:t.maxFileSize===2*1024*1024*1024?"Deepgram":"Whisper"})}async validate(t){let e=[],r=[],i=`.${t.extension.toLowerCase()}`;if(this.SUPPORTED_FORMATS.includes(i)||e.push(`Unsupported format: ${i}. Supported formats: ${this.SUPPORTED_FORMATS.join(", ")}`),t.stat.size>this.maxFileSize){let n=Math.round(t.stat.size/1024/1024),s=Math.round(this.maxFileSize/1024/1024);e.push(`File size (${n}MB) exceeds maximum allowed size (${s}MB)`)}return t.stat.size>10*1024*1024&&r.push("Large file may take longer to process"),{valid:e.length===0,errors:e.length>0?e:void 0,warnings:r.length>0?r:void 0}}async process(t){this.logger.debug("Processing audio file",{fileName:t.name,extension:t.extension,sizeBytes:t.stat.size});let e=await this.vault.readBinary(t),r=await this.extractMetadata(e,t);return this.logger.debug("Audio processing completed",{bufferSize:e.byteLength,detectedFormat:r.format}),{buffer:e,metadata:r,originalFile:t,compressed:!1}}async extractMetadata(t,e){let r;if(e){let n=e.extension.toLowerCase();r=n,this.logger.debug("Audio format detected from file extension",{fileName:e.name,extension:n,format:r})}let i=Math.round(t.byteLength/1024);return this.logger.debug("Audio file analysis",{sizeKB:i,sizeBytes:t.byteLength,format:r}),{duration:void 0,bitrate:void 0,sampleRate:void 0,channels:void 0,codec:void 0,format:r,fileSize:t.byteLength}}};var pe=class{constructor(t){this.settings=t}format(t,e){let r=this.cleanUp(t);return this.settings.timestampFormat!=="none"&&(e!=null&&e.includeTimestamps),r}insertTimestamps(t,e){if(!e||e.length===0)return t;let r=t.split(` +- Convert to MP3 or OGG format for smaller file size`;throw new y(u,o.code,o.provider,o.isRetryable,o.statusCode)}throw this.enhanceTranscriptionError(o,t,e)}}async transcribeStandard(t,e){var i,n,s;let r=Date.now();try{let a=this.convertOptions(e),o=e==null?void 0:e.language;this.logger.debug("Calling Deepgram API with options:",this.sanitizeForLogging({deepgramOptions:a,language:o}));let d=await this.deepgramService.transcribe(t,a,o);this.logger.debug("Deepgram API response received:",{hasResponse:!!d,responseType:typeof d,hasResults:!!(d!=null&&d.results)});let m=this.createDiarizationConfig(a),u=this.deepgramService.parseResponse(d,m);return this.logger.debug("Parsed response:",{hasText:!!(u!=null&&u.text),textLength:((i=u==null?void 0:u.text)==null?void 0:i.length)||0,textPreview:(n=u==null?void 0:u.text)==null?void 0:n.substring(0,100)}),u.metadata={...u.metadata,processingTime:Date.now()-r},this.logger.info("=== DeepgramAdapter.transcribe COMPLETE ===",{processingTime:u.metadata.processingTime,textLength:((s=u.text)==null?void 0:s.length)||0,language:u.language}),u}finally{}}async transcribeWithChunking(t,e){var i,n;let r=Date.now();try{let s=await this.audioChunker.splitAudio(t);this.logger.info(`Processing ${s.length} audio chunks`);let a=[],o=0,d;for(let v=0;v0?o/a.length:0;if(!m||m.trim().length===0)throw new y("All chunks failed to produce transcription","CHUNKING_FAILED","deepgram",!1);let g={text:m,language:d,confidence:u,provider:"deepgram",metadata:{processingTime:Date.now()-r,chunksProcessed:s.length,chunksSuccessful:a.length,isPartial:a.length{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 o=s.toLowerCase();e.some(d=>o.includes(d))?n[s]="***":n[s]=r(a)}return n};return r(t)}estimateCost(t,e){let r=e||this.config.model||j.DEFAULT_TIER,i={"nova-3":.0043,"nova-2":.0145,nova:.0125,enhanced:.0085,base:.0059},n=t/60,s=i[r]||i[j.DEFAULT_TIER];return n*s}},Z=j;Z.DEFAULT_TIER="nova-3";var $e=class{constructor(t){this.logger=t;this.metrics=new Map;this.initializeMetrics()}initializeMetrics(){["whisper","deepgram"].forEach(e=>{this.metrics.set(e,{provider:e,totalRequests:0,successfulRequests:0,failedRequests:0,averageLatency:0,averageCost:0})})}recordRequest(t,e,r,i,n){let s=this.metrics.get(t);s&&(s.totalRequests++,e?(s.successfulRequests++,r!==void 0&&(s.averageLatency=(s.averageLatency*(s.successfulRequests-1)+r)/s.successfulRequests),i!==void 0&&(s.averageCost=(s.averageCost*(s.successfulRequests-1)+i)/s.successfulRequests)):(s.failedRequests++,n&&(s.lastError={message:n.message,timestamp:new Date})),this.logger.debug(`Metrics updated for ${t}`,s))}getMetrics(t){return this.metrics.get(t)}getAllMetrics(){return Array.from(this.metrics.values())}getSuccessRate(t){let e=this.metrics.get(t);return!e||e.totalRequests===0?0:e.successfulRequests/e.totalRequests}},Ue=class{constructor(t,e){this.logger=t;this.metricsTracker=e;this.roundRobinIndex=0}select(t,e,r){let i=Array.from(t.entries()).filter(([n,s])=>s.getConfig().enabled);if(i.length===0)throw new Error("No transcription providers available");switch(e){case"cost_optimized":return this.selectByCost(i);case"performance_optimized":return this.selectByPerformance(i);case"quality_optimized":return this.selectByQuality(i);case"round_robin":return this.selectRoundRobin(i);case"ab_test":return this.selectForABTest(i,r);case"manual":default:return i[0][1]}}selectByCost(t){let e=t.find(([r])=>r==="deepgram");return e?e[1]:t[0][1]}selectByPerformance(t){let e=t[0],r=1/0;for(let[i,n]of t){let s=this.metricsTracker.getMetrics(i);s&&s.averageLatencyr&&(r=s,e=[i,n])}return e[1]}selectRoundRobin(t){let e=t[this.roundRobinIndex%t.length];return this.roundRobinIndex++,e[1]}selectForABTest(t,e){if(!e)return this.selectRoundRobin(t);if(this.hashString(e)<.5){let n=t.find(([s])=>s==="whisper");return n?n[1]:t[0][1]}else{let n=t.find(([s])=>s==="deepgram");return n?n[1]:t[0][1]}}hashString(t){let e=0;for(let r=0;re.getConfig().enabled).map(([t])=>t)}recordMetrics(t,e,r,i,n){var s;this.metricsTracker.recordRequest(t,e,r,i,n),(s=this.config.monitoring)!=null&&s.enabled&&this.config.monitoring.metricsEndpoint&&this.sendMetricsToEndpoint(t)}getMetrics(t){if(t){let e=this.metricsTracker.getMetrics(t);if(!e)throw new Error(`No metrics found for provider: ${t}`);return e}return this.metricsTracker.getAllMetrics()}async sendMetricsToEndpoint(t){let e=this.metricsTracker.getMetrics(t);this.logger.debug("Sending metrics to monitoring endpoint",e)}async updateConfig(t){this.config={...this.config,...t},await this.settingsManager.set("transcription",this.config),this.reinitializeProviders()}reinitializeProviders(){this.providers.clear(),this.initializeProviders(),this.logger.info("Providers reinitialized with new configuration")}async toggleProvider(t,e){let r=t==="whisper"?this.config.whisper:this.config.deepgram;r&&(r.enabled=e,await this.updateConfig(this.config))}async setDefaultProvider(t){this.config.defaultProvider=t,await this.updateConfig(this.config)}};var ue=class{constructor(t,e){this.transcriber=t;this.logger=e}async transcribe(t,e){var s,a,o,d,m,u,g,v;(s=this.logger)==null||s.debug("=== TranscriberToWhisperAdapter.transcribe START ===",{audioSize:t.byteLength,provider:this.transcriber.getProviderName(),options:e});let r={language:e==null?void 0:e.language,model:e==null?void 0:e.model,whisper:{temperature:e==null?void 0:e.temperature,prompt:e==null?void 0:e.prompt,responseFormat:e==null?void 0:e.responseFormat}},i=await this.transcriber.transcribe(t,r);(m=this.logger)==null||m.debug("Transcriber response received:",{hasText:!!(i!=null&&i.text),textLength:((a=i==null?void 0:i.text)==null?void 0:a.length)||0,textPreview:(o=i==null?void 0:i.text)==null?void 0:o.substring(0,100),language:i==null?void 0:i.language,segmentsCount:((d=i==null?void 0:i.segments)==null?void 0:d.length)||0});let n={text:i.text||"",language:i.language,duration:i.duration,segments:(u=i.segments)==null?void 0:u.map(h=>({id:h.id,seek:0,start:h.start,end:h.end,text:h.text,tokens:[],temperature:0,avg_logprob:0,compression_ratio:0,no_speech_prob:0}))};return(v=this.logger)==null||v.info("=== TranscriberToWhisperAdapter.transcribe COMPLETE ===",{textLength:((g=n.text)==null?void 0:g.length)||0,language:n.language}),n}async validateApiKey(t){return this.transcriber.validateApiKey(t)}cancel(){this.transcriber.cancel()}getTranscriber(){return this.transcriber}getProviderName(){return this.transcriber.getProviderName()}};var ge=class{constructor(t,e){this.vault=t;this.logger=e;this.DEFAULT_MAX_FILE_SIZE=25*1024*1024;this.SUPPORTED_FORMATS=[".m4a",".mp3",".wav",".mp4"];this.maxFileSize=this.DEFAULT_MAX_FILE_SIZE}setProviderCapabilities(t){this.maxFileSize=t.maxFileSize,this.logger.debug("AudioProcessor capabilities updated",{previousLimit:this.DEFAULT_MAX_FILE_SIZE/1024/1024,newLimit:t.maxFileSize/1024/1024,provider:t.maxFileSize===2*1024*1024*1024?"Deepgram":"Whisper"})}async validate(t){let e=[],r=[],i=`.${t.extension.toLowerCase()}`;if(this.SUPPORTED_FORMATS.includes(i)||e.push(`Unsupported format: ${i}. Supported formats: ${this.SUPPORTED_FORMATS.join(", ")}`),t.stat.size>this.maxFileSize){let n=Math.round(t.stat.size/1024/1024),s=Math.round(this.maxFileSize/1024/1024);e.push(`File size (${n}MB) exceeds maximum allowed size (${s}MB)`)}return t.stat.size>10*1024*1024&&r.push("Large file may take longer to process"),{valid:e.length===0,errors:e.length>0?e:void 0,warnings:r.length>0?r:void 0}}async process(t){this.logger.debug("Processing audio file",{fileName:t.name,extension:t.extension,sizeBytes:t.stat.size});let e=await this.vault.readBinary(t),r=await this.extractMetadata(e,t);return this.logger.debug("Audio processing completed",{bufferSize:e.byteLength,detectedFormat:r.format}),{buffer:e,metadata:r,originalFile:t,compressed:!1}}async extractMetadata(t,e){let r;if(e){let n=e.extension.toLowerCase();r=n,this.logger.debug("Audio format detected from file extension",{fileName:e.name,extension:n,format:r})}let i=Math.round(t.byteLength/1024);return this.logger.debug("Audio file analysis",{sizeKB:i,sizeBytes:t.byteLength,format:r}),{duration:void 0,bitrate:void 0,sampleRate:void 0,channels:void 0,codec:void 0,format:r,fileSize:t.byteLength}}};var pe=class{constructor(t){this.settings=t}format(t,e){let r=this.cleanUp(t);return this.settings.timestampFormat!=="none"&&(e!=null&&e.includeTimestamps),r}insertTimestamps(t,e){if(!e||e.length===0)return t;let r=t.split(` `),i=[];return e.forEach(n=>{let s=this.formatTimestamp(n.start);switch(this.settings.timestampFormat){case"inline":i.push(`[${s}] ${n.text}`);break;case"sidebar":i.push(`${s} | ${n.text}`);break;default:i.push(n.text)}}),i.join(` `)}cleanUp(t){return t.trim().replace(/\s+/g," ").replace(/\n{3,}/g,` @@ -111,7 +111,7 @@ ${r}`),this.options.template&&(r=this.options.template.replace("{{content}}",r). - --- -*Transcribed at {{datetime}}*`}]}onClose(){let{contentEl:e}=this;e.empty()}};var y=require("obsidian");var A=require("obsidian");var R="[Deepgram]",N={DEBUG:"debug",INFO:"info",WARN:"warn",ERROR:"error"},c={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:"padding: 8px; margin-bottom: 16px; border-radius: 4px;",INFO_CONTAINER:` +*Transcribed at {{datetime}}*`}]}onClose(){let{contentEl:e}=this;e.empty()}};var b=require("obsidian");var A=require("obsidian");var R="[Deepgram]",N={DEBUG:"debug",INFO:"info",WARN:"warn",ERROR:"error"},c={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:"padding: 8px; margin-bottom: 16px; border-radius: 4px;",INFO_CONTAINER:` background: var(--background-secondary); padding: 12px; border-radius: 6px; @@ -131,7 +131,7 @@ ${r}`),this.options.template&&(r=this.options.template.replace("{{content}}",r).   - Using the 'enhanced' model for faster processing
  - Reducing audio bitrate to 64-128 kbps
  - Converting to efficient formats (MP3, OGG) - `}renderCostEstimation(){let t=this.uiBuilder.createCostEstimationContainer();this.estimatedCostEl=t.createEl("div",{cls:c.CLASSES.COST_DETAILS}),this.updateCostEstimation()}updateCostEstimation(){if(!this.estimatedCostEl)return;let t=this.costCalculator.calculateEstimation(this.selectedModel,this.plugin.settings.monthlyBudget);if(!t){this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,null);return}this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,this.selectedModel,t.monthly),t.exceeedsBudget&&this.plugin.settings.monthlyBudget&&this.uiBuilder.addBudgetWarning(this.estimatedCostEl.parentElement,t.monthly,this.plugin.settings.monthlyBudget)}renderValidationButton(){new A.Setting(this.containerEl).setName(c.MESSAGES.VALIDATION_LABEL).setDesc(c.MESSAGES.VALIDATION_DESC).addButton(t=>{this.setupValidationButton(t)})}setupValidationButton(t){t.setButtonText(c.MESSAGES.VALIDATION_BUTTON).setCta().onClick(async()=>{await this.handleValidation(t)})}async handleValidation(t){t.setDisabled(!0),t.setButtonText(c.MESSAGES.VALIDATING);try{if(await this.validator.validateApiKey(this.plugin.settings.deepgramApiKey||""))this.handleValidationSuccess(t);else throw new Error("Invalid API key")}catch(e){this.handleValidationError(t,e)}}handleValidationSuccess(t){new A.Notice(c.MESSAGES.VALIDATION_SUCCESS),t.setButtonText("Valid \u2713"),t.removeCta(),setTimeout(()=>{t.setButtonText(c.MESSAGES.VALIDATION_BUTTON),t.setCta(),t.setDisabled(!1)},k.VALIDATION_RESET_DELAY)}handleValidationError(t,e){this.logger.error("Validation error",e),new A.Notice(c.MESSAGES.VALIDATION_ERROR),t.setButtonText(c.MESSAGES.VALIDATION_BUTTON),t.setWarning(),t.setDisabled(!1)}updateUIState(){let t=!!this.plugin.settings.deepgramApiKey,e=this.containerEl.querySelector("select");e&&(e.disabled=!t),this.containerEl.querySelectorAll(".checkbox-container input").forEach(i=>{i.disabled=!t||!this.selectedModel})}renderDefaultFeatures(t){ct.forEach(e=>{new A.Setting(t).setName(e.name).setDesc(e.description).addToggle(r=>{let i=this.getFeatureValue(e.key,e.default);r.setValue(i).onChange(async n=>{await this.saveFeatureSetting(e.key,n)})})})}updateFeatureAvailability(){if(!this.selectedModel||!this.registry)return;this.registry.getAllFeatures().forEach((e,r)=>{this.updateFeatureToggleState(r)})}updateFeatureToggleState(t){let e=this.containerEl.querySelector(`[data-feature="${t}"]`);if(!e||!this.selectedModel||!this.registry)return;let r=this.registry.isFeatureSupported(this.selectedModel.id,t);e.disabled=!r,!r&&e.checked&&(e.checked=!1,e.dispatchEvent(new Event("change")))}addDefaultModelOptions(t){lt.forEach(e=>{let r=`${e.name} (${e.tier}) - $${e.price}/min`;t.addOption(e.id,r)}),this.logger.info("Added default model options")}renderFallbackUI(t){this.logger.info("Rendering fallback UI due to error");try{this.uiBuilder.clearContainer(),this.uiBuilder.createErrorContainer(t),this.renderMinimalSettings(),this.logger.info("Fallback UI rendered successfully")}catch(e){this.logger.error("Failed to render fallback UI",e),this.renderCriticalError()}}renderMinimalSettings(){new A.Setting(this.containerEl).setName(c.MESSAGES.API_KEY_LABEL).setDesc(c.MESSAGES.API_KEY_DESC).addText(t=>{t.setPlaceholder(c.MESSAGES.API_KEY_PLACEHOLDER).setValue(this.plugin.settings.deepgramApiKey||"").onChange(async e=>{this.plugin.settings.deepgramApiKey=e,await this.plugin.saveSettings(),new A.Notice(c.MESSAGES.API_KEY_SAVED)}),t.inputEl.type="password"}),new A.Setting(this.containerEl).setName(c.MESSAGES.MODEL_LABEL).setDesc(c.MESSAGES.MODEL_DESC).addDropdown(t=>{var r,i;t.addOption("",c.MESSAGES.MODEL_PLACEHOLDER),this.addDefaultModelOptions(t);let e=((i=(r=this.plugin.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.model)||"";t.setValue(e),t.onChange(async n=>{await this.saveModelSelection(n)})})}renderCriticalError(){this.uiBuilder.clearContainer(),this.containerEl.createEl("p",{text:c.MESSAGES.CRITICAL_ERROR,cls:c.CLASSES.WARNING})}};var xe=class extends y.PluginSettingTab{constructor(e,r){super(e,r);this.plugin=r}display(){var a,o,d,m,u,g,v,h,M,S,F,K,B,$;let{containerEl:e}=this;(a=e==null?void 0:e.constructor)==null||a.name,this.plugin,this.plugin,(o=this.plugin)==null||o.settings,(d=this.plugin)!=null&&d.settings&&Object.keys(this.plugin.settings),e&&(e.parentElement,e.isConnected,window.getComputedStyle(e).display),e.empty();let r=e.createEl("h2",{text:"Speech to Text Settings"}),i=e.createEl("details",{cls:"speech-to-text-debug"}),n=i.createEl("summary",{text:"Debug Information"}),s=i.createEl("pre",{text:JSON.stringify({pluginExists:!!this.plugin,settingsExists:!!((m=this.plugin)!=null&&m.settings),apiKey:(g=(u=this.plugin)==null?void 0:u.settings)!=null&&g.apiKey?"Set (hidden)":"Not set",language:((h=(v=this.plugin)==null?void 0:v.settings)==null?void 0:h.language)||"Not set",autoInsert:(S=(M=this.plugin)==null?void 0:M.settings)==null?void 0:S.autoInsert,insertPosition:(K=(F=this.plugin)==null?void 0:F.settings)==null?void 0:K.insertPosition,model:($=(B=this.plugin)==null?void 0:B.settings)==null?void 0:$.model,timestamp:new Date().toISOString()},null,2)});try{this.createApiSection(e),this.createGeneralSection(e),this.createAudioSection(e),this.createAdvancedSection(e),e.children.length}catch(C){console.error("=== Error displaying settings ==="),console.error("Error details:",C),console.error("Error stack:",C instanceof Error?C.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: ${C instanceof Error?C.message:String(C)}`,cls:"error-details"})}}createApiSection(e){e.createEl("h3",{text:"API Configuration"});let r=e.createEl("div",{cls:"provider-selection"});this.createProviderSelection(r);let i=e.createEl("div",{cls:"provider-settings"}),n=this.plugin.settings.provider||"auto";this.renderProviderSettings(i,n)}createProviderSelection(e){var i;try{let n=new y.Setting(e);n.settingEl,(i=n.settingEl)==null||i.isConnected,n.setName("Transcription Provider").setDesc("Select the speech-to-text provider").addDropdown(s=>{var a;s.addOption("auto","Auto (Intelligent Selection)").addOption("whisper","OpenAI Whisper").addOption("deepgram","Deepgram").setValue(this.plugin.settings.provider||"auto").onChange(async o=>{var u;this.plugin.settings.provider=o,await this.plugin.saveSettings();let d=(u=e.parentElement)==null?void 0:u.querySelector(".provider-settings");d?this.renderProviderSettings(d,o):console.error("Could not find .provider-settings container");let m=e.querySelector(".provider-info");m&&this.updateProviderInfo(m,o),new y.Notice(`Provider changed to: ${o}`)}),s.selectEl,(a=s.selectEl)==null||a.options.length})}catch(n){console.error("Error creating provider selection:",n),console.error("Error stack:",n instanceof Error?n.stack:"N/A")}let r=e.createEl("div",{cls:"provider-info"});r.style.cssText="margin: 10px 0; padding: 10px; background: var(--background-secondary); border-radius: 4px;",this.updateProviderInfo(r,this.plugin.settings.provider||"auto")}renderProviderSettings(e,r){let i=e.isConnected;e.empty();try{switch(r){case"auto":this.renderAutoProviderSettings(e);break;case"whisper":this.renderWhisperSettings(e);break;case"deepgram":this.renderDeepgramSettings(e);break;default:console.warn("Unknown provider:",r),e.createEl("p",{text:`Unknown provider: ${r}`,cls:"mod-warning"})}}catch(n){console.error("Error rendering provider settings:",n),e.createEl("p",{text:"Error loading provider settings",cls:"mod-warning"})}e.children.length}renderAutoProviderSettings(e){e.createEl("h4",{text:"Automatic Provider Selection"}),new y.Setting(e).setName("Selection Strategy").setDesc("How to choose between available providers").addDropdown(r=>{r.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 i=>{this.plugin.settings.selectionStrategy=i,await this.plugin.saveSettings()})}),new y.Setting(e).setName("Fallback Strategy").setDesc("What to do when primary provider fails").addDropdown(r=>{r.addOption("auto","Automatic Fallback").addOption("manual","Ask User").addOption("none","No Fallback").setValue(this.plugin.settings.fallbackStrategy||"auto").onChange(async i=>{this.plugin.settings.fallbackStrategy=i,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 y.Setting(e).setName("API Endpoint").setDesc("OpenAI API endpoint (leave default unless using custom endpoint)").addText(r=>r.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.apiEndpoint||"https://api.openai.com/v1").onChange(async i=>{this.plugin.settings.apiEndpoint=i||"https://api.openai.com/v1",await this.plugin.saveSettings()}))}renderDeepgramSettings(e){e.isConnected,e.children.length,e.empty();let r=e.createEl("div",{cls:"deepgram-settings-container"});try{new De(this.plugin,r).render()}catch(i){console.error("Error rendering Deepgram settings:",i),r.createEl("p",{text:"Error loading Deepgram settings",cls:"mod-warning"})}e.children.length}renderWhisperApiKey(e){new y.Setting(e).setName("OpenAI API Key").setDesc("Enter your OpenAI API key for Whisper transcription").addText(r=>{r.setPlaceholder("sk-...").setValue(this.maskApiKey(this.plugin.settings.apiKey||"")).onChange(async i=>{i&&!i.includes("*")&&(this.plugin.settings.apiKey=i,this.plugin.settings.whisperApiKey=i,await this.plugin.saveSettings(),r.setValue(this.maskApiKey(i)),new y.Notice("OpenAI API key saved"))}),r.inputEl.type="password",r.inputEl.addEventListener("focus",()=>{this.plugin.settings.apiKey&&r.setValue(this.plugin.settings.apiKey)}),r.inputEl.addEventListener("blur",()=>{this.plugin.settings.apiKey&&r.setValue(this.maskApiKey(this.plugin.settings.apiKey))})})}renderDeepgramApiKey(e){new y.Setting(e).setName("Deepgram API Key").setDesc("Enter your Deepgram API key for transcription").addText(r=>{r.setPlaceholder("Enter Deepgram API key...").setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey||"")).onChange(async i=>{i&&!i.includes("*")&&(this.plugin.settings.deepgramApiKey=i,await this.plugin.saveSettings(),r.setValue(this.maskApiKey(i)),new y.Notice("Deepgram API key saved"))}),r.inputEl.type="password",r.inputEl.addEventListener("focus",()=>{this.plugin.settings.deepgramApiKey&&r.setValue(this.plugin.settings.deepgramApiKey)}),r.inputEl.addEventListener("blur",()=>{this.plugin.settings.deepgramApiKey&&r.setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey))})})}updateProviderInfo(e,r){e.empty();let i={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:i[r]})}createGeneralSection(e){e.createEl("h3",{text:"General Settings"}),new y.Setting(e).setName("Language").setDesc("Primary language for transcription").addDropdown(r=>r.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 i=>{this.plugin.settings.language=i,await this.plugin.saveSettings()})),new y.Setting(e).setName("Auto-insert transcription").setDesc("Automatically insert transcribed text into the active note").addToggle(r=>r.setValue(this.plugin.settings.autoInsert||!1).onChange(async i=>{this.plugin.settings.autoInsert=i,await this.plugin.saveSettings()})),new y.Setting(e).setName("Insert position").setDesc("Where to insert transcribed text").addDropdown(r=>r.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 i=>{this.plugin.settings.insertPosition=i,await this.plugin.saveSettings()})),new y.Setting(e).setName("Show format options").setDesc("Show formatting options before inserting text").addToggle(r=>r.setValue(this.plugin.settings.showFormatOptions||!1).onChange(async i=>{this.plugin.settings.showFormatOptions=i,await this.plugin.saveSettings()}))}createAudioSection(e){e.createEl("h3",{text:"Audio Settings"});let r=this.plugin.settings.provider||"auto";(r==="whisper"||r==="auto")&&new y.Setting(e).setName("Whisper Model").setDesc("Select the Whisper model to use").addDropdown(i=>i.addOption("whisper-1","Whisper v1 (Default)").setValue(this.plugin.settings.model||"whisper-1").onChange(async n=>{this.plugin.settings.model=n,await this.plugin.saveSettings()})),new y.Setting(e).setName("Temperature").setDesc("Sampling temperature (0-1). Lower values make output more focused and deterministic").addText(i=>i.setPlaceholder("0.0").setValue(String(this.plugin.settings.temperature||0)).onChange(async n=>{let s=parseFloat(n);!isNaN(s)&&s>=0&&s<=1&&(this.plugin.settings.temperature=s,await this.plugin.saveSettings())})),new y.Setting(e).setName("Add timestamp").setDesc("Add timestamp to transcribed text").addToggle(i=>i.setValue(this.plugin.settings.addTimestamp||!1).onChange(async n=>{this.plugin.settings.addTimestamp=n,await this.plugin.saveSettings()}))}createAdvancedSection(e){e.createEl("h3",{text:"Advanced Settings"}),new y.Setting(e).setName("Enable cache").setDesc("Cache transcription results to avoid re-processing").addToggle(r=>r.setValue(this.plugin.settings.enableCache!==!1).onChange(async i=>{this.plugin.settings.enableCache=i,await this.plugin.saveSettings()})),new y.Setting(e).setName("Debug mode").setDesc("Enable debug logging in console").addToggle(r=>r.setValue(this.plugin.settings.debugMode||!1).onChange(async i=>{this.plugin.settings.debugMode=i,await this.plugin.saveSettings(),i&&new y.Notice("Debug mode enabled. Check console for logs.")})),new y.Setting(e).setName("Reset to defaults").setDesc("Reset all settings to their default values").addButton(r=>r.setButtonText("Reset").setWarning().onClick(async()=>{if(confirm("Are you sure you want to reset all settings to defaults?")){let{DEFAULT_SETTINGS:n}=await Promise.resolve().then(()=>(Le(),Je));this.plugin.settings={...n},await this.plugin.saveSettings(),this.display(),new y.Notice("Settings reset to defaults")}}))}maskApiKey(e){if(!e||e.length<10)return"";let r=7,i=4;if(e.length<=r+i)return e;let n="*".repeat(e.length-r-i);return e.substring(0,r)+n+e.substring(e.length-i)}};var Me=class extends f.Plugin{async onload(){try{await this.initializeServices(),this.registerCommands(),this.registerContextMenu(),this.addSettingTab(new xe(this.app,this)),this.registerEventHandlers(),this.app.workspace.onLayoutReady(()=>{this.createStatusBarItem()}),new f.Notice("Speech-to-Text plugin loaded successfully")}catch(e){console.error("Failed to load Speech-to-Text plugin:",e),new f.Notice("Failed to load Speech-to-Text plugin. Check console for details.")}}onunload(){this.cleanupEventHandlers(),this.cancelPendingOperations(),this.editorService&&this.editorService.destroy(),this.textInsertionHandler&&this.textInsertionHandler.destroy()}async initializeServices(){await this.loadSettings(),this.logger=new _("SpeechToText"),this.errorHandler=new he(this.logger),this.settingsManager=new me(this),this.stateManager=new fe,this.eventManager=new O,this.editorService=new ye(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 r=>{this.settings=r,await this.saveSettings()},get:r=>{var i,n;return r==="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:(n=(i=this.settings.transcription)==null?void 0:i.deepgram)==null?void 0:n.features},abTest:{enabled:this.settings.abTestEnabled,trafficSplit:this.settings.abTestSplit},monitoring:{enabled:this.settings.metricsEnabled}}:r==="apiKey"?this.settings.apiKey:this.settings[r]},set:async(r,i)=>{var n,s;r==="transcription"?(i.defaultProvider&&(this.settings.provider=i.defaultProvider),(n=i.whisper)!=null&&n.apiKey&&(this.settings.whisperApiKey=i.whisper.apiKey),(s=i.deepgram)!=null&&s.apiKey&&(this.settings.deepgramApiKey=i.deepgram.apiKey)):this.settings[r]=i,await this.saveSettings()}};this.transcriberFactory=new de(e,this.logger)}initializeTranscriptionService(){let e=this.settings.provider||"whisper",r;try{let i=this.transcriberFactory.getProvider(e==="auto"?"auto":e);r=new ue(i,this.logger),this.logger.info(`Initialized transcription service with provider: ${i.getProviderName()}`)}catch(i){this.logger.warn("Failed to initialize transcriber from factory, using fallback",i);let n=this.settings.whisperApiKey||this.settings.apiKey;n?(r=new V(n,this.logger),this.logger.info("Initialized fallback WhisperService")):(r=null,this.logger.warn("No transcription service initialized - API key missing"))}if(r){let i=new ge(this.app.vault,this.logger);try{let s=this.transcriberFactory.getProvider(e==="auto"?"auto":e),a=s.getCapabilities();i.setProviderCapabilities({maxFileSize:a.maxFileSize}),this.logger.info("AudioProcessor configured with provider capabilities",{provider:s.getProviderName(),maxFileSize:a.maxFileSize/1024/1024+"MB"})}catch(s){this.logger.warn("Failed to get provider capabilities, using default limits",s)}let n=new pe(this.settings);this.transcriptionService=new ee(r,i,n,this.eventManager,this.logger,this.settings),this.logger.debug("TranscriptionService initialized successfully")}}registerContextMenu(){this.registerEvent(this.app.workspace.on("file-menu",(e,r)=>{if(!r||!(r instanceof f.TFile))return;["m4a","mp3","wav","mp4","webm","ogg"].includes(r.extension.toLowerCase())&&e.addItem(n=>{n.setTitle("Transcribe audio file").setIcon("microphone").onClick(async()=>{await this.transcribeFile(r)})})}))}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 f.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 f.Notice("Transcription history not yet implemented")}}),this.addCommand({id:"cancel-transcription",name:"Cancel current transcription",callback:()=>{this.transcriptionService.cancel(),new f.Notice("Transcription cancelled")}}),this.addCommand({id:"undo-insertion",name:"Undo last text insertion",callback:async()=>{await this.editorService.undo()?new f.Notice("Text insertion undone"):new f.Notice("Nothing to undo")}}),this.addCommand({id:"redo-insertion",name:"Redo last text insertion",callback:async()=>{await this.editorService.redo()?new f.Notice("Text insertion redone"):new f.Notice("Nothing to redo")}})}registerEventHandlers(){this.eventManager.on("transcription:start",e=>{this.stateManager.setState({status:"processing"}),new f.Notice(`Transcribing: ${e.fileName}`)}),this.eventManager.on("transcription:complete",async e=>{var i;this.logger.debug("=== Transcription complete event received ===",{hasData:!!e,hasText:!!(e!=null&&e.text),textLength:((i=e==null?void 0:e.text)==null?void 0:i.length)||0,autoInsert:this.settings.autoInsert}),this.stateManager.setState({status:"completed"}),new f.Notice("Transcription completed successfully");let r=e.text;if(!r){this.logger.error("No text found in transcription complete event",void 0,{data:e}),new f.Notice("Transcription completed but no text was returned");return}this.settings.autoInsert?(this.logger.debug("Auto-inserting transcribed text",{textLength:r.length,textPreview:r.substring(0,100)}),await this.insertTranscriptionWithOptions(r)):this.logger.debug("Auto-insert disabled, text not inserted")}),this.eventManager.on("transcription:error",e=>{this.stateManager.setState({status:"error",error:e.error}),new f.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(){try{if(!this.app.workspace){console.warn("Workspace not ready, skipping status bar creation");return}let e=this.addStatusBarItem();if(!e){console.warn("Failed to create status bar item");return}e.textContent="";let r=i=>{if(e)try{let n=i?String(i):"";e.textContent=n}catch(n){console.warn("Failed to update status bar text:",n)}};this.stateManager.subscribe(i=>{if(e)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}})}catch(e){console.error("Error creating status bar item:",e)}}async showAudioFilePicker(){let e=this.app.vault.getFiles().filter(r=>r.extension==="m4a"||r.extension==="mp3"||r.extension==="wav"||r.extension==="mp4");if(e.length===0){new f.Notice("No audio files found in vault");return}new qe(this.app,e,async r=>{await this.transcribeFile(r)}).open()}async transcribeFile(e){var r,i;try{let n=this.settings.provider||"whisper",s=!1,a="";if(n==="whisper"?(s=!!(this.settings.apiKey||this.settings.whisperApiKey),a="Please configure your OpenAI API key in settings"):n==="deepgram"?(s=!!this.settings.deepgramApiKey,a="Please configure your Deepgram API key in settings"):n==="auto"&&(s=!!(this.settings.apiKey||this.settings.whisperApiKey||this.settings.deepgramApiKey),a="Please configure at least one API key (OpenAI or Deepgram) in settings"),!s){new f.Notice(a);return}if(!this.transcriptionService&&(this.initializeTranscriptionService(),!this.transcriptionService)){new f.Notice("Failed to initialize transcription service. Please check your API keys.");return}this.logger.debug("Starting transcription for file:",{fileName:e.name});let o=await this.transcriptionService.transcribe(e);if(this.logger.debug("Transcription result received:",{hasResult:!!o,hasText:!!(o!=null&&o.text),textLength:((r=o==null?void 0:o.text)==null?void 0:r.length)||0,textPreview:(i=o==null?void 0:o.text)==null?void 0:i.substring(0,100)}),!o||!o.text){this.logger.error("Transcription returned no text",void 0,{result:o}),new f.Notice("Transcription completed but no text was returned");return}this.settings.showFormatOptions?(this.logger.debug("Showing format options with text"),this.showFormatOptionsWithText(o.text)):(this.logger.debug("Inserting text directly without format options"),await this.insertTranscriptionWithOptions(o.text))}catch(n){this.errorHandler.handle(n)}}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 r={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:",r),await this.textInsertionHandler.insertText(e,r)?(this.logger.info("Text successfully inserted"),new f.Notice("Transcription inserted successfully")):(this.logger.warn("TextInsertionHandler failed, using legacy method"),await this.insertTranscriptionLegacy(e))}async insertTranscriptionLegacy(e){let r=this.app.workspace.getActiveViewOfType(f.MarkdownView);if(!r){new f.Notice("No active editor found. Opening new note...");let s=await this.app.vault.create(`Transcription ${new Date().toISOString()}.md`,e);await this.app.workspace.openLinkText(s.path,"",!0);return}let i=r.editor;switch(this.settings.insertPosition){case"cursor":i.replaceSelection(e);break;case"end":let s=i.lastLine(),a=i.getLine(s);i.setLine(s,a+` + `}renderCostEstimation(){let t=this.uiBuilder.createCostEstimationContainer();this.estimatedCostEl=t.createEl("div",{cls:c.CLASSES.COST_DETAILS}),this.updateCostEstimation()}updateCostEstimation(){if(!this.estimatedCostEl)return;let t=this.costCalculator.calculateEstimation(this.selectedModel,this.plugin.settings.monthlyBudget);if(!t){this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,null);return}this.uiBuilder.updateCostDetails(this.estimatedCostEl.parentElement,this.selectedModel,t.monthly),t.exceeedsBudget&&this.plugin.settings.monthlyBudget&&this.uiBuilder.addBudgetWarning(this.estimatedCostEl.parentElement,t.monthly,this.plugin.settings.monthlyBudget)}renderValidationButton(){new A.Setting(this.containerEl).setName(c.MESSAGES.VALIDATION_LABEL).setDesc(c.MESSAGES.VALIDATION_DESC).addButton(t=>{this.setupValidationButton(t)})}setupValidationButton(t){t.setButtonText(c.MESSAGES.VALIDATION_BUTTON).setCta().onClick(async()=>{await this.handleValidation(t)})}async handleValidation(t){t.setDisabled(!0),t.setButtonText(c.MESSAGES.VALIDATING);try{if(await this.validator.validateApiKey(this.plugin.settings.deepgramApiKey||""))this.handleValidationSuccess(t);else throw new Error("Invalid API key")}catch(e){this.handleValidationError(t,e)}}handleValidationSuccess(t){new A.Notice(c.MESSAGES.VALIDATION_SUCCESS),t.setButtonText("Valid \u2713"),t.removeCta(),setTimeout(()=>{t.setButtonText(c.MESSAGES.VALIDATION_BUTTON),t.setCta(),t.setDisabled(!1)},k.VALIDATION_RESET_DELAY)}handleValidationError(t,e){this.logger.error("Validation error",e),new A.Notice(c.MESSAGES.VALIDATION_ERROR),t.setButtonText(c.MESSAGES.VALIDATION_BUTTON),t.setWarning(),t.setDisabled(!1)}updateUIState(){let t=!!this.plugin.settings.deepgramApiKey,e=this.containerEl.querySelector("select");e&&(e.disabled=!t),this.containerEl.querySelectorAll(".checkbox-container input").forEach(i=>{i.disabled=!t||!this.selectedModel})}renderDefaultFeatures(t){ct.forEach(e=>{new A.Setting(t).setName(e.name).setDesc(e.description).addToggle(r=>{let i=this.getFeatureValue(e.key,e.default);r.setValue(i).onChange(async n=>{await this.saveFeatureSetting(e.key,n)})})})}updateFeatureAvailability(){if(!this.selectedModel||!this.registry)return;this.registry.getAllFeatures().forEach((e,r)=>{this.updateFeatureToggleState(r)})}updateFeatureToggleState(t){let e=this.containerEl.querySelector(`[data-feature="${t}"]`);if(!e||!this.selectedModel||!this.registry)return;let r=this.registry.isFeatureSupported(this.selectedModel.id,t);e.disabled=!r,!r&&e.checked&&(e.checked=!1,e.dispatchEvent(new Event("change")))}addDefaultModelOptions(t){lt.forEach(e=>{let r=`${e.name} (${e.tier}) - $${e.price}/min`;t.addOption(e.id,r)}),this.logger.info("Added default model options")}renderFallbackUI(t){this.logger.info("Rendering fallback UI due to error");try{this.uiBuilder.clearContainer(),this.uiBuilder.createErrorContainer(t),this.renderMinimalSettings(),this.logger.info("Fallback UI rendered successfully")}catch(e){this.logger.error("Failed to render fallback UI",e),this.renderCriticalError()}}renderMinimalSettings(){new A.Setting(this.containerEl).setName(c.MESSAGES.API_KEY_LABEL).setDesc(c.MESSAGES.API_KEY_DESC).addText(t=>{t.setPlaceholder(c.MESSAGES.API_KEY_PLACEHOLDER).setValue(this.plugin.settings.deepgramApiKey||"").onChange(async e=>{this.plugin.settings.deepgramApiKey=e,await this.plugin.saveSettings(),new A.Notice(c.MESSAGES.API_KEY_SAVED)}),t.inputEl.type="password"}),new A.Setting(this.containerEl).setName(c.MESSAGES.MODEL_LABEL).setDesc(c.MESSAGES.MODEL_DESC).addDropdown(t=>{var r,i;t.addOption("",c.MESSAGES.MODEL_PLACEHOLDER),this.addDefaultModelOptions(t);let e=((i=(r=this.plugin.settings.transcription)==null?void 0:r.deepgram)==null?void 0:i.model)||"";t.setValue(e),t.onChange(async n=>{await this.saveModelSelection(n)})})}renderCriticalError(){this.uiBuilder.clearContainer(),this.containerEl.createEl("p",{text:c.MESSAGES.CRITICAL_ERROR,cls:c.CLASSES.WARNING})}};var xe=class extends b.PluginSettingTab{constructor(e,r){super(e,r);this.plugin=r}display(){var a,o,d,m,u,g,v,h,M,S,F,K,B,$;let{containerEl:e}=this;(a=e==null?void 0:e.constructor)==null||a.name,this.plugin,this.plugin,(o=this.plugin)==null||o.settings,(d=this.plugin)!=null&&d.settings&&Object.keys(this.plugin.settings),e&&(e.parentElement,e.isConnected,window.getComputedStyle(e).display),e.empty();let r=e.createEl("h2",{text:"Speech to Text Settings"}),i=e.createEl("details",{cls:"speech-to-text-debug"}),n=i.createEl("summary",{text:"Debug Information"}),s=i.createEl("pre",{text:JSON.stringify({pluginExists:!!this.plugin,settingsExists:!!((m=this.plugin)!=null&&m.settings),apiKey:(g=(u=this.plugin)==null?void 0:u.settings)!=null&&g.apiKey?"Set (hidden)":"Not set",language:((h=(v=this.plugin)==null?void 0:v.settings)==null?void 0:h.language)||"Not set",autoInsert:(S=(M=this.plugin)==null?void 0:M.settings)==null?void 0:S.autoInsert,insertPosition:(K=(F=this.plugin)==null?void 0:F.settings)==null?void 0:K.insertPosition,model:($=(B=this.plugin)==null?void 0:B.settings)==null?void 0:$.model,timestamp:new Date().toISOString()},null,2)});try{this.createApiSection(e),this.createGeneralSection(e),this.createAudioSection(e),this.createAdvancedSection(e),e.children.length}catch(C){console.error("=== Error displaying settings ==="),console.error("Error details:",C),console.error("Error stack:",C instanceof Error?C.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: ${C instanceof Error?C.message:String(C)}`,cls:"error-details"})}}createApiSection(e){e.createEl("h3",{text:"API Configuration"});let r=e.createEl("div",{cls:"provider-selection"});this.createProviderSelection(r);let i=e.createEl("div",{cls:"provider-settings"}),n=this.plugin.settings.provider||"auto";this.renderProviderSettings(i,n)}createProviderSelection(e){var i;try{let n=new b.Setting(e);n.settingEl,(i=n.settingEl)==null||i.isConnected,n.setName("Transcription Provider").setDesc("Select the speech-to-text provider").addDropdown(s=>{var a;s.addOption("auto","Auto (Intelligent Selection)").addOption("whisper","OpenAI Whisper").addOption("deepgram","Deepgram").setValue(this.plugin.settings.provider||"auto").onChange(async o=>{var u;this.plugin.settings.provider=o,await this.plugin.saveSettings();let d=(u=e.parentElement)==null?void 0:u.querySelector(".provider-settings");d?this.renderProviderSettings(d,o):console.error("Could not find .provider-settings container");let m=e.querySelector(".provider-info");m&&this.updateProviderInfo(m,o),new b.Notice(`Provider changed to: ${o}`)}),s.selectEl,(a=s.selectEl)==null||a.options.length})}catch(n){console.error("Error creating provider selection:",n),console.error("Error stack:",n instanceof Error?n.stack:"N/A")}let r=e.createEl("div",{cls:"provider-info"});r.style.cssText="margin: 10px 0; padding: 10px; background: var(--background-secondary); border-radius: 4px;",this.updateProviderInfo(r,this.plugin.settings.provider||"auto")}renderProviderSettings(e,r){let i=e.isConnected;e.empty();try{switch(r){case"auto":this.renderAutoProviderSettings(e);break;case"whisper":this.renderWhisperSettings(e);break;case"deepgram":this.renderDeepgramSettings(e);break;default:console.warn("Unknown provider:",r),e.createEl("p",{text:`Unknown provider: ${r}`,cls:"mod-warning"})}}catch(n){console.error("Error rendering provider settings:",n),e.createEl("p",{text:"Error loading provider settings",cls:"mod-warning"})}e.children.length}renderAutoProviderSettings(e){e.createEl("h4",{text:"Automatic Provider Selection"}),new b.Setting(e).setName("Selection Strategy").setDesc("How to choose between available providers").addDropdown(r=>{r.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 i=>{this.plugin.settings.selectionStrategy=i,await this.plugin.saveSettings()})}),new b.Setting(e).setName("Fallback Strategy").setDesc("What to do when primary provider fails").addDropdown(r=>{r.addOption("auto","Automatic Fallback").addOption("manual","Ask User").addOption("none","No Fallback").setValue(this.plugin.settings.fallbackStrategy||"auto").onChange(async i=>{this.plugin.settings.fallbackStrategy=i,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(r=>r.setPlaceholder("https://api.openai.com/v1").setValue(this.plugin.settings.apiEndpoint||"https://api.openai.com/v1").onChange(async i=>{this.plugin.settings.apiEndpoint=i||"https://api.openai.com/v1",await this.plugin.saveSettings()}))}renderDeepgramSettings(e){e.isConnected,e.children.length,e.empty();let r=e.createEl("div",{cls:"deepgram-settings-container"});try{new De(this.plugin,r).render()}catch(i){console.error("Error rendering Deepgram settings:",i),r.createEl("p",{text:"Error loading Deepgram settings",cls:"mod-warning"})}e.children.length}renderWhisperApiKey(e){new b.Setting(e).setName("OpenAI API Key").setDesc("Enter your OpenAI API key for Whisper transcription").addText(r=>{r.setPlaceholder("sk-...").setValue(this.maskApiKey(this.plugin.settings.apiKey||"")).onChange(async i=>{i&&!i.includes("*")&&(this.plugin.settings.apiKey=i,this.plugin.settings.whisperApiKey=i,await this.plugin.saveSettings(),r.setValue(this.maskApiKey(i)),new b.Notice("OpenAI API key saved"))}),r.inputEl.type="password",r.inputEl.addEventListener("focus",()=>{this.plugin.settings.apiKey&&r.setValue(this.plugin.settings.apiKey)}),r.inputEl.addEventListener("blur",()=>{this.plugin.settings.apiKey&&r.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(r=>{r.setPlaceholder("Enter Deepgram API key...").setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey||"")).onChange(async i=>{i&&!i.includes("*")&&(this.plugin.settings.deepgramApiKey=i,await this.plugin.saveSettings(),r.setValue(this.maskApiKey(i)),new b.Notice("Deepgram API key saved"))}),r.inputEl.type="password",r.inputEl.addEventListener("focus",()=>{this.plugin.settings.deepgramApiKey&&r.setValue(this.plugin.settings.deepgramApiKey)}),r.inputEl.addEventListener("blur",()=>{this.plugin.settings.deepgramApiKey&&r.setValue(this.maskApiKey(this.plugin.settings.deepgramApiKey))})})}updateProviderInfo(e,r){e.empty();let i={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:i[r]})}createGeneralSection(e){e.createEl("h3",{text:"General Settings"}),new b.Setting(e).setName("Language").setDesc("Primary language for transcription").addDropdown(r=>r.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 i=>{this.plugin.settings.language=i,await this.plugin.saveSettings()})),new b.Setting(e).setName("Auto-insert transcription").setDesc("Automatically insert transcribed text into the active note").addToggle(r=>r.setValue(this.plugin.settings.autoInsert||!1).onChange(async i=>{this.plugin.settings.autoInsert=i,await this.plugin.saveSettings()})),new b.Setting(e).setName("Insert position").setDesc("Where to insert transcribed text").addDropdown(r=>r.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 i=>{this.plugin.settings.insertPosition=i,await this.plugin.saveSettings()})),new b.Setting(e).setName("Show format options").setDesc("Show formatting options before inserting text").addToggle(r=>r.setValue(this.plugin.settings.showFormatOptions||!1).onChange(async i=>{this.plugin.settings.showFormatOptions=i,await this.plugin.saveSettings()}))}createAudioSection(e){e.createEl("h3",{text:"Audio Settings"});let r=this.plugin.settings.provider||"auto";(r==="whisper"||r==="auto")&&new b.Setting(e).setName("Whisper Model").setDesc("Select the Whisper model to use").addDropdown(i=>i.addOption("whisper-1","Whisper v1 (Default)").setValue(this.plugin.settings.model||"whisper-1").onChange(async n=>{this.plugin.settings.model=n,await this.plugin.saveSettings()})),new b.Setting(e).setName("Temperature").setDesc("Sampling temperature (0-1). Lower values make output more focused and deterministic").addText(i=>i.setPlaceholder("0.0").setValue(String(this.plugin.settings.temperature||0)).onChange(async n=>{let s=parseFloat(n);!isNaN(s)&&s>=0&&s<=1&&(this.plugin.settings.temperature=s,await this.plugin.saveSettings())})),new b.Setting(e).setName("Add timestamp").setDesc("Add timestamp to transcribed text").addToggle(i=>i.setValue(this.plugin.settings.addTimestamp||!1).onChange(async n=>{this.plugin.settings.addTimestamp=n,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(r=>r.setValue(this.plugin.settings.enableCache!==!1).onChange(async i=>{this.plugin.settings.enableCache=i,await this.plugin.saveSettings()})),new b.Setting(e).setName("Debug mode").setDesc("Enable debug logging in console").addToggle(r=>r.setValue(this.plugin.settings.debugMode||!1).onChange(async i=>{this.plugin.settings.debugMode=i,await this.plugin.saveSettings(),i&&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(r=>r.setButtonText("Reset").setWarning().onClick(async()=>{if(confirm("Are you sure you want to reset all settings to defaults?")){let{DEFAULT_SETTINGS:n}=await Promise.resolve().then(()=>(Le(),Je));this.plugin.settings={...n},await this.plugin.saveSettings(),this.display(),new b.Notice("Settings reset to defaults")}}))}maskApiKey(e){if(!e||e.length<10)return"";let r=7,i=4;if(e.length<=r+i)return e;let n="*".repeat(e.length-r-i);return e.substring(0,r)+n+e.substring(e.length-i)}};var Me=class extends f.Plugin{async onload(){try{await this.initializeServices(),this.registerCommands(),this.registerContextMenu(),this.addSettingTab(new xe(this.app,this)),this.registerEventHandlers(),this.app.workspace.onLayoutReady(()=>{this.createStatusBarItem()}),new f.Notice("Speech-to-Text plugin loaded successfully")}catch(e){console.error("Failed to load Speech-to-Text plugin:",e),new f.Notice("Failed to load Speech-to-Text plugin. Check console for details.")}}onunload(){this.cleanupEventHandlers(),this.cancelPendingOperations(),this.editorService&&this.editorService.destroy(),this.textInsertionHandler&&this.textInsertionHandler.destroy()}async initializeServices(){await this.loadSettings(),this.logger=new _("SpeechToText"),this.errorHandler=new he(this.logger),this.settingsManager=new me(this),this.stateManager=new fe,this.eventManager=new O,this.editorService=new ye(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 r=>{this.settings=r,await this.saveSettings()},get:r=>{var i,n;return r==="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:(n=(i=this.settings.transcription)==null?void 0:i.deepgram)==null?void 0:n.features},abTest:{enabled:this.settings.abTestEnabled,trafficSplit:this.settings.abTestSplit},monitoring:{enabled:this.settings.metricsEnabled}}:r==="apiKey"?this.settings.apiKey:this.settings[r]},set:async(r,i)=>{var n,s;r==="transcription"?(i.defaultProvider&&(this.settings.provider=i.defaultProvider),(n=i.whisper)!=null&&n.apiKey&&(this.settings.whisperApiKey=i.whisper.apiKey),(s=i.deepgram)!=null&&s.apiKey&&(this.settings.deepgramApiKey=i.deepgram.apiKey)):this.settings[r]=i,await this.saveSettings()}};this.transcriberFactory=new de(e,this.logger)}initializeTranscriptionService(){let e=this.settings.provider||"whisper",r;try{let i=this.transcriberFactory.getProvider(e==="auto"?"auto":e);r=new ue(i,this.logger),this.logger.info(`Initialized transcription service with provider: ${i.getProviderName()}`)}catch(i){this.logger.warn("Failed to initialize transcriber from factory, using fallback",i);let n=this.settings.whisperApiKey||this.settings.apiKey;n?(r=new V(n,this.logger),this.logger.info("Initialized fallback WhisperService")):(r=null,this.logger.warn("No transcription service initialized - API key missing"))}if(r){let i=new ge(this.app.vault,this.logger);try{let s=this.transcriberFactory.getProvider(e==="auto"?"auto":e),a=s.getCapabilities();i.setProviderCapabilities({maxFileSize:a.maxFileSize}),this.logger.info("AudioProcessor configured with provider capabilities",{provider:s.getProviderName(),maxFileSize:a.maxFileSize/1024/1024+"MB"})}catch(s){this.logger.warn("Failed to get provider capabilities, using default limits",s)}let n=new pe(this.settings);this.transcriptionService=new ee(r,i,n,this.eventManager,this.logger,this.settings),this.logger.debug("TranscriptionService initialized successfully")}}registerContextMenu(){this.registerEvent(this.app.workspace.on("file-menu",(e,r)=>{if(!r||!(r instanceof f.TFile))return;["m4a","mp3","wav","mp4","webm","ogg"].includes(r.extension.toLowerCase())&&e.addItem(n=>{n.setTitle("Transcribe audio file").setIcon("microphone").onClick(async()=>{await this.transcribeFile(r)})})}))}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 f.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 f.Notice("Transcription history not yet implemented")}}),this.addCommand({id:"cancel-transcription",name:"Cancel current transcription",callback:()=>{this.transcriptionService.cancel(),new f.Notice("Transcription cancelled")}}),this.addCommand({id:"undo-insertion",name:"Undo last text insertion",callback:async()=>{await this.editorService.undo()?new f.Notice("Text insertion undone"):new f.Notice("Nothing to undo")}}),this.addCommand({id:"redo-insertion",name:"Redo last text insertion",callback:async()=>{await this.editorService.redo()?new f.Notice("Text insertion redone"):new f.Notice("Nothing to redo")}})}registerEventHandlers(){this.eventManager.on("transcription:start",e=>{this.stateManager.setState({status:"processing"}),new f.Notice(`Transcribing: ${e.fileName}`)}),this.eventManager.on("transcription:complete",async e=>{var i;this.logger.debug("=== Transcription complete event received ===",{hasData:!!e,hasText:!!(e!=null&&e.text),textLength:((i=e==null?void 0:e.text)==null?void 0:i.length)||0,autoInsert:this.settings.autoInsert}),this.stateManager.setState({status:"completed"}),new f.Notice("Transcription completed successfully");let r=e.text;if(!r){this.logger.error("No text found in transcription complete event",void 0,{data:e}),new f.Notice("Transcription completed but no text was returned");return}this.settings.autoInsert?(this.logger.debug("Auto-inserting transcribed text",{textLength:r.length,textPreview:r.substring(0,100)}),await this.insertTranscriptionWithOptions(r)):this.logger.debug("Auto-insert disabled, text not inserted")}),this.eventManager.on("transcription:error",e=>{this.stateManager.setState({status:"error",error:e.error}),new f.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(){try{if(!this.app.workspace){console.warn("Workspace not ready, skipping status bar creation");return}let e=this.addStatusBarItem();if(!e){console.warn("Failed to create status bar item");return}e.textContent="";let r=i=>{if(e)try{let n=i?String(i):"";e.textContent=n}catch(n){console.warn("Failed to update status bar text:",n)}};this.stateManager.subscribe(i=>{if(e)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}})}catch(e){console.error("Error creating status bar item:",e)}}async showAudioFilePicker(){let e=this.app.vault.getFiles().filter(r=>r.extension==="m4a"||r.extension==="mp3"||r.extension==="wav"||r.extension==="mp4");if(e.length===0){new f.Notice("No audio files found in vault");return}new qe(this.app,e,async r=>{await this.transcribeFile(r)}).open()}async transcribeFile(e){var r,i;try{let n=this.settings.provider||"whisper",s=!1,a="";if(n==="whisper"?(s=!!(this.settings.apiKey||this.settings.whisperApiKey),a="Please configure your OpenAI API key in settings"):n==="deepgram"?(s=!!this.settings.deepgramApiKey,a="Please configure your Deepgram API key in settings"):n==="auto"&&(s=!!(this.settings.apiKey||this.settings.whisperApiKey||this.settings.deepgramApiKey),a="Please configure at least one API key (OpenAI or Deepgram) in settings"),!s){new f.Notice(a);return}if(!this.transcriptionService&&(this.initializeTranscriptionService(),!this.transcriptionService)){new f.Notice("Failed to initialize transcription service. Please check your API keys.");return}this.logger.debug("Starting transcription for file:",{fileName:e.name});let o=await this.transcriptionService.transcribe(e);if(this.logger.debug("Transcription result received:",{hasResult:!!o,hasText:!!(o!=null&&o.text),textLength:((r=o==null?void 0:o.text)==null?void 0:r.length)||0,textPreview:(i=o==null?void 0:o.text)==null?void 0:i.substring(0,100)}),!o||!o.text){this.logger.error("Transcription returned no text",void 0,{result:o}),new f.Notice("Transcription completed but no text was returned");return}this.settings.showFormatOptions?(this.logger.debug("Showing format options with text"),this.showFormatOptionsWithText(o.text)):(this.logger.debug("Inserting text directly without format options"),await this.insertTranscriptionWithOptions(o.text))}catch(n){this.errorHandler.handle(n)}}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 r={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:",r),await this.textInsertionHandler.insertText(e,r)?(this.logger.info("Text successfully inserted"),new f.Notice("Transcription inserted successfully")):(this.logger.warn("TextInsertionHandler failed, using legacy method"),await this.insertTranscriptionLegacy(e))}async insertTranscriptionLegacy(e){let r=this.app.workspace.getActiveViewOfType(f.MarkdownView);if(!r){new f.Notice("No active editor found. Opening new note...");let s=await this.app.vault.create(`Transcription ${new Date().toISOString()}.md`,e);await this.app.workspace.openLinkText(s.path,"",!0);return}let i=r.editor;switch(this.settings.insertPosition){case"cursor":i.replaceSelection(e);break;case"end":let s=i.lastLine(),a=i.getLine(s);i.setLine(s,a+` `+e);break;case"beginning":let o=i.getLine(0);i.setLine(0,e+` diff --git a/src/infrastructure/api/providers/deepgram/DeepgramAdapter.ts b/src/infrastructure/api/providers/deepgram/DeepgramAdapter.ts index 6ff7704..9aa6b31 100644 --- a/src/infrastructure/api/providers/deepgram/DeepgramAdapter.ts +++ b/src/infrastructure/api/providers/deepgram/DeepgramAdapter.ts @@ -456,10 +456,24 @@ export class DeepgramAdapter implements ITranscriber { try { return await this.deepgramService.validateApiKey(key); } catch (error) { - this.logger.debug('DeepgramAdapter: API key validation failed', { - error: (error as Error).message + const err = error as TranscriptionError; + + if ( + err instanceof TranscriptionError && + (err.code === 'AUTH_ERROR' || err.statusCode === 401 || err.statusCode === 403) + ) { + this.logger.warn('DeepgramAdapter: API key authentication failed', { + statusCode: err.statusCode + }); + return false; + } + + this.logger.error('DeepgramAdapter: API key validation error (non-auth)', err, { + statusCode: err?.statusCode, + errorType: err?.constructor?.name }); - return false; + + throw error; } }