@dvai-bridge/core 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +51 -0
- package/README.md +199 -0
- package/bin/dvai-bridge.js +72 -0
- package/dist/dvai-transformers.worker.js +48 -0
- package/dist/dvai-webllm.worker.js +89 -0
- package/dist/index.cjs +69 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1030 -0
- package/dist/index.d.ts +1030 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/package.json +75 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";var ir=Object.create;var Z=Object.defineProperty;var sr=Object.getOwnPropertyDescriptor;var or=Object.getOwnPropertyNames;var ar=Object.getPrototypeOf,cr=Object.prototype.hasOwnProperty;var u=(t,e)=>()=>(t&&(e=t(t=0)),e);var b=(t,e)=>{for(var r in e)Z(t,r,{get:e[r],enumerable:!0})},Ke=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of or(e))!cr.call(t,i)&&i!==r&&Z(t,i,{get:()=>e[i],enumerable:!(n=sr(e,i))||n.enumerable});return t};var y=(t,e,r)=>(r=t!=null?ir(ar(t)):{},Ke(e||!t||!t.__esModule?Z(r,"default",{value:t,enumerable:!0}):r,t)),dr=t=>Ke(Z({},"__esModule",{value:!0}),t);function mr(t){let e=t[t.length-1];if(!e||!Array.isArray(e.content))return{audio:null,images:null};let r=null,n=[];for(let i of e.content)i&&(i.type==="audio"&&i.data?r=i.data:i.type==="image"&&(i.image||i.data||i.url)&&n.push(i.image??i.data??i.url));return{audio:r,images:n.length>0?n:null}}function it(t,e,r={}){let n=r.defaultMaxNewTokens??1024,i=async(s,o)=>{let a=e.apply_chat_template(s,{enable_thinking:!1,add_generation_prompt:!0}),{audio:c,images:d}=mr(s),l=await e(a,d,c,{add_special_tokens:!1}),m={...l,max_new_tokens:o?.max_new_tokens??n,temperature:o?.temperature??0,do_sample:o?.do_sample??!1,top_p:o?.top_p??1};o?.streamer&&(m.streamer=o.streamer);let p=await t.generate(m),h=l.input_ids.dims.at(-1),f=p.slice(null,[h,null]);return[{generated_text:e.batch_decode(f,{skip_special_tokens:!0})[0]??""}]};return i.tokenizer=e.tokenizer,i.dispose=async()=>{try{await t.dispose?.()}catch{}},i}function st(t,e){if(!(!e||e.length===0))for(let r of e)try{t&&t[r]&&(t[r]=null)}catch{}}var ot=u(()=>{"use strict"});var at={};b(at,{TransformersBackend:()=>Te,detectWebGPU:()=>ee});function hr(t){if(!t)return[];if(Array.isArray(t))return t.length>0&&Array.isArray(t[0])?t:[t];if(typeof t.tolist=="function"){let e=t.tolist();return Array.isArray(e)&&e.length>0&&Array.isArray(e[0])?e:[e]}if(t.data&&t.dims){let[e,r]=t.dims.length===2?t.dims:[1,t.dims[t.dims.length-1]],n=Array.from(t.data),i=[];for(let s=0;s<e;s++)i.push(n.slice(s*r,(s+1)*r));return i}return[]}function De(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>De(e)).join(""):t&&typeof t=="object"?t.text||t.content||JSON.stringify(t):String(t||"")}async function ee(){if(typeof navigator>"u"||!("gpu"in navigator))return!1;try{return await navigator.gpu.requestAdapter()!==null}catch{return!1}}var Te,xe=u(()=>{"use strict";ot();Te=class{pipeline=null;worker=null;modelId;device;resolvedDevice="wasm";generationTimeout;workerUrl;pipelineTask;dtype;createPipelineFn;modelClass;processorClass;disableEncoders;usingWorker=!1;pendingRequests=new Map;pendingStreams=new Map;constructor(e){this.modelId=e.modelId,this.device=e.device,this.generationTimeout=e.generationTimeout,this.workerUrl=e.workerUrl,this.pipelineTask=e.pipelineTask||"text-generation",this.dtype=e.dtype,this.createPipelineFn=e.createPipeline,this.modelClass=e.modelClass,this.processorClass=e.processorClass,this.disableEncoders=e.disableEncoders}async initialize(e){let r=typeof window>"u"&&typeof process<"u"&&process.versions?.node!==void 0;if(this.device==="auto"){let n=await ee();this.resolvedDevice=n?"webgpu":r?"cpu":"wasm",console.log(`[DVAI/Transformers] Auto-detected device: ${this.resolvedDevice}`)}else this.device==="cpu"?this.resolvedDevice=r?"cpu":"wasm":this.resolvedDevice=this.device;if(this.workerUrl&&typeof Worker<"u")try{await this.initializeWithWorker(e);return}catch(n){console.error(`[DVAI/Transformers] Worker initialization FAILED \u2014 falling back to main thread. This WILL block the UI during inference. Check that the worker file is deployed at "${this.workerUrl}" (run \`dvai-bridge init\` to copy it).`,n),this.worker=null}else this.workerUrl||console.warn("[DVAI/Transformers] No workerUrl configured \u2014 running on main thread. This blocks the UI during inference. Set `transformersWorkerUrl` (defaults to '/dvai-transformers.worker.js') to enable the worker path.");await this.initializeMainThread(e)}async initializeWithWorker(e){return new Promise((r,n)=>{let i=new Worker(this.workerUrl,{type:"module"}),s=this.generateRequestId(),o=c=>{let d=c.data;if(d.id===s)switch(d.type){case"progress":if(e){let l=d.data,m=l.progress??0,p=l.status==="progress"?`Downloading ${l.file}: ${Math.round(m)}%`:l.status==="ready"?"Model ready":`${l.status}${l.file?`: ${l.file}`:""}`;e({text:p,progress:m/100,timeElapsed:0})}break;case"init_complete":i.removeEventListener("message",o),this.worker=i,this.usingWorker=!0,i.addEventListener("message",l=>this.handleWorkerMessage(l)),console.log("[DVAI/Transformers] Initialized with Web Worker (main thread unblocked)"),r();break;case"error":i.removeEventListener("message",o),i.terminate(),n(new Error(d.error));break}};i.addEventListener("message",o),i.addEventListener("error",c=>{i.removeEventListener("message",o);let d=c.message||(c.error?c.error.message:"Unknown worker error");n(new Error(`Worker error: ${d}`))});let a={type:"init",id:s,pipelineTask:this.pipelineTask,modelId:this.modelId,device:this.resolvedDevice,dtype:this.dtype,modelClass:this.modelClass,processorClass:this.processorClass,disableEncoders:this.disableEncoders};console.log("[DVAI/Transformers] Sending init to worker:",a),i.postMessage(a)})}handleWorkerMessage(e){let r=e.data;if(!r.id)return;let n=this.pendingStreams.get(r.id);if(n)switch(r.type){case"stream_chunk":n.onChunk(r.text);return;case"stream_complete":this.pendingStreams.delete(r.id),n.onComplete();return;case"error":this.pendingStreams.delete(r.id),n.onError(new Error(r.error||"Unknown worker internal error"));return}let i=this.pendingRequests.get(r.id);if(i)switch(r.type){case"generate_complete":case"embed_complete":this.pendingRequests.delete(r.id),i.resolve(r.data);break;case"unload_complete":this.pendingRequests.delete(r.id),i.resolve(void 0);break;case"error":this.pendingRequests.delete(r.id),i.reject(new Error(r.error||"Unknown worker internal error"));break}}sendWorkerRequest(e,r={}){return new Promise((n,i)=>{let s=this.generateRequestId();this.pendingRequests.set(s,{resolve:n,reject:i}),this.worker.postMessage({type:e,id:s,...r})})}async initializeMainThread(e){let r=await import("@huggingface/transformers"),{pipeline:n,env:i}=r;i.allowLocalModels=!1,i.allowRemoteModels=!0,i.remoteHost="https://huggingface.co",i.remotePathTemplate="{model}/resolve/{revision}/";let s=e?o=>{let a=o.progress??0,c=o.status==="progress"?`Downloading ${o.file}: ${Math.round(a)}%`:o.status==="ready"?`Model ready (${this.pipelineTask})`:`${o.status}${o.file?`: ${o.file}`:""}`;e({text:c,progress:a/100,timeElapsed:0})}:void 0;if(this.createPipelineFn)console.log("[DVAI/Transformers] Using custom createPipeline factory."),this.pipeline=await this.createPipelineFn(r,{modelId:this.modelId,device:this.resolvedDevice,dtype:this.dtype,onProgress:s});else if(this.modelClass){console.log(`[DVAI/Transformers] Using declarative loader: ${this.modelClass} + ${this.processorClass||"AutoProcessor"}`);let o=r[this.modelClass];if(!o)throw new Error(`transformers.js has no export named "${this.modelClass}". Check your modelClass config.`);let a=this.processorClass||"AutoProcessor",c=r[a];if(!c)throw new Error(`transformers.js has no export named "${a}". Check your processorClass config.`);let d=await c.from_pretrained(this.modelId,{progress_callback:s}),l=await o.from_pretrained(this.modelId,{dtype:this.dtype,device:this.resolvedDevice,progress_callback:s});st(l,this.disableEncoders),this.pipeline=it(l,d)}else this.pipeline=await n(this.pipelineTask,this.modelId,{device:this.resolvedDevice,progress_callback:s,dtype:this.dtype});this.usingWorker=!1,this.resolvedDevice==="wasm"||this.resolvedDevice==="cpu"?console.warn(`[DVAI/Transformers] Running on main thread with ${this.resolvedDevice.toUpperCase()} (CPU). `+(this.resolvedDevice==="wasm"?"Inference may block the UI. Set `workerUrl` to a deployed transformers worker for better performance.":"(Node host \u2014 no UI thread to block.)")):console.log("[DVAI/Transformers] Initialized on main thread (WebGPU compute is async)")}getPipelineTask(){return this.pipelineTask}getResolvedDevice(){return this.resolvedDevice}isWorkerBased(){return this.usingWorker}getPipeline(){return this.pipeline}isTextTask(){return["text-generation","text2text-generation","summarization","translation","image-text-to-text","any-to-any"].includes(this.pipelineTask)}async runPipeline(e,r){if(this.usingWorker&&this.worker)return this.withTimeout(this.sendWorkerRequest("generate",{requestBody:{raw:!0,inputs:e,options:r}}),this.generationTimeout);if(!this.pipeline)throw new Error("Transformers.js pipeline not initialized");return this.withTimeout(this.pipeline(e,r),this.generationTimeout)}async chatCompletion(e){if(!this.isTextTask())throw new Error(`chatCompletion() is only available for text-generation tasks. Current task: "${this.pipelineTask}". Use runPipeline() instead.`);let r=(e.messages||[]).map(l=>({...l,content:De(l.content)})),n=e.max_tokens??e.max_completion_tokens??256,i=e.temperature??.7,s=e.top_p??1,o={max_new_tokens:n,temperature:i,top_p:s,do_sample:i>0,return_full_text:!1},a;if(this.usingWorker&&this.worker)a=await this.withTimeout(this.sendWorkerRequest("generate",{requestBody:{...e,messages:r}}),this.generationTimeout);else if(this.pipeline)console.log("[DVAI/Transformers] Running local inference:",r),a=await this.withTimeout(this.pipeline(r,o),this.generationTimeout);else throw new Error("Transformers.js backend not initialized");let c=a?.[0]?.generated_text??"",d=typeof c=="string"?c:Array.isArray(c)?c[c.length-1]?.content??"":String(c);return{id:`chatcmpl-${Date.now()}`,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:this.modelId,choices:[{index:0,message:{role:"assistant",content:d},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}}}createStreamingResponse(e){if(!this.isTextTask())throw new Error(`Streaming chat completion is only available for text-generation tasks. Current task: "${this.pipelineTask}".`);let r=this.modelId,n=this,i=this.generationTimeout;return new ReadableStream({async start(s){let o=`chatcmpl-${Date.now()}`,a=Math.floor(Date.now()/1e3),c=new TextEncoder,d=p=>{let h={id:o,object:"chat.completion.chunk",created:a,model:r,choices:[{index:0,delta:{content:p},finish_reason:null}]};s.enqueue(c.encode(`data: ${JSON.stringify(h)}
|
|
2
|
+
|
|
3
|
+
`))},l=(p="stop")=>{let h={id:o,object:"chat.completion.chunk",created:a,model:r,choices:[{index:0,delta:{},finish_reason:p}]};s.enqueue(c.encode(`data: ${JSON.stringify(h)}
|
|
4
|
+
|
|
5
|
+
`))},m=null;try{let p=new Promise((f,g)=>{if(n.usingWorker&&n.worker){let C=n.generateRequestId();n.pendingStreams.set(C,{onChunk:d,onComplete:f,onError:g}),n.worker.postMessage({type:"generate_stream",id:C,requestBody:e})}else n.pipeline?(async()=>{try{let{TextStreamer:C}=await import("@huggingface/transformers"),S=n.pipeline.tokenizer;if(!S)throw new Error("Streaming requires a tokenizer on the pipeline.");let v=(e.messages||[]).map(I=>({...I,content:De(I.content)})),k={max_new_tokens:e.max_tokens??e.max_completion_tokens??256,temperature:e.temperature??.7,top_p:e.top_p??1,do_sample:(e.temperature??.7)>0,return_full_text:!1,streamer:new C(S,{skip_prompt:!0,skip_special_tokens:!0,callback_function:I=>{I&&d(I)}})};await n.pipeline(v,k),f()}catch(C){g(C)}})():g(new Error("Transformers.js backend not initialized"))}),h=new Promise((f,g)=>{m=setTimeout(()=>g(new Error(`Generation timed out after ${i}ms`)),i)});await Promise.race([p,h]),l("stop")}catch(p){console.error("[DVAI/Transformers] Stream error:",p.message),s.enqueue(c.encode(`data: ${JSON.stringify({error:p.message})}
|
|
6
|
+
|
|
7
|
+
`))}finally{m&&clearTimeout(m),s.enqueue(c.encode(`data: [DONE]
|
|
8
|
+
|
|
9
|
+
`)),s.close()}}})}async embedding(e){if(this.pipelineTask!=="feature-extraction")throw new Error(`embedding() requires pipelineTask="feature-extraction". Current task: "${this.pipelineTask}".`);let r=Array.isArray(e)?e:[e];if(this.usingWorker&&this.worker)return await this.withTimeout(this.sendWorkerRequest("embed",{inputs:r,pooling:"mean",normalize:!0}),this.generationTimeout);if(!this.pipeline)throw new Error("Transformers.js pipeline not initialized");let n=await this.withTimeout(this.pipeline(r,{pooling:"mean",normalize:!0}),this.generationTimeout);return hr(n)}async unload(){if(this.usingWorker&&this.worker){try{await this.sendWorkerRequest("unload")}catch{}this.worker.terminate(),this.worker=null}this.pipeline&&(typeof this.pipeline.dispose=="function"&&await this.pipeline.dispose(),this.pipeline=null),this.pendingRequests.clear(),this.usingWorker=!1}withTimeout(e,r){return new Promise((n,i)=>{let s=setTimeout(()=>i(new Error(`Generation timed out after ${r}ms`)),r);e.then(o=>{clearTimeout(s),n(o)}).catch(o=>{clearTimeout(s),i(o)})})}generateRequestId(){return`${Date.now()}-${Math.random().toString(36).substring(2,9)}`}}});function te(t){return{id:(t.id||"").replace("chatcmpl-","cmpl-")||`cmpl-${Date.now()}`,object:"text_completion",created:t.created??Math.floor(Date.now()/1e3),model:t.model,choices:(t.choices||[]).map(e=>({text:e.message?.content??"",index:e.index??0,finish_reason:e.finish_reason??"stop",logprobs:null})),usage:t.usage??{prompt_tokens:0,completion_tokens:0,total_tokens:0}}}function re(t,e){let r=new TextDecoder,n=new TextEncoder,i="";return new ReadableStream({async start(s){let o=t.getReader();try{for(;;){let{done:a,value:c}=await o.read();if(a)break;i+=r.decode(c,{stream:!0});let d;for(;(d=i.indexOf(`
|
|
10
|
+
|
|
11
|
+
`))!==-1;){let l=i.slice(0,d);i=i.slice(d+2);let m=l.split(`
|
|
12
|
+
`).find(h=>h.startsWith("data:"));if(!m)continue;let p=m.slice(5).trim();if(p==="[DONE]"){s.enqueue(n.encode(`data: [DONE]
|
|
13
|
+
|
|
14
|
+
`));continue}try{let h=JSON.parse(p),f={id:(h.id||"").replace("chatcmpl-","cmpl-"),object:"text_completion.chunk",created:h.created,model:h.model||e,choices:(h.choices||[]).map(g=>({text:g.delta?.content??"",index:g.index??0,finish_reason:g.finish_reason??null,logprobs:null}))};s.enqueue(n.encode(`data: ${JSON.stringify(f)}
|
|
15
|
+
|
|
16
|
+
`))}catch{s.enqueue(n.encode(`data: ${p}
|
|
17
|
+
|
|
18
|
+
`))}}}}finally{s.close()}}})}async function N(t,e){if(!e.backend)return Response.json({error:"AI engine not initialized"},{status:503});let r=t.prompt,n=Array.isArray(r)?r.join(`
|
|
19
|
+
`):r??"",i={...t,messages:[{role:"user",content:n}]};delete i.prompt;try{if(i.stream){let o=e.backend.createStreamingResponse(i),a=re(o,t.model||e.modelId);return new Response(a,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}let s=await e.backend.chatCompletion(i);return Response.json(te(s))}catch(s){return Response.json({error:s.message},{status:500})}}var Ae=u(()=>{"use strict"});function ne(t){let e="";for(let n of t)e+=String.fromCharCode(n);return(typeof btoa<"u"?btoa(e):Buffer.from(e,"binary").toString("base64")).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var fr,ct=u(()=>{"use strict";fr=require("@noble/curves/ed25519")});function R(){let t=typeof globalThis.crypto<"u"?globalThis.crypto:void 0;if(!t||typeof t.getRandomValues!="function")throw new Error("[DVAI/pairing] no secure random source");let e=new Uint8Array(32);return t.getRandomValues(e),ne(e)}function ie(){let t=typeof globalThis.crypto<"u"?globalThis.crypto:void 0;if(!t||typeof t.getRandomValues!="function")throw new Error("[DVAI/pairing] no secure random source");let e=new Uint8Array(16);return t.getRandomValues(e),ne(e)}async function U(t,e){let r=globalThis.crypto;if(!r?.subtle)throw new Error("[DVAI/pairing] WebCrypto subtle not available");let n=gr(t),i=await r.subtle.importKey("raw",n,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),s=await r.subtle.sign("HMAC",i,new TextEncoder().encode(e));return ne(new Uint8Array(s))}async function se(t,e,r){let n=await U(t,e);return yr(n,r)}function yr(t,e){if(t.length!==e.length)return!1;let r=0;for(let n=0;n<t.length;n++)r|=t.charCodeAt(n)^e.charCodeAt(n);return r===0}function gr(t){let e=t.replace(/-/g,"+").replace(/_/g,"/"),r=e+"=".repeat((4-e.length%4)%4),n=typeof atob<"u"?atob(r):Buffer.from(r,"base64").toString("binary"),i=new Uint8Array(n.length);for(let s=0;s<n.length;s++)i[s]=n.charCodeAt(s);return i}async function oe(t,e,r,n){let i=n?await vr(n):"0000000000000000000000000000000000000000000000000000000000000000";return`${t}
|
|
20
|
+
${e.toUpperCase()}
|
|
21
|
+
${r}
|
|
22
|
+
${i}`}async function vr(t){let e=globalThis.crypto;if(!e?.subtle)throw new Error("[DVAI/pairing] WebCrypto subtle not available");let r=await e.subtle.digest("SHA-256",new TextEncoder().encode(t));return Array.from(new Uint8Array(r)).map(n=>n.toString(16).padStart(2,"0")).join("")}var ae=u(()=>{"use strict";ct()});function j(t){let e={none:3,integrated:8,discrete:35,"apple-silicon":40},r={low:.6,mid:1,high:1.3},n;t.ramGb<4?n=.3:t.ramGb<8?n=.7:n=1;let i=t.hasNpu?1.4:1,s=e[t.gpuClass]*r[t.cpuClass]*n*i;return Math.round(s*10)/10}function Se(){if(typeof navigator<"u"){let t=navigator,e=t.deviceMemory??4,r=t.hardwareConcurrency??4,n=typeof t.gpu<"u";return{hasNpu:!1,ramGb:e,gpuClass:n?"discrete":"none",cpuClass:r>=8?"high":r>=4?"mid":"low"}}return typeof globalThis.process<"u"&&globalThis.process.versions?.node,{hasNpu:!1,ramGb:4,gpuClass:"integrated",cpuClass:"mid"}}async function H(){if(typeof globalThis.process<"u"&&globalThis.process.versions?.node)try{let t=await import("os"),e=t.totalmem(),r=Math.round(e/1024**3),n=t.cpus().length;return{hasNpu:!1,ramGb:r,gpuClass:"integrated",cpuClass:n>=12?"high":n>=6?"mid":"low"}}catch{}return Se()}var Ee=u(()=>{"use strict"});var Re={};b(Re,{HardwareTooWeakError:()=>B,assessCapability:()=>Me});async function Me(t={}){let e=t.hardwareMinimum??br,r=t.minLocalCapability??wr;e>r;let n=t.hints??await H(),i=j(n);return i<e?{mode:"too-weak",tokPerSec:i,hints:n,reason:`estimated ${i} tok/s, below the ${e} tok/s hardware floor \u2014 local inference would be unusable, no peer to offload to either (a peer-only mode still requires the host to bring up discovery + pairing).`}:i<r?{mode:"offload-only",tokPerSec:i,hints:n,reason:`estimated ${i} tok/s, below the ${r} tok/s comfort threshold \u2014 model will not be loaded locally; every request will be forwarded to a paired peer.`}:{mode:"ok",tokPerSec:i,hints:n,reason:`estimated ${i} tok/s, above the ${r} tok/s local-capability threshold \u2014 running normally.`}}var br,wr,B,ce=u(()=>{"use strict";Ee();br=3,wr=10;B=class extends Error{tokPerSec;hardwareMinimum;hints;constructor(e){super(`DVAI: ${e.reason}`),this.name="HardwareTooWeakError",this.tokPerSec=e.tokPerSec,this.hardwareMinimum=e.hardwareMinimum,this.hints=e.hints}}});async function $(t,e,r){if(e.chatCompletionInterceptor)try{let i=await e.chatCompletionInterceptor(t,e,r);if(i!==null)return i}catch(i){return Response.json({error:i?.message??"interceptor failed"},{status:500})}if(!e.backend)return Response.json({error:"AI engine not initialized"},{status:503});let n=async()=>{let i=e.backend;if(!i)return Response.json({error:"AI engine not initialized"},{status:503});if(t.stream){let o=i.createStreamingResponse(t);return new Response(o,{headers:kr})}let s=await i.chatCompletion(t);return Response.json(s)};try{return e.backend.lastFatalError&&e.onRecovery&&await e.onRecovery(),await n()}catch(i){if(e.backend?.lastFatalError&&e.onRecovery)try{return await e.onRecovery(),await n()}catch{}return Response.json({error:i.message},{status:500})}}var kr,dt=u(()=>{"use strict";kr={"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}});async function W(t,e){if(!e.backend)return Response.json({error:"AI engine not initialized"},{status:503});if(e.resolvedBackend==="webllm")return Response.json({error:"Embeddings are not supported on the WebLLM backend. Use backend: 'transformers' with pipelineTask: 'feature-extraction'."},{status:400});if(typeof e.backend.embedding!="function")return Response.json({error:"The current backend does not support embeddings. For transformers: use pipelineTask: 'feature-extraction'."},{status:400});let r=t?.input;if(r==null)return Response.json({error:"Missing 'input' field."},{status:400});try{let n=await e.backend.embedding(r);return Response.json({object:"list",data:n.map((i,s)=>({object:"embedding",embedding:i,index:s})),model:t.model||e.modelId,usage:{prompt_tokens:0,total_tokens:0}})}catch(n){return Response.json({error:n.message},{status:500})}}var lt=u(()=>{"use strict"});async function z(t){return Response.json({object:"list",data:[{id:t.modelId,object:"model",created:Math.floor(Date.now()/1e3),owned_by:"dvai-bridge"}]})}var pt=u(()=>{"use strict"});var _e=u(()=>{"use strict";dt();Ae();lt();pt()});function Pr(t){let e=t,r=e,n="/chat/completions";if(e.endsWith(n))r=e.slice(0,-n.length);else try{let i=new URL(e),s=i.pathname.split("/").filter(Boolean);s.pop(),i.pathname="/"+s.join("/"),r=i.toString().replace(/\/$/,"")}catch{}return{chat:e,completions:`${r}/completions`,embeddings:`${r}/embeddings`,models:`${r}/models`,base:r}}var ut,F,de,mt=u(()=>{"use strict";ut=require("msw/browser"),F=require("msw");_e();de=class{constructor(e){this.opts=e}opts;kind="msw";worker=null;async start(e){let r=Pr(this.opts.mockUrl);if(this.opts.serviceWorkerUrl){let n=[F.http.post(r.chat,async({request:i})=>$(await i.json(),e)),F.http.post(r.completions,async({request:i})=>N(await i.json(),e)),F.http.post(r.embeddings,async({request:i})=>W(await i.json(),e)),F.http.get(r.models,async()=>z(e))];this.worker=(0,ut.setupWorker)(...n),await this.worker.start({onUnhandledRequest:"bypass",serviceWorker:{url:this.opts.serviceWorkerUrl}})}return{baseUrl:r.base}}async stop(){this.worker&&(this.worker.stop(),this.worker=null)}}});async function le(t,e=38883,r=16,n="127.0.0.1"){for(let i=0;i<r;i++){let s=e+i;try{return await new Promise((o,a)=>{let c=d=>{t.off("error",c),a(d)};t.once("error",c),t.listen(s,n,()=>{t.off("error",c),o()})}),s}catch(o){if(o.code!=="EADDRINUSE")throw o}}throw new Error(`[DVAI] Could not bind HTTP transport to any port in range ${e}..${e+r-1} (all in use). Another local AI server may already be running.`)}var ht,ft,Oe=u(()=>{"use strict";ht=38883,ft=16});function Cr(t,e){return e==="*"?"*":typeof e=="string"?e:t&&e.includes(t)?t:null}function Ir(t,e){let r=Cr(t,e),n={"Access-Control-Allow-Methods":"POST, GET, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization","Access-Control-Allow-Private-Network":"true"};return r&&(n["Access-Control-Allow-Origin"]=r),n}async function pe(t){let e=[];for await(let n of t)e.push(n);let r=Buffer.concat(e).toString("utf8");if(!r)return{};try{return JSON.parse(r)}catch{throw new Error("Invalid JSON body")}}async function ue(t,e,r){let n={...r};if(e.headers.forEach((s,o)=>{n[o]=s}),e.body){t.writeHead(e.status,n);let s=e.body.getReader();try{for(;;){let{done:o,value:a}=await s.read();if(o)break;t.write(Buffer.from(a))}}finally{t.end()}return}let i=await e.text();t.writeHead(e.status,n),t.end(i)}async function Dr(t,e,r,n){let i=t.headers.origin,s=Ir(i,n.corsOrigin);if(t.method==="OPTIONS"){e.writeHead(204,s),e.end();return}let a=new URL(t.url||"/","http://127.0.0.1").pathname;try{if(t.method==="POST"&&a==="/v1/chat/completions"){let d=await pe(t),l={};for(let[p,h]of Object.entries(t.headers))typeof h=="string"?l[p.toLowerCase()]=h:Array.isArray(h)&&h.length>0&&(l[p.toLowerCase()]=h.join(", "));let m=await $(d,r,l);return ue(e,m,s)}if(t.method==="POST"&&a==="/v1/completions"){let d=await pe(t),l=await N(d,r);return ue(e,l,s)}if(t.method==="POST"&&a==="/v1/embeddings"){let d=await pe(t),l=await W(d,r);return ue(e,l,s)}if(t.method==="GET"&&a==="/v1/models"){let d=await z(r);return ue(e,d,s)}let c=r.dvaiRoutes;if(c){let d=`${t.method??"GET"} ${a}`,l=c[d];if(l){let m;(t.method==="POST"||t.method==="PUT"||t.method==="PATCH")&&(m=await pe(t));let p=await l({body:m}),h={...s,"Content-Type":"application/json"};e.writeHead(p.status,h),e.end(JSON.stringify(p.body));return}}e.writeHead(404,{...s,"Content-Type":"application/json"}),e.end(JSON.stringify({error:"not found"}))}catch(c){e.writeHead(500,{...s,"Content-Type":"application/json"}),e.end(JSON.stringify({error:c?.message??"unknown error"}))}}var me,yt=u(()=>{"use strict";_e();Oe();me=class{constructor(e){this.opts=e}opts;kind="http";server=null;boundPort;async start(e){let{createServer:r}=await import("http"),n=r((o,a)=>{Dr(o,a,e,this.opts).catch(c=>{try{a.writeHead(500,{"Content-Type":"application/json"}),a.end(JSON.stringify({error:c.message}))}catch{}})}),i=this.opts.bindHost??"127.0.0.1",s=await le(n,this.opts.httpBasePort,this.opts.httpMaxPortAttempts,i);return this.server=n,this.boundPort=s,{baseUrl:`http://${i}:${s}/v1`,port:s}}async stop(){this.server&&(await new Promise(e=>this.server.close(()=>e())),this.server=null,this.boundPort=void 0)}}});var he,gt=u(()=>{"use strict";he=class{constructor(e){this.opts=e}opts;kind="capacitor";async start(e){let{DVAIBridge:r}=await import("@dvai-bridge/capacitor"),n=await r.start({backend:this.opts.capacitorBackend,modelPath:this.opts.nativeModelPath,mmprojPath:this.opts.nativeMmprojPath,gpuLayers:this.opts.nativeGpuLayers,contextSize:this.opts.nativeContextSize,threads:this.opts.nativeThreads,embeddingMode:this.opts.nativeEmbeddingMode,httpBasePort:this.opts.httpBasePort,httpMaxPortAttempts:this.opts.httpMaxPortAttempts,corsOrigin:this.opts.corsOrigin,autoUnloadOnLowMemory:this.opts.autoUnloadOnLowMemory,logLevel:this.opts.logLevel});return{baseUrl:n.baseUrl,port:n.port}}async stop(){let{DVAIBridge:e}=await import("@dvai-bridge/capacitor");await e.stop()}}});var vt={};b(vt,{BASE_PORT:()=>ht,CapacitorTransport:()=>he,HttpTransport:()=>me,MAX_PORT_ATTEMPTS:()=>ft,MswTransport:()=>de,selectTransport:()=>Tr,tryBind:()=>le});function Tr(t){if(t.serviceWorkerUrl===""&&t.transport==null)return"none";let e=t.transport??"auto";return e!=="auto"?e:xr()?"capacitor":Ar()?"msw":Sr()?"http":"none"}function xr(){return typeof window<"u"&&!!window.Capacitor?.isNativePlatform?.()}function Ar(){return typeof window<"u"&&typeof document<"u"&&typeof navigator<"u"&&typeof navigator.serviceWorker<"u"}function Sr(){return typeof process<"u"&&process.versions!=null&&process.versions.node!=null}var bt=u(()=>{"use strict";mt();yt();gt();Oe()});function fe(t){if(!t.config.enabled)return{kind:"local"};if(t.header==="never")return{kind:"local"};let e=t.peers.map(s=>({peer:s,score:s.capability[t.modelId]??0,hasModel:s.loadedModels.includes(t.modelId)})).filter(s=>s.score>0).sort((s,o)=>{if(s.hasModel!==o.hasModel)return s.hasModel?-1:1;if(s.score!==o.score)return o.score-s.score;let a={mdns:0,static:1,custom:2,rendezvous:3};return a[s.peer.via]-a[o.peer.via]}),r=e[0]?.peer,n=e[0]?.score??0,i=t.config.minLocalCapability;return t.header==="require"?r&&n>=i?{kind:"offload",peer:r}:{kind:"no_capable_device",checked:wt(t),localCapability:t.localCapability,required:i}:t.localCapability>=i?{kind:"local"}:r&&n>t.localCapability?{kind:"offload",peer:r}:t.localCapability>0?{kind:"local"}:{kind:"no_capable_device",checked:wt(t),localCapability:t.localCapability,required:i}}function wt(t){let e=[{deviceId:"self",capabilityScore:t.localCapability,reason:t.localCapability<t.config.minLocalCapability?"below threshold":"no eligible peer found"}];for(let r of t.peers){let n=r.capability[t.modelId]??0;e.push({deviceId:r.deviceId,deviceName:r.deviceName,capabilityScore:n,reason:n===0?"model not advertised":n<t.config.minLocalCapability?"below threshold":"checked"})}return e}var Le=u(()=>{"use strict"});function ye(t,e){let r=`No device with capability \u2265 ${t.required} tok/s for model ${e.modelId} was reachable. Local: ${t.localCapability} tok/s; ${t.checked.length-1} peer(s) checked.`;return{status:503,headers:{"Content-Type":"application/json","Retry-After":"30"},body:{error:{type:"no_capable_device",code:503,message:r,checked:t.checked,localCapability:t.localCapability,requiredAtLeast:t.required,rendezvousConfigured:e.rendezvousConfigured,pairedRemotePeers:e.pairedRemotePeers,requestId:e.requestId}}}}var Ve=u(()=>{"use strict"});function ge(t){let e;if(t instanceof Headers)e=t.get("x-dvai-offload");else for(let[n,i]of Object.entries(t))if(n.toLowerCase()==="x-dvai-offload"){e=i;break}if(!e)return"prefer";let r=e.toLowerCase().trim();return Er.has(r)?r:"prefer"}var Er,Ne=u(()=>{"use strict";Er=new Set(["never","prefer","require"])});async function ve(t,e){if(t.via==="rendezvous"&&(!t.baseUrl||!t.baseUrl.startsWith("http")))throw new Error("[DVAI/offload] rendezvous-paired peers require WebSocket relay (not yet implemented in v3.0.0-rc1; expected in v3.0.0 final).");let r=`${t.baseUrl.replace(/\/$/,"")}${e.path}`,n={"Content-Type":"application/json","X-DVAI-Forwarded":"1",...e.headers??{}},i=await fetch(r,{method:e.method,headers:n,body:e.body!==void 0?JSON.stringify(e.body):void 0,signal:e.signal}),s={};return i.headers.forEach((o,a)=>{s[a]=o}),e.stream&&i.body?{status:i.status,headers:s,stream:i.body}:{status:i.status,headers:s,body:await i.json().catch(()=>{})}}var Ue=u(()=>{"use strict"});function Pt(t){return async function(r,n,i){if(!t.config.enabled)return null;let s=Mr(i),o=t.getPeers(),a=n.modelId,c=t.getLocalCapability(a),d=fe({config:t.config,modelId:a,localCapability:c,peers:o,header:s});if(d.kind==="local")return t.offloadOnlyMode?kt(503,{error:{type:"no_local_backend",code:503,message:"DVAI is running in offload-only mode (device below minLocalCapability) and the request requested local execution (X-DVAI-Offload: never). Either drop the header or route to a peer."}}):null;if(d.kind==="offload"){let m=r&&typeof r=="object"&&r.stream===!0;try{let p=await ve(d.peer,{method:"POST",path:"/chat/completions",body:r,stream:m,headers:Rr(i)});try{t.config.onOffload?.(d.peer)}catch{}return p.stream?new Response(p.stream,{status:p.status,headers:p.headers}):new Response(JSON.stringify(p.body),{status:p.status,headers:p.headers})}catch(p){return kt(502,{error:{type:"peer_unreachable",code:502,message:`Offload to peer ${d.peer.deviceId} failed: ${p instanceof Error?p.message:String(p)}`,peerId:d.peer.deviceId}})}}let l=ye(d,{rendezvousConfigured:!!t.config.rendezvousUrl,pairedRemotePeers:o.filter(m=>m.via==="rendezvous").length,modelId:a});return new Response(JSON.stringify(l.body),{status:l.status,headers:l.headers})}}function Mr(t){return t?ge(t):"prefer"}function Rr(t){if(!t)return{};let e={},r=new Set(["host","content-length","connection","keep-alive","transfer-encoding"]);for(let[n,i]of Object.entries(t))r.has(n.toLowerCase())||(e[n]=i);return e}function kt(t,e){return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}var Ct=u(()=>{"use strict";Le();Ve();Ue();Ne()});var It={};b(It,{buildNoCapableDeviceResponse:()=>ye,buildOffloadInterceptor:()=>Pt,decide:()=>fe,parseOffloadHeader:()=>ge,proxyToPeer:()=>ve});var Dt=u(()=>{"use strict";Le();Ve();Ne();Ue();Ct()});function Or(){if(typeof globalThis.process<"u"){let t=globalThis.process.env,e=t.HOME??t.USERPROFILE??".";return t.LOCALAPPDATA?`${t.LOCALAPPDATA}/dvai-bridge/capability.json`:t.XDG_CACHE_HOME?`${t.XDG_CACHE_HOME}/dvai-bridge/capability.json`:`${e}/.cache/dvai-bridge/capability.json`}return"./.dvai-bridge-capability.json"}function Tt(){return typeof indexedDB<"u"?new O:typeof globalThis.process<"u"&&globalThis.process.versions?.node?new L:new q}var q,_r,P,_,O,L,xt=u(()=>{"use strict";q=class{map=new Map;async get(e){return this.map.get(this.keyOf(e))}async set(e){this.map.set(this.keyOf({modelId:e.modelId,libraryVersion:e.libraryVersion}),e)}async list(){return Array.from(this.map.values())}async clear(){this.map.clear()}keyOf(e){return`${e.libraryVersion}::${e.modelId}`}},_r="dvai-bridge",P="capability-v1",_="meta-v1",O=class{dbPromise;openDb(){return this.dbPromise||(this.dbPromise=new Promise((e,r)=>{let n=indexedDB.open(_r,1);n.onupgradeneeded=()=>{let i=n.result;i.objectStoreNames.contains(P)||i.createObjectStore(P),i.objectStoreNames.contains(_)||i.createObjectStore(_)},n.onsuccess=()=>e(n.result),n.onerror=()=>r(n.error)})),this.dbPromise}async get(e){let r=await this.openDb();return await new Promise((n,i)=>{let o=r.transaction(P,"readonly").objectStore(P).get(this.keyOf(e));o.onsuccess=()=>n(o.result),o.onerror=()=>i(o.error)})}async set(e){let r=await this.openDb();await new Promise((n,i)=>{let s=r.transaction(P,"readwrite");s.objectStore(P).put(e,this.keyOf({modelId:e.modelId,libraryVersion:e.libraryVersion})),s.oncomplete=()=>n(),s.onerror=()=>i(s.error)})}async list(){let e=await this.openDb();return await new Promise((r,n)=>{let s=e.transaction(P,"readonly").objectStore(P).getAll();s.onsuccess=()=>r(s.result),s.onerror=()=>n(s.error)})}async clear(){let e=await this.openDb();await new Promise((r,n)=>{let i=e.transaction(P,"readwrite");i.objectStore(P).clear(),i.oncomplete=()=>r(),i.onerror=()=>n(i.error)})}async getMeta(e){let r=await this.openDb();return await new Promise((n,i)=>{let o=r.transaction(_,"readonly").objectStore(_).get(e);o.onsuccess=()=>n(o.result),o.onerror=()=>i(o.error)})}async setMeta(e,r){let n=await this.openDb();await new Promise((i,s)=>{let o=n.transaction(_,"readwrite");o.objectStore(_).put(r,e),o.oncomplete=()=>i(),o.onerror=()=>s(o.error)})}keyOf(e){return`${e.libraryVersion}::${e.modelId}`}},L=class{cachePath;cache;constructor(e){this.cachePath=e??Or()}async load(){if(this.cache)return this.cache;let e=await import("fs/promises"),r=await import("path");try{let n=await e.readFile(this.cachePath,"utf8");this.cache=JSON.parse(n)}catch{this.cache={deviceId:"",scores:{}}}return await e.mkdir(r.dirname(this.cachePath),{recursive:!0}),this.cache}async save(){if(!this.cache)return;await(await import("fs/promises")).writeFile(this.cachePath,JSON.stringify(this.cache,null,2),"utf8")}async get(e){return(await this.load()).scores[this.keyOf(e)]}async set(e){let r=await this.load();r.scores[this.keyOf({modelId:e.modelId,libraryVersion:e.libraryVersion})]=e,await this.save()}async list(){let e=await this.load();return Object.values(e.scores)}async clear(){let e=await this.load();e.scores={},await this.save()}async getDeviceId(){return(await this.load()).deviceId}async setDeviceId(e){let r=await this.load();r.deviceId=e,await this.save()}keyOf(e){return`${e.libraryVersion}::${e.modelId}`}}});function K(){let t=typeof globalThis.crypto<"u"?globalThis.crypto:void 0;if(!t||typeof t.getRandomValues!="function")throw new Error("[DVAI/capability] No secure random source available. globalThis.crypto.getRandomValues required (Node \u226519, modern browsers, Bun, Deno).");let e=new Uint8Array(16);return t.getRandomValues(e),Lr(e)}function Lr(t){let e="";for(let n of t)e+=String.fromCharCode(n);return(typeof btoa<"u"?btoa(e):Buffer.from(e,"binary").toString("base64")).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var At=u(()=>{"use strict"});async function je(t){let e=performance.now(),r=await t.backend.chatCompletion({messages:[{role:"user",content:Vr}],max_tokens:50,stream:!1}),n=(performance.now()-e)/1e3,i=r.usage?.completion_tokens,s=r.choices[0]?.message?.content??r.choices[0]?.text??"",o=i??Nr(s),a=o>0&&n>0?Math.round(o/n*10)/10:0;return{modelId:t.modelId,deviceId:t.deviceId,libraryVersion:t.libraryVersion,tokPerSec:a,source:"probe",measuredAt:Date.now()}}function Nr(t){return Math.max(1,Math.round(t.length/4))}var Vr,St=u(()=>{"use strict";Vr="Generate a single short sentence about clouds."});var be={};b(be,{HardwareTooWeakError:()=>B,InMemoryCapabilityCache:()=>q,IndexedDBCapabilityCache:()=>O,NodeFsCapabilityCache:()=>L,assessCapability:()=>Me,clearCapabilityCache:()=>jr,createCapabilityCache:()=>Tt,detectDeviceHints:()=>Se,detectDeviceHintsAsync:()=>H,ensureDeviceId:()=>He,generateDeviceId:()=>K,getCapability:()=>Ur,heuristicTokPerSec:()=>j,probeAndCache:()=>Be,probeCapability:()=>je});async function He(t){if(t instanceof O){let r=await t.getMeta(Et);if(r)return r;let n=K();return await t.setMeta(Et,n),n}if(t instanceof L){let r=await t.getDeviceId();if(r)return r;let n=K();return await t.setDeviceId(n),n}return K()}async function Ur(t){let e=await t.cache.get({modelId:t.modelId,libraryVersion:t.libraryVersion});if(e)return e;let r=t.hints??await H(),n=await He(t.cache);return{modelId:t.modelId,deviceId:n,libraryVersion:t.libraryVersion,tokPerSec:j(r),source:"heuristic",measuredAt:Date.now()}}async function Be(t){let e=await He(t.cache),r=await je({backend:t.backend,modelId:t.modelId,libraryVersion:t.libraryVersion,deviceId:e});return await t.cache.set(r),r}async function jr(t){await t.clear()}var Et,J=u(()=>{"use strict";xt();Ee();At();St();ce();Et="dvai.deviceId"});var x,$e=u(()=>{"use strict";x="_dvai-bridge._tcp.local"});var we,Mt=u(()=>{"use strict";we=class{listeners=new Set;peerList;started=!1;constructor(e){let r=Date.now();this.peerList=e.map(n=>({...n,lastSeenAt:n.lastSeenAt&&n.lastSeenAt>0?n.lastSeenAt:r,via:"static"}))}async start(){if(!this.started){this.started=!0;for(let e of this.peerList)this.emit({type:"peer-up",peer:e})}}async stop(){this.started=!1;for(let e of this.peerList)this.emit({type:"peer-down",deviceId:e.deviceId})}peers(){return this.started?[...this.peerList]:[]}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}emit(e){for(let r of this.listeners)try{r(e)}catch(n){console.error("[DVAI/discovery] listener threw:",n)}}}});var Rt={};b(Rt,{NodeMdnsDiscovery:()=>We});var We,_t=u(()=>{"use strict";$e();We=class{constructor(e){this.opts=e}opts;mdns;peerMap=new Map;listeners=new Set;queryTimer;gcTimer;started=!1;async start(){if(this.started)return;let e;try{e=await import("multicast-dns")}catch{this.emit({type:"error",message:"[DVAI/discovery] `multicast-dns` not installed; LAN discovery disabled. Install with `npm i multicast-dns` (optional dep) to enable peer discovery."});return}let r=typeof e=="function"?e:e.default;this.mdns=r(),this.started=!0,this.mdns.on("response",s=>this.onResponse(s)),this.broadcastQuery();let n=this.opts.queryIntervalMs??3e4;this.queryTimer=setInterval(()=>this.broadcastQuery(),n);let i=this.opts.gcIntervalMs??6e4;this.gcTimer=setInterval(()=>this.gc(),i)}async stop(){if(this.started){this.started=!1,this.queryTimer&&clearInterval(this.queryTimer),this.gcTimer&&clearInterval(this.gcTimer),this.mdns?.destroy(),this.mdns=void 0;for(let e of this.peerMap.values())this.emit({type:"peer-down",deviceId:e.deviceId});this.peerMap.clear()}}peers(){return Array.from(this.peerMap.values())}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}broadcastQuery(){if(this.mdns){try{this.mdns.query({questions:[{name:x,type:"PTR"}]})}catch(e){this.emit({type:"error",message:`mDNS query failed: ${String(e)}`})}if(this.opts.advertise)try{this.mdns.respond({answers:this.buildAdvertisementAnswers(this.opts.advertise)})}catch(e){this.emit({type:"error",message:`mDNS respond failed: ${String(e)}`})}}}buildAdvertisementAnswers(e){let r=`${e.deviceId}.${x}`;return[{name:x,type:"PTR",data:r,ttl:120},{name:r,type:"SRV",data:{port:e.port,target:`${e.deviceId}.local`},ttl:120},{name:r,type:"TXT",data:this.encodeTxt(e),ttl:120}]}encodeTxt(e){return[`dvaiVersion=${e.dvaiVersion}`,`deviceId=${e.deviceId}`,`deviceName=${e.deviceName}`,`models=${e.models.join(",")}`,`capability=${JSON.stringify(e.capability)}`,`port=${e.port}`,`secure=${e.secure?"1":"0"}`]}onResponse(e){let r=[...e.answers,...e.additionals??[]],n,i;for(let l of r)l.type==="SRV"&&String(l.name).endsWith(x)&&(n=l),l.type==="TXT"&&String(l.name).endsWith(x)&&(i=l);if(!n||!i)return;let s=this.decodeTxt(i.data);if(!s||s.deviceId===this.opts.selfDeviceId)return;let o=n.data,a=`${s.secure?"https":"http"}://${o.target}:${o.port}/v1`,c={deviceId:s.deviceId,deviceName:s.deviceName,dvaiVersion:s.dvaiVersion,baseUrl:a,loadedModels:s.models,capability:s.capability,via:"mdns",secure:s.secure,lastSeenAt:Date.now()},d=this.peerMap.get(c.deviceId);this.peerMap.set(c.deviceId,c),d||this.emit({type:"peer-up",peer:c})}decodeTxt(e){let r;if(Array.isArray(e))r=e.map(s=>Buffer.isBuffer(s)?s.toString("utf8"):String(s));else if(Buffer.isBuffer(e))r=e.toString("utf8").split(`
|
|
23
|
+
`);else if(typeof e=="string")r=e.split(`
|
|
24
|
+
`);else return;let n={};for(let s of r){let o=s.indexOf("=");o<0||(n[s.slice(0,o)]=s.slice(o+1))}if(!n.deviceId||!n.dvaiVersion)return;let i={};try{i=JSON.parse(n.capability??"{}")}catch{}return{dvaiVersion:n.dvaiVersion,deviceId:n.deviceId,deviceName:n.deviceName??n.deviceId,models:n.models?n.models.split(",").filter(Boolean):[],capability:i,port:Number.parseInt(n.port??"0",10),secure:n.secure==="1"}}gc(){let e=this.opts.peerTtlMs??9e4,r=Date.now()-e;for(let[n,i]of this.peerMap)i.lastSeenAt<r&&(this.peerMap.delete(n),this.emit({type:"peer-down",deviceId:n}))}emit(e){for(let r of this.listeners)try{r(e)}catch(n){console.error("[DVAI/discovery] listener threw:",n)}}}});var Ot={};b(Ot,{BrowserMdnsDiscovery:()=>G});var G,ze=u(()=>{"use strict";G=class{constructor(e={}){}async start(){}async stop(){}peers(){return[]}subscribe(e){return()=>{}}}});async function Lt(t){if(typeof globalThis.process<"u"&&globalThis.process.versions?.node){let{NodeMdnsDiscovery:r}=await Promise.resolve().then(()=>(_t(),Rt));return new r(t)}let{BrowserMdnsDiscovery:e}=await Promise.resolve().then(()=>(ze(),Ot));return new e}var ke,Vt=u(()=>{"use strict";ke=class{constructor(e){this.sources=e}sources;listeners=new Set;subscriptions=[];started=!1;async start(){if(!this.started){this.started=!0;for(let e of this.sources){let r=e.subscribe(n=>this.onEvent(n));this.subscriptions.push(r),await e.start()}}}async stop(){if(this.started){this.started=!1;for(let e of this.subscriptions)e();this.subscriptions.length=0;for(let e of this.sources)await e.stop()}}peers(){let e=new Map;for(let r of this.sources)for(let n of r.peers()){let i=e.get(n.deviceId);(!i||n.lastSeenAt>i.lastSeenAt)&&e.set(n.deviceId,n)}return Array.from(e.values())}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}onEvent(e){for(let r of this.listeners)try{r(e)}catch(n){console.error("[DVAI/discovery] listener threw:",n)}}}});var Nt={};b(Nt,{BrowserMdnsDiscovery:()=>G,CompositeDiscovery:()=>ke,MDNS_SERVICE_TYPE:()=>x,StaticDiscovery:()=>we,createMdnsDiscovery:()=>Lt});var Ut=u(()=>{"use strict";$e();Mt();Vt();ze()});function Br(){if(typeof globalThis.process<"u"){let t=globalThis.process.env,e=t.HOME??t.USERPROFILE??".";return t.LOCALAPPDATA?`${t.LOCALAPPDATA}/dvai-bridge/pairings.json`:t.XDG_CACHE_HOME?`${t.XDG_CACHE_HOME}/dvai-bridge/pairings.json`:`${e}/.cache/dvai-bridge/pairings.json`}return"./.dvai-bridge-pairings.json"}function jt(){return typeof indexedDB<"u"?new Y:typeof globalThis.process<"u"&&globalThis.process.versions?.node?new Q:new X}var X,Hr,w,Y,Q,Ht=u(()=>{"use strict";X=class{map=new Map;async get(e){return this.map.get(e)}async set(e){this.map.set(e.peerDeviceId,e)}async list(){return Array.from(this.map.values())}async remove(e){this.map.delete(e)}async clear(){this.map.clear()}},Hr="dvai-bridge",w="pairings-v1",Y=class{dbPromise;openDb(){return this.dbPromise||(this.dbPromise=new Promise((e,r)=>{let n=indexedDB.open(Hr,1);n.onupgradeneeded=()=>{let i=n.result;i.objectStoreNames.contains(w)||i.createObjectStore(w,{keyPath:"peerDeviceId"})},n.onsuccess=()=>e(n.result),n.onerror=()=>r(n.error)})),this.dbPromise}async get(e){let r=await this.openDb();return await new Promise((n,i)=>{let s=r.transaction(w,"readonly").objectStore(w).get(e);s.onsuccess=()=>n(s.result),s.onerror=()=>i(s.error)})}async set(e){let r=await this.openDb();await new Promise((n,i)=>{let s=r.transaction(w,"readwrite");s.objectStore(w).put(e),s.oncomplete=()=>n(),s.onerror=()=>i(s.error)})}async list(){let e=await this.openDb();return await new Promise((r,n)=>{let i=e.transaction(w,"readonly").objectStore(w).getAll();i.onsuccess=()=>r(i.result),i.onerror=()=>n(i.error)})}async remove(e){let r=await this.openDb();await new Promise((n,i)=>{let s=r.transaction(w,"readwrite");s.objectStore(w).delete(e),s.oncomplete=()=>n(),s.onerror=()=>i(s.error)})}async clear(){let e=await this.openDb();await new Promise((r,n)=>{let i=e.transaction(w,"readwrite");i.objectStore(w).clear(),i.oncomplete=()=>r(),i.onerror=()=>n(i.error)})}},Q=class{cachePath;cache;constructor(e){this.cachePath=e??Br()}async load(){if(this.cache)return this.cache;let e=await import("fs/promises"),r=await import("path");try{let n=await e.readFile(this.cachePath,"utf8");this.cache=JSON.parse(n)}catch{this.cache={}}return await e.mkdir(r.dirname(this.cachePath),{recursive:!0}),this.cache}async save(){if(!this.cache)return;await(await import("fs/promises")).writeFile(this.cachePath,JSON.stringify(this.cache,null,2),"utf8")}async get(e){return(await this.load())[e]}async set(e){let r=await this.load();r[e.peerDeviceId]=e,await this.save()}async list(){let e=await this.load();return Object.values(e)}async remove(e){let r=await this.load();delete r[e],await this.save()}async clear(){this.cache={},await this.save()}}});var Pe,Bt=u(()=>{"use strict";ae();Pe=class{constructor(e){this.opts=e}opts;async getActive(e){let r=await this.opts.store.get(e);if(!r)return;let n=(this.opts.expireAfterDays??30)*24*60*60*1e3;if(Date.now()-r.lastUsedAt>n){await this.opts.store.remove(e);return}return r}async approveOrFetch(e){let r=await this.getActive(e.peerDeviceId);if(r)return r.lastUsedAt=Date.now(),await this.opts.store.set(r),r;let n=this.opts.onPairingRequest,i=n?await n(e.peerDeviceId,e.peerDeviceName,e.appId):!1;if(!(typeof i=="boolean"?i:i.approved))throw new Error(`[DVAI/pairing] denied: peer ${e.peerDeviceId} (${e.peerDeviceName})${n?"":" (no onPairingRequest callback supplied)"}`);let o=typeof i=="object"&&"pairingKey"in i?i.pairingKey:void 0,a={peerDeviceId:e.peerDeviceId,peerDeviceName:e.peerDeviceName,pairingKey:o??R(),pairedAt:Date.now(),lastUsedAt:Date.now(),via:e.via};return await this.opts.store.set(a),a}async touch(e){let r=await this.opts.store.get(e);r&&(r.lastUsedAt=Date.now(),await this.opts.store.set(r))}async revoke(e){await this.opts.store.remove(e)}}});var $t={};b($t,{InMemoryPairingStore:()=>X,IndexedDBPairingStore:()=>Y,NodeFsPairingStore:()=>Q,PairingPolicy:()=>Pe,composeSignedMessage:()=>oe,createPairingStore:()=>jt,generateNonce:()=>ie,generatePairingKey:()=>R,signHmac:()=>U,verifyHmac:()=>se});var Wt=u(()=>{"use strict";ae();Ht();Bt()});var Yt={};b(Yt,{buildDvaiRoutes:()=>$r,handleCapability:()=>Ft,handleHandshake:()=>Jt,handleHealth:()=>zt,handlePairQr:()=>Gt,handlePairScan:()=>Xt,handlePeers:()=>qt,handleProbe:()=>Kt});function zt(t){return async()=>({status:200,body:{status:"ok",version:t.libraryVersion,uptimeSec:Math.floor((Date.now()-t.startedAt)/1e3),currentModelId:t.currentModelId??null}})}function Ft(t){return async()=>({status:200,body:{scores:await t.capabilityCache.list()}})}function qt(t){return async()=>({status:200,body:{peers:t.discovery?.peers()??[]}})}function Kt(t){return async e=>{if(!t.backend)return{status:503,body:{error:{type:"no_backend",message:"no backend currently loaded"}}};let n=(e.body??{}).modelId??t.currentModelId;return n?{status:200,body:{score:await Be({cache:t.capabilityCache,backend:t.backend,modelId:n,libraryVersion:t.libraryVersion})}}:{status:400,body:{error:{type:"missing_model_id",message:"supply `modelId` in request body or call after a model is loaded"}}}}}function Jt(t){return async e=>{if(!t.pairingPolicy)return{status:503,body:{error:{type:"pairing_disabled",message:"pairing not configured"}}};let r=e.body;if(!r?.peerDeviceId||!r?.peerDeviceName)return{status:400,body:{error:{type:"malformed_handshake",message:"missing peerDeviceId / peerDeviceName"}}};try{let n=await t.pairingPolicy.approveOrFetch({peerDeviceId:r.peerDeviceId,peerDeviceName:r.peerDeviceName,via:r.via??"lan-handshake",...r.appId!==void 0?{appId:r.appId}:{}});return{status:200,body:{paired:!0,pairedAt:n.pairedAt,via:n.via,pairingKey:n.pairingKey,peerDeviceId:n.peerDeviceId}}}catch(n){return{status:403,body:{error:{type:"pairing_denied",message:String(n)}}}}}}function Gt(t){return async()=>({status:501,body:{error:{type:"not_implemented_yet",message:"POST /v1/dvai/pair-qr requires per-SDK integration (Task 8); the rendezvous client surface (rendezvous/client.ts) is callable directly until then."}}})}function Xt(t){return async()=>({status:501,body:{error:{type:"not_implemented_yet",message:"POST /v1/dvai/pair-scan requires per-SDK integration (Task 8)."}}})}function $r(t){return{"GET /v1/dvai/health":zt(t),"GET /v1/dvai/capability":Ft(t),"GET /v1/dvai/peers":qt(t),"POST /v1/dvai/probe":Kt(t),"POST /v1/dvai/handshake":Jt(t),"POST /v1/dvai/pair-qr":Gt(t),"POST /v1/dvai/pair-scan":Xt(t)}}var Qt=u(()=>{"use strict";J()});var Zt={};b(Zt,{NodeLlamaCppBackend:()=>Fe});var Fe,er=u(()=>{"use strict";Fe=class{modelPath;gpuLayers;threads;contextSize;generationTimeout;modelId;llama=null;model=null;context=null;session=null;lastFatalError=null;constructor(e){if(!e.modelPath)throw new Error("[DVAI/NodeLlamaCpp] modelPath is required (path to a GGUF file).");this.modelPath=e.modelPath,this.gpuLayers=e.gpuLayers??99,this.threads=e.threads,this.contextSize=e.contextSize??2048,this.generationTimeout=e.generationTimeout??6e4,this.modelId=e.modelId||this.modelPath.split(/[\\/]/).pop()?.replace(/\.gguf$/i,"")||"node-llama-cpp"}clearFatalError(){this.lastFatalError=null}async initialize(e){let r;try{r=await import("node-llama-cpp")}catch{throw new Error(`[DVAI/NodeLlamaCpp] backend selected but "node-llama-cpp" is not installed.
|
|
25
|
+
Install it with: npm install node-llama-cpp`)}e?.({text:"Loading llama.cpp runtime...",progress:0}),this.llama=await r.getLlama(),e?.({text:`Loading model: ${this.modelId}`,progress:.1}),this.model=await this.llama.loadModel({modelPath:this.modelPath,gpuLayers:this.gpuLayers}),e?.({text:"Creating context...",progress:.9}),this.context=await this.model.createContext({contextSize:this.contextSize,threads:this.threads}),this.session=new r.LlamaChatSession({contextSequence:this.context.getSequence()}),e?.({text:"Ready",progress:1}),console.log(`[DVAI/NodeLlamaCpp] Loaded "${this.modelId}" (gpuLayers=${this.gpuLayers}, contextSize=${this.contextSize})`)}isWorkerBased(){return!1}getModelId(){return this.modelId}withTimeout(e,r){return new Promise((n,i)=>{let s=setTimeout(()=>i(new Error(`Generation timed out after ${r}ms`)),r);e.then(o=>{clearTimeout(s),n(o)},o=>{clearTimeout(s),i(o)})})}extractUserPrompt(e){let r=e.find(s=>s.role==="system"),n=[...e].reverse().find(s=>s.role==="user"),i=s=>typeof s=="string"?s:Array.isArray(s)?s.map(i).join(""):s&&typeof s=="object"?s.text||s.content||JSON.stringify(s):String(s||"");return{systemPrompt:r?i(r.content):void 0,userPrompt:n?i(n.content):""}}async chatCompletion(e){if(!this.session)throw new Error("[DVAI/NodeLlamaCpp] Backend not initialized.");let r=e.messages||[],{systemPrompt:n,userPrompt:i}=this.extractUserPrompt(r),s=e.max_tokens??e.max_completion_tokens??256,o=e.temperature??.7,a=e.top_p??1,c={maxTokens:s,temperature:o,topP:a};n&&(c.systemPrompt=n);let d=await this.withTimeout(this.session.prompt(i,c),this.generationTimeout);return{id:`chatcmpl-${Date.now()}`,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:this.modelId,choices:[{index:0,message:{role:"assistant",content:d},finish_reason:"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}}}createStreamingResponse(e){if(!this.session)throw new Error("[DVAI/NodeLlamaCpp] Backend not initialized.");let r=this.session,n=this.modelId,i=this.generationTimeout,s=e.messages||[],{systemPrompt:o,userPrompt:a}=this.extractUserPrompt(s),c=e.max_tokens??e.max_completion_tokens??256,d=e.temperature??.7,l=e.top_p??1;return new ReadableStream({async start(m){let p=`chatcmpl-${Date.now()}`,h=Math.floor(Date.now()/1e3),f=new TextEncoder,g=v=>{let k={id:p,object:"chat.completion.chunk",created:h,model:n,choices:[{index:0,delta:{content:v},finish_reason:null}]};m.enqueue(f.encode(`data: ${JSON.stringify(k)}
|
|
26
|
+
|
|
27
|
+
`))},C=(v="stop")=>{let k={id:p,object:"chat.completion.chunk",created:h,model:n,choices:[{index:0,delta:{},finish_reason:v}]};m.enqueue(f.encode(`data: ${JSON.stringify(k)}
|
|
28
|
+
|
|
29
|
+
`))},S=null;try{let v={maxTokens:c,temperature:d,topP:l,onTextChunk:k=>{k&&g(k)}};o&&(v.systemPrompt=o),await new Promise((k,I)=>{S=setTimeout(()=>I(new Error(`Generation timed out after ${i}ms`)),i),r.prompt(a,v).then(()=>k(),nr=>I(nr))}),C("stop")}catch(v){console.error("[DVAI/NodeLlamaCpp] Stream error:",v?.message??v),m.enqueue(f.encode(`data: ${JSON.stringify({error:v?.message??String(v)})}
|
|
30
|
+
|
|
31
|
+
`))}finally{S&&clearTimeout(S),m.enqueue(f.encode(`data: [DONE]
|
|
32
|
+
|
|
33
|
+
`)),m.close()}}})}async unload(){try{this.session&&typeof this.session.dispose=="function"&&await this.session.dispose()}catch{}try{this.context&&typeof this.context.dispose=="function"&&await this.context.dispose()}catch{}try{this.model&&typeof this.model.dispose=="function"&&await this.model.dispose()}catch{}this.session=null,this.context=null,this.model=null,this.llama=null}}});var tr={};b(tr,{WebLLMBackend:()=>qe});var qe,rr=u(()=>{"use strict";qe=class{engine=null;modelId;generationTimeout;maxBlankChunks;workerUrl;usingWorker=!1;lastFatalError=null;constructor(e){this.modelId=e.modelId,this.generationTimeout=e.generationTimeout,this.maxBlankChunks=e.maxBlankChunks,this.workerUrl=e.workerUrl}clearFatalError(){this.lastFatalError=null}async initialize(e){let r=await import("@mlc-ai/web-llm");if(this.workerUrl&&typeof Worker<"u")try{let n=new Worker(this.workerUrl,{type:"module"});this.engine=new r.WebWorkerMLCEngine(n,{initProgressCallback:e}),await this.engine.reload(this.modelId),this.usingWorker=!0,console.log("[DVAI/WebLLM] Initialized with Web Worker (main thread unblocked)");return}catch(n){console.warn("[DVAI/WebLLM] Worker initialization failed, falling back to main thread:",n)}this.engine=await r.CreateMLCEngine(this.modelId,{initProgressCallback:e}),this.usingWorker=!1,console.log("[DVAI/WebLLM] Initialized on main thread (WebGPU compute is async)")}isWorkerBased(){return this.usingWorker}getEngine(){return this.engine}async chatCompletion(e){if(!this.engine)throw new Error("WebLLM engine not initialized");let r=await this.withTimeout(this.engine.chat.completions.create({...e,stream:!1}),this.generationTimeout),n=r?.choices?.[0]?.message?.content;if(n==null||n===""){console.warn("[DVAI/WebLLM] Warning: Engine returned blank content \u2014 flagging for full restart."),this.lastFatalError="blank_output";try{await this.engine.resetChat()}catch{}throw new Error("WebLLM engine returned blank content. A full engine restart is required.")}return r}createStreamingResponse(e){let r=this.engine;if(!r)throw new Error("WebLLM engine not initialized");let n=this.maxBlankChunks,i=this.generationTimeout,s=this;return new ReadableStream({async start(o){let a=0,c=null;try{let d=await r.chat.completions.create({...e,stream:!0}),l=new Promise((p,h)=>{c=setTimeout(()=>{h(new Error(`Generation timed out after ${i}ms`))},i)}),m=(async()=>{for await(let p of d){let h=p?.choices?.[0]?.delta,f=p?.choices?.[0]?.finish_reason;if(!h?.content&&h?.content!==void 0){if(a++,a>=n){console.warn(`[DVAI/WebLLM] ${n} consecutive blank chunks detected \u2014 flagging for full restart.`),s.lastFatalError="blank_stream";try{r.interruptGenerate()}catch{}try{await r.resetChat()}catch{}o.enqueue(new TextEncoder().encode(`data: ${JSON.stringify({error:"Stream aborted: too many blank chunks. Engine restart required."})}
|
|
34
|
+
|
|
35
|
+
`));break}}else a=0;if(o.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(p)}
|
|
36
|
+
|
|
37
|
+
`)),f==="stop"||f==="length")break}})();await Promise.race([m,l])}catch(d){console.error("[DVAI/WebLLM] Stream error:",d.message),d.message?.includes("timed out")&&(s.lastFatalError="timeout");try{r.interruptGenerate()}catch{}try{await r.resetChat()}catch{}o.enqueue(new TextEncoder().encode(`data: ${JSON.stringify({error:d.message})}
|
|
38
|
+
|
|
39
|
+
`))}finally{c&&clearTimeout(c),o.enqueue(new TextEncoder().encode(`data: [DONE]
|
|
40
|
+
|
|
41
|
+
`)),o.close()}}})}async unload(){this.engine&&(await this.engine.unload(),this.engine=null)}withTimeout(e,r){return new Promise((n,i)=>{let s=setTimeout(()=>i(new Error(`Generation timed out after ${r}ms`)),r);e.then(o=>{clearTimeout(s),n(o)}).catch(o=>{clearTimeout(s),i(o)})})}}});var zr={};b(zr,{DEFAULT_LICENSE_FILENAME:()=>M,DVAI:()=>Ce,DVAI_PUBLIC_KEYS:()=>V,LicenseRequiredError:()=>D,LicenseValidator:()=>A,PLACEHOLDER_KID:()=>E,chatToLegacyCompletion:()=>te,composeSignedMessage:()=>oe,detectWebGPU:()=>ee,dvai:()=>Wr,generateNonce:()=>ie,generatePairingKey:()=>R,isPaidTier:()=>Ie,legacyCompletionStreamAdapter:()=>re,signHmac:()=>U,verifyHmac:()=>se});module.exports=dr(zr);var T=require("jose");var V={"2026-05":{kty:"EC",crv:"P-256",x:"2Y8TuhnlE4tiVDtliozYTgc1TAqi4_TBTI6FHe1p_Vw",y:"pyxMJHj10HPe2hnpJvMpnZ4AzpYZRfqGEMhpBr1-Oto",alg:"ES256",use:"sig",kid:"2026-05"},"placeholder-do-not-ship":{kty:"EC",crv:"P-256",x:"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",y:"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",alg:"ES256",use:"sig",kid:"placeholder-do-not-ship"}},E="placeholder-do-not-ship";function Je(){if(typeof globalThis<"u"){let t=globalThis;if(t.Capacitor?.isNativePlatform?.())return"capacitor";if(t.process?.versions?.node&&typeof t.window>"u")return"node"}return typeof window<"u"&&typeof document<"u"?"web":"node"}function Ge(){if(typeof window<"u"){let e=window.location?.hostname;if(typeof e=="string"&&e.length>0)return e}return typeof process<"u"&&process.env?.DVAI_AUDIENCE?process.env.DVAI_AUDIENCE:null}function Xe(){if(typeof process<"u"&&process.env){if(process.env.DVAI_FORCE_PROD==="1"||process.env.DVAI_FORCE_PROD==="true")return{isDev:!1,reason:"DVAI_FORCE_PROD set"};if(process.env.DVAI_FORCE_DEV==="1"||process.env.DVAI_FORCE_DEV==="true")return{isDev:!0,reason:"DVAI_FORCE_DEV set"};if(process.env.NODE_ENV==="test")return{isDev:!0,reason:"NODE_ENV=test"}}if((typeof globalThis<"u"?globalThis:{}).Capacitor?.DEBUG===!0)return{isDev:!0,reason:"Capacitor.DEBUG=true"};if(typeof window<"u"){let n=window.location?.hostname??"";if(n==="localhost"||n==="127.0.0.1"||n==="::1"||n.endsWith(".local")||n.startsWith("192.168.")||n.startsWith("10.")||n.startsWith("172."))return{isDev:!0,reason:`localhost-class hostname: ${n}`};try{let i=window.localStorage;if(i?.getItem("DVAI_FORCE_PROD")==="true")return{isDev:!1,reason:"localStorage DVAI_FORCE_PROD=true"};if(i?.getItem("DVAI_FORCE_DEV")==="true")return{isDev:!0,reason:"localStorage DVAI_FORCE_DEV=true"}}catch{}}return{isDev:!1,reason:"production-class environment"}}function Ye(t,e){if(t===null)return e.includes("*")?"*":null;let r=t.toLowerCase();for(let n of e){let i=n.toLowerCase();if(i==="*"||i===r)return n;if(i.startsWith("*.")){let s=i.slice(2);if(r===s||r.endsWith("."+s))return n}}return null}var M="dvai-license.jwt";async function Ze(t={}){if(typeof t.token=="string"&&t.token.length>0)return{token:t.token.trim(),source:"config.licenseToken"};if(typeof t.path=="string"&&t.path.length>0){let e=await Qe(t.path);return e!==null?{token:e,source:t.path}:null}if(typeof process<"u"&&process.env?.DVAI_LICENSE_PATH){let e=process.env.DVAI_LICENSE_PATH,r=await Qe(e);if(r!==null)return{token:r,source:`DVAI_LICENSE_PATH=${e}`}}return typeof process<"u"&&process.env?.DVAI_LICENSE_TOKEN?{token:process.env.DVAI_LICENSE_TOKEN.trim(),source:"DVAI_LICENSE_TOKEN env var"}:await lr()}async function Qe(t){return/^https?:\/\//i.test(t)?await et(t):await tt(t)}async function et(t){try{let e=await fetch(t,{method:"GET"});if(!e.ok)return null;let r=(await e.text()).trim();return r.length>0?r:null}catch{return null}}async function tt(t){try{let n=(await(await import("fs/promises")).readFile(t,"utf-8")).trim();return n.length>0?n:null}catch{return null}}async function lr(){if(typeof window<"u"){let t=`/${M}`,e=await et(t);return e!==null?{token:e,source:t}:null}if(typeof process<"u"&&typeof process.cwd=="function"){let t=await import("path").catch(()=>null);if(t===null)return null;let e=[t.join(process.cwd(),M),t.join(process.cwd(),"..",M)];for(let r of e){let n=await tt(r);if(n!==null)return{token:n,source:r}}}return null}function Ie(t){return t.kind==="commercial"||t.kind==="trial"}var D=class t extends Error{constructor(r,n){super(r);this.status=n;Object.setPrototypeOf(this,t.prototype)}status;name="LicenseRequiredError"};var A=class{opts;constructor(e={}){this.opts=e}async validate(){let e=Xe();if(e.isDev)return{kind:"free-dev",reason:e.reason};let r=await Ze({...this.opts.token!==void 0?{token:this.opts.token}:{},...this.opts.path!==void 0?{path:this.opts.path}:{}});if(r===null)return{kind:"free-prod",reason:"no license token found; checked config.licenseToken, config.licenseKeyPath, DVAI_LICENSE_PATH env, DVAI_LICENSE_TOKEN env, and platform-default paths"};let n=Je(),i=Ge();return await this.verifyToken(r.token,n,i)}async validateAndAssert(){let e=await this.validate();if(e.kind==="free-prod")throw new D(nt(e),e);if(e.kind==="free-expired")throw new D(nt(e),e);return e}async verifyToken(e,r,n){let i=this.opts.publicKeys??V,s;try{let d=e.split(".");if(d.length!==3||!d[0])return{kind:"free-prod",reason:"license token is not a well-formed JWT (need 3 segments)"};let l=ur(d[0]);s=JSON.parse(l)}catch(d){return{kind:"free-prod",reason:`license token header is not parseable JSON: ${rt(d)}`}}if(s.alg!=="ES256")return{kind:"free-prod",reason:`license token uses unsupported alg "${s.alg??"(missing)"}", expected ES256`};if(typeof s.kid!="string"||s.kid.length===0)return{kind:"free-prod",reason:"license token header missing kid; cannot select verification key"};let o=i[s.kid];if(o===void 0)return{kind:"free-prod",reason:`license token kid "${s.kid}" is not in the SDK's public-key registry; either the key was rotated and you're on an old SDK, or the token was signed with a key we don't recognise`};if(s.kid===E&&this.opts.allowPlaceholderKey!==!0)return{kind:"free-prod",reason:`license token signed with the placeholder key (kid "${E}"); replace the placeholder in publicKeys.ts with a real key generated via scripts/license/generate-keypair.mjs before issuing real licenses`};let a;try{let d=await(0,T.importJWK)(o,"ES256");a=(await(0,T.jwtVerify)(e,d,{algorithms:["ES256"],issuer:"DVAI-Bridge"})).payload}catch(d){if(d instanceof T.errors.JWTExpired){let l=d.payload?.exp??0;return{kind:"free-expired",licensee:d.payload?.licensee??"(unknown)",expiredAt:l}}return d instanceof T.errors.JWSSignatureVerificationFailed?{kind:"free-prod",reason:`license token signature did not verify against kid "${s.kid}"; the token may have been tampered with or was signed by a different key`}:d instanceof T.errors.JWTClaimValidationFailed?{kind:"free-prod",reason:`license token claim "${d.claim}" failed: ${d.reason}`}:{kind:"free-prod",reason:`license token verification failed: ${rt(d)}`}}if(!pr(a))return{kind:"free-prod",reason:"license token payload missing required DVAI fields (tier/platforms/aud/licensee)"};if(!a.platforms.includes(r))return{kind:"free-prod",reason:`license token does not authorise platform "${r}"; the token covers [${a.platforms.join(", ")}]`};let c=Ye(n,a.aud);return c===null?{kind:"free-prod",reason:`license token's audience entries [${a.aud.join(", ")}] do not match the current runtime audience "${n??"(none)"}"`+(n===null?' \u2014 set DVAI_AUDIENCE in your environment, or use a "*" aud entry for any-domain licenses':"")}:{kind:a.tier,licensee:a.licensee,expiresAt:a.exp,platform:r,audienceMatched:c}}};function pr(t){return typeof t.iss=="string"&&typeof t.sub=="string"&&Array.isArray(t.aud)&&t.aud.every(e=>typeof e=="string")&&(t.tier==="commercial"||t.tier==="trial")&&Array.isArray(t.platforms)&&t.platforms.every(e=>typeof e=="string")&&typeof t.licensee=="string"&&typeof t.iat=="number"&&typeof t.exp=="number"}function ur(t){let e=t.length%4===0?"":"=".repeat(4-t.length%4),r=t.replace(/-/g,"+").replace(/_/g,"/")+e;if(typeof atob=="function"){let n=atob(r),i=new Uint8Array(n.length);for(let s=0;s<n.length;s++)i[s]=n.charCodeAt(s);return new TextDecoder().decode(i)}return Buffer.from(r,"base64").toString("utf-8")}function rt(t){return t instanceof Error?t.message:String(t)}function nt(t){let e=`
|
|
42
|
+
DVAI-Bridge Commercial License Required
|
|
43
|
+
=======================================
|
|
44
|
+
`,r=t.kind==="free-expired"?`License for "${t.licensee}" expired at ${new Date(t.expiredAt*1e3).toISOString()}.`:t.kind==="free-prod"?t.reason:"(unknown status)";return e+`
|
|
45
|
+
`+r+`
|
|
46
|
+
`+`
|
|
47
|
+
This SDK is licensed under BSL 1.1 and requires a valid commercial
|
|
48
|
+
or trial license to run in production / release builds.
|
|
49
|
+
|
|
50
|
+
To resolve:
|
|
51
|
+
1. Obtain a license at https://deepvoiceai.com/dvai-bridge/license
|
|
52
|
+
2. Place the file at one of these locations (any will work):
|
|
53
|
+
- <project-root>/dvai-license.jwt (auto-discovered)
|
|
54
|
+
- the path you pass as DVAIConfig.licenseKeyPath
|
|
55
|
+
- the path in $DVAI_LICENSE_PATH
|
|
56
|
+
- inline JWT in DVAIConfig.licenseToken or $DVAI_LICENSE_TOKEN
|
|
57
|
+
3. Re-run.
|
|
58
|
+
|
|
59
|
+
Developing locally? The SDK auto-detects dev mode on:
|
|
60
|
+
- localhost / 127.0.0.1 / *.local hostnames in the browser
|
|
61
|
+
- NODE_ENV=test or NODE_ENV=development in Node
|
|
62
|
+
- DVAI_FORCE_DEV=1 environment variable (explicit override)
|
|
63
|
+
- Capacitor.DEBUG=true on hybrid mobile builds
|
|
64
|
+
Any of these silences this error and lets the SDK run without a
|
|
65
|
+
license.
|
|
66
|
+
`}xe();Ae();ae();var Ce=class{modelId;mockUrl;serviceWorkerUrl;licenseKeyPath;licenseToken;licenseStatus=null;backend;transformersModelId;pipelineTask;device;generationTimeout;maxBlankChunks;maxRetries;webllmWorkerUrl;transformersWorkerUrl;dtype;createPipeline;transformersModelClass;transformersProcessorClass;transformersDisableEncoders;nativeModelPath;nativeGpuLayers;nativeThreads;nativeContextSize;nativeEmbeddingMode;capacitorBackend;nativeMmprojPath;transport;httpBasePort;httpMaxPortAttempts;corsOrigin;httpBindHost;chatCompletionInterceptor;resolvedTransport="none";baseUrl;port;activeTransport=null;validator;backendInstance=null;isReady=!1;recoveryAttempts=0;resolvedBackend="webllm";offload;offloadOnlyMode=!1;capabilityCache;dvaiRoutes;startedAt=Date.now();discovery;pairingPolicy;deviceId;constructor(e={}){this.modelId=e.modelId||"gemma-2-2b-it-q4f16_1-MLC",this.backend=e.backend||"webllm",this.transformersModelId=e.transformersModelId||e.modelId||"onnx-community/gemma-3n-E2B-it-ONNX",this.pipelineTask=e.pipelineTask||"text-generation",this.device=e.device||"auto",this.dtype=e.dtype,this.createPipeline=e.createPipeline,this.transformersModelClass=e.transformersModelClass,this.transformersProcessorClass=e.transformersProcessorClass,this.transformersDisableEncoders=e.transformersDisableEncoders,this.generationTimeout=e.generationTimeout??6e4,this.maxBlankChunks=e.maxBlankChunks??20,this.maxRetries=e.maxRetries??2,this.webllmWorkerUrl=e.webllmWorkerUrl??"/dvai-webllm.worker.js",this.transformersWorkerUrl=e.transformersWorkerUrl??"/dvai-transformers.worker.js",this.mockUrl=e.mockUrl??"https://api.openai.local/v1/chat/completions",this.serviceWorkerUrl=e.serviceWorkerUrl??"/mockServiceWorker.js",this.licenseKeyPath=e.licenseKeyPath,this.licenseToken=e.licenseToken,this.validator=new A({...this.licenseKeyPath!==void 0?{path:this.licenseKeyPath}:{},...this.licenseToken!==void 0?{token:this.licenseToken}:{}}),this.nativeModelPath=e.nativeModelPath||"",this.nativeGpuLayers=e.nativeGpuLayers??99,this.nativeThreads=e.nativeThreads??4,this.nativeContextSize=e.nativeContextSize??2048,this.nativeEmbeddingMode=e.nativeEmbeddingMode??!1,this.capacitorBackend=e.capacitorBackend??"llama",this.nativeMmprojPath=e.nativeMmprojPath,this.transport=e.transport??"auto",this.httpBasePort=e.httpBasePort??38883,this.httpMaxPortAttempts=e.httpMaxPortAttempts??16,this.corsOrigin=e.corsOrigin??"*",this.httpBindHost=e.httpBindHost,this.chatCompletionInterceptor=e.chatCompletionInterceptor,this.backend!=="auto"&&(this.resolvedBackend=this.backend),this.offload=e.offload}getActiveBackend(){return this.resolvedBackend}getActiveTransport(){return this.resolvedTransport}getBaseUrl(){return this.baseUrl}getPort(){return this.port}resolveBackend(){return this.backend==="auto"?(console.log("[DVAI] Auto-detected web environment \u2192 using webllm backend"),"webllm"):this.backend}async initialize(e=console.log){if(this.isReady)return!0;if(this.resolvedBackend=this.resolveBackend(),this.licenseStatus=await this.validator.validateAndAssert(),!(typeof window>"u"&&typeof self<"u"&&typeof self.importScripts=="function")&&this.serviceWorkerUrl)try{(await fetch(this.serviceWorkerUrl,{method:"HEAD"})).ok||console.warn(`[DVAI] Warning: Service Worker not found at "${this.serviceWorkerUrl}". Please run "dvai-bridge init" or "npx msw init <public_dir>" to generate it.`)}catch{console.warn(`[DVAI] Could not verify Service Worker existence at "${this.serviceWorkerUrl}".`)}try{if(this.offload?.enabled){let{assessCapability:a}=await Promise.resolve().then(()=>(ce(),Re)),c=await a({hardwareMinimum:this.offload.hardwareMinimum,minLocalCapability:this.offload.minLocalCapability});this.offloadOnlyMode=c.mode==="offload-only"||c.mode==="too-weak",e({phase:"precheck",mode:c.mode,tokPerSec:c.tokPerSec,reason:c.reason})}this.offloadOnlyMode?e({phase:"backend",skipped:!0,reason:"offload-only mode (device below minLocalCapability or below hardwareMinimum)"}):await this.initializeBackend(e);let{selectTransport:n,MswTransport:i,HttpTransport:s,CapacitorTransport:o}=await Promise.resolve().then(()=>(bt(),vt));if(this.resolvedTransport=n({transport:this.transport==="auto"?void 0:this.transport,serviceWorkerUrl:this.serviceWorkerUrl}),this.resolvedTransport==="http"&&this.mockUrl!=="https://api.openai.local/v1/chat/completions"&&console.warn('[DVAI] mockUrl config is ignored under transport="http". The HTTP server always serves at /v1/*. Use dvai.baseUrl to get the exact endpoint.'),this.resolvedTransport==="msw"&&this.serviceWorkerUrl===""&&this.transport==="msw"&&console.warn("[DVAI] serviceWorkerUrl is empty but transport='msw' was requested; MSW will fail to register."),this.resolvedTransport==="none"&&typeof window>"u"&&typeof self<"u"&&console.log("[DVAI] Running in a Web Worker \u2014 no transport started. Use dvai.chatCompletion() directly, or register MSW on the main thread."),this.resolvedTransport==="msw"?this.activeTransport=new i({mockUrl:this.mockUrl,serviceWorkerUrl:this.serviceWorkerUrl}):this.resolvedTransport==="http"?this.activeTransport=new s({httpBasePort:this.httpBasePort,httpMaxPortAttempts:this.httpMaxPortAttempts,corsOrigin:this.corsOrigin,...this.httpBindHost!==void 0?{bindHost:this.httpBindHost}:{}}):this.resolvedTransport==="capacitor"?this.activeTransport=new o({capacitorBackend:this.capacitorBackend,nativeModelPath:this.nativeModelPath||void 0,nativeMmprojPath:this.nativeMmprojPath,nativeGpuLayers:this.nativeGpuLayers,nativeContextSize:this.nativeContextSize,nativeThreads:this.nativeThreads,nativeEmbeddingMode:this.nativeEmbeddingMode,httpBasePort:this.httpBasePort,httpMaxPortAttempts:this.httpMaxPortAttempts,corsOrigin:this.corsOrigin}):this.activeTransport=null,this.activeTransport){let a=this.getHandlerContext(e),c=await this.activeTransport.start(a);this.baseUrl=c.baseUrl,this.port=c.port}else this.baseUrl=void 0,this.port=void 0;if(this.isReady=!0,this.recoveryAttempts=0,this.offload?.enabled)try{if(await this.initializeOffload(),this.chatCompletionInterceptor===void 0&&this.offloadOnlyMode){let{buildOffloadInterceptor:a}=await Promise.resolve().then(()=>(Dt(),It)),c=this.offload;this.chatCompletionInterceptor=a({config:c,getPeers:()=>this.discovery?.peers()??[],getLocalCapability:()=>0,offloadOnlyMode:!0})}}catch(a){console.warn("[DVAI/offload] failed to initialize offload state; local inference still works. Cause:",a)}return!0}catch(n){throw console.error("[DVAI] Failed to initialize:",n),n}}async initializeOffload(){let{createCapabilityCache:e,ensureDeviceId:r}=await Promise.resolve().then(()=>(J(),be)),{CompositeDiscovery:n,StaticDiscovery:i,createMdnsDiscovery:s}=await Promise.resolve().then(()=>(Ut(),Nt)),{PairingPolicy:o,createPairingStore:a}=await Promise.resolve().then(()=>(Wt(),$t));this.capabilityCache=e(),this.deviceId=await r(this.capabilityCache);let c=[];if(this.offload?.discoverLAN!==!1){let m=typeof globalThis.process<"u"&&globalThis.process.platform==="darwin",p=this.offload?.advertiseLAN&&!m?{deviceId:this.deviceId,deviceName:typeof globalThis.process<"u"&&(globalThis.process.env.DVAI_DEVICE_NAME??"")||"DVAI",dvaiVersion:"3.2.1",port:this.offload.advertisePort??this.port??38883,secure:!1,models:[],capability:{}}:void 0;c.push(await s({selfDeviceId:this.deviceId,...p?{advertise:p}:{}}))}this.offload?.knownPeers&&this.offload.knownPeers.length>0&&c.push(new i(this.offload.knownPeers)),c.length>0&&(this.discovery=new n(c),await this.discovery.start()),this.pairingPolicy=new o({store:a(),onPairingRequest:this.offload?.onPairingRequest?async(m,p,h)=>{let f=this.offload?.onPairingRequest;return f?f({deviceId:m,deviceName:p,dvaiVersion:"unknown",baseUrl:"",loadedModels:[],capability:{},via:"static",secure:!1,lastSeenAt:Date.now(),...h!==void 0?{appId:h}:{}}):!1}:void 0});let{buildDvaiRoutes:d}=await Promise.resolve().then(()=>(Qt(),Yt)),l=this;this.dvaiRoutes=d({libraryVersion:"3.0.0",get currentModelId(){return l.resolvedBackend==="transformers"?l.transformersModelId:l.modelId},capabilityCache:this.capabilityCache,get backend(){let m=l.backendInstance;if(m)return m},discovery:this.discovery,pairingPolicy:this.pairingPolicy,startedAt:this.startedAt})}async shutdownOffload(){if(this.discovery){try{await this.discovery.stop()}catch{}this.discovery=void 0}this.capabilityCache=void 0,this.pairingPolicy=void 0,this.dvaiRoutes=void 0,this.deviceId=void 0}getHandlerContext(e){let r=this;return{get backend(){return r.backendInstance},resolvedBackend:this.resolvedBackend,modelId:this.resolvedBackend==="transformers"?this.transformersModelId:this.modelId,onRecovery:this.resolvedBackend==="webllm"?async()=>{if(this.backendInstance?.lastFatalError&&this.recoveryAttempts<this.maxRetries)await this.attemptRecovery(e);else if(this.recoveryAttempts>=this.maxRetries)throw new Error("Recovery exhausted")}:void 0,get dvaiRoutes(){return r.dvaiRoutes},...this.chatCompletionInterceptor!==void 0?{chatCompletionInterceptor:this.chatCompletionInterceptor}:{}}}async attemptRecovery(e){this.recoveryAttempts++;let r=this.backendInstance?.lastFatalError;if(console.log(`[DVAI] Auto-recovery: unloading engine due to "${r}" (attempt ${this.recoveryAttempts}/${this.maxRetries})`),this.backendInstance){try{await this.backendInstance.unload()}catch(n){console.warn("[DVAI] Error during recovery unload:",n)}this.backendInstance=null}await this.initializeBackend(e),this.backendInstance?.clearFatalError&&this.backendInstance.clearFatalError(),console.log("[DVAI] Auto-recovery: engine reloaded successfully")}async initializeBackend(e){if(this.resolvedBackend==="native"){let r;try{r=(await Promise.resolve().then(()=>(er(),Zt))).NodeLlamaCppBackend}catch{throw new Error("[DVAI] native backend selected but the NodeLlamaCppBackend module failed to load.")}if(!this.nativeModelPath)throw new Error('[DVAI] backend: "native" requires `nativeModelPath` (path to a GGUF file).');let n=this.modelId!=="gemma-2-2b-it-q4f16_1-MLC"?this.modelId:void 0,i=new r({modelPath:this.nativeModelPath,gpuLayers:this.nativeGpuLayers,threads:this.nativeThreads,contextSize:this.nativeContextSize,generationTimeout:this.generationTimeout,modelId:n});await i.initialize(e),this.backendInstance=i,this.modelId=i.getModelId(),console.log(`[DVAI] node-llama-cpp backend ready (modelId="${this.modelId}", gpuLayers=${this.nativeGpuLayers}, contextSize=${this.nativeContextSize})`);return}if(this.resolvedBackend==="transformers"){let r;try{r=(await Promise.resolve().then(()=>(xe(),at))).TransformersBackend}catch{throw new Error(`[DVAI] Transformers.js backend selected but "@huggingface/transformers" is not installed.
|
|
67
|
+
Install it with: npm install @huggingface/transformers`)}let n=new r({modelId:this.transformersModelId,device:this.device,generationTimeout:this.generationTimeout,workerUrl:this.transformersWorkerUrl,pipelineTask:this.pipelineTask,dtype:this.dtype,createPipeline:this.createPipeline,modelClass:this.transformersModelClass,processorClass:this.transformersProcessorClass,disableEncoders:this.transformersDisableEncoders});await n.initialize(e),this.backendInstance=n,console.log(`[DVAI] Transformers.js backend ready (task: ${this.pipelineTask}, device: ${n.getResolvedDevice()}, worker: ${n.isWorkerBased()})`)}else{let r;try{r=(await Promise.resolve().then(()=>(rr(),tr))).WebLLMBackend}catch{throw new Error(`[DVAI] WebLLM backend selected but "@mlc-ai/web-llm" is not installed.
|
|
68
|
+
Install it with: npm install @mlc-ai/web-llm`)}let n=new r({modelId:this.modelId,generationTimeout:this.generationTimeout,maxBlankChunks:this.maxBlankChunks,workerUrl:this.webllmWorkerUrl});await n.initialize(e),this.backendInstance=n,console.log(`[DVAI] WebLLM backend ready (worker: ${n.isWorkerBased()})`)}}getEngine(){return this.backendInstance?this.resolvedBackend==="webllm"?this.backendInstance.getEngine?.()??null:this.resolvedBackend==="native"?this.backendInstance??null:this.backendInstance.getPipeline?.()??null:null}async chatCompletion(e){if(!this.backendInstance)throw new Error("[DVAI] Backend not initialized. Call initialize() first.");return this.backendInstance.chatCompletion(e)}async embedding(e){if(!this.backendInstance)throw new Error("[DVAI] Backend not initialized. Call initialize() first.");if(this.resolvedBackend==="webllm")throw new Error("[DVAI] Embeddings are not supported on the WebLLM backend. Use backend: 'transformers' with pipelineTask: 'feature-extraction'.");if(this.resolvedBackend==="native")throw new Error("[DVAI] Embeddings are not yet supported on the node-llama-cpp backend. Use backend: 'transformers' with pipelineTask: 'feature-extraction'.");if(typeof this.backendInstance.embedding!="function")throw new Error("[DVAI] The current backend does not expose an embedding() method.");return this.backendInstance.embedding(e)}async runPipeline(e,r){if(!this.backendInstance)throw new Error("[DVAI] Backend not initialized. Call initialize() first.");if(this.resolvedBackend!=="transformers"||!this.backendInstance.runPipeline)throw new Error("[DVAI] runPipeline() is only available with the Transformers.js backend.");return this.backendInstance.runPipeline(e,r)}async unload(){await this.shutdownOffload(),this.backendInstance&&(await this.backendInstance.unload(),this.backendInstance=null),this.activeTransport&&(await this.activeTransport.stop(),this.activeTransport=null),this.baseUrl=void 0,this.port=void 0,this.isReady=!1,this.recoveryAttempts=0,console.log("[DVAI] Unloaded model and transport.")}async assessHardware(e={}){let{assessCapability:r}=await Promise.resolve().then(()=>(ce(),Re)),n=await r({hardwareMinimum:e.hardwareMinimum,minLocalCapability:e.minLocalCapability});return{mode:n.mode,tokPerSec:n.tokPerSec,reason:n.reason,hints:n.hints}}async probeCapability(){if(!this.capabilityCache||!this.backendInstance)return;let{probeAndCache:e}=await Promise.resolve().then(()=>(J(),be)),r=this.resolvedBackend==="transformers"?this.transformersModelId:this.modelId;return e({cache:this.capabilityCache,backend:this.backendInstance,modelId:r,libraryVersion:"3.0.0"})}async getCapability(e){if(!this.capabilityCache)return;let{getCapability:r}=await Promise.resolve().then(()=>(J(),be)),n=e??(this.resolvedBackend==="transformers"?this.transformersModelId:this.modelId);return r({cache:this.capabilityCache,modelId:n,libraryVersion:"3.0.0"})}getPeers(){return this.discovery?.peers()??[]}},Wr=new Ce;0&&(module.exports={DEFAULT_LICENSE_FILENAME,DVAI,DVAI_PUBLIC_KEYS,LicenseRequiredError,LicenseValidator,PLACEHOLDER_KID,chatToLegacyCompletion,composeSignedMessage,detectWebGPU,dvai,generateNonce,generatePairingKey,isPaidTier,legacyCompletionStreamAdapter,signHmac,verifyHmac});
|
|
69
|
+
//# sourceMappingURL=index.cjs.map
|