mirror of
https://github.com/asyouplz/SpeechNote.git
synced 2026-07-22 16:30:31 +00:00
138 lines
143 KiB
JavaScript
138 lines
143 KiB
JavaScript
/*
|
|
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 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 h=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 f=this.textFormatter.format(g.text);this.logger.debug("Text formatted:",{originalLength:g.text.length,formattedLength:f.length,formattedPreview:f.substring(0,100)});let S={text:f,language:g.language,segments:(a=g.segments)==null?void 0:a.map((M,E)=>({id:E,start:M.start,end:M.end,text:M.text}))};return this.status="completed",this.logger.debug("Emitting transcription:complete event",{textLength:S.text.length,hasSegments:!!S.segments,segmentsCount:((o=S.segments)==null?void 0:o.length)||0}),this.eventManager.emit("transcription:complete",{result:S,text:S.text}),S}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(l<t||l>e)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.maxRetries;r++)try{return await t()}catch(i){if(e=i,!this.isRetryable(i))throw i;if(r<this.maxRetries-1){let n=this.calculateDelay(r);this.logger.debug(`Retrying after ${n}ms (attempt ${r+1}/${this.maxRetries})`),await this.sleep(n)}}throw new P(`Operation failed after ${this.maxRetries} attempts: ${e.message}`,"MAX_RETRIES_EXCEEDED",void 0,!1)}isRetryable(t){var e;return t instanceof P?t.isRetryable:(e=t.message)==null?void 0:e.toLowerCase().includes("network")}calculateDelay(t){return Math.min(this.baseDelay*Math.pow(2,t),this.maxDelay)+Math.random()*1e3}sleep(t){return et(t)}},Ne=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 P(`Circuit breaker is open. Try again after ${new Date(this.nextAttemptTime).toLocaleTimeString()}`,"CIRCUIT_OPEN",void 0,!1);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("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;s<t.length;s++){let a=t[s];this.shouldCreateNewSegment(a,i,e,s>0?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;n<t.length;n++){let s=e[n].speaker;i!==null&&i!==s&&r.push(""),r.push(t[n]),i=s}return r.join(`
|
|
`)}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.size<se.SIZE_WARNING_THRESHOLD&&e.push(W.AUDIO_VALIDATION.VERY_SMALL_WARNING),i.size>se.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;u<n.length;u++){let g=Math.abs(n[u]);s+=g,a=Math.max(a,g)}let o=n.length>0?s/n.length:0,d=327;return{isSilent:o<d&&a<d*5,averageAmplitude:o,peakAmplitude:a}}catch(r){return this.logger.warn("Failed to analyze audio for silence",r),{isSilent:!1,averageAmplitude:-1,peakAmplitude:-1}}}},ze=class{constructor(t,e){this.requestsPerMinute=t;this.logger=e;this.queue=[];this.processing=!1;this.lastRequestTime=0}async acquire(){return new Promise(t=>{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(r<t){let n=t-r;await this.sleep(n)}let i=this.queue.shift();i&&(this.lastRequestTime=Date.now(),i())}this.processing=!1}sleep(t){return new Promise(e=>setTimeout(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;r<this.maxRetries;r++)try{return await t()}catch(i){if(e=i,!this.isRetryable(i))throw i;if(r<this.maxRetries-1){let n=this.calculateDelay(r);this.logger.debug(`Deepgram: Retrying after ${n}ms (attempt ${r+1}/${this.maxRetries})`),await this.sleep(n)}}throw new y(`Deepgram operation failed after ${this.maxRetries} attempts: ${e.message}`,"MAX_RETRIES_EXCEEDED","deepgram",!1)}isRetryable(t){var e;return t instanceof y?t.isRetryable:(e=t.message)==null?void 0:e.toLowerCase().includes("network")}calculateDelay(t){return Math.min(this.baseDelay*Math.pow(2,t),this.maxDelay)+Math.random()*1e3}sleep(t){return new Promise(e=>setTimeout(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,f,S,M;this.abortController=new AbortController;let i=Date.now();this.lastAudioSize=t.byteLength;let n=this.calculateDynamicTimeout(t.byteLength);try{let E=this.audioValidator.validateAudio(t);if(this.logger.debug("Audio validation results",{isValid:E.isValid,warnings:E.warnings,errors:E.errors,metadata:E.metadata}),!E.isValid)throw new y(`Audio validation failed: ${E.errors.join(", ")}`,"INVALID_AUDIO","deepgram",!1);if(E.warnings.forEach(p=>{this.logger.warn(`Audio validation warning: ${p}`)}),E.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(E.metadata.format);this.logger.debug("Starting Deepgram transcription request",{fileSize:t.byteLength,detectedFormat:E.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:((f=w.alternatives[0].transcript)==null?void 0:f.substring(0,200))+(w.alternatives[0].transcript&&w.alternatives[0].transcript.length>200?"...":""),confidence:w.alternatives[0].confidence,hasWords:!!w.alternatives[0].words,wordsCount:((S=w.alternatives[0].words)==null?void 0:S.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(E){throw E.name==="AbortError"?new y("Transcription cancelled","CANCELLED","deepgram",!1):E}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,f,S,M,E,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:((f=(g=t==null?void 0:t.results)==null?void 0:g.channels)==null?void 0:f.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:((S=r==null?void 0:r.alternatives)==null?void 0:S.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:(E=i==null?void 0:i.transcript)==null?void 0:E.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 T=[];i.confidence===0&&T.push("Zero confidence - possibly no speech detected"),!i.words||i.words.length===0?T.push("No word timestamps - indicates no speech recognition"):T.push(`${i.words.length} words detected but empty transcript`),t.metadata.duration<1&&T.push("Very short audio duration"),r.detected_language||T.push("No language detected"),this.logger.warn("Empty transcript diagnostic analysis",{possibleCauses:T,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=T.length>0?` Possible causes: ${T.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(T=>T.speaker!==void 0&&T.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(T=>({word:T.word,speaker:T.speaker,hasSpeaker:T.speaker!==void 0}))}),e!=null&&e.enabled&&m){this.logger.debug("Processing diarization with config:",e);try{let T=(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:T.length,speakersFound:[...new Set(T.map(I=>I.speaker))],firstFewWords:T.slice(0,5).map(I=>({word:I.word,speaker:I.speaker}))});let L=this.diarizationFormatter.formatTranscript(T,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(T){this.logger.error("Diarization formatting failed, falling back to original transcript",T),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;i<t.length;i+=10){let n=t.slice(i,Math.min(i+10,t.length));n.length>0&&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;o<a;o++){let d=o*s,m=Math.min(d+s,n),u=i.slice(d,m),g=new ArrayBuffer(this.WAV_HEADER_SIZE+u.byteLength),f=new Uint8Array(g);f.set(new Uint8Array(r),0),f.set(new Uint8Array(u),this.WAV_HEADER_SIZE),this.updateWavHeader(g,u.byteLength),e.push(g),this.logger.debug(`Created chunk ${o+1}/${a}`,{sizeMB:Math.round(g.byteLength/(1024*1024))})}return e}updateWavHeader(t,e){let r=new DataView(t);r.setUint32(4,e+36,!0),r.setUint32(40,e,!0)}splitByteArray(t){let e=[],r=t.byteLength,i=Math.ceil(r/this.CHUNK_SIZE);this.logger.warn("Using simple byte splitting for non-WAV format. Results may vary.");for(let n=0;n<i;n++){let s=n*this.CHUNK_SIZE,a=Math.min(s+this.CHUNK_SIZE,r);e.push(t.slice(s,a)),this.logger.debug(`Created chunk ${n+1}/${i}`,{sizeMB:Math.round((a-s)/(1024*1024))})}return e}mergeTranscriptionResults(t){return t.filter(e=>e&&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 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;let r=Date.now();try{let n=await this.audioChunker.splitAudio(t);this.logger.info(`Processing ${n.length} audio chunks`);let s=[],a=0,o;for(let g=0;g<n.length;g++){this.logger.debug(`Processing chunk ${g+1}/${n.length}`,{chunkSizeMB:Math.round(n[g].byteLength/(1024*1024))});try{let f=await this.transcribeStandard(n[g],e);f.text&&f.text.trim()&&(s.push(f.text),a+=f.confidence||0,!o&&f.language&&(o=f.language))}catch(f){this.logger.error(`Failed to process chunk ${g+1}`,f)}}let d=this.audioChunker.mergeTranscriptionResults(s),m=s.length>0?a/s.length:0;if(!d||d.trim().length===0)throw new y("All chunks failed to produce transcription","CHUNKING_FAILED","deepgram",!1);let u={text:d,language:o,confidence:m,provider:"deepgram",metadata:{processingTime:Date.now()-r,chunksProcessed:n.length,chunksSuccessful:s.length,isPartial:s.length<n.length}};return this.logger.info("Chunked transcription completed",{totalChunks:n.length,successfulChunks:s.length,processingTime:(i=u.metadata)==null?void 0:i.processingTime,textLength:u.text.length}),u}catch(n){throw this.logger.error("Chunked transcription failed",n),n}}enhanceTranscriptionError(t,e,r){let i=t;if(i instanceof y){if(i.code==="EMPTY_TRANSCRIPT"){this.logger.error("DeepgramAdapter: Empty transcript detected",i,{originalMessage:i.message,audioSize:e.byteLength,language:r==null?void 0:r.language,model:r==null?void 0:r.model});let n=[`No transcript was returned. ${i.message}`,"","Try the following:","- Ensure the audio contains clear speech","- Increase microphone input volume if the recording is quiet","- Reduce background noise or apply noise reduction","- Confirm the file format is supported (WAV, MP3, FLAC, etc.)","- Verify the language setting matches the spoken language","- Enable chunking for files that exceed the recommended size"].join(`
|
|
`);return new y(n,i.code,i.provider,i.isRetryable,i.statusCode)}if(i.code==="INVALID_AUDIO"){this.logger.error("DeepgramAdapter: Invalid audio format",i,{originalMessage:i.message,audioSize:e.byteLength});let n=[`The audio file could not be processed: ${i.message}`,"","Resolution steps:","- Confirm you selected the correct file and it is not corrupted","- Use a supported audio format (WAV, MP3, FLAC, OGG, etc.)","- Keep files under 2GB in size","- Enable automatic chunking for files larger than 50MB"].join(`
|
|
`);return new y(n,i.code,i.provider,i.isRetryable,i.statusCode)}}return this.logger.error("DeepgramAdapter: Transcription failed",t,{audioSize:e.byteLength,audioSizeMB:Math.round(e.byteLength/(1024*1024)),options:this.sanitizeForLogging(r),errorType:t.constructor.name,needsChunking:this.audioChunker.needsChunking(e.byteLength)}),t}convertOptions(t){var o;let e={tier:j.DEFAULT_TIER,punctuate:!0,smartFormat:!0,diarize:!0,utterances:!0},r={"nova-3":"nova-3","nova-2":"nova-2",nova:"nova-2",enhanced:"enhanced",base:"base"},i=t!=null&&t.model?r[t.model]:void 0;i&&(e.tier=i);let n=(o=this.settingsManager)==null?void 0:o.get("transcription"),s=n==null?void 0:n.deepgram,a=s==null?void 0:s.features;return a&&(this.logger.debug("Applying Deepgram feature overrides",this.sanitizeForLogging(a)),typeof a.punctuation=="boolean"&&(e.punctuate=a.punctuation),typeof a.smartFormat=="boolean"&&(e.smartFormat=a.smartFormat),typeof a.diarization=="boolean"&&(e.diarize=a.diarization),typeof a.utterances=="boolean"&&(e.utterances=a.utterances),typeof a.numerals=="boolean"&&(e.numerals=a.numerals)),t!=null&&t.deepgram&&Object.assign(e,t.deepgram),this.logger.debug("Resolved Deepgram options",this.sanitizeForLogging(e)),e}createDiarizationConfig(t){var i;if(!t.diarize)return{...oe,enabled:!1};let e=null;if(this.settingsManager){let n=this.settingsManager.get("transcription");e=(i=n==null?void 0:n.deepgram)==null?void 0:i.diarizationConfig}let r={...oe,enabled:!0,...e};return this.logger.debug("Diarization config created:",this.sanitizeForLogging(r)),r}async validateApiKey(t){try{return await this.deepgramService.validateApiKey(t)}catch(e){return this.logger.debug("DeepgramAdapter: API key validation failed",{error:e.message}),!1}}cancel(){this.deepgramService.cancel()}getProviderName(){return"Deepgram"}getCapabilities(){return{streaming:!0,realtime:!0,languages:["en","es","fr","de","it","pt","nl","ru","zh","ja","ko","ar","tr","hi","pl","sv","da","no","fi","el","he","id","ms","th","vi","ta","te","uk","cs","ro","hu","bg","ca","hr","sr","sl","sk","lt","lv","et","is","mk","sq","eu","gl","cy","bn","ur","fa","gu","mr","pa","kn","ml","or","as","ne","si","my","km","lo","ka","hy","az","kk","uz","tg","ky","tk","mn","bo","am","ti","so","sw","rw","yo","ig","ha","zu","xh","af","mt","lb","ga","gd","br","fy","yi","jv","su","tl","ceb","haw","eo","la"],maxFileSize:2*1024*1024*1024,audioFormats:["mp3","mp4","wav","flac","ogg","opus","m4a","webm","amr","ac3","aac","wma"],features:["transcription","punctuation","smart_formatting","diarization","numerals","profanity_filter","redaction","keywords","language_detection","streaming","real_time","multi_channel","custom_vocabulary","sentiment_analysis","topic_detection","entity_detection","summarization"],models:["nova-3","nova-2","enhanced","base"]}}async isAvailable(){try{let t=new ArrayBuffer(1024);return await this.deepgramService.transcribe(t),!0}catch(t){let e=t.message.toLowerCase();return!(e.includes("circuit")||e.includes("unavailable")||e.includes("timeout")||e.includes("rate limit"))}}getConfig(){return{...this.config}}resetCircuitBreaker(){this.deepgramService.resetCircuitBreaker()}updateConfig(t){this.config={...this.config,...t}}sanitizeForLogging(t){let e=["apikey","api_key","token","authorization","secret"],r=i=>{if(i==null||typeof i!="object")return i;if(i instanceof ArrayBuffer)return"[ArrayBuffer]";if(Array.isArray(i))return i.map(s=>r(s));let n={};for(let[s,a]of Object.entries(i)){let 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.averageLatency<r&&(r=s.averageLatency,e=[i,n])}return e[1]}selectByQuality(t){let e=t[0],r=0;for(let[i,n]of t){let s=this.metricsTracker.getSuccessRate(i);s>r&&(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;r<t.length;r++)e=(e<<5)-e+t.charCodeAt(r),e=e&e;return Math.abs(e)/2147483647}},de=class{constructor(t,e){this.settingsManager=t;this.logger=e;this.providers=new Map;this.metricsTracker=new $e(e),this.selector=new Ue(e,this.metricsTracker),this.config=this.loadConfig(),this.initializeProviders()}loadConfig(){var e,r,i,n,s;let t=this.settingsManager.get("transcription")||{};return{defaultProvider:t.defaultProvider||"whisper",autoSelect:t.autoSelect||!1,selectionStrategy:t.selectionStrategy||"manual",fallbackEnabled:t.fallbackEnabled!==!1,whisper:{enabled:((e=t.whisper)==null?void 0:e.enabled)!==!1,apiKey:((r=t.whisper)==null?void 0:r.apiKey)||t.apiKey||"",model:"whisper-1",maxConcurrency:1,timeout:3e4},deepgram:{enabled:((i=t.deepgram)==null?void 0:i.enabled)||!1,apiKey:((n=t.deepgram)==null?void 0:n.apiKey)||"",model:((s=t.deepgram)==null?void 0:s.model)||"nova-2",maxConcurrency:5,timeout:3e4,rateLimit:{requests:100,window:6e4}},abTest:t.abTest,monitoring:t.monitoring}}initializeProviders(){var t,e,r,i;if((t=this.config.whisper)!=null&&t.enabled&&this.config.whisper.apiKey)try{let n=new V(this.config.whisper.apiKey,this.logger),s=new ie(n,this.logger,this.config.whisper);this.providers.set("whisper",s),this.logger.info("Whisper provider initialized")}catch(n){this.logger.error("Failed to initialize Whisper provider",n)}if((e=this.config.deepgram)!=null&&e.enabled&&this.config.deepgram.apiKey)try{let n=((r=this.settingsManager)==null?void 0:r.get("requestTimeout"))||3e4,s=this.config.deepgram.timeout||n,a=new le(this.config.deepgram.apiKey,this.logger,(i=this.config.deepgram.rateLimit)==null?void 0:i.requests,s),o=new Z(a,this.logger,this.settingsManager,this.config.deepgram);this.providers.set("deepgram",o),this.logger.info("Deepgram provider initialized")}catch(n){this.logger.error("Failed to initialize Deepgram provider",n)}}getProvider(t){if(t&&t!=="auto"){let r=this.providers.get(t);if(r&&r.getConfig().enabled)return r;if(this.config.fallbackEnabled)return this.logger.warn(`Preferred provider ${t} not available, falling back`),this.getFallbackProvider(t);throw new U(t)}if(this.config.autoSelect||t==="auto")return this.selector.select(this.providers,this.config.selectionStrategy||"manual");let e=this.providers.get(this.config.defaultProvider);if(e&&e.getConfig().enabled)return e;for(let[r,i]of this.providers)if(i.getConfig().enabled)return this.logger.warn(`Default provider not available, using ${r}`),i;throw new Error("No transcription provider available")}getFallbackProvider(t){for(let[e,r]of this.providers)if(e!==t&&r.getConfig().enabled)return r;throw new Error("No fallback provider available")}getProviderForABTest(t){var e;return(e=this.config.abTest)!=null&&e.enabled?this.selector.select(this.providers,"ab_test",t):this.getProvider()}getAvailableProviders(){return Array.from(this.providers.entries()).filter(([t,e])=>e.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,f;(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(S=>({id:S.id,seek:0,start:S.start,end:S.end,text:S.text,tokens:[],temperature:0,avg_logprob:0,compression_ratio:0,no_speech_prob:0}))};return(f=this.logger)==null||f.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,`
|
|
|
|
`).replace(/([.!?])\s*\n/g,`$1
|
|
|
|
`)}formatTimestamp(t){let e=Math.floor(t/3600),r=Math.floor(t%3600/60),i=Math.floor(t%60);return e>0?`${e.toString().padStart(2,"0")}:${r.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}`:`${r.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}`}};var He={apiKey:"",provider:"auto",selectionStrategy:"performance_optimized",abTestSplit:50,model:"whisper-1",language:"auto",autoInsert:!0,insertPosition:"cursor",timestampFormat:"none",maxFileSize:25*1024*1024,enableCache:!0,cacheTTL:36e5,enableDebugLogging:!1,responseFormat:"json"},Ve=class{constructor(){this.SALT="obsidian-speech-to-text-v1"}encrypt(t){if(!t)return"";let e=btoa(t),r="";for(let i=0;i<e.length;i++){let n=e.charCodeAt(i),s=this.SALT.charCodeAt(i%this.SALT.length);r+=String.fromCharCode(n^s)}return btoa(r)}decrypt(t){if(!t)return"";try{let e=atob(t),r="";for(let i=0;i<e.length;i++){let n=e.charCodeAt(i),s=this.SALT.charCodeAt(i%this.SALT.length);r+=String.fromCharCode(n^s)}return atob(r)}catch(e){return console.error("Failed to decrypt API key:",e),""}}validateApiKeyFormat(t){return t?/^sk-[A-Za-z0-9]{20,}$/.test(t):!1}mask(t){if(!t||t.length<10)return"***";let e=7,r=4,i="*".repeat(Math.max(0,t.length-e-r));return t.substring(0,e)+i+t.substring(t.length-r)}},me=class{constructor(t,e){this.plugin=t;this.settings={...He},this.encryption=new Ve,this.logger=e}async load(){var t,e;try{let r=await this.plugin.loadData();return r&&(this.settings={...He,...r},this.settings.encryptedApiKey&&!this.settings.apiKey&&(this.settings.apiKey=this.encryption.decrypt(this.settings.encryptedApiKey)),this.settings.apiKey&&!this.settings.encryptedApiKey&&await this.encryptAndSaveApiKey(this.settings.apiKey)),(t=this.logger)==null||t.debug("Settings loaded successfully"),this.settings}catch(r){return(e=this.logger)==null||e.error("Failed to load settings",r),this.settings}}async save(t){var e,r;try{if(this.settings=t,t.apiKey){t.encryptedApiKey=this.encryption.encrypt(t.apiKey);let i={...t};delete i.apiKey,await this.plugin.saveData(i)}else await this.plugin.saveData(t);(e=this.logger)==null||e.debug("Settings saved successfully")}catch(i){throw(r=this.logger)==null||r.error("Failed to save settings",i),i}}get(t){return this.settings[t]}async set(t,e){this.settings[t]=e,t==="apiKey"&&typeof e=="string"?await this.encryptAndSaveApiKey(e):await this.save(this.settings)}async setApiKey(t){var e;return this.encryption.validateApiKeyFormat(t)?(await this.encryptAndSaveApiKey(t),!0):((e=this.logger)==null||e.warn("Invalid API key format"),!1)}getApiKey(){return this.settings.apiKey||""}getMaskedApiKey(){let t=this.getApiKey();return t?this.encryption.mask(t):"Not configured"}async encryptAndSaveApiKey(t){var r;this.settings.apiKey=t,this.settings.encryptedApiKey=this.encryption.encrypt(t);let e={...this.settings};delete e.apiKey,await this.plugin.saveData(e),(r=this.logger)==null||r.debug("API key encrypted and saved",{masked:this.encryption.mask(t)})}async reset(){var t;this.settings={...He},await this.save(this.settings),(t=this.logger)==null||t.info("Settings reset to defaults")}exportSettings(){let t={...this.settings};return delete t.apiKey,delete t.encryptedApiKey,t}async importSettings(t){var e;delete t.apiKey,delete t.encryptedApiKey,this.settings={...this.settings,...t},await this.save(this.settings),(e=this.logger)==null||e.info("Settings imported successfully")}validateSettings(){let t=[];return!this.settings.apiKey&&!this.settings.encryptedApiKey&&t.push("API key is not configured"),(this.settings.maxFileSize<=0||this.settings.maxFileSize>25*1024*1024)&&t.push("Invalid max file size (must be between 0 and 25MB)"),this.settings.cacheTTL<0&&t.push("Invalid cache TTL (must be positive)"),this.settings.temperature!==void 0&&(this.settings.temperature<0||this.settings.temperature>1)&&t.push("Invalid temperature (must be between 0 and 1)"),{valid:t.length===0,errors:t}}};var _=class{constructor(t){this.prefix=t}debug(t,e){`${this.prefix}`}info(t,e){console.info(`[${this.prefix}] INFO:`,t,e||"")}warn(t,e){console.warn(`[${this.prefix}] WARN:`,t,e||"")}error(t,e,r){console.error(`[${this.prefix}] ERROR:`,t,e,r||"")}};var st=require("obsidian"),he=class{constructor(t){this.logger=t}handle(t,e){let r=t instanceof Error?t:new Error(String(t));this.logger.error(r.message,r,e);let i=this.getUserMessage(r);new st.Notice(i,5e3)}getUserMessage(t){return t.message.includes("API key")?"Invalid API key. Please check your settings.":t.message.includes("network")||t.message.includes("fetch")?"Network error. Please check your connection.":t.message.includes("size")?"File is too large. Maximum size is 25MB.":t.message.includes("format")?"Unsupported file format. Please use M4A, MP3, WAV, or MP4.":`An error occurred: ${t.message}`}};var fe=class{constructor(){this.state={status:"idle",currentFile:null,progress:0,error:null,history:[]};this.listeners=new Set}getState(){return Object.freeze({...this.state})}setState(t){let e={...this.state};this.state={...this.state,...t},this.notifyListeners(e)}subscribe(t){return this.listeners.add(t),()=>this.listeners.delete(t)}reset(){this.setState({status:"idle",currentFile:null,progress:0,error:null})}notifyListeners(t){this.listeners.forEach(e=>{e(this.state,t)})}};var ve=class{constructor(){this.events=new Map;this.onceEvents=new Map}on(t,e){return this.events.has(t)||this.events.set(t,new Set),this.events.get(t).add(e),()=>this.off(t,e)}once(t,e){return this.onceEvents.has(t)||this.onceEvents.set(t,new Set),this.onceEvents.get(t).add(e),()=>this.off(t,e)}off(t,e){var r,i;(r=this.events.get(t))==null||r.delete(e),(i=this.onceEvents.get(t))==null||i.delete(e)}emit(t,e){var i;(i=this.events.get(t))==null||i.forEach(n=>{try{n(e)}catch(s){console.error(`Error in event listener for ${String(t)}:`,s)}});let r=this.onceEvents.get(t);r&&(r.forEach(n=>{try{n(e)}catch(s){console.error(`Error in once listener for ${String(t)}:`,s)}}),this.onceEvents.delete(t))}async emitAsync(t,e){var n;let r=[];(n=this.events.get(t))==null||n.forEach(s=>{r.push(Promise.resolve(s(e)).catch(a=>{console.error(`Error in async event listener for ${String(t)}:`,a)}))});let i=this.onceEvents.get(t);i&&(i.forEach(s=>{r.push(Promise.resolve(s(e)).catch(a=>{console.error(`Error in async once listener for ${String(t)}:`,a)}))}),this.onceEvents.delete(t)),await Promise.all(r)}removeAllListeners(t){t?(this.events.delete(t),this.onceEvents.delete(t)):(this.events.clear(),this.onceEvents.clear())}listenerCount(t){var i,n;let e=((i=this.events.get(t))==null?void 0:i.size)||0,r=((n=this.onceEvents.get(t))==null?void 0:n.size)||0;return e+r}eventNames(){let t=new Set([...this.events.keys(),...this.onceEvents.keys()]);return Array.from(t)}};var z=class{static getInstance(...t){let e=this.name;if(!z.instances.has(e)){let r=new this(...t);z.instances.set(e,r)}return z.instances.get(e)}static hasInstance(t){return z.instances.has(t)}static clearInstance(t){z.instances.delete(t)}static clearAllInstances(){z.instances.clear()}},We=z;We.instances=new Map;function at(l){let t;return class extends l{constructor(...e){if(t)return t;super(...e),t=this}}}var O=class extends ve{constructor(e){super();this.eventStats=new Map;this.eventHistory=[];this.maxHistorySize=100;this.isDebugMode=!1;this.logger=e}static getInstance(e){return O.instance||(O.instance=new O(e)),O.instance}emit(e,r){this.updateStats(e),this.recordHistory(e,r),this.isDebugMode&&this.logger&&this.logger.debug(`Event emitted: ${String(e)}`,r),super.emit(e,r)}async emitAsync(e,r){this.updateStats(e),this.recordHistory(e,r),this.isDebugMode&&this.logger&&this.logger.debug(`Async event emitted: ${String(e)}`,r),await super.emitAsync(e,r)}on(e,r){return this.isDebugMode&&this.logger&&this.logger.debug(`Listener registered for: ${String(e)}`),super.on(e,r)}once(e,r){return this.isDebugMode&&this.logger&&this.logger.debug(`Once listener registered for: ${String(e)}`),super.once(e,r)}chain(e,r,i){return this.on(e,n=>{let s=i?i(n):n;this.emit(r,s)})}filter(e,r,i){return this.on(e,n=>{r(n)&&i(n)})}debounce(e,r,i){let n=null;return this.on(e,s=>{n!==null&&clearTimeout(n),n=setTimeout(()=>{i(s),n=null},r)})}throttle(e,r,i){let n=!1;return this.on(e,s=>{n||(i(s),n=!0,setTimeout(()=>{n=!1},r))})}updateStats(e){let r=this.eventStats.get(e)||0;this.eventStats.set(e,r+1)}recordHistory(e,r){let i={event:String(e),data:this.isDebugMode?r:void 0,timestamp:Date.now()};this.eventHistory.push(i),this.eventHistory.length>this.maxHistorySize&&this.eventHistory.shift()}getStats(){return new Map(this.eventStats)}getHistory(){return[...this.eventHistory]}getEventStats(e){return this.eventStats.get(e)||0}clearStats(){this.eventStats.clear()}clearHistory(){this.eventHistory=[]}setDebugMode(e){this.isDebugMode=e,this.logger&&this.logger.info(`Event manager debug mode: ${e?"enabled":"disabled"}`)}getStatus(){let e=this.eventNames();return{totalEvents:e.length,totalListeners:e.reduce((r,i)=>r+this.listenerCount(i),0),totalEmitted:Array.from(this.eventStats.values()).reduce((r,i)=>r+i,0),debugMode:this.isDebugMode,historySize:this.eventHistory.length}}destroy(){this.removeAllListeners(),this.clearStats(),this.clearHistory(),this.logger&&this.logger.debug("EventManager destroyed")}};O=Qe([at],O);var be=require("obsidian");var ye=class{constructor(t,e,r){this.app=t;this.eventManager=e;this.activeEditor=null;this.activeView=null;this.undoHistory=[];this.redoHistory=[];this.maxHistorySize=50;this.logger=r||new _("EditorService"),this.setupEventListeners()}setupEventListeners(){this.app.workspace.on("active-leaf-change",()=>{this.updateActiveEditor()}),this.app.workspace.on("editor-change",t=>{this.activeEditor=t,this.eventManager.emit("editor:changed",{editor:t})})}updateActiveEditor(){var e;let t=this.app.workspace.getActiveViewOfType(be.MarkdownView);t?(this.activeView=t,this.activeEditor=t.editor,this.logger.debug("Active editor updated",{file:(e=t.file)==null?void 0:e.path}),this.eventManager.emit("editor:active",{view:t,editor:this.activeEditor})):(this.activeView=null,this.activeEditor=null,this.logger.debug("No active markdown view"))}getActiveEditor(){return this.activeEditor||this.updateActiveEditor(),this.activeEditor}getActiveView(){return this.activeView||this.updateActiveEditor(),this.activeView}hasActiveEditor(){return this.getActiveEditor()!==null}getCursorPosition(){let t=this.getActiveEditor();return t?t.getCursor():null}getSelection(){let t=this.getActiveEditor();return t?t.getSelection():""}getSelectionRange(){let t=this.getActiveEditor();if(!t)return null;let e=t.getCursor("from"),r=t.getCursor("to");return{from:e,to:r}}async insertAtCursor(t,e=!0){let r=this.getActiveEditor();if(!r)return this.logger.warn("No active editor for text insertion"),!1;try{let i=r.getCursor();e&&this.recordAction({type:"insert",position:i,text:t,timestamp:Date.now()}),r.replaceRange(t,i);let n={line:i.line,ch:i.ch+t.length};return r.setCursor(n),this.logger.debug("Text inserted at cursor",{position:i,textLength:t.length}),this.eventManager.emit("editor:text-inserted",{text:t,position:i}),!0}catch(i){return this.logger.error("Failed to insert text at cursor",i),!1}}async replaceSelection(t,e=!0){let r=this.getActiveEditor();if(!r)return this.logger.warn("No active editor for text replacement"),!1;try{let i=r.getSelection(),n=this.getSelectionRange();return e&&n&&this.recordAction({type:"replace",range:n,oldText:i,newText:t,timestamp:Date.now()}),r.replaceSelection(t),this.logger.debug("Selection replaced",{oldLength:i.length,newLength:t.length}),this.eventManager.emit("editor:text-replaced",{oldText:i,newText:t}),!0}catch(i){return this.logger.error("Failed to replace selection",i),!1}}async insertAtPosition(t,e,r=!0){let i=this.getActiveEditor();if(!i)return this.logger.warn("No active editor for text insertion"),!1;try{return r&&this.recordAction({type:"insert",position:e,text:t,timestamp:Date.now()}),i.replaceRange(t,e),this.logger.debug("Text inserted at position",{position:e,textLength:t.length}),!0}catch(n){return this.logger.error("Failed to insert text at position",n),!1}}async appendToLine(t,e){let r=this.getActiveEditor();if(!r)return!1;try{let i=r.getLine(t);if(i===void 0)return this.logger.warn("Invalid line number",{lineNumber:t}),!1;let n={line:t,ch:i.length};return await this.insertAtPosition(e,n)}catch(i){return this.logger.error("Failed to append to line",i),!1}}async appendToDocument(t,e=!0){let r=this.getActiveEditor();if(!r)return!1;try{let i=r.lastLine(),n=r.getLine(i),s={line:i,ch:n.length},a=e?`
|
|
${t}`:t;return await this.insertAtPosition(a,s)}catch(i){return this.logger.error("Failed to append to document",i),!1}}async prependToDocument(t,e=!0){if(!this.getActiveEditor())return!1;try{let i={line:0,ch:0},n=e?`${t}
|
|
`:t;return await this.insertAtPosition(n,i)}catch(i){return this.logger.error("Failed to prepend to document",i),!1}}getCurrentLine(){let t=this.getActiveEditor();if(!t)return null;let e=t.getCursor();return t.getLine(e.line)}getCurrentLineNumber(){let t=this.getCursorPosition();return t?t.line:null}getDocumentContent(){let t=this.getActiveEditor();return t?t.getValue():null}async setDocumentContent(t){let e=this.getActiveEditor();if(!e)return!1;try{let r=e.getValue();return this.recordAction({type:"set-content",oldText:r,newText:t,timestamp:Date.now()}),e.setValue(t),this.logger.debug("Document content updated"),!0}catch(r){return this.logger.error("Failed to set document content",r),!1}}recordAction(t){this.undoHistory.push(t),this.undoHistory.length>this.maxHistorySize&&this.undoHistory.shift(),this.redoHistory.length=0}async undo(){if(this.undoHistory.length===0)return this.logger.debug("No actions to undo"),!1;let t=this.getActiveEditor();if(!t)return!1;let e=this.undoHistory.pop();this.redoHistory.push(e);try{switch(e.type){case"insert":if(e.position&&e.text){let r=e.position,i={line:r.line,ch:r.ch+e.text.length};t.replaceRange("",r,i)}break;case"replace":e.range&&e.oldText!==void 0&&t.replaceRange(e.oldText,e.range.from,e.range.to);break;case"set-content":e.oldText!==void 0&&t.setValue(e.oldText);break}return this.logger.debug("Undo executed",{actionType:e.type}),!0}catch(r){return this.logger.error("Failed to execute undo",r),!1}}async redo(){if(this.redoHistory.length===0)return this.logger.debug("No actions to redo"),!1;let t=this.getActiveEditor();if(!t)return!1;let e=this.redoHistory.pop();this.undoHistory.push(e);try{switch(e.type){case"insert":e.position&&e.text&&t.replaceRange(e.text,e.position);break;case"replace":e.range&&e.newText!==void 0&&t.replaceRange(e.newText,e.range.from,e.range.to);break;case"set-content":e.newText!==void 0&&t.setValue(e.newText);break}return this.logger.debug("Redo executed",{actionType:e.type}),!0}catch(r){return this.logger.error("Failed to execute redo",r),!1}}clearHistory(){this.undoHistory.length=0,this.redoHistory.length=0,this.logger.debug("Editor history cleared")}async createAndOpenNote(t,e,r=""){try{let i=r?`${r}/${t}`:t,n=await this.app.vault.create(i,e);return await this.app.workspace.openLinkText(n.path,"",!0),this.logger.debug("New note created and opened",{path:i}),this.eventManager.emit("editor:note-created",{file:n,content:e}),!0}catch(i){return this.logger.error("Failed to create and open note",i),new be.Notice("Failed to create new note"),!1}}setCursorPosition(t){let e=this.getActiveEditor();if(!e)return!1;try{return e.setCursor(t),!0}catch(r){return this.logger.error("Failed to set cursor position",r),!1}}selectRange(t,e){let r=this.getActiveEditor();if(!r)return!1;try{return r.setSelection(t,e),!0}catch(i){return this.logger.error("Failed to select range",i),!1}}focus(){let t=this.getActiveEditor();if(!t)return!1;try{return t.focus(),!0}catch(e){return this.logger.error("Failed to focus editor",e),!1}}destroy(){this.clearHistory(),this.activeEditor=null,this.activeView=null,this.logger.debug("EditorService destroyed")}};var Te=require("obsidian");var Ee=class{constructor(t,e,r){this.editorService=t;this.eventManager=e;this.previewMode=!1;this.lastInsertedText="";this.insertionHistory=[];this.maxHistorySize=20;this.logger=r||new _("TextInsertionHandler"),this.setupEventListeners()}setupEventListeners(){this.eventManager.on("transcription:complete",async t=>{t.autoInsert&&await this.handleTranscriptionComplete(t.text,t.options)})}async handleTranscriptionComplete(t,e){let r={mode:"cursor",format:"plain",addTimestamp:!1,...e};await this.insertText(t,r)}async insertText(t,e){try{if(!this.editorService.hasActiveEditor())return e.createNewNote?await this.createNewNoteWithText(t,e):(new Te.Notice("No active editor. Please open a note first."),!1);let r=await this.formatText(t,e);if(this.previewMode||e.preview)return await this.showPreview(r,e);let i=await this.executeInsertion(r,e);return i&&(this.recordInsertion({text:r,originalText:t,options:e,timestamp:Date.now()}),this.eventManager.emit("text:inserted",{text:r,options:e}),this.logger.debug("Text inserted successfully",{mode:e.mode,textLength:r.length})),i}catch(r){return this.logger.error("Failed to insert text",r),new Te.Notice("Failed to insert text. Please try again."),!1}}async formatText(t,e){let r=t;switch(r=this.cleanupText(r),e.format){case"markdown":r=this.applyMarkdownFormat(r,e);break;case"quote":r=this.applyQuoteFormat(r,e);break;case"bullet":r=this.applyBulletFormat(r,e);break;case"heading":r=this.applyHeadingFormat(r,e);break;case"code":r=this.applyCodeFormat(r,e);break;case"callout":r=this.applyCalloutFormat(r,e);break}return e.addTimestamp&&(r=this.addTimestamp(r,e.timestampFormat)),e.template&&(r=this.applyTemplate(r,e.template)),e.language&&(r=this.processLanguageSpecific(r,e.language)),r}cleanupText(t){return t.trim().replace(/\r\n/g,`
|
|
`).replace(/\n{3,}/g,`
|
|
|
|
`).replace(/^\s+|\s+$/gm,"")}applyMarkdownFormat(t,e){let r=t;return e.paragraphBreaks&&(r=r.split(/\n+/).filter(i=>i.trim()).join(`
|
|
|
|
`)),r}applyQuoteFormat(t,e){let i=t.split(`
|
|
`).map(n=>`> ${n}`).join(`
|
|
`);return e.quoteAuthor?`${i}
|
|
>
|
|
> \u2014 ${e.quoteAuthor}`:i}applyBulletFormat(t,e){let r=t.split(`
|
|
`).filter(n=>n.trim()),i=e.bulletChar||"-";return r.map(n=>`${i} ${n}`).join(`
|
|
`)}applyHeadingFormat(t,e){let r=e.headingLevel||2,i="#".repeat(r),n=t.split(`
|
|
`);return n.length>0&&(n[0]=`${i} ${n[0]}`),n.join(`
|
|
`)}applyCodeFormat(t,e){return`\`\`\`${e.codeLanguage||""}
|
|
${t}
|
|
\`\`\``}applyCalloutFormat(t,e){let r=e.calloutType||"info",i=e.calloutTitle||"",n=e.calloutFoldable?"+":"";return`> [!${r}]${n} ${i}
|
|
> ${t.replace(/\n/g,`
|
|
> `)}`}addTimestamp(t,e){let r=new Date;return`[${e?this.formatDate(r,e):r.toISOString()}]
|
|
${t}`}formatDate(t,e){let r={YYYY:t.getFullYear().toString(),MM:(t.getMonth()+1).toString().padStart(2,"0"),DD:t.getDate().toString().padStart(2,"0"),HH:t.getHours().toString().padStart(2,"0"),mm:t.getMinutes().toString().padStart(2,"0"),ss:t.getSeconds().toString().padStart(2,"0")},i=e;for(let[n,s]of Object.entries(r))i=i.replace(new RegExp(n,"g"),s);return i}applyTemplate(t,e){return e.replace("{{content}}",t).replace("{{date}}",new Date().toLocaleDateString()).replace("{{time}}",new Date().toLocaleTimeString()).replace("{{datetime}}",new Date().toLocaleString())}processLanguageSpecific(t,e){switch(e){case"ko":return this.processKoreanText(t);case"ja":return this.processJapaneseText(t);case"zh":return this.processChineseText(t);default:return t}}processKoreanText(t){return t.replace(/\s+([.,!?])/g,"$1").replace(/([.,!?])\s*/g,"$1 ").trim()}processJapaneseText(t){return t}processChineseText(t){return t}async executeInsertion(t,e){switch(e.mode){case"cursor":return await this.editorService.insertAtCursor(t);case"replace":return await this.editorService.replaceSelection(t);case"append":return await this.editorService.appendToDocument(t,!0);case"prepend":return await this.editorService.prependToDocument(t,!0);case"line-end":let r=this.editorService.getCurrentLineNumber();return r!==null?await this.editorService.appendToLine(r,t):!1;case"new-line":let i=this.editorService.getCursorPosition();if(i){let n={line:i.line+1,ch:0};return await this.editorService.insertAtPosition(`
|
|
${t}`,i)}return!1;default:return await this.editorService.insertAtCursor(t)}}async showPreview(t,e){return new Te.Notice(`Preview:
|
|
${t.substring(0,100)}...`),this.eventManager.emit("text:preview",{text:t,options:e}),!0}async createNewNoteWithText(t,e){let r=new Date().toISOString().replace(/[:.]/g,"-"),i=e.noteTitle||`Transcription-${r}.md`,n=e.noteFolder||"",s=await this.formatText(t,e);return await this.editorService.createAndOpenNote(i,s,n)}recordInsertion(t){this.insertionHistory.push(t),this.insertionHistory.length>this.maxHistorySize&&this.insertionHistory.shift(),this.lastInsertedText=t.text}getLastInsertedText(){return this.lastInsertedText}getInsertionHistory(){return[...this.insertionHistory]}setPreviewMode(t){this.previewMode=t,this.logger.debug("Preview mode changed",{enabled:t})}isPreviewMode(){return this.previewMode}clearHistory(){this.insertionHistory=[],this.lastInsertedText="",this.logger.debug("Insertion history cleared")}destroy(){this.clearHistory(),this.logger.debug("TextInsertionHandler destroyed")}};var b=require("obsidian"),Se=class extends b.Modal{constructor(e,r,i,n){super(e);this.previewContainer=null;this.templates=[];this.onConfirm=i,this.onCancel=n,this.options={mode:"cursor",format:"plain",addTimestamp:!1,timestampFormat:"YYYY-MM-DD HH:mm:ss",...r},this.loadDefaultTemplates()}onOpen(){let{contentEl:e}=this;e.empty(),e.addClass("format-options-modal"),e.createEl("h2",{text:"Text Formatting Options"});let r=e.createDiv("format-tabs"),i=["Basic","Format","Advanced","Templates"],n=[];i.forEach((s,a)=>{let o=r.createEl("button",{text:s,cls:"format-tab"}),d=e.createDiv({cls:"format-tab-content"});a===0?(o.addClass("active"),d.addClass("active")):d.style.display="none",n.push(d),o.onclick=()=>{r.querySelectorAll(".format-tab").forEach(m=>{m.removeClass("active")}),n.forEach(m=>{m.removeClass("active"),m.style.display="none"}),o.addClass("active"),d.addClass("active"),d.style.display="block"}}),this.createBasicTab(n[0]),this.createFormatTab(n[1]),this.createAdvancedTab(n[2]),this.createTemplatesTab(n[3]),this.createPreviewSection(e),this.createButtonSection(e)}createBasicTab(e){new b.Setting(e).setName("Insertion Mode").setDesc("Where to insert the text").addDropdown(r=>{r.addOption("cursor","At Cursor").addOption("replace","Replace Selection").addOption("append","End of Document").addOption("prepend","Beginning of Document").addOption("line-end","End of Current Line").addOption("new-line","New Line Below").setValue(this.options.mode).onChange(i=>{this.options.mode=i,this.updatePreview()})}),new b.Setting(e).setName("Text Format").setDesc("How to format the inserted text").addDropdown(r=>{r.addOption("plain","Plain Text").addOption("markdown","Markdown").addOption("quote","Quote Block").addOption("bullet","Bullet List").addOption("heading","Heading").addOption("code","Code Block").addOption("callout","Callout Block").setValue(this.options.format).onChange(i=>{this.options.format=i,this.updateFormatSpecificOptions(),this.updatePreview()})}),new b.Setting(e).setName("Add Timestamp").setDesc("Add timestamp before the text").addToggle(r=>{r.setValue(this.options.addTimestamp||!1).onChange(i=>{this.options.addTimestamp=i,this.updatePreview()})}),this.options.addTimestamp&&new b.Setting(e).setName("Timestamp Format").setDesc("Format for the timestamp (YYYY-MM-DD HH:mm:ss)").addText(r=>{r.setPlaceholder("YYYY-MM-DD HH:mm:ss").setValue(this.options.timestampFormat||"").onChange(i=>{this.options.timestampFormat=i,this.updatePreview()})})}createFormatTab(e){let r=e.createDiv("format-specific-options");this.updateFormatSpecificOptions(r)}updateFormatSpecificOptions(e){let r=e||document.querySelector(".format-specific-options");if(r)switch(r.empty(),this.options.format){case"quote":new b.Setting(r).setName("Quote Author").setDesc("Author attribution for the quote").addText(i=>{i.setPlaceholder("Author name").setValue(this.options.quoteAuthor||"").onChange(n=>{this.options.quoteAuthor=n,this.updatePreview()})});break;case"bullet":new b.Setting(r).setName("Bullet Character").setDesc("Character to use for bullets").addDropdown(i=>{i.addOption("-","- (Dash)").addOption("*","* (Asterisk)").addOption("+","+ (Plus)").addOption("\u2022","\u2022 (Bullet)").setValue(this.options.bulletChar||"-").onChange(n=>{this.options.bulletChar=n,this.updatePreview()})});break;case"heading":new b.Setting(r).setName("Heading Level").setDesc("Level of the heading (1-6)").addDropdown(i=>{for(let n=1;n<=6;n++)i.addOption(String(n),`H${n}`);i.setValue(String(this.options.headingLevel||2)).onChange(n=>{this.options.headingLevel=parseInt(n),this.updatePreview()})});break;case"code":new b.Setting(r).setName("Language").setDesc("Programming language for syntax highlighting").addText(i=>{i.setPlaceholder("javascript, python, etc.").setValue(this.options.codeLanguage||"").onChange(n=>{this.options.codeLanguage=n,this.updatePreview()})});break;case"callout":new b.Setting(r).setName("Callout Type").setDesc("Type of callout block").addDropdown(i=>{i.addOption("info","Info").addOption("tip","Tip").addOption("warning","Warning").addOption("danger","Danger").addOption("note","Note").addOption("abstract","Abstract").addOption("success","Success").addOption("question","Question").addOption("failure","Failure").addOption("example","Example").addOption("quote","Quote").setValue(this.options.calloutType||"info").onChange(n=>{this.options.calloutType=n,this.updatePreview()})}),new b.Setting(r).setName("Callout Title").setDesc("Title for the callout").addText(i=>{i.setPlaceholder("Title").setValue(this.options.calloutTitle||"").onChange(n=>{this.options.calloutTitle=n,this.updatePreview()})}),new b.Setting(r).setName("Foldable").setDesc("Make callout foldable").addToggle(i=>{i.setValue(this.options.calloutFoldable||!1).onChange(n=>{this.options.calloutFoldable=n,this.updatePreview()})});break}}createAdvancedTab(e){new b.Setting(e).setName("Language").setDesc("Language for special processing").addDropdown(r=>{r.addOption("","Auto Detect").addOption("en","English").addOption("ko","Korean").addOption("ja","Japanese").addOption("zh","Chinese").addOption("es","Spanish").addOption("fr","French").addOption("de","German").setValue(this.options.language||"").onChange(i=>{this.options.language=i,this.updatePreview()})}),new b.Setting(e).setName("Paragraph Breaks").setDesc("Add paragraph breaks between sentences").addToggle(r=>{r.setValue(this.options.paragraphBreaks||!1).onChange(i=>{this.options.paragraphBreaks=i,this.updatePreview()})}),new b.Setting(e).setName("Create New Note").setDesc("Create a new note for the text").addToggle(r=>{r.setValue(this.options.createNewNote||!1).onChange(i=>{this.options.createNewNote=i,this.updateNewNoteOptions()})}),this.options.createNewNote&&(new b.Setting(e).setName("Note Title").setDesc("Title for the new note").addText(r=>{r.setPlaceholder("Transcription-YYYY-MM-DD").setValue(this.options.noteTitle||"").onChange(i=>{this.options.noteTitle=i})}),new b.Setting(e).setName("Note Folder").setDesc("Folder for the new note").addText(r=>{r.setPlaceholder("Transcriptions").setValue(this.options.noteFolder||"").onChange(i=>{this.options.noteFolder=i})})),new b.Setting(e).setName("Preview Before Insert").setDesc("Show preview before inserting text").addToggle(r=>{r.setValue(this.options.preview||!1).onChange(i=>{this.options.preview=i})})}createTemplatesTab(e){let r=new b.Setting(e).setName("Template").setDesc("Select a template to apply"),i=new b.DropdownComponent(r.controlEl);i.addOption("","None"),this.templates.forEach(o=>{i.addOption(o.id,o.name)}),i.onChange(o=>{let d=this.templates.find(m=>m.id===o);d?(this.options.template=d.content,this.updatePreview()):(this.options.template=void 0,this.updatePreview())}),new b.Setting(e).setName("Custom Template").setDesc("Use {{content}} for the text placeholder").addTextArea(o=>{o.setPlaceholder(`## {{date}}
|
|
|
|
{{content}}
|
|
|
|
---
|
|
Transcribed at {{time}}`).setValue(this.options.template||"").onChange(d=>{this.options.template=d,this.updatePreview()}),o.inputEl.rows=5,o.inputEl.cols=50});let n=e.createDiv("template-help");n.createEl("h4",{text:"Available Variables:"});let s=n.createEl("ul");[{var:"{{content}}",desc:"The transcribed text"},{var:"{{date}}",desc:"Current date"},{var:"{{time}}",desc:"Current time"},{var:"{{datetime}}",desc:"Current date and time"}].forEach(o=>{let d=s.createEl("li");d.createEl("code",{text:o.var}),d.createSpan({text:` - ${o.desc}`})})}createPreviewSection(e){let r=e.createDiv("preview-section");r.createEl("h3",{text:"Preview"}),this.previewContainer=r.createDiv("preview-content"),this.previewContainer.createEl("p",{text:"Preview will appear here...",cls:"preview-placeholder"})}createButtonSection(e){let r=e.createDiv("button-container"),i=r.createEl("button",{text:"Reset to Defaults",cls:"mod-cta-secondary"});i.onclick=()=>{this.resetToDefaults()};let n=r.createEl("button",{text:"Cancel"});n.onclick=()=>{this.onCancel(),this.close()};let s=r.createEl("button",{text:"Apply",cls:"mod-cta"});s.onclick=()=>{this.onConfirm(this.options),this.close()}}updatePreview(){if(!this.previewContainer)return;let e="This is a sample transcribed text to show how the formatting will be applied.",r=this.simulateFormatting(e);this.previewContainer.empty();let i=this.previewContainer.createEl("pre",{text:r,cls:"format-preview"})}simulateFormatting(e){let r=e;switch(this.options.format){case"quote":r=`> ${r}`,this.options.quoteAuthor&&(r+=`
|
|
>
|
|
> \u2014 ${this.options.quoteAuthor}`);break;case"bullet":r=`${this.options.bulletChar||"-"} ${r}`;break;case"heading":let n=this.options.headingLevel||2;r=`${"#".repeat(n)} ${r}`;break;case"code":r=`\`\`\`${this.options.codeLanguage||""}
|
|
${r}
|
|
\`\`\``;break;case"callout":let a=this.options.calloutType||"info",o=this.options.calloutTitle||"",d=this.options.calloutFoldable?"+":"";r=`> [!${a}]${d} ${o}
|
|
> ${r}`;break}return this.options.addTimestamp&&(r=`[${this.formatCurrentDate(this.options.timestampFormat||"YYYY-MM-DD HH:mm:ss")}]
|
|
${r}`),this.options.template&&(r=this.options.template.replace("{{content}}",r).replace("{{date}}",new Date().toLocaleDateString()).replace("{{time}}",new Date().toLocaleTimeString()).replace("{{datetime}}",new Date().toLocaleString())),r}formatCurrentDate(e){let r=new Date,i={YYYY:r.getFullYear().toString(),MM:(r.getMonth()+1).toString().padStart(2,"0"),DD:r.getDate().toString().padStart(2,"0"),HH:r.getHours().toString().padStart(2,"0"),mm:r.getMinutes().toString().padStart(2,"0"),ss:r.getSeconds().toString().padStart(2,"0")},n=e;for(let[s,a]of Object.entries(i))n=n.replace(new RegExp(s,"g"),a);return n}updateNewNoteOptions(){let e=document.querySelectorAll(".format-tab-content")[2];e&&this.createAdvancedTab(e)}resetToDefaults(){this.options={mode:"cursor",format:"plain",addTimestamp:!1,timestampFormat:"YYYY-MM-DD HH:mm:ss"},this.onOpen()}loadDefaultTemplates(){this.templates=[{id:"meeting",name:"Meeting Notes",format:"markdown",content:`## Meeting Notes - {{date}}
|
|
|
|
### Attendees
|
|
-
|
|
|
|
### Agenda
|
|
-
|
|
|
|
### Discussion
|
|
{{content}}
|
|
|
|
### Action Items
|
|
-
|
|
|
|
---
|
|
*Transcribed at {{datetime}}*`},{id:"daily",name:"Daily Note",format:"markdown",content:`## {{date}}
|
|
|
|
### Transcription
|
|
{{content}}
|
|
|
|
### Thoughts
|
|
|
|
|
|
### Tasks
|
|
- [ ]
|
|
|
|
---
|
|
*Created at {{time}}*`},{id:"interview",name:"Interview",format:"markdown",content:`# Interview Notes
|
|
**Date:** {{date}}
|
|
**Time:** {{time}}
|
|
|
|
## Transcript
|
|
{{content}}
|
|
|
|
## Key Points
|
|
-
|
|
|
|
## Follow-up Questions
|
|
-
|
|
|
|
---`},{id:"lecture",name:"Lecture Notes",format:"markdown",content:`# Lecture Notes
|
|
**Date:** {{date}}
|
|
**Topic:**
|
|
|
|
## Main Content
|
|
{{content}}
|
|
|
|
## Key Concepts
|
|
1.
|
|
2.
|
|
3.
|
|
|
|
## Questions
|
|
-
|
|
|
|
## References
|
|
-
|
|
|
|
---
|
|
*Transcribed at {{datetime}}*`}]}onClose(){let{contentEl:e}=this;e.empty()}};var v=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;
|
|
margin: 10px 0;
|
|
font-size: 0.9em;
|
|
`,METRICS_ROW:"display: flex; gap: 20px; margin-top: 8px;",LANGUAGES_ROW:"margin-top: 8px;",COST_CONTAINER:`
|
|
background: var(--background-modifier-border);
|
|
padding: 12px;
|
|
border-radius: 6px;
|
|
margin-top: 20px;
|
|
`,ERROR_CONTAINER:"padding: 12px; margin-bottom: 20px; border-radius: 6px;",ERROR_DETAILS:"font-size: 0.85em; overflow: auto;",DESCRIPTION_MARGIN:"margin-bottom: 20px;"}},H={ENDPOINTS:{VALIDATION:"https://api.deepgram.com/v1/projects"},HEADERS:{AUTHORIZATION_PREFIX:"Token",CONTENT_TYPE:"application/json"},METHODS:{GET:"GET",POST:"POST"},MASK:{VISIBLE_START:8,VISIBLE_END:4,CHAR:"*"},TIMEOUT:{MIN:5e3,MAX:12e4}},k={TIMEOUT:{MIN:5e3,MAX:12e4,DEFAULT:3e4},RETRIES:{MIN:0,MAX:3,DEFAULT:3},COST_ESTIMATION:{DAILY_MINUTES:10,DAYS_PER_MONTH:30},VALIDATION_RESET_DELAY:3e3},ot=[{value:"auto",label:"Auto-detect"},{value:"en",label:"English"},{value:"es",label:"Spanish"},{value:"fr",label:"French"},{value:"de",label:"German"},{value:"pt",label:"Portuguese"},{value:"nl",label:"Dutch"},{value:"it",label:"Italian"},{value:"pl",label:"Polish"},{value:"ru",label:"Russian"},{value:"zh",label:"Chinese"},{value:"ja",label:"Japanese"},{value:"ko",label:"Korean"},{value:"ar",label:"Arabic"},{value:"hi",label:"Hindi"}],lt=[{id:"nova-3",name:"Nova 3",tier:"Premium",price:.0043},{id:"nova-2",name:"Nova 2",tier:"Premium",price:.0059},{id:"nova",name:"Nova",tier:"Standard",price:.0025},{id:"enhanced",name:"Enhanced",tier:"Standard",price:.0145},{id:"base",name:"Base",tier:"Economy",price:.0125}],ct=[{key:"punctuation",name:"Punctuation",description:"Add punctuation to transcript",default:!0},{key:"smartFormat",name:"Smart Format",description:"Format numbers, dates, etc.",default:!0},{key:"diarization",name:"Speaker Diarization",description:"Identify different speakers",default:!0},{key:"numerals",name:"Numerals",description:"Convert numbers to digits",default:!1}];var D=class{constructor(){this.enabled=!0;this.minLevel=N.INFO}static getInstance(){return D.instance||(D.instance=new D),D.instance}setEnabled(t){this.enabled=t}setMinLevel(t){this.minLevel=t}debug(t,...e){this.shouldLog(N.DEBUG)&&(`${R}${t}`,[...e])}info(t,...e){this.shouldLog(N.INFO)&&(`${R}${t}`,[...e])}warn(t,...e){this.shouldLog(N.WARN)&&console.warn(`${R} ${t}`,...e)}error(t,e){this.shouldLog(N.ERROR)&&(console.error(`${R} ${t}`),e&&(e instanceof Error?console.error(`${R} Error details:`,{message:e.message,stack:e.stack}):console.error(`${R} Error details:`,e)))}group(t){this.enabled&&console.group(`${R} ${t}`)}groupEnd(){this.enabled&&console.groupEnd()}shouldLog(t){if(!this.enabled)return!1;let e=[N.DEBUG,N.INFO,N.WARN,N.ERROR],r=e.indexOf(t),i=e.indexOf(this.minLevel);return r>=i}time(t){this.enabled&&console.time(`${R} ${t}`)}timeEnd(t){this.enabled&&console.timeEnd(`${R} ${t}`)}};var Ae={models:{"nova-3":{id:"nova-3",name:"Nova 3",description:"Latest premium model with higher accuracy and improved diarization",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi"],performance:{accuracy:98,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"}},"nova-2":{id:"nova-2",name:"Nova 2",description:"Most accurate and powerful model with advanced features",tier:"premium",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!0,utterances:!0,summarization:!0},languages:["en","es","fr","de","pt","nl","it","pl","ru","zh","ja","ko","ar","hi"],performance:{accuracy:95,speed:"fast",latency:"low"},pricing:{perMinute:.0043,currency:"USD"}},nova:{id:"nova",name:"Nova",description:"Balanced model with good accuracy and speed",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!0,numerals:!0,profanityFilter:!0,redaction:!1,utterances:!0,summarization:!1},languages:["en","es","fr","de","pt","nl","it"],performance:{accuracy:90,speed:"fast",latency:"low"},pricing:{perMinute:.0025,currency:"USD"}},enhanced:{id:"enhanced",name:"Enhanced",description:"Enhanced accuracy for challenging audio",tier:"standard",features:{punctuation:!0,smartFormat:!0,diarization:!1,numerals:!0,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:85,speed:"moderate",latency:"medium"},pricing:{perMinute:.0145,currency:"USD"}},base:{id:"base",name:"Base",description:"Cost-effective option for simple transcription",tier:"economy",features:{punctuation:!0,smartFormat:!1,diarization:!1,numerals:!1,profanityFilter:!1,redaction:!1,utterances:!1,summarization:!1},languages:["en"],performance:{accuracy:80,speed:"moderate",latency:"medium"},pricing:{perMinute:.0125,currency:"USD"}}},features:{punctuation:{name:"Punctuation",description:"Add punctuation marks to transcript",default:!0,requiresPremium:!1},smartFormat:{name:"Smart Format",description:"Format numbers, dates, and other entities",default:!0,requiresPremium:!1},diarization:{name:"Speaker Diarization",description:"Identify different speakers",default:!1,requiresPremium:!1},numerals:{name:"Numerals",description:"Convert numbers to digits",default:!1,requiresPremium:!1},profanityFilter:{name:"Profanity Filter",description:"Filter out profanity from transcript",default:!1,requiresPremium:!1},redaction:{name:"Redaction",description:"Redact sensitive information",default:!1,requiresPremium:!0},utterances:{name:"Utterances",description:"Split transcript into utterances",default:!1,requiresPremium:!1},summarization:{name:"Summarization",description:"Generate summary of transcript",default:!1,requiresPremium:!0}}},Ge,ut=D.getInstance();try{Ge=dt(),ut.info("Successfully loaded config from JSON file")}catch(l){ut.warn("Could not load deepgram-models.json, using fallback"),Ge=Ae}var x=class{constructor(){this.models=new Map,this.features=new Map,this.logger=D.getInstance();try{this.loadConfiguration(),this.logger.info("Constructor completed successfully")}catch(t){this.logger.error("Error during initialization",t)}}static getInstance(){try{return x.instance||(x.instance=new x),x.instance}catch(t){if(!x.instance){let e=Object.create(x.prototype);e.models=new Map,e.features=new Map,e.logger=D.getInstance(),e.logger.error("Failed to create instance, using fallback",t),x.instance=e}return x.instance}}loadConfiguration(){try{let t=Ge||Ae;this.loadModels(t),this.loadFeatures(t),this.models.size===0&&this.features.size===0&&(this.logger.warn("No data loaded, loading fallback configuration"),this.loadFallbackConfiguration())}catch(t){this.logger.error("Error loading configuration",t),this.loadFallbackConfiguration()}}loadModels(t){if(!t.models||typeof t.models!="object"){this.logger.warn("No models in configuration");return}Object.entries(t.models).forEach(([e,r])=>{try{this.isValidModel(r)?this.models.set(e,r):this.logger.warn(`Invalid model structure for ${e}`)}catch(i){this.logger.error(`Failed to load model ${e}`,i)}}),this.logger.info(`Loaded ${this.models.size} models`)}loadFeatures(t){if(!t.features||typeof t.features!="object"){this.logger.warn("No features in configuration");return}Object.entries(t.features).forEach(([e,r])=>{try{this.isValidFeature(r)?this.features.set(e,r):this.logger.warn(`Invalid feature structure for ${e}`)}catch(i){this.logger.error(`Failed to load feature ${e}`,i)}}),this.logger.info(`Loaded ${this.features.size} features`)}loadFallbackConfiguration(){try{Object.entries(Ae.models).forEach(([t,e])=>{this.models.set(t,e)}),Object.entries(Ae.features).forEach(([t,e])=>{this.features.set(t,e)}),this.logger.info("Fallback configuration loaded")}catch(t){this.logger.error("Failed to load fallback configuration",t)}}isValidModel(t){return t&&typeof t=="object"&&typeof t.id=="string"&&typeof t.name=="string"&&t.features&&t.languages&&Array.isArray(t.languages)&&t.performance&&t.pricing}isValidFeature(t){return t&&typeof t=="object"&&typeof t.name=="string"&&typeof t.description=="string"&&typeof t.default=="boolean"}getAllModels(){try{return Array.from(this.models.values())}catch(t){return this.logger.error("Error getting all models",t),[]}}getModel(t){return this.models.get(t)}getAllFeatures(){try{return this.features}catch(t){return this.logger.error("Error getting all features",t),new Map}}getFeature(t){return this.features.get(t)}isLanguageSupported(t,e){let r=this.models.get(t);return r?r.languages.includes(e):!1}isFeatureSupported(t,e){let r=this.models.get(t);return r?r.features[e]===!0:!1}getModelsByLanguage(t){return Array.from(this.models.values()).filter(e=>e.languages.includes(t))}getModelsByTier(t){return Array.from(this.models.values()).filter(e=>e.tier===t)}getModelsByPriceRange(t){return Array.from(this.models.values()).filter(e=>e.pricing.perMinute<=t)}calculateCost(t,e){let r=this.models.get(t);return r?r.pricing.perMinute*e:0}getPerformanceScore(t){let e=this.models.get(t);if(!e)return 0;let r=e.performance.accuracy;return e.performance.speed==="fast"?r+=5:e.performance.speed==="moderate"&&(r+=2),e.performance.latency==="high"?r-=5:e.performance.latency==="medium"&&(r-=2),Math.min(100,Math.max(0,r))}getRecommendedModel(t){let e=Array.from(this.models.values());return t.language&&(e=e.filter(r=>r.languages.includes(t.language))),t.maxPrice!==void 0&&(e=e.filter(r=>r.pricing.perMinute<=t.maxPrice)),t.minAccuracy!==void 0&&(e=e.filter(r=>r.performance.accuracy>=t.minAccuracy)),t.requiredFeatures&&t.requiredFeatures.length>0&&(e=e.filter(r=>t.requiredFeatures.every(i=>r.features[i]===!0))),e.length>0?(e.sort((r,i)=>this.getPerformanceScore(i.id)-this.getPerformanceScore(r.id)),e[0]):null}validateModel(t){let e=[],r=this.models.get(t);return r?(r.id||e.push("Model ID is missing"),r.name||e.push("Model name is missing"),r.tier||e.push("Model tier is missing"),(!r.languages||r.languages.length===0)&&e.push("Model must support at least one language"),r.pricing.perMinute<0&&e.push("Model pricing cannot be negative"),(r.performance.accuracy<0||r.performance.accuracy>100)&&e.push("Model accuracy must be between 0 and 100"),{valid:e.length===0,errors:e}):(e.push(`Model '${t}' not found`),{valid:!1,errors:e})}};var we=class{constructor(t){this.containerEl=t}createHeader(t){return this.containerEl.createEl("h4",{text:t})}createDescription(t){let e=this.containerEl.createEl("p",{text:t,cls:c.CLASSES.SETTING_DESCRIPTION});return e.style.cssText=c.STYLES.DESCRIPTION_MARGIN,e}createWarning(t){let e=this.containerEl.createEl("div",{cls:c.CLASSES.WARNING,text:t});return e.style.cssText=c.STYLES.WARNING_BOX,e}createModelInfoCard(t){this.removeElement(`.${c.CLASSES.MODEL_INFO}`);let e=this.containerEl.createEl("div",{cls:c.CLASSES.MODEL_INFO});return e.style.cssText=c.STYLES.INFO_CONTAINER,e.createEl("p",{text:t.description,cls:c.CLASSES.MODEL_DESCRIPTION}),this.createMetricsRow(e,t),this.createLanguagesRow(e,t),e}createMetricsRow(t,e){let r=t.createEl("div",{cls:c.CLASSES.MODEL_METRICS});r.style.cssText=c.STYLES.METRICS_ROW,r.createEl("span",{text:`Accuracy: ${e.performance.accuracy}%`}),r.createEl("span",{text:`Speed: ${e.performance.speed}`}),r.createEl("span",{text:`Latency: ${e.performance.latency}`})}createLanguagesRow(t,e){let r=t.createEl("div",{cls:c.CLASSES.SUPPORTED_LANGUAGES});r.style.cssText=c.STYLES.LANGUAGES_ROW,r.createEl("span",{text:`Supported languages: ${e.languages.join(", ")}`})}createCostEstimationContainer(){let t=this.containerEl.createEl("div",{cls:c.CLASSES.COST_ESTIMATION});return t.style.cssText=c.STYLES.COST_CONTAINER,t.createEl("h5",{text:c.MESSAGES.COST_HEADER}),t}updateCostDetails(t,e,r){let i=t.querySelector(`.${c.CLASSES.COST_DETAILS}`)||t.createEl("div",{cls:c.CLASSES.COST_DETAILS});if(i.empty(),!e){i.createEl("p",{text:"Select a model to see cost estimation",cls:c.CLASSES.WARNING});return}let n=i.createEl("div");if(n.createEl("p",{text:`Cost per minute: $${e.pricing.perMinute}`}),r!==void 0){let s=k.COST_ESTIMATION.DAILY_MINUTES;n.createEl("p",{text:`Estimated monthly cost (${s} min/day): $${r.toFixed(2)}`})}}addBudgetWarning(t,e,r){if(e>r){let i=t.querySelector(".budget-warning")||t.createEl("p",{cls:"budget-warning"});i.textContent=`\u26A0\uFE0F Exceeds monthly budget of $${r}`,i.classList.add(c.CLASSES.WARNING)}}createErrorContainer(t){let e=this.containerEl.createEl("div",{cls:c.CLASSES.WARNING});if(e.style.cssText=c.STYLES.ERROR_CONTAINER,e.createEl("h5",{text:c.MESSAGES.FALLBACK_ERROR_TITLE}),e.createEl("p",{text:c.MESSAGES.FALLBACK_ERROR_DESC}),t instanceof Error){let r=e.createEl("details");r.createEl("summary",{text:"Error details"}),r.createEl("pre",{text:t.message,cls:c.CLASSES.ERROR_DETAILS}).style.cssText=c.STYLES.ERROR_DETAILS}return e}createSection(t,e){let r=this.containerEl.createEl("div",{cls:t});return e&&r.createEl("h5",{text:e}),r}removeElement(t){let e=this.containerEl.querySelector(t);e&&e.remove()}clearContainer(){this.containerEl.empty()}};var gt=require("obsidian");var Ie=class{constructor(){this.logger=D.getInstance()}async validateApiKey(t){if(!t)return this.logger.warn("API key validation failed: No key provided"),!1;try{this.logger.info("Validating API key via Obsidian requestUrl...");let e={url:H.ENDPOINTS.VALIDATION,method:H.METHODS.GET,headers:{Authorization:`${H.HEADERS.AUTHORIZATION_PREFIX} ${t}`,"Content-Type":H.HEADERS.CONTENT_TYPE},throw:!1},r=await(0,gt.requestUrl)(e),i=r.status===200;return i?this.logger.info("API key validation successful"):this.logger.warn(`API key validation failed with status: ${r.status}`),i}catch(e){return this.logger.error("API validation error (requestUrl)",e),!1}}maskApiKey(t){if(!t||t.length<10)return"";let{VISIBLE_START:e,VISIBLE_END:r,CHAR:i}=H.MASK;if(t.length<=e+r)return t;let n=i.repeat(t.length-e-r);return t.substring(0,e)+n+t.substring(t.length-r)}validateTimeout(t){let e=parseInt(t)*1e3,{MIN:r,MAX:i}=H.TIMEOUT;return isNaN(e)||e<r||e>i?(this.logger.warn(`Invalid timeout value: ${t}`),null):e}validateRetries(t){let e=parseInt(t),{MIN:r,MAX:i}=k.RETRIES;return isNaN(e)||e<r||e>i?(this.logger.warn(`Invalid retries value: ${t}`),null):e}};var Ce=class{constructor(){this.logger=D.getInstance()}calculateEstimation(t,e){if(!t)return this.logger.debug("No model selected for cost calculation"),null;let{DAILY_MINUTES:r,DAYS_PER_MONTH:i}=k.COST_ESTIMATION,n=t.pricing.perMinute,s=n*r,a=s*i,o=e?a>e:!1;return this.logger.debug(`Cost calculated for ${t.name}:`,{perMinute:n,daily:s,monthly:a,exceeedsBudget:o}),{perMinute:n,daily:s,monthly:a,exceeedsBudget:o}}calculateCostByUsage(t,e){let r=t.pricing.perMinute*e;return this.logger.debug(`Usage cost calculated: ${e} minutes = $${r}`),r}calculateAvailableMinutes(t,e){let r=e/t.pricing.perMinute;return this.logger.debug(`Available minutes for budget $${e}: ${r.toFixed(2)}`),r}compareModelCosts(t,e){let r=new Map;return t.forEach(i=>{let n=this.calculateCostByUsage(i,e);r.set(i.id,n)}),r}calculateEfficiencyScore(t,e){if(t.pricing.perMinute>e)return 0;let r=1-t.pricing.perMinute/e,n=(t.performance.accuracy/100*.7+r*.3)*100;return this.logger.debug(`Efficiency score for ${t.name}: ${n.toFixed(2)}`),Math.round(n)}};var De=class{constructor(t,e){this.registry=null;this.selectedModel=null;this.estimatedCostEl=null;this.plugin=t,this.containerEl=e,this.logger=D.getInstance(),this.uiBuilder=new we(e),this.validator=new Ie,this.costCalculator=new Ce,this.initializeRegistry()}initializeRegistry(){try{this.logger.info("Attempting to initialize DeepgramModelRegistry..."),this.registry=x.getInstance();let t=this.registry.getAllModels();this.logger.info(`Registry initialized successfully with ${t.length} models`),t.length===0&&(this.logger.warn("Registry has no models, will use fallback"),this.registry=null)}catch(t){this.logger.error("Failed to initialize registry",t),this.registry=null,this.logger.info("Will continue with fallback UI")}}render(){this.logger.group("render()"),this.logRenderState();try{this.uiBuilder.clearContainer(),this.renderHeader(),this.renderSections(),this.logger.info(`Total elements created: ${this.containerEl.children.length}`),this.logger.groupEnd()}catch(t){this.logger.error("Critical error in render()",t),this.renderFallbackUI(t)}}logRenderState(){this.logger.debug("Container element:",this.containerEl),this.logger.debug("Container is connected:",this.containerEl.isConnected),this.logger.debug("Registry available:",!!this.registry),this.logger.debug("API key exists:",!!this.plugin.settings.deepgramApiKey),this.containerEl.isConnected||this.logger.warn("Container is not connected to DOM, attempting to render anyway"),this.registry||this.logger.warn("Registry not available, using fallback UI")}renderHeader(){this.uiBuilder.createHeader(c.MESSAGES.HEADER),this.uiBuilder.createDescription(c.MESSAGES.DESCRIPTION),this.registry||this.uiBuilder.createWarning(c.MESSAGES.REGISTRY_WARNING)}renderSections(){this.logger.info("Rendering API key section..."),this.renderApiKeySection(),this.logger.info("Rendering model selection..."),this.renderModelSelection(),this.logger.info("Rendering feature toggles..."),this.renderFeatureToggles(),this.logger.info("Rendering advanced settings..."),this.renderAdvancedSettings(),this.logger.info("Rendering cost estimation..."),this.renderCostEstimation(),this.logger.info("Rendering validation button..."),this.renderValidationButton()}renderApiKeySection(){new A.Setting(this.containerEl).setName(c.MESSAGES.API_KEY_LABEL).setDesc(c.MESSAGES.API_KEY_DESC).addText(t=>{this.setupApiKeyInput(t)})}setupApiKeyInput(t){let e=this.plugin.settings.deepgramApiKey||"";t.setPlaceholder(c.MESSAGES.API_KEY_PLACEHOLDER).setValue(this.validator.maskApiKey(e)).onChange(async r=>{await this.handleApiKeyChange(r,t)}),t.inputEl.type="password",t.inputEl.addClass(c.CLASSES.API_KEY_INPUT),this.attachApiKeyEventListeners(t)}async handleApiKeyChange(t,e){t&&!t.includes("*")&&(this.plugin.settings.deepgramApiKey=t,await this.plugin.saveSettings(),e.setValue(this.validator.maskApiKey(t)),new A.Notice(c.MESSAGES.API_KEY_SAVED),this.updateUIState())}attachApiKeyEventListeners(t){t.inputEl.addEventListener("focus",()=>{this.plugin.settings.deepgramApiKey&&t.setValue(this.plugin.settings.deepgramApiKey)}),t.inputEl.addEventListener("blur",()=>{this.plugin.settings.deepgramApiKey&&t.setValue(this.validator.maskApiKey(this.plugin.settings.deepgramApiKey))})}renderModelSelection(){let t=new A.Setting(this.containerEl).setName(c.MESSAGES.MODEL_LABEL).setDesc(c.MESSAGES.MODEL_DESC),e=t.addDropdown(r=>(this.populateModelDropdown(r),this.setupModelDropdownHandlers(r),r));this.disableIfNoApiKey(t)}populateModelDropdown(t){if(t.addOption("",c.MESSAGES.MODEL_PLACEHOLDER),!this.registry){this.logger.warn("Registry not available, using default models"),this.addDefaultModelOptions(t);return}try{let e=this.registry.getAllModels();e.length===0?(this.logger.warn("No models in registry, using defaults"),this.addDefaultModelOptions(t)):(this.addModelOptions(t,e),this.logger.info(`Added ${e.length} models to dropdown`))}catch(e){this.logger.error("Error loading models",e),this.addDefaultModelOptions(t)}}addModelOptions(t,e){e.forEach(r=>{let i=this.formatModelOption(r);t.addOption(r.id,i)})}formatModelOption(t){return`${t.name} (${t.tier}) - $${t.pricing.perMinute}/min`}setupModelDropdownHandlers(t){var r,i;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.handleModelChange(n)})}async handleModelChange(t){var e;if(!t){this.selectedModel=null;return}this.selectedModel=((e=this.registry)==null?void 0:e.getModel(t))||null,await this.saveModelSelection(t),this.updateUIAfterModelChange(),this.selectedModel&&new A.Notice(`Selected model: ${this.selectedModel.name}`)}async saveModelSelection(t){this.plugin.settings.transcription||(this.plugin.settings.transcription={}),this.plugin.settings.transcription.deepgram?this.plugin.settings.transcription.deepgram.model=t:this.plugin.settings.transcription.deepgram={enabled:!0,model:t},await this.plugin.saveSettings()}updateUIAfterModelChange(){this.updateModelInfo(),this.updateFeatureAvailability(),this.updateCostEstimation()}disableIfNoApiKey(t){if(!this.plugin.settings.deepgramApiKey){let e=t.settingEl.querySelector("select");e&&(e.disabled=!0),t.setDesc(c.MESSAGES.API_KEY_REQUIRED)}}updateModelInfo(){this.selectedModel&&this.uiBuilder.createModelInfoCard(this.selectedModel)}renderFeatureToggles(){let t=this.uiBuilder.createSection(c.CLASSES.FEATURES_CONTAINER,c.MESSAGES.FEATURES_HEADER);if(!this.registry){this.renderDefaultFeatures(t);return}this.registry.getAllFeatures().forEach((r,i)=>{this.renderFeatureToggle(t,r,i)})}renderFeatureToggle(t,e,r){let i=new A.Setting(t).setName(e.name).setDesc(this.getFeatureDescription(e));i.addToggle(n=>{let s=this.getFeatureValue(r,e.default);return n.setValue(s).onChange(async a=>{await this.saveFeatureSetting(r,a),this.updateCostEstimation()}),this.updateFeatureAvailabilityForToggle(n,i,e,r),n})}getFeatureDescription(t){return t.requiresPremium?`${t.description} (Premium feature)`:t.description}getFeatureValue(t,e){var i,n,s;let r=(n=(i=this.plugin.settings.transcription)==null?void 0:i.deepgram)==null?void 0:n.features;return(s=r==null?void 0:r[t])!=null?s:e}async saveFeatureSetting(t,e){this.ensureTranscriptionSettings(),this.plugin.settings.transcription.deepgram.features||(this.plugin.settings.transcription.deepgram.features={});let r=this.plugin.settings.transcription.deepgram.features;r[t]=e,await this.plugin.saveSettings()}ensureTranscriptionSettings(){this.plugin.settings.transcription||(this.plugin.settings.transcription={}),this.plugin.settings.transcription.deepgram||(this.plugin.settings.transcription.deepgram={enabled:!0})}updateFeatureAvailabilityForToggle(t,e,r,i){this.selectedModel&&this.registry&&!this.registry.isFeatureSupported(this.selectedModel.id,i)&&(t.setDisabled(!0),e.setDesc(`${r.description} (Not supported by selected model)`))}renderAdvancedSettings(){let t=this.uiBuilder.createSection(c.CLASSES.ADVANCED_CONTAINER,c.MESSAGES.ADVANCED_HEADER);this.renderLanguagePreference(t),this.renderTimeoutSetting(t),this.renderRetrySetting(t),this.renderChunkingSettings(t)}renderLanguagePreference(t){new A.Setting(t).setName("Preferred Language").setDesc("Set preferred language for better accuracy").addDropdown(e=>{ot.forEach(r=>{e.addOption(r.value,r.label)}),e.setValue(this.plugin.settings.language||"auto"),e.onChange(async r=>{this.plugin.settings.language=r,await this.plugin.saveSettings()})})}renderTimeoutSetting(t){new A.Setting(t).setName("Request Timeout").setDesc("Maximum time to wait for transcription (in seconds)").addText(e=>{let r=this.plugin.settings.requestTimeout||k.TIMEOUT.DEFAULT;e.setPlaceholder("30").setValue(String(r/1e3)).onChange(async i=>{let n=this.validator.validateTimeout(i);n!==null&&(this.plugin.settings.requestTimeout=n,await this.plugin.saveSettings())})})}renderRetrySetting(t){new A.Setting(t).setName("Max Retries").setDesc("Number of retry attempts on failure").addDropdown(e=>{for(let i=0;i<=k.RETRIES.MAX;i++){let n=i===0?"No retries":`${i} ${i===1?"retry":"retries"}`;e.addOption(String(i),n)}let r=this.plugin.settings.maxRetries||k.RETRIES.DEFAULT;e.setValue(String(r)),e.onChange(async i=>{this.plugin.settings.maxRetries=parseInt(i),await this.plugin.saveSettings()})})}renderChunkingSettings(t){new A.Setting(t).setName("Automatic File Chunking").setDesc("Automatically split large audio files (>50MB) into smaller chunks for reliable processing").addToggle(i=>{var n;i.setValue((n=this.plugin.settings.autoChunking)!=null?n:!0).onChange(async s=>{this.plugin.settings.autoChunking=s,await this.plugin.saveSettings();let a=t.querySelector(".chunk-size-setting");a&&(a.style.display=s?"flex":"none")})});let e=new A.Setting(t).setName("Maximum Chunk Size").setDesc("Maximum size per chunk in MB (recommended: 50MB)").addSlider(i=>{var n;i.setLimits(10,100,10).setValue((n=this.plugin.settings.maxChunkSizeMB)!=null?n:50).setDynamicTooltip().onChange(async s=>{this.plugin.settings.maxChunkSizeMB=s,await this.plugin.saveSettings()})});e.settingEl.addClass("chunk-size-setting"),this.plugin.settings.autoChunking||(e.settingEl.style.display="none");let r=t.createDiv();r.addClass("setting-item-description"),r.style.marginTop="10px",r.innerHTML=`
|
|
<strong>Note on Large Files:</strong><br>
|
|
\u2022 Files larger than 50MB may experience timeout errors<br>
|
|
\u2022 Auto-chunking splits files into manageable pieces<br>
|
|
\u2022 Each chunk is processed separately and results are merged<br>
|
|
\u2022 For best results with very large files (>100MB), consider:<br>
|
|
- Using the 'enhanced' model for faster processing<br>
|
|
- Reducing audio bitrate to 64-128 kbps<br>
|
|
- 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 v.PluginSettingTab{constructor(e,r){super(e,r);this.plugin=r}display(){var a,o,d,m,u,g,f,S,M,E,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:((S=(f=this.plugin)==null?void 0:f.settings)==null?void 0:S.language)||"Not set",autoInsert:(E=(M=this.plugin)==null?void 0:M.settings)==null?void 0:E.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.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 v.Notice("Debug mode enabled. Check console for logs.")})),new v.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 v.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 h.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 h.Notice("Speech-to-Text plugin loaded successfully")}catch(e){console.error("Failed to load Speech-to-Text plugin:",e),new h.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 h.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 h.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 h.Notice("Transcription history not yet implemented")}}),this.addCommand({id:"cancel-transcription",name:"Cancel current transcription",callback:()=>{this.transcriptionService.cancel(),new h.Notice("Transcription cancelled")}}),this.addCommand({id:"undo-insertion",name:"Undo last text insertion",callback:async()=>{await this.editorService.undo()?new h.Notice("Text insertion undone"):new h.Notice("Nothing to undo")}}),this.addCommand({id:"redo-insertion",name:"Redo last text insertion",callback:async()=>{await this.editorService.redo()?new h.Notice("Text insertion redone"):new h.Notice("Nothing to redo")}})}registerEventHandlers(){this.eventManager.on("transcription:start",e=>{this.stateManager.setState({status:"processing"}),new h.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 h.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 h.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 h.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 h.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 h.Notice(a);return}if(!this.transcriptionService&&(this.initializeTranscriptionService(),!this.transcriptionService)){new h.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 h.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 h.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(h.MarkdownView);if(!r){new h.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+`
|
|
|
|
`+o);break}}showFormatOptions(){this.showFormatOptionsWithText("")}showFormatOptionsWithText(e){new Se(this.app,{mode:"cursor",format:this.settings.textFormat||"plain",addTimestamp:this.settings.addTimestamp||!1,language:this.settings.language},async i=>{e?await this.textInsertionHandler.insertText(e,i):new h.Notice("No text to insert")},()=>{this.logger.debug("Format options cancelled")}).open()}async loadSettings(){this.settings=Object.assign({},Pe,await this.loadData())}async saveSettings(){await this.saveData(this.settings)}async saveSettingsAndReinitialize(){await this.saveData(this.settings),this.transcriberFactory&&(this.initializeTranscriberFactory(),this.initializeTranscriptionService())}},qe=class extends h.Modal{constructor(e,r,i){super(e);this.files=r,this.onChoose=i}onOpen(){let{contentEl:e}=this;e.createEl("h2",{text:"Select an audio file to transcribe"});let r=e.createEl("div",{cls:"speech-to-text-file-list"});this.files.forEach(i=>{r.createEl("div",{cls:"speech-to-text-file-item",text:i.path}).addEventListener("click",()=>{this.onChoose(i),this.close()})})}onClose(){let{contentEl:e}=this;e.empty()}};
|