
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *--------------------------------------------------------------------------------------------*/
import __module from "module";
import __path from "path";
import __fs from "fs";
const __rootRequire = __module.createRequire(import.meta.url);
const __appPath = __fs.realpathSync(import.meta.dirname);
const __sharpEntrypoint = __path.join(__appPath, "sharp", "index.js");
const __clipboardEntrypoint = __path.join(__appPath, "clipboard", "index.js");
const __foundryEntrypoint = __path.join(__appPath, "foundry-local-sdk", "index.js");
const __pvRecorderEntrypoint = __path.join(__appPath, "pvrecorder", "index.js");
const __sharpRequire = __fs.existsSync(__sharpEntrypoint)
    ? __module.createRequire(__sharpEntrypoint)
    : __rootRequire;
const __clipboardRequire = __fs.existsSync(__clipboardEntrypoint)
    ? __module.createRequire(__clipboardEntrypoint)
    : __rootRequire;
const __foundryRequire = __fs.existsSync(__foundryEntrypoint)
    ? __module.createRequire(__foundryEntrypoint)
    : __rootRequire;
const __pvRecorderRequire = __fs.existsSync(__pvRecorderEntrypoint)
    ? __module.createRequire(__pvRecorderEntrypoint)
    : __rootRequire;
const __isVendoredNativeModule = (module) =>
    typeof module === "string" &&
    (module.startsWith("@img/") || module.startsWith("@teddyzhu/") || module === "foundry-local-sdk" || module === "@picovoice/pvrecorder-node");
const require = (module) => {
    let req = __rootRequire;
    if (typeof module === "string" && module.startsWith("@img/")) {
        req = __sharpRequire;
    }
    if (typeof module === "string" && module.startsWith("@teddyzhu/")) {
        req = __clipboardRequire;
    }
    if (module === "foundry-local-sdk") {
        req = __foundryRequire;
    }
    if (module === "@picovoice/pvrecorder-node") {
        req = __pvRecorderRequire;
    }

    if (typeof module === "string" && (__module.isBuiltin(module) || __isVendoredNativeModule(module))) {
        return req(module);
    }

    const modulePath = __fs.realpathSync(req.resolve(module));
    const relativePath = __path.relative(__appPath, modulePath);

    if (relativePath.startsWith("..")) {
        throw new Error("Requiring module outside of application is a security concern; module: " + modulePath + ", app: " + __appPath);
    }

    return req(module);
};import __url from "url";
const __filename = __url.fileURLToPath(import.meta.url);
const __dirname = __path.dirname(__filename);
var j=(s=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(s,{get:(e,n)=>(typeof require<"u"?require:e)[n]}):s)(function(s){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+s+'" is not supported')});import{parentPort as v,workerData as re}from"node:worker_threads";var a=class extends Error{constructor(n,t,o){super(n,o);this.code=t;this.name="VoiceBackendError"}},V=16;function S(s){return E(s,new WeakSet,0)}function E(s,e,n){if(n>=V)return{name:"Error",message:"<cause chain truncated>"};if(typeof s=="object"&&s!==null){if(e.has(s))return{name:"Error",message:"<cyclic cause>"};e.add(s)}let t;if(s instanceof a)t={name:s.name,message:s.message,stack:s.stack,code:s.code};else if(s instanceof Error)t={name:s.name,message:s.message,stack:s.stack};else return{name:"Error",message:String(s)};return s instanceof Error&&s.cause!==void 0&&(t.cause=E(s.cause,e,n+1)),t}function L(s){return s instanceof Error?s:new Error(String(s))}function k(s,e){s.on("message",n=>{if(n==null||typeof n!="object")return;let t=n;t.kind==="request"&&W(s,e,t).catch(()=>{})})}async function W(s,e,n){try{let t=n.method,o=n.params,i=await e.call(t,o),r={kind:"response",id:n.id,ok:!0,result:i};s.postMessage(r)}catch(t){let o={kind:"response",id:n.id,ok:!1,error:S(t)};s.postMessage(o)}}var p=class{initialQueue=[];initialQueueResolvers=Promise.withResolvers();logWriter=null;writePromise=this.initialQueueResolvers.promise;setLogWriter(e){this.logWriter=e;for(let n of this.initialQueue)this.writePromise=this.logWriter.writeLog(n.method,n.message);this.initialQueue=[],this.initialQueueResolvers.resolve()}async flush(){await this.writePromise}async dispose(){await this.flush()}outputPath(){return this.logWriter?.outputPath()}logToLevel(e,n){this.logWriter?this.writePromise=this.logWriter.writeLog(e,n):this.initialQueue.push({method:e,message:n})}info(e){this.logToLevel("info",e)}debug(e){this.logToLevel("debug",e)}warning(e){this.logToLevel("warning",e)}error(e){this.logToLevel("error",e instanceof Error?e.message:e)}log(e){this.error(e)}isDebug(){return!1}shouldLog(e){return!0}notice(e){this.info(e instanceof Error?e.message:e)}startGroup(e,n){this.info(`--- Start of group: ${e} ---`)}endGroup(e){this.info("--- End of group ---")}},P=new p;var f=16*1024,m=class{constructor(e){this.port=e}writeLog(e,n){let t={kind:"log",level:e,message:H(n)};try{this.port.postMessage(t)}catch{}return Promise.resolve()}outputPath(){return"<voice-worker>"}};function I(s,e=P){e.setLogWriter(new m(s))}function H(s){return s.length<=f?s:`${s.slice(0,f)}\u2026 [truncated, ${s.length-f} more chars]`}import*as D from"node:fs/promises";import*as G from"node:os";import*as C from"node:path";function $(s){if(s.includes("<!DOCTYPE")||s.includes("<html")){let e=Math.min(s.indexOf("<!DOCTYPE")!==-1?s.indexOf("<!DOCTYPE"):1/0,s.indexOf("<html")!==-1?s.indexOf("<html"):1/0),n=s.substring(0,e).trim();return n?`${n} [HTML error page omitted]`:"[HTML error page omitted]"}return s}function b(s){let e;if(s instanceof Error)e=String(s);else if(typeof s=="object"&&s!==null)try{e=JSON.stringify(s)??"[object]"}catch{return"[object with circular reference]"}else e=String(s);return $(e)}var u=class{listeners=new Map;on(e,n){let t=this.listeners.get(e);t||(t=new Set,this.listeners.set(e,t));let o=n,i=t;return i.add(o),()=>{i.delete(o)}}emit(e,n){let t=this.listeners.get(e);if(!t)return;let o=[...t];for(let i of o)try{i(n)}catch{}}clear(){this.listeners.clear()}};var z={listModels:!0,downloadModel:!0,deleteModel:!0,loadModel:!0,openSession:!0,appendSession:!0,stopSession:!0,cancelSession:!0,shutdown:!0},me=Object.keys(z),T="automatic-speech-recognition",Y={modelDownloadProgress:!0,sessionPreview:!0},we=Object.keys(Y);import*as A from"node:fs/promises";import{open as q}from"node:fs/promises";var x=16e3,w=1,y=16,R=44,g=class{constructor(e){this.path=e}handle;dataSize=0;writeTail=Promise.resolve();async open(){this.handle=await q(this.path,"w"),await this.handle.write(F(0))}append(e){let n=this.writeTail.then(async()=>{if(!this.handle)throw new Error("WavStreamWriter not opened");await this.handle.write(e),this.dataSize+=e.byteLength});return this.writeTail=n.catch(()=>{}),n}async finalize(){if(!this.handle||(await this.writeTail,!this.handle))return;let e=this.handle;this.handle=void 0;try{await e.write(F(this.dataSize),0,R,0)}finally{await e.close()}}async discard(){this.handle&&(await this.handle.close().catch(()=>{}),this.handle=void 0),await A.unlink(this.path).catch(()=>{})}};function F(s){let e=x*w*y/8,n=w*y/8,t=Buffer.alloc(R);return t.write("RIFF",0,"ascii"),t.writeUInt32LE(36+s,4),t.write("WAVE",8,"ascii"),t.write("fmt ",12,"ascii"),t.writeUInt32LE(16,16),t.writeUInt16LE(1,20),t.writeUInt16LE(w,22),t.writeUInt32LE(x,24),t.writeUInt32LE(e,28),t.writeUInt16LE(n,32),t.writeUInt16LE(y,34),t.write("data",36,"ascii"),t.writeUInt32LE(s,40),t}var Q="github-copilot-cli",J={AzureCatalogFilter:"'',test"},K=1e4,X=2e3,Z="voice-foundry-batch-";function ee(s){switch(s.tag){case"opening":return;case"active":case"stopping":case"cancelling":return s.session;default:return s}}var h=class{managerPromise;state={tag:"unloaded"};lastModelGeneration=0;downloads=new Map;shutdownPromise;events=new u;foundryAdditionalSettings;nativeLocation;tempDir;managerFactory;handlers={listModels:()=>this.handleListModels(),downloadModel:e=>this.handleDownloadModel(e),deleteModel:e=>this.handleDeleteModel(e),loadModel:e=>this.handleLoadModel(e),openSession:e=>this.handleOpenSession(e),appendSession:e=>this.handleAppendSession(e),stopSession:e=>this.handleStopSession(e),cancelSession:e=>this.handleCancelSession(e),shutdown:()=>this.handleShutdown()};constructor(e={}){this.foundryAdditionalSettings=e.foundryAdditionalSettings??J,this.nativeLocation=e.nativeLocation,this.tempDir=e.tempDir??G.tmpdir(),this.managerFactory=e.managerFactory}call(e,n,t){if(this.shutdownPromise&&e!=="shutdown")return Promise.reject(this.disposedError());let o=this.handlers[e];return o(n)}on(e,n){return this.events.on(e,n)}onFatalError(e){return()=>{}}shutdown(e){return this.handleShutdown()}async handleListModels(){return O(async()=>{let n=await(await this.getManager()).catalog.getModels(),t=[];for(let o of n)for(let i of o.variants)se(i)&&t.push(await ie(i));return t})}async handleDownloadModel(e){let{variantId:n,downloadId:t}=e,o=this.downloads.get(n);if(o){if(o.downloadId===t)return o.promise;throw new a(`A different download for '${n}' is in flight.`,"io")}let i=(async()=>{await(await this.getVariant(n)).download(d=>{this.events.emit("modelDownloadProgress",{downloadId:t,variantId:n,percent:d})})})(),r={downloadId:t,promise:i};this.downloads.set(n,r);try{await i}finally{this.downloads.get(n)===r&&this.downloads.delete(n)}}async handleDeleteModel(e){let{variantId:n}=e;if(this.downloads.has(n))throw new a(`Cannot delete '${n}' while a download is in flight.`,"io");let t=this.state;switch(t.tag){case"unloaded":break;case"loading":t.selection.variantId===n&&await this.unloadSelected();break;case"ready":if(t.selection.variantId===n){if(t.session!==void 0)throw new a(`Cannot delete '${n}' while a session is active.`,"session-active");await this.unloadSelected()}break;default:}(await this.getVariant(n)).removeFromCache()}async handleLoadModel(e){let{variantId:n}=e;if(this.shutdownPromise)throw this.disposedError();let t=this.state;switch(t.tag){case"unloaded":return this.startLoad(n,void 0);case"loading":if(t.selection.variantId===n){let o=await t.selection.loadedModel;return o.modelGeneration=this.bumpModelGeneration(),{modelGeneration:o.modelGeneration}}return this.startLoad(n,t.selection);case"ready":if(t.session!==void 0&&t.selection.variantId!==n)throw new a(`Cannot load '${n}' while a session is active.`,"session-active");return t.selection.variantId===n?(t.selection.loaded.modelGeneration=this.bumpModelGeneration(),{modelGeneration:t.selection.loaded.modelGeneration}):this.startLoad(n,t.selection);default:return t}}async startLoad(e,n){let t=this.loadVariant(e,n),o={variantId:e,loadedModel:t,previous:n};return this.state={tag:"loading",selection:o},t.then(r=>{this.state.tag==="loading"&&this.state.selection===o&&(this.state={tag:"ready",selection:{variantId:e,loadedModel:t,loaded:r}})},()=>{this.state.tag==="loading"&&this.state.selection===o&&(this.state={tag:"unloaded"})}),{modelGeneration:(await t).modelGeneration}}async loadVariant(e,n){if(n){let o=await n.loadedModel.catch(()=>{});o&&await o.variant.unload().catch(()=>{})}if(this.shutdownPromise)throw this.disposedError();let t=await this.getVariant(e);if(!t.isCached)throw new a(`Voice model '${e}' is not downloaded.`,"model-not-downloaded");if(await t.load(),this.shutdownPromise)throw await t.unload().catch(()=>{}),this.disposedError();return{variant:t,isStreaming:ne(t.alias),modelGeneration:this.bumpModelGeneration()}}bumpModelGeneration(){return this.lastModelGeneration=this.lastModelGeneration+1,this.lastModelGeneration}async unloadSelected(){if(this.state.tag==="unloaded")return;let e=this.state.selection;this.state={tag:"unloaded"};let n=await e.loadedModel.catch(()=>{});n&&await n.variant.unload().catch(()=>{})}async handleOpenSession(e){let n=this.state;switch(n.tag){case"unloaded":throw new a("Loaded model has changed since this session was prepared.","stale-model");case"loading":return await n.selection.loadedModel.catch(()=>{}),this.handleOpenSession(e);case"ready":{let t=n,{sessionId:o,modelGeneration:i}=e;if(t.session!==void 0)throw new a("A voice session is already active.","session-active");if(t.selection.loaded.modelGeneration!==i)throw new a("Loaded model has changed since this session was prepared.","stale-model");let r=t.selection.loaded,c=(async()=>{try{let d=r.isStreaming?await this.openStreamingSession(r,o):await this.openBatchSession(o),l=t.session;this.state===t&&l?.tag==="opening"&&l.sessionId===o?t.session={tag:"active",session:d}:await this.teardownSession(d).catch(()=>{})}catch(d){let l=t.session;throw this.state===t&&l?.tag==="opening"&&l.sessionId===o&&(t.session=void 0),d}})();t.session={tag:"opening",sessionId:o,opening:c},await c;return}default:return n}}async handleAppendSession(e){let n=this.state;switch(n.tag){case"unloaded":case"loading":return;case"ready":{let t=n.session;if(t===void 0)return;switch(t.tag){case"opening":case"stopping":case"cancelling":return;case"active":{if(t.session.sessionId!==e.sessionId)return;let o=t.session;if(o.kind==="streaming"){await o.foundrySdkSession.append(e.pcm);return}await o.wav.append(e.pcm);return}default:return t}}default:return n}}async handleStopSession(e){let n=()=>{throw new a(`No session '${e.sessionId}'.`,"session-not-found")},t=this.state;switch(t.tag){case"unloaded":case"loading":return n();case"ready":{let o=t,i=o.session;if(i===void 0)return n();switch(i.tag){case"opening":case"stopping":case"cancelling":return n();case"active":{if(i.session.sessionId!==e.sessionId)return n();let r=i.session,c=r.error;if(c)throw o.session=void 0,await this.teardownSession(r).catch(()=>{}),c;o.session={tag:"stopping",session:r};try{return{text:r.kind==="streaming"?await this.stopStreaming(r):await this.stopBatch(r)}}catch(d){throw r.error?r.error:d}finally{let d=o.session;this.state===o&&d?.tag==="stopping"&&d.session===r&&(o.session=void 0),await this.teardownSession(r).catch(()=>{})}}default:return i}}default:return t}}async handleCancelSession(e){let n=this.state;switch(n.tag){case"unloaded":case"loading":return;case"ready":{let t=n,o=t.session;if(o===void 0)return;switch(o.tag){case"opening":case"cancelling":return;case"active":{if(o.session.sessionId!==e.sessionId)return;let i=o.session;t.session={tag:"cancelling",session:i};try{await this.teardownSession(i)}finally{let r=t.session;this.state===t&&r?.tag==="cancelling"&&r.session===i&&(t.session=void 0)}return}case"stopping":{if(o.session.sessionId!==e.sessionId)return;let i=o.session;i.error=i.error??new a("Session cancelled.","cancelled"),t.session={tag:"cancelling",session:i},await this.teardownSession(i).catch(()=>{});return}default:return o}}default:return n}}async openStreamingSession(e,n){let t=e.variant.createAudioClient().createLiveTranscriptionSession();try{await t.start()}catch(i){throw await this.disposeSdk(t),i}let o={kind:"streaming",sessionId:n,foundrySdkSession:t,committed:"",tail:"",drainTask:Promise.resolve("")};return o.drainTask=this.runStreamingDrain(o),o.drainTask.catch(()=>{}),o}async openBatchSession(e){let n=new g(C.join(this.tempDir,`${Z}${e}.wav`));try{await n.open()}catch(t){throw await n.discard(),t}return{kind:"batch",sessionId:e,wav:n}}async runStreamingDrain(e){try{for await(let n of e.foundrySdkSession.getStream()){if(this.isCancellingSession(e))break;let t=te(n);t&&(n.is_final?(e.committed+=t,e.tail=""):e.tail+=t,this.events.emit("sessionPreview",{sessionId:e.sessionId,text:e.committed+e.tail}))}return e.committed+e.tail}catch(n){let t=L(n);throw e.error=t,t}}isCancellingSession(e){let n=this.state;switch(n.tag){case"unloaded":case"loading":return!1;case"ready":{let t=n.session;if(t===void 0)return!1;switch(t.tag){case"opening":case"active":case"stopping":return!1;case"cancelling":return t.session===e;default:return t}}default:return n}}async stopStreaming(e){return _((async()=>(await e.foundrySdkSession.stop(),e.drainTask))(),K,"session-timeout","Streaming session drain timed out.")}async stopBatch(e){if(this.state.tag!=="ready")return"";let n=this.state.selection.loaded;await e.wav.finalize();try{return(await n.variant.createAudioClient().transcribe(e.wav.path)).text??""}finally{await D.unlink(e.wav.path).catch(()=>{})}}async teardownSession(e){e.kind==="streaming"?await this.disposeSdk(e.foundrySdkSession):await e.wav.discard()}async disposeSdk(e){await _(e.dispose(),X,"io","SDK dispose timed out.").catch(()=>{})}async handleShutdown(){return this.shutdownPromise?this.shutdownPromise:(this.shutdownPromise=(async()=>{if(this.state.tag==="ready"&&this.state.session?.tag==="opening"&&await this.state.session.opening.catch(()=>{}),this.state.tag==="ready"){let e=this.state,n=e.session;if(n!==void 0){let t=ee(n);t&&(e.session=void 0,await this.teardownSession(t).catch(()=>{}))}}await this.unloadSelected().catch(()=>{}),this.managerPromise=void 0,this.events.clear()})(),this.shutdownPromise)}disposedError(){return new a("Foundry backend has been shut down.","disposed")}async getVariant(e){return(await this.getManager()).catalog.getModelVariant(e)}getManager(){return this.managerPromise||(this.managerPromise=this.initManager().catch(e=>{throw this.managerPromise=void 0,e})),this.managerPromise}async initManager(){if(this.managerFactory)return this.managerFactory();if(!this.nativeLocation)throw new a("Voice runtime is not downloaded. RuntimeInstaller must resolve it before backend construction.","runtime-not-downloaded");let e=this.nativeLocation;return O(async()=>{let n=j("foundry-local-sdk"),t={...this.foundryAdditionalSettings};return e.needsBootstrap&&!("Bootstrap"in t)&&(t.Bootstrap="true"),n.FoundryLocalManager.create({appName:Q,libraryPath:e.corePath,additionalSettings:t})})}};function te(s){return s.content?.[0]?.text??""}function ne(s){return s.toLowerCase().includes("streaming")}function se(s){return s.info.task===T}async function O(s,e){try{return await s()}catch(n){if((e?.platform??process.platform)!=="win32")throw n;let o=b(n);if(!/Failed to load (?:dependency|core) library/i.test(o))throw n;let r=(e?.arch??process.arch)==="arm64"?"https://aka.ms/vs/17/release/vc_redist.arm64.exe":"https://aka.ms/vs/17/release/vc_redist.x64.exe";throw new a(`Voice mode requires the Microsoft Visual C++ Redistributable (2015-2022). Download and install it, then try again: ${r}`,"windows-runtime-missing",{cause:n})}}function oe(s){return Array.isArray(s)?s.filter(e=>typeof e=="string"):typeof s=="string"?s.split(/[,\s]+/).filter(e=>e.length>0):s&&typeof s=="object"?Object.keys(s):[]}async function ie(s){let e=s.isCached,n=oe(s.info.capabilities),t=s.info,o=s.info.runtime?.deviceType??t.device,i=o?o.toLowerCase():void 0,r=t.sizeInBytes??(typeof s.info.fileSizeMb=="number"?Math.round(s.info.fileSizeMb*1024*1024):void 0);return{id:s.id,alias:s.alias,name:s.info.name??s.id,cached:e,capabilities:n,sizeBytes:r,device:i}}function _(s,e,n,t){let o,i=new Promise((r,c)=>{o=setTimeout(()=>c(new a(t,n)),e)});return Promise.race([s,i]).finally(()=>{o&&clearTimeout(o)})}if(!v)throw new Error("voice-foundry.worker.js must be loaded as a worker thread.");I(v);var N=re;if(!N?.nativeLocation)throw new Error("voice-foundry.worker.ts requires workerData.nativeLocation.");var B=v,M=new h({nativeLocation:N.nativeLocation});M.on("modelDownloadProgress",s=>U("modelDownloadProgress",s));M.on("sessionPreview",s=>U("sessionPreview",s));k(B,M);function U(s,e){let n={kind:"event",event:s,payload:e};B.postMessage(n)}
