@degreesign/chat 1.3.0 → 1.4.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/README.md +92 -24
- package/dist/browser/chat.min.mjs +1 -1
- package/dist/engines/engine.d.ts +1 -1
- package/dist/engines/litert.d.ts +3 -3
- package/dist/node/chat.node.min.js +1 -1
- package/dist/node/chat.node.min.mjs +1 -1
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
# @degreesign/chat
|
|
2
2
|
|
|
3
|
-
One-shot on-device AI chat for browsers, workers and Node, using wllama CPU
|
|
4
|
-
engine and LiteRT-LM WebGPU engine.
|
|
5
|
-
|
|
6
|
-
Includes voice transcription to many languages
|
|
7
|
-
and a super accurate image vision function.
|
|
8
|
-
The package manages download of AI models automatically,
|
|
9
|
-
with auto resume for low network connections.
|
|
3
|
+
One-shot on-device AI chat for browsers, workers and Node, using a wllama CPU
|
|
4
|
+
engine and a LiteRT-LM WebGPU engine. It streams text, describes images,
|
|
5
|
+
manages model downloads with automatic resume, and renders no UI.
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
Voice notes are transcribed on device by `@degreesign/voice`, a companion
|
|
8
|
+
package, then passed to `@degreesign/chat` as text.
|
|
9
|
+
|
|
10
|
+
`@degreesign/chat` is a plug and play engine for any UI.
|
|
12
11
|
|
|
13
12
|
[](https://www.npmjs.com/package/@degreesign/chat)
|
|
14
13
|
[](#licensing)
|
|
@@ -22,6 +21,7 @@ with auto resume for low network connections.
|
|
|
22
21
|
- [Why](#why)
|
|
23
22
|
- [Install](#install)
|
|
24
23
|
- [Quick start](#quick-start)
|
|
24
|
+
- [Case study: DoListy](#case-study-dolisty)
|
|
25
25
|
- [Enable WebGPU](#enable-webgpu)
|
|
26
26
|
- [Public API](#public-api)
|
|
27
27
|
- [Tools](#tools)
|
|
@@ -39,6 +39,8 @@ with auto resume for low network connections.
|
|
|
39
39
|
|
|
40
40
|
## Why
|
|
41
41
|
|
|
42
|
+
- Proven: [DoListy](https://dolisty.com/#chat), a no-signup PWA, answers
|
|
43
|
+
with the network off.
|
|
42
44
|
- On device: model weights download once, then every reply is generated locally.
|
|
43
45
|
- Headless: the package returns text through callbacks and renders no UI.
|
|
44
46
|
- Stateless: the host passes the whole message list and keeps its own history.
|
|
@@ -147,6 +149,62 @@ audio encoder, so a text turn drops the clip and an audio-only turn reports
|
|
|
147
149
|
The package never writes storage, so the host appends the user message before
|
|
148
150
|
the call and appends the assistant message after the last `onResponse`.
|
|
149
151
|
|
|
152
|
+
## Case study: DoListy
|
|
153
|
+
|
|
154
|
+
[DoListy](https://dolisty.com/#chat) is a DegreeSign project: a private
|
|
155
|
+
to-do list PWA with no sign-up. It ships `@degreesign/chat` for replies
|
|
156
|
+
and image descriptions, and `@degreesign/voice` for voice notes.
|
|
157
|
+
|
|
158
|
+
I wanted an assistant that could read my daily tasks, but I did not want
|
|
159
|
+
to give 100% of my data to big tech. I was also working on a new project
|
|
160
|
+
that had to stay under wraps until its soft launch, so I could not send
|
|
161
|
+
that work to a hosted model. The assistant had to run on the device, and
|
|
162
|
+
it had to be easy for any developer to drop into an app. Most days I have
|
|
163
|
+
that conversation on my phone: a voice note, a transcript, a few tasks,
|
|
164
|
+
all local. DoListy is where that engine got its first real use.
|
|
165
|
+
|
|
166
|
+
![DoListy assistant answering a question on a phone][dolisty-shot]
|
|
167
|
+
|
|
168
|
+
[dolisty-shot]: https://degreesign.github.io/ds_chat/case-study-dolisty.png
|
|
169
|
+
|
|
170
|
+
*A real session on dolisty.com. The green dot is the local model, not a
|
|
171
|
+
server.*
|
|
172
|
+
|
|
173
|
+
### What it does
|
|
174
|
+
|
|
175
|
+
- Describes a photo and tags it without uploading it.
|
|
176
|
+
- Turns a voice note into a task through `@degreesign/voice`.
|
|
177
|
+
- Writes titles, tags and a running summary in 19 languages. The persona
|
|
178
|
+
is the app's; the package adds no identity text.
|
|
179
|
+
- Answers with the network off, from the model already on disk.
|
|
180
|
+
|
|
181
|
+
### What it costs
|
|
182
|
+
|
|
183
|
+
- No per-reply cost, no API key, no rate limit. The only bill is the
|
|
184
|
+
one-time download: about 1.5 GB for Qwen3-VL, 2.0 GB for Gemma 4.
|
|
185
|
+
- An image waits about 70 seconds for its first token on an 8-thread
|
|
186
|
+
desktop CPU. That is the cost of the CPU vision path, chosen so images
|
|
187
|
+
work on phones without WebGPU; text takes the GPU path when the browser
|
|
188
|
+
has one.
|
|
189
|
+
- A 2 GB download resumes from the last committed part. A reload costs at
|
|
190
|
+
most one part, never the whole file.
|
|
191
|
+
- The gallery describes images in the background while you work.
|
|
192
|
+
|
|
193
|
+
### How it is wired
|
|
194
|
+
|
|
195
|
+
- One `createChat` per send, over a prompt assembled from the app's
|
|
196
|
+
encrypted stores.
|
|
197
|
+
- The reply is committed when `onStatus` reports the end; a newer send
|
|
198
|
+
drops the stale one.
|
|
199
|
+
- `gpuAdapter()` picks Gemma on WebGPU and Qwen everywhere else.
|
|
200
|
+
- One model stays resident, so a switch reloads the engine but never the
|
|
201
|
+
file.
|
|
202
|
+
|
|
203
|
+
**See it work:** open [dolisty.com](https://dolisty.com/#chat) on a phone,
|
|
204
|
+
let the model download once, then turn off the network and ask for a
|
|
205
|
+
summary. Speed numbers are in the
|
|
206
|
+
[web-llm comparison](https://degreesign.github.io/ds_chat/vs_web_llm.html).
|
|
207
|
+
|
|
150
208
|
## Enable WebGPU
|
|
151
209
|
|
|
152
210
|
A request without `model` picks `gemma4_e2b_limited` when the browser exposes a
|
|
@@ -218,11 +276,16 @@ other GPU tabs, unload the model, or switch to the CPU model. A lost device
|
|
|
218
276
|
needs a page or model reload; later calls cannot reuse it.
|
|
219
277
|
|
|
220
278
|
While a reply streams, the GPU engine rests after every token readback, so the
|
|
221
|
-
card stays near
|
|
222
|
-
desktop compositor.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
the
|
|
279
|
+
card stays near 50% of wall time instead of pegging at 100% and starving the
|
|
280
|
+
desktop compositor. `limits.gpuShare` overrides that share for one reply, from
|
|
281
|
+
0.05 to 1; `1` disables the rest and the default is 0.5. Each rest is capped
|
|
282
|
+
at 500 ms, so a very slow token still makes progress. The rest applies after
|
|
283
|
+
the prefill, so the first token is not delayed, but the prefill itself still
|
|
284
|
+
runs unpaced. A freeze during loading or before the first token falls outside
|
|
285
|
+
that rest; use a CPU model on those devices. Unloading releases the WebGPU
|
|
286
|
+
device and resets the LiteRT wasm, because a deleted engine leaves both
|
|
287
|
+
unusable; a later load rebuilds them from the stored model file without
|
|
288
|
+
downloading it again.
|
|
226
289
|
|
|
227
290
|
## Public API
|
|
228
291
|
|
|
@@ -263,7 +326,8 @@ WebGPU adapter and the CPU build when it does not. `gpuAdapter` runs the same
|
|
|
263
326
|
probe, so a host can check the device before it names a model. The budget
|
|
264
327
|
defaults are 250 reply tokens, 128 CPU thinking tokens, 1200 GPU reasoning
|
|
265
328
|
tokens (320 on the CPU), 2 images, 1 audio clip, 1000 characters per message,
|
|
266
|
-
10000 prompt characters
|
|
329
|
+
10000 prompt characters, 32 CPU threads and a 0.5 GPU busy share. The CPU
|
|
330
|
+
engine ignores `gpuShare`; the GPU engine applies it after prefill.
|
|
267
331
|
|
|
268
332
|
`CancelChat` is `() => void`. Its meaning depends on the current state:
|
|
269
333
|
|
|
@@ -298,7 +362,7 @@ in memory at a time. A load of the same model still joins the one in flight.
|
|
|
298
362
|
| Field | Description |
|
|
299
363
|
| ----- | ----------- |
|
|
300
364
|
| `model?` | `ChatModelId` to download and load. Defaults like `ChatInput.model`. |
|
|
301
|
-
| `limits?` | Partial `LlmLimits`; `maxThreads` applies
|
|
365
|
+
| `limits?` | Partial `LlmLimits`; `maxThreads` applies at load, `gpuShare` per reply. |
|
|
302
366
|
| `logging?` | Whether package and engine console logs are written. Defaults to `false`. |
|
|
303
367
|
| `onStatus?` | Receives a `ChatStatusSnapshot` on every progress and state change. |
|
|
304
368
|
|
|
@@ -357,11 +421,13 @@ function uses the shared runtime, so it loads the describer and then the
|
|
|
357
421
|
translator, replacing whichever model was loaded before.
|
|
358
422
|
|
|
359
423
|
`onStatus` follows the same snapshots as `createChat`. The describer reports
|
|
360
|
-
first, with `supportsImages: true`.
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
424
|
+
first, with `supportsImages: true`. A finished load reports `percent: 100` and
|
|
425
|
+
`phase: LlmPhase.load` before the first text, so a host can clear its progress
|
|
426
|
+
row. When a translation pass follows, the snapshots switch to
|
|
427
|
+
`gemma4_e2b_limited` while it loads and translates. The final snapshot has
|
|
428
|
+
`requesting: false`; when the translator cannot load, it also carries that error
|
|
429
|
+
and the descriptions stay English. An empty `images` list touches no model and
|
|
430
|
+
reports nothing.
|
|
365
431
|
|
|
366
432
|
### Translate descriptions
|
|
367
433
|
|
|
@@ -437,9 +503,11 @@ search and currency tools fetch over the network; `calculate` does not.
|
|
|
437
503
|
| `error?` | The last failure, cleared when a reply starts. |
|
|
438
504
|
|
|
439
505
|
The first snapshot fires synchronously inside `createChat`. A final snapshot
|
|
440
|
-
with `requesting: false` marks the end of the call.
|
|
441
|
-
|
|
442
|
-
|
|
506
|
+
with `requesting: false` marks the end of the call. A cancelled call also ends
|
|
507
|
+
with that snapshot, once the model unloads or its wait on the load ends, so a
|
|
508
|
+
host can clear its loading row. `describeImages` reports the same snapshot for
|
|
509
|
+
each model it loads: `qwen3_vl_2b_instruct` while it describes, then
|
|
510
|
+
`gemma4_e2b_limited` while it translates.
|
|
443
511
|
|
|
444
512
|
A stream that never produces its first chunk ends with an error after 5
|
|
445
513
|
minutes on a desktop or 50 minutes on a phone or tablet, and an image turn
|
|
@@ -700,7 +768,7 @@ const useReply = () => {
|
|
|
700
768
|
| `CancelChat` | The function returned by `createChat`. |
|
|
701
769
|
| `ChatMessage` | One prompt turn, `role`, `content` and optional `images` and `audio`. |
|
|
702
770
|
| `ChatStatusSnapshot` | Availability, engine status, backend, progress and request state. |
|
|
703
|
-
| `LlmLimits` | Token, prompt, image, audio and
|
|
771
|
+
| `LlmLimits` | Token, prompt, image, audio, thread and GPU share budgets, all overridable. |
|
|
704
772
|
| `WllamaAssets` | Wasm, compat wasm and compat worker URLs. |
|
|
705
773
|
|
|
706
774
|
The public enums are `ChatModelId`, `LlmRole`, `ChatStatus`, `LlmStatus`,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! For license information please see chat.min.mjs.LICENSE.txt */
|
|
2
|
-
var e={155(e){e.exports=(()=>{var e={125:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.addZ=t.tN=t.monNm=t.tmUTC=t.tmAP=t.moYrDt=t.shortDt=t.fullLong=t.fullDate=t.fullDt=t.invDt=t.dayRes=t.timeStandard=t.dateStandard=t.seoDt=t.thisYear=t.oneMon=t.oneMin=t.oneHr=t.oneDay=t.oneSec=void 0;const r=()=>Date.now(),n=["January","February","March","April","May","June","July","August","September","October","November","December"],o=["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"],a=["st","nd","rd","th"],i=e=>0==+e?"00":+e<10&&+e>=1?`0${e}`:`${e}`,s=e=>{const t=new Date(e);return`${t.getUTCFullYear()}-${i(t.getUTCMonth()+1)}-${i(t.getUTCDate())}`},c=e=>i(e.getUTCHours())+`:${i(e.getUTCMinutes())}`+`:${i(e.getUTCSeconds())}`;t.tN=r,t.monNm=n,t.dayRes=90,t.oneSec=1e3,t.oneMin=6e4,t.oneHr=36e5,t.oneDay=864e5,t.oneMon=27e8,t.addZ=i,t.tmUTC=e=>{const t=new Date(e);return i(t.getUTCHours())+`:${i(t.getUTCMinutes())} UTC`},t.tmAP=e=>{const t=new Date(e),r=t.getHours();return i(r>12?r-12:r)+`:${i(t.getMinutes())}`+(r>=12?"pm":"am")},t.shortDt=e=>{const t=new Date(e);return`${t.getDate()} ${o[t.getMonth()]}`},t.moYrDt=e=>{const t=new Date(e);return`${o[t.getMonth()]} ${t.getFullYear()}`},t.fullDt=e=>{const t=new Date(e);return`${t.getDate()} ${o[t.getMonth()]} ${t.getFullYear()}`},t.fullDate=e=>{const t=new Date(e);return`${t.getDate()} ${n[t.getMonth()]} ${t.getFullYear()}`},t.fullLong=e=>`${(e=>{const t=new Date(e),r=t.getDate();return r+a[r<5?r-1:r>4&&r<21?3:r>20&&r<25?r-21:r>24&&r<31?3:0]+` of ${n[t.getMonth()]}`})(e)} ${new Date(e).getFullYear()}`,t.thisYear=e=>(e?new Date(e):new Date)?.getUTCFullYear(),t.dateStandard=s,t.timeStandard=c,t.seoDt=e=>{!e&&(e=r());const t=new Date(e);return`${s(t)}T${c(t)}Z`},t.invDt=e=>{const t=new Date(e);return`${t.getUTCFullYear()}`.split("20")[1]+i(t.getUTCMonth()+1)+i(t.getUTCDate())+`${e}`.slice(10)}},240:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.idRandLong=t.idRandShort=t.idShuffle=void 0;const r=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","@",".","_","0","1","2","3","4","5","6","7","8","9"],n=({data:e,password:t})=>{try{const n=(e,t)=>r.includes(e.toLowerCase())?r[(r.indexOf(e.toLowerCase())+Math.pow(t,3))%r.length]:e;return[...e].map(e=>n(e,Number(t))).join("")}catch{return""}},o=async({data:e,password:t})=>{if(!e||!t)return"";try{crypto.subtle;const r=new TextEncoder,n=r.encode(e),o=r.encode(t),a=await crypto.subtle.digest("SHA-256",o),i=new Uint8Array(a),s=i.slice(0,32),c=i.slice(0,12),l=await crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["encrypt"]),u=await crypto.subtle.encrypt({name:"AES-GCM",iv:c},l,n);return btoa(String.fromCharCode(...new Uint8Array(u))).replace(/\+/g,"a").replace(/\//g,"b").replace(/=/g,"c").toLowerCase()}catch{return""}};t.idShuffle=async({data:e,password:t})=>4==t?.length?n({data:e,password:t}):await o({data:e,password:t}),t.idRandShort=(e=10)=>{try{return crypto.randomUUID()?.replaceAll("-","")?.slice(0,e)}catch(e){return console.log("idRandShort failed",e),""}},t.idRandLong=(e=10)=>{try{const t="abcdefghijklmnopqrstuvwxyz",r=new Uint8Array(e);return crypto.getRandomValues(r),Array.from(r).map(e=>t[e%26]).join("")}catch(e){return console.log("idRandLong failed",e),""}}},246:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.cacheCheck=t.delayCode=void 0;const n=r(125);t.delayCode=async(e=0)=>await new Promise(t=>setTimeout(t,e)),t.cacheCheck=({analysisCacheLimit:e,lastUpdated:t,forceRefresh:r})=>{const o=Date.now();if(t&&(!r&&t>o-e||r&&t>o-n.oneDay))return!0}},792:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isEven=t.pNum=t.sharpeRatio=t.priceVariations=t.nTxtAr=t.zNum=t.addCom=t.adjNum=t.rNum=void 0;const r=[1,.1,.01,.001,1e-4,1e-5,1e-6,1e-7,1e-8,1e-9,1e-10,1e-11,1e-12,1e-13,1e-14,1e-15,1e-16,1e-17,1e-18,1e-19],n=(e,t=6)=>{const n=+e,o=n?Math.abs(n):0,a=o>1&&t?t-`${Math.round(o)}`.length:0;return n?(n<0?-1:1)*(Number.isInteger(o)||o<1e-16?o:o>1e5?Math.round(o):o>1?Number(o.toFixed(a<0?0:a)):((e,t)=>{let n=0;for(const o of r){if(o<e)return Number(e.toFixed(t+n-1));n++}return e})(o,t)):e},o=(e,t)=>{const r=(n(e,t)+"").split(".");return r[0]=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,","),r.join(".")},a=(e,t=3)=>{const r=Number(e);if(!e||!r)return e+"";const a=Math.abs(r);return(r<0?"-":"")+(a>1e9?o(a/1e9,t)+"b":a>1e6?o(a/1e6,t)+"m":a<1e-6&&a>1e-16?(1+n(a,t)+"").replace(/1./g,"0."):o(a,t))};t.nTxtAr=["zero","one","two","three","four","five","six","seven","eight","nine","ten"],t.rNum=n,t.addCom=o,t.adjNum=a,t.zNum=e=>{const t=Number(e);let r=t?Math.abs(t):0,n=1e10;for(;n>1;)r>n&&(r=Math.round(r/(n/10))*(n/10)),n/=10;return t?(t<0?"-":"")+a(r,2):e},t.pNum=e=>+e||0==+e?Math.round(1e6*+e)/1e6:null,t.priceVariations=e=>{try{let t=0;const r=[...e].sort((e,t)=>e[0]-t[0]),n=e.reduce((e,[,t])=>e+t,0),o=r.find(([,e])=>(t+=e,t>=n/2))[0];return e.filter(([e])=>Math.abs(e-o)/o<.05).map(([e])=>e)}catch{return[]}},t.sharpeRatio=({assetPrices:e,minExpectedReturn:t=.05})=>{if(!e?.length||e?.length<2)return 0;const r=e.slice(1).map((t,r)=>(t-e[r])/e[r]),n=r.reduce((e,t)=>e+t,0)/r.length,o=Math.sqrt(r.reduce((e,t)=>e+Math.pow(t-n,2),0)/r.length);return(n-t)/o},t.isEven=e=>e%2==0},794:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restoreObj=t.restoreObjStr=t.storeObj=t.storeObjStr=t.objNestValueCount=t.objLen=t.objSortSimple=t.objSort=void 0;const n=r(125),o=e=>{try{return Object.keys(e||{})?.length||0}catch(e){return console.log(e),0}},a=e=>{try{return e?.replace(/"/g,"'")}catch(e){return console.log((0,n.tN)(),"storeObjStr failed",e),""}},i=e=>{try{return e?.toString()?.replace(/'/g,'"')}catch(e){console.log((0,n.tN)(),"restoreObjStr failed",e)}};t.objLen=o,t.objNestValueCount=e=>{let t=0;if(o(e))for(const r in e)t+=o(e[r])?1:0;return t},t.objSort=(e={},t,r=-1)=>Object.fromEntries(Object.entries(e).sort(([,e],[,n])=>null===e[t]||void 0===e[t]?1:null===n[t]||void 0===n[t]?-1:e[t]>n[t]?1*r:-1*r)),t.objSortSimple=(e={},t=-1)=>Object.fromEntries(Object.entries(e).sort(([,e],[,r])=>null==e?1:null==r?-1:e>r?1*t:-1*t)),t.storeObjStr=a,t.storeObj=e=>{try{return a(JSON.stringify(e))}catch(e){return console.log((0,n.tN)(),"storeObj failed",e),""}},t.restoreObjStr=i,t.restoreObj=e=>{try{if(!e)return;const t=i(e);return t?JSON.parse(t):void 0}catch(e){console.log((0,n.tN)(),"restoreObj failed",e)}}},830:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.phaseDifference=t.compareArrays=t.squeezeArray=t.forecastNextTotal=t.forecastNext=t.getMax=t.getMean=t.getSum=t.maxVl=t.minVl=t.sumArr=void 0;const r=e=>{try{return e?.length?e.reduce((e,t)=>e+t):0}catch(e){return console.log("sumArr failed",e),0}},n=e=>{try{return e?.length?e.reduce((e,t)=>e+t,0):0}catch(e){return console.log("getSum failed",e),0}},o=e=>{try{return e?.length?n(e)/e.length:0}catch(e){return console.log("getMean failed",e),0}},a=e=>{try{return e?.length?Math.max(...e):0}catch(e){return console.log("getMax failed",e),0}},i=e=>{try{if(!e?.length)return 0;const t=[...e].sort((e,t)=>e-t),r=Math.floor(t.length/2);return t.length%2?t[r]:(t[r-1]+t[r])/2}catch(e){return console.log("median failed",e),0}},s=({currentPeriod:e,steps:t=1})=>{try{const r=(Array.isArray(e)?e:[]).filter(Number.isFinite);if(!r.length||t<=0)return[];if(r.length<2){const e=Math.max(0,o(r));return Array.from({length:t},()=>e)}const n=r.length,{slope:s,intercept:c}=(e=>{try{const t=e.length,r=[];for(let n=0;n<t-1;n++)for(let o=n+1;o<t;o++)r.push((e[o]-e[n])/(o-n));const n=i(r);return{slope:n,intercept:i(e.map((e,t)=>e-n*t))}}catch(e){return console.log("theilSen failed",e),{slope:0,intercept:0}}})(r),l=c+s*(n-1),u=a(r),d=u>0?3*u:1/0;return Array.from({length:t},(e,t)=>{const r=t+1,o=l+s*n*Math.log1p(r/n);return Math.max(0,Math.min(o,d))})}catch(e){return console.log("forecastNext failed",e),[]}};t.sumArr=r,t.maxVl=(e,t)=>{let r=0;for(let n=0;n<e.length;n++){const o=e[n];o[t]>r&&(r=o[t])}return r},t.minVl=(e,t)=>{let r=0;for(let n=0;n<e.length;n++){const o=e[n];o[t]<r&&(r=o[t])}return r},t.getSum=n,t.getMean=o,t.getMax=a,t.forecastNext=s,t.forecastNextTotal=e=>{try{const t=s({currentPeriod:e,steps:e?.length});return n(t)}catch(e){return console.log("forecastNextTotal failed",e),0}},t.squeezeArray=({arr:e,targetLength:t})=>{try{if(!e||0===e.length||t<=0)throw new Error("Invalid input");const n=Math.ceil(e.length/t);return Array.from({length:t},(t,o)=>{const a=o*n,i=Math.min(a+n,e.length),s=e.slice(a,i);return r(s)}).slice(0,t)}catch(e){return console.log("squeezeArray failed",e),[]}},t.compareArrays=({arrays:e})=>{try{const t=[...e],n=Math.min(...t.map(e=>e.length));for(let e=0;e<t.length;e++)t.splice(n);const o=t.map(e=>r(e)),a=[],i=Math.min(...o),s=o.indexOf(i),c=i/Math.max(...o);for(let e=0;e<t.length;e++){const r=t[e];if(a[e]=[],e==s)a[e]=r;else for(let t=0;t<r.length;t++)a[e].push(c*r[t])}return a}catch(t){return console.log("compareArrays failed",t),e}},t.phaseDifference=({array1:e,array2:t})=>{try{let r=e.length,n=e.reduce((e,t)=>e+t)/r,o=t.reduce((e,t)=>e+t)/r,a=e.map(e=>e-n),i=t.map(e=>e-o),s=Math.floor(r/2),c=-1/0,l=0;for(let e=-s;e<=s;e++){let t=0,n=0,o=0,s=0;for(let c=0;c<r;c++){let l=c+e;l>=0&&l<r&&(t+=a[c]*i[l],n+=a[c]*a[c],o+=i[l]*i[l],s++)}if(n>0&&o>0&&s>=.8*r){let r=t/Math.sqrt(n*o);r>c&&(c=r,l=e)}}return l}catch(e){return console.log("phaseDifference failed",e),0}}}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}var n={};return(()=>{var e=n;Object.defineProperty(e,"__esModule",{value:!0}),e.idShuffle=e.isEven=e.pNum=e.nTxtAr=e.zNum=e.addCom=e.adjNum=e.rNum=e.sharpeRatio=e.priceVariations=e.timeStandard=e.dateStandard=e.addZ=e.tN=e.monNm=e.tmUTC=e.tmAP=e.moYrDt=e.shortDt=e.fullLong=e.fullDate=e.fullDt=e.invDt=e.dayRes=e.thisYear=e.seoDt=e.oneMon=e.oneMin=e.oneHr=e.oneDay=e.oneSec=e.restoreObj=e.restoreObjStr=e.storeObj=e.storeObjStr=e.objSortSimple=e.objSort=e.objNestValueCount=e.objLen=e.phaseDifference=e.compareArrays=e.squeezeArray=e.forecastNextTotal=e.forecastNext=e.getMax=e.getMean=e.getSum=e.maxVl=e.minVl=e.sumArr=void 0,e.cacheCheck=e.delayCode=e.idRandLong=e.idRandShort=void 0;const t=r(246);Object.defineProperty(e,"cacheCheck",{enumerable:!0,get:function(){return t.cacheCheck}}),Object.defineProperty(e,"delayCode",{enumerable:!0,get:function(){return t.delayCode}});const o=r(830);Object.defineProperty(e,"sumArr",{enumerable:!0,get:function(){return o.sumArr}}),Object.defineProperty(e,"minVl",{enumerable:!0,get:function(){return o.minVl}}),Object.defineProperty(e,"maxVl",{enumerable:!0,get:function(){return o.maxVl}}),Object.defineProperty(e,"getMax",{enumerable:!0,get:function(){return o.getMax}}),Object.defineProperty(e,"getMean",{enumerable:!0,get:function(){return o.getMean}}),Object.defineProperty(e,"getSum",{enumerable:!0,get:function(){return o.getSum}}),Object.defineProperty(e,"forecastNext",{enumerable:!0,get:function(){return o.forecastNext}}),Object.defineProperty(e,"forecastNextTotal",{enumerable:!0,get:function(){return o.forecastNextTotal}}),Object.defineProperty(e,"squeezeArray",{enumerable:!0,get:function(){return o.squeezeArray}}),Object.defineProperty(e,"compareArrays",{enumerable:!0,get:function(){return o.compareArrays}}),Object.defineProperty(e,"phaseDifference",{enumerable:!0,get:function(){return o.phaseDifference}});const a=r(240);Object.defineProperty(e,"idRandLong",{enumerable:!0,get:function(){return a.idRandLong}}),Object.defineProperty(e,"idRandShort",{enumerable:!0,get:function(){return a.idRandShort}}),Object.defineProperty(e,"idShuffle",{enumerable:!0,get:function(){return a.idShuffle}});const i=r(792);Object.defineProperty(e,"addCom",{enumerable:!0,get:function(){return i.addCom}}),Object.defineProperty(e,"adjNum",{enumerable:!0,get:function(){return i.adjNum}}),Object.defineProperty(e,"priceVariations",{enumerable:!0,get:function(){return i.priceVariations}}),Object.defineProperty(e,"nTxtAr",{enumerable:!0,get:function(){return i.nTxtAr}}),Object.defineProperty(e,"rNum",{enumerable:!0,get:function(){return i.rNum}}),Object.defineProperty(e,"zNum",{enumerable:!0,get:function(){return i.zNum}}),Object.defineProperty(e,"sharpeRatio",{enumerable:!0,get:function(){return i.sharpeRatio}}),Object.defineProperty(e,"pNum",{enumerable:!0,get:function(){return i.pNum}}),Object.defineProperty(e,"isEven",{enumerable:!0,get:function(){return i.isEven}});const s=r(125);Object.defineProperty(e,"oneSec",{enumerable:!0,get:function(){return s.oneSec}}),Object.defineProperty(e,"oneDay",{enumerable:!0,get:function(){return s.oneDay}}),Object.defineProperty(e,"oneHr",{enumerable:!0,get:function(){return s.oneHr}}),Object.defineProperty(e,"oneMin",{enumerable:!0,get:function(){return s.oneMin}}),Object.defineProperty(e,"oneMon",{enumerable:!0,get:function(){return s.oneMon}}),Object.defineProperty(e,"seoDt",{enumerable:!0,get:function(){return s.seoDt}}),Object.defineProperty(e,"dayRes",{enumerable:!0,get:function(){return s.dayRes}}),Object.defineProperty(e,"invDt",{enumerable:!0,get:function(){return s.invDt}}),Object.defineProperty(e,"fullDt",{enumerable:!0,get:function(){return s.fullDt}}),Object.defineProperty(e,"fullDate",{enumerable:!0,get:function(){return s.fullDate}}),Object.defineProperty(e,"fullLong",{enumerable:!0,get:function(){return s.fullLong}}),Object.defineProperty(e,"shortDt",{enumerable:!0,get:function(){return s.shortDt}}),Object.defineProperty(e,"moYrDt",{enumerable:!0,get:function(){return s.moYrDt}}),Object.defineProperty(e,"tmAP",{enumerable:!0,get:function(){return s.tmAP}}),Object.defineProperty(e,"tmUTC",{enumerable:!0,get:function(){return s.tmUTC}}),Object.defineProperty(e,"monNm",{enumerable:!0,get:function(){return s.monNm}}),Object.defineProperty(e,"tN",{enumerable:!0,get:function(){return s.tN}}),Object.defineProperty(e,"addZ",{enumerable:!0,get:function(){return s.addZ}}),Object.defineProperty(e,"timeStandard",{enumerable:!0,get:function(){return s.timeStandard}}),Object.defineProperty(e,"dateStandard",{enumerable:!0,get:function(){return s.dateStandard}}),Object.defineProperty(e,"thisYear",{enumerable:!0,get:function(){return s.thisYear}});const c=r(794);Object.defineProperty(e,"objSort",{enumerable:!0,get:function(){return c.objSort}}),Object.defineProperty(e,"objLen",{enumerable:!0,get:function(){return c.objLen}}),Object.defineProperty(e,"objNestValueCount",{enumerable:!0,get:function(){return c.objNestValueCount}}),Object.defineProperty(e,"restoreObj",{enumerable:!0,get:function(){return c.restoreObj}}),Object.defineProperty(e,"restoreObjStr",{enumerable:!0,get:function(){return c.restoreObjStr}}),Object.defineProperty(e,"storeObj",{enumerable:!0,get:function(){return c.storeObj}}),Object.defineProperty(e,"storeObjStr",{enumerable:!0,get:function(){return c.storeObjStr}}),Object.defineProperty(e,"objSortSimple",{enumerable:!0,get:function(){return c.objSortSimple}})})(),n})()}};const t={};function r(n){const o=t[n];if(void 0!==o)return o.exports;const a=t[n]={exports:{}};return e[n].call(a.exports,a,a.exports,r),a.exports}var n,o,a,i,s,c,l,u;let d;r.m=e,r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.f={},r.e=e=>{const t=[];return r.f.j(e,t),Promise.all(t)},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{const e={520:()=>import("./engine-litert.min.mjs"),924:()=>import("./engine-wllama.min.mjs")},t={792:0},n=e=>{let{__webpack_esm_ids__:n,__webpack_esm_modules__:o,__webpack_esm_runtime__:a}=e;var i,s,c=0;for(i in o)r.o(o,i)&&(r.m[i]=o[i]);for(a&&a(r);c<n.length;c++)s=n[c],r.o(t,s)&&t[s]&&t[s][0](),t[s]=0};r.f.j=(o,a)=>{let i=r.o(t,o)?t[o]:void 0;if(0!==i)if(i)a.push(i[1]);else{let r=e[o]().then(n,e=>{throw 0!==t[o]&&(t[o]=void 0),e});r=Promise.race([r,new Promise(e=>i=t[o]=[e])]),a.push(i[1]=r)}}})(),function(e){e.system="system",e.user="user",e.assistant="assistant"}(n||(n={})),function(e){e[e.online=0]="online",e[e.away=1]="away",e[e.offline=2]="offline"}(o||(o={})),function(e){e[e.idle=0]="idle",e[e.downloading=1]="downloading",e[e.ready=2]="ready",e[e.error=3]="error",e[e.unsupported=4]="unsupported"}(a||(a={})),function(e){e.cpu="cpu",e.gpu="gpu",e.none="none"}(i||(i={})),function(e){e.download="download",e.load="load"}(s||(s={})),function(e){e.qwen3_vl_2b="qwen3-vl-2b",e.qwen3_vl_2b_instruct="qwen3-vl-2b-instruct",e.qwen3_vl_2b_instruct_q3="qwen3-vl-2b-instruct-q3",e.gemma4_e2b_limited="gemma4-e2b-limited"}(c||(c={})),function(e){e.websearch="websearch",e.calculate="calculate",e.currency="currency"}(l||(l={})),function(e){e.wikipedia="wikipedia",e.duckduckgo="duckduckgo"}(u||(u={}));const g=[{id:c.qwen3_vl_2b,reasoning:!0,cpu:{repo:"Qwen/Qwen3-VL-2B-Thinking-GGUF",file:"Qwen3VL-2B-Thinking-Q4_K_M.gguf",mmproj:{file:"mmproj-Qwen3VL-2B-Thinking-Q8_0.gguf"}}},{id:c.qwen3_vl_2b_instruct,reasoning:!1,cpu:{repo:"unsloth/Qwen3-VL-2B-Instruct-GGUF",file:"Qwen3-VL-2B-Instruct-Q4_K_M.gguf",mmproj:{repo:"Qwen/Qwen3-VL-2B-Instruct-GGUF",file:"mmproj-Qwen3VL-2B-Instruct-Q8_0.gguf"}}},{id:c.qwen3_vl_2b_instruct_q3,reasoning:!1,cpu:{repo:"unsloth/Qwen3-VL-2B-Instruct-GGUF",file:"Qwen3-VL-2B-Instruct-Q3_K_M.gguf",mmproj:{repo:"Qwen/Qwen3-VL-2B-Instruct-GGUF",file:"mmproj-Qwen3VL-2B-Instruct-Q8_0.gguf"}}},{id:c.gemma4_e2b_limited,reasoning:!0,litert:{repo:"litert-community/gemma-4-E2B-it-litert-lm",file:"gemma-4-E2B-it-gpu.litertlm",vision:!1,audio:!1}}],m=e=>{const t=e??("undefined"==typeof navigator?void 0:navigator);if(!t)return!1;if("boolean"==typeof t.userAgentData?.mobile)return t.userAgentData.mobile;const r=t.userAgent||"";return/Android|iPhone|iPad|iPod|Mobile/i.test(r)||/Macintosh/.test(r)&&t.maxTouchPoints>1},p=e=>e?g.find(t=>t.id==e):void 0,f=async()=>{const e="undefined"==typeof navigator?void 0:navigator.gpu;if(!e)return!1;let t;try{return!!await Promise.race([e.requestAdapter({powerPreference:"high-performance"}),new Promise(e=>{t=setTimeout(()=>e(void 0),1500)})])}catch{return!1}finally{t&&clearTimeout(t)}},h=async e=>p(e??await(async()=>(d||(d=(async()=>await f()?c.gemma4_e2b_limited:c.qwen3_vl_2b)()),await d))()),y=e=>!!e.cpu?.mmproj||!0===e.litert?.vision,w=e=>!!e.cpu?.mmproj?.audio||!0===e.litert?.audio,b=new URL("./../assets/wllama/wllama.wasm",import.meta.url).href,v=new URL("./../assets/wllama/compat/wllama.wasm",import.meta.url).href,x=new URL("./../assets/wllama/compat/wllama.js",import.meta.url).href,M=new URL("./../assets/litert/litertlm_wasm_internal.js",import.meta.url).href,j=(new URL("./../assets/litert/litertlm_wasm_internal.wasm",import.meta.url).href,{width:384,height:384}),k=async e=>{if(!e.startsWith("data:"))return await(await fetch(e)).arrayBuffer();const t=e.indexOf(","),r=t>=0?e.slice(0,t):"";if(t<0)throw new Error("Invalid image data");if(!r.includes(";base64"))return await(await fetch(e)).arrayBuffer();const n=atob(e.slice(t+1)),o=new Uint8Array(n.length);for(let e=0;e<n.length;e++)o[e]=n.charCodeAt(e);return o.buffer},_=async(e,t,r=128)=>{if(!e||"function"!=typeof fetch||"function"!=typeof createImageBitmap)return e;try{const n=await fetch(e),o=await createImageBitmap(await n.blob()),a=t??((e,t,r=128)=>{const n=e/Math.max(1,t);let o=32,a=32,i=1/0,s=1/0;for(let e=1;e<=r;e++){const t=Math.ceil(r/e),c=Math.floor((r+8)/e);for(let r=t;r<=c;r++){const t=r*e,c=Math.abs(r/e-n);(c<i-1e-9||Math.abs(c-i)<=1e-9&&t<s)&&(o=32*r,a=32*e,i=c,s=t)}}return{width:o,height:a}})(o.width,o.height,r),i=o.width/Math.max(1,o.height),s=a.width/a.height,c=Math.min(o.width,i>s?o.height*s:o.width),l=Math.min(o.height,i>s?o.height:o.width/s),u=(o.width-c)/2,d=(o.height-l)/2,g=((e,t)=>{if("undefined"!=typeof OffscreenCanvas)return new OffscreenCanvas(e,t);if("undefined"==typeof document)return;const r=document.createElement("canvas");return r.width=e,r.height=t,r})(a.width,a.height),m=g?g.getContext("2d"):null;if(!g||!m||o.width<1||o.height<1)return o.close(),e;if(m.drawImage(o,u,d,c,l,0,0,a.width,a.height),o.close(),(e=>"undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)(g)){const t=await g.convertToBlob({type:"image/jpeg",quality:.85});return await(e=>new Promise(t=>{if("undefined"==typeof FileReader)return void t("");const r=new FileReader;r.onerror=()=>t(""),r.onload=()=>t(`${r.result}`),r.readAsDataURL(e)}))(t)||e}return g.toDataURL("image/jpeg",.85)}catch{return e}};var P=r(155);const T={maxReplyTokens:250,maxThinkingTokens:128,maxReasoningTokens:320,maxImages:2,imageTokens:128,maxAudio:1,maxContentLength:1e3,promptCharBudget:1e4,maxThreads:32},S=(e,t,r)=>"number"==typeof e&&Number.isFinite(e)&&e>=r?Math.floor(e):t,O=(e={},t=!1)=>{const r=T;return{maxReplyTokens:S(e.maxReplyTokens,r.maxReplyTokens,1),maxThinkingTokens:S(e.maxThinkingTokens,r.maxThinkingTokens,1),maxReasoningTokens:S(e.maxReasoningTokens,t?1200:r.maxReasoningTokens,1),maxImages:S(e.maxImages,r.maxImages,0),imageTokens:S(e.imageTokens,r.imageTokens,1),maxAudio:S(e.maxAudio,r.maxAudio,0),maxContentLength:S(e.maxContentLength,r.maxContentLength,1),promptCharBudget:S(e.promptCharBudget,r.promptCharBudget,1),maxThreads:S(e.maxThreads,r.maxThreads,1)}},D=(e,t,r=.7)=>({stream:!0,temperature:r,max_tokens:t?e.maxReasoningTokens:e.maxReplyTokens}),N=(e,t)=>`https://huggingface.co/${e}/resolve/main/${t}`,C=e=>Number(e.headers.get("content-length"))||0,E=(e,t)=>e.some(e=>Array.isArray(e.content)&&e.content.some(e=>e.type==t)),L=e=>E(e,"image"),A=e=>E(e,"audio"),R=["<|channel>thought\n","<|channel>thought","..."],$=["<channel|>","..."],U=(e,t,r)=>t.length||r.length?[...e?[{type:"text",text:e}]:[],...t.map(e=>({type:"image",url:e})),...r.map(e=>({type:"audio",url:e}))]:e,q=e=>"string"==typeof e?e?[{type:"text",text:e}]:[]:e,z=(e,t)=>{if("string"==typeof e&&"string"==typeof t)return`${e}\n${t}`;const r=[];for(const n of[...q(e),{type:"text",text:"\n"},...q(t)]){const e=r[r.length-1];"text"==n.type&&"text"==e?.type?e.text+=n.text:r.push(n)}return r},I=m()?3e6:3e5,F=Math.max(I,84e4);class W extends Error{}const V=async(e,t,r)=>{let n;try{return await Promise.race([e,new Promise((e,o)=>{n=setTimeout(()=>o(new W(r)),t)})])}finally{n&&clearTimeout(n)}},B=e=>{try{Promise.resolve(e.next?.()).catch(()=>{}).finally(()=>{try{Promise.resolve(e.return?.()).catch(()=>{})}catch{}})}catch{}},G=async({model:e,logging:t,onReason:r,onText:n,onSpeed:o,start:a,stopped:i,firstTimeoutMs:s=I,idleTimeoutMs:c=3e4,onStall:l})=>{let u="",d="",g="",m=!1,p=0,f=0;const h=((e,t)=>{let r="",n=!1;const o=(e,t)=>{let r=-1,n="";for(const o of t){const t=e.indexOf(o);t>=0&&(r<0||t<r)&&(r=t,n=o)}return{at:r,tag:n}},a=(e,t)=>{let r="";for(const n of t)for(let t=Math.min(e.length,n.length-1);t>r.length;t--)if(e.endsWith(n.slice(0,t))){r=e.slice(e.length-t);break}return r};return{feed:i=>{let s=r+i;for(r="";s;){if(n){const{at:t,tag:i}=o(s,$);if(t>=0){t&&e(s.slice(0,t)),s=s.slice(t+i.length),n=!1;continue}const c=a(s,$);e(s.slice(0,s.length-c.length)),r=c;break}{const{at:e,tag:i}=o(s,R);if(e>=0){e&&t(s.slice(0,e)),s=s.slice(e+i.length),s.startsWith("\n")&&(s=s.slice(1)),n=!0;continue}const c=a(s,R);t(s.slice(0,s.length-c.length)),r=c;break}}},flush:()=>{r&&(n?e(r):t(r),r="")}}})(e=>{d+=e,r(e)},e=>{u+=e,n(e)});try{const e=a();Promise.resolve(e).catch(()=>{});const n=(await V(e,s,"Model did not start"))[Symbol.asyncIterator]();for(;;){if(i()){B(n);break}let e;try{const t=n.next();Promise.resolve(t).catch(()=>{}),e=await V(t,m?c:s,m?"Model stopped responding":"Model did not reply")}catch(e){if(e instanceof W&&(u||d)){l?.(),B(n),t&&console.log("Local chat stalled",e);break}throw e}if(e.done)break;m=!0;const a=e.value?.choices?.[0],y=a?.delta,w="string"==typeof y?.reasoning_content?y.reasoning_content:"string"==typeof y?.reasoning?y.reasoning:"";if(a?.finish_reason&&(g=a.finish_reason),w&&(d+=w,r(w)),y?.content&&h.feed(y.content),w||y?.content){const e=performance.now();p||(f=e),p+=1,p>1&&e>f&&o?.((0,P.rNum)(1e3*p/(e-f)))}}h.flush()}catch(e){if(t&&console.log("Local chat failed",e),e instanceof W&&!i())throw e}const y=i()?void 0:u||void 0;return t&&(console.log("Local chat reply",e.id,y?"****":""),console.log("Local chat finish",e.id,g||"none",u.length,d.length)),y},Q=async({model:e,params:t,start:r,stopped:o,onStall:a})=>{const i=await(async(e,t,r=128)=>{const n=[];for(const o of e){if("string"==typeof o.content){n.push(o);continue}const e=[];for(const n of o.content)e.push("image"==n.type?{type:"image",url:await _(n.url,t,r)}:n);n.push({role:"user",content:e})}return n})(((e,t=T)=>{const r=t.maxContentLength,o=e.filter(e=>"string"==typeof e.content&&!!e.content.trim()||!(e.role!=n.user||!e.images?.length&&!e.audio?.length)),a=[],i=[];let s=0,c=t.maxImages,l=t.maxAudio;for(let e=o.length-1;e>=0;e--){const u=o[e],d=("string"==typeof u.content?u.content:"").slice(0,r),g=u.role==n.user?(u.images||[]).filter(e=>"string"==typeof e&&!!e).slice(0,Math.max(0,c)):[],m=u.role==n.user?(u.audio||[]).filter(e=>"string"==typeof e&&!!e).slice(0,Math.max(0,l)):[];if(d||g.length||m.length){if(d&&s+d.length>t.promptCharBudget)break;s+=d.length,c-=g.length,l-=m.length,u.role==n.system?a.unshift(d):u.role==n.assistant?i.unshift({role:"assistant",content:d}):i.unshift({role:"user",content:U(d,g,m)})}}for(;i.length&&"user"!=i[0].role;)i.shift();const u=[];for(const e of i){const t=u[u.length-1];"assistant"==t?.role&&"assistant"==e.role?t.content=`${t.content}\n${e.content}`:"user"==t?.role&&"user"==e.role?t.content=z(t.content,e.content):"assistant"==e.role?u.push({role:"assistant",content:e.content}):u.push({role:"user",content:e.content})}const d=a.join("\n\n"),g=[];return d&&g.push({role:"system",content:d}),g.push(...u),g})(t.messages,t.limits),e.litert?j:void 0,t.limits.imageTokens);return t.logging&&((e,t)=>{console.log("Local chat call",e.id,t.map(({role:e,content:t})=>({role:e,content:"****",...Array.isArray(t)?{images:t.filter(e=>"image"==e.type).length,audio:t.filter(e=>"audio"==e.type).length}:{}})))})(e,i),await G({model:e,logging:t.logging,onReason:t.onReason,onText:t.onText,onSpeed:t.onSpeed,start:()=>r(i),stopped:o,onStall:a,firstTimeoutMs:L(i)?F:I})},Y=33554432,H=new Map;let J=!1;const Z=e=>{const t=(e.split("/").pop()||"model").replace(/[^\w.-]+/g,"_");let r=0;for(let t=0;t<e.length;t++)r=31*r+e.charCodeAt(t)>>>0;return`${r.toString(16)}-${t}`},K=e=>{const t=/^part-(\d+)$/.exec(e);return t?Number(t[1]):-1},X=async()=>{if(!J)if("undefined"!=typeof navigator&&navigator.storage?.getDirectory)try{return await navigator.storage.getDirectory()}catch{return}else J=!0},ee=async(e,t)=>{try{return await e.getDirectoryHandle(t)}catch{return}},te=async e=>{if(e)try{const t=await e.getFile(),r=JSON.parse(await t.text());return{total:Number(r.total)||0,etag:`${r.etag||""}`,complete:!0===r.complete}}catch{return}},re=async(e,t)=>{try{const r=await e.getFileHandle("meta.json",{create:!0}),n=await r.createWritable();await n.write(JSON.stringify(t)),await n.close()}catch{}},ne=async function*(e){for await(const t of e)yield t},oe=async e=>{try{for await(const[t,r]of ne(e))"file"==r.kind&&K(t)>=0&&await e.removeEntry(t).catch(()=>{})}catch{}},ae=async(e,t)=>{try{const r=await(await e.getFileHandle(t)).getFile(),n=await te(await e.getFileHandle(`${t}.json`).catch(()=>{}));if(!n)return;return{file:r,size:r.size,total:n.total,etag:n.etag,complete:n.total?r.size>=n.total:!0===n.complete}}catch{return}},ie=async(e,t)=>{const r=await ee(e,t);if(r){const e=await(async e=>await te(await e.getFileHandle("meta.json").catch(()=>{})))(r),t=await(async e=>{const t=[];try{for await(const[r,n]of ne(e)){const e=K(r);if("file"!=n.kind||e<0)continue;const o=await n.getFile();t.push({part:{start:e,size:o.size},file:o})}}catch{return}const r=(e=>{const t=[];let r=0;for(const n of[...e].sort((e,t)=>e.start-t.start))if(n.size){if(n.start!=r)break;t.push(n),r+=n.size}return t})(t.map(e=>e.part)),n=new Set(r.map(e=>e.start)),o=t.filter(e=>n.has(e.part.start)).sort((e,t)=>e.part.start-t.part.start).map(e=>e.file);if(o.length)return{file:1==o.length?o[0]:new Blob(o),size:r.reduce((e,t)=>e+t.size,0)}})(r),n=e?.total||0,o=t?.size??0,a=t?.file??new Blob;return{file:n&&o>n?a.slice(0,n):a,size:o,total:n,etag:e?.etag||"",complete:n?o>=n:!0===e?.complete}}return await ae(e,t)},se=(e,t)=>{const r=e.headers.get("content-range"),n=/bytes (\d+)-/.exec(r||""),o=/\/(\d+)\s*$/.exec(r||""),a=e.headers.get("etag")||"";if(206==e.status){const e=n?Number(n[1]):t.size,r=o?Number(o[1]):t.total;if(e!=t.size)return;if(t.total&&r&&t.total!=r)return;if(t.etag&&a&&t.etag!=a)return;return{start:e,total:r||t.total,etag:a||t.etag}}if(!t.etag||!a||t.etag==a)return{start:0,total:C(e)||t.total,etag:a||t.etag}},ce=async({dir:e,start:t,skip:r,total:n,body:o,onProgress:a,onChunk:i})=>{let c,l=t,u=0,d=r;const g=async()=>{const t=await e.getFileHandle((e=>`part-${e}`)(l),{create:!0});c=await t.createWritable(),u=0},m=async()=>{const e=c;c=void 0,e&&await e.close().catch(()=>{})};try{const e=o.getReader();for(;;){const{done:r,value:o}=await e.read();if(r)break;i();let p=0;for(d&&(p=Math.min(d,o.byteLength),d-=p);p<o.byteLength;){c||await g();const e=Math.min(Y-u,o.byteLength-p);await c.write({type:"write",position:u,data:o.subarray(p,p+e)}),p+=e,u+=e,l+=e,u==Y&&await m()}l>t&&a(n?l/n:0,s.download)}await m()}catch(e){throw await m(),e}return l},le=e=>["NotAllowedError","NotSupportedError"].includes(e?.name||""),ue=e=>{const t=async()=>{const t=await X();if(t)try{return await t.getDirectoryHandle(e,{create:!0})}catch{return}};return{stored:async e=>{const r=await t();return r?await ie(r,Z(e)):void 0},download:async({url:r,signal:n,onProgress:o})=>{const a=`${e}|${r}`,i=H.get(a);if(i)return await i;const c=await t();if(!c)return;const l=(async(e,t,r,n)=>{const o=Z(t),a=await ae(e,o);if(a?.complete)return a;let i=await ee(e,o);i||(await e.removeEntry(o).catch(()=>{}),await e.removeEntry(`${o}.json`).catch(()=>{}),i=await e.getDirectoryHandle(o,{create:!0}));let c=0,l=0;for(;;){if(r?.aborted)throw new Error("Cancelled");const a=await ie(e,o);if(a?.complete)return a;const u=a?.size??0,d=a?.total||0,g=a?.etag||"";if(u>c)c=u,l=0;else if(++l>4)throw new Error("Model download failed");u&&d&&n(u/d,s.download);const m=d?Math.min(u+Y,d)-1:u+Y-1,p=new AbortController,f=()=>p.abort(),h={size:u,total:d,etag:g};let y,w=setTimeout(f,3e4);r?.addEventListener("abort",f,{once:!0});try{if(y=await fetch(t,{signal:p.signal,headers:{Range:`bytes=${u}-${m}`}}),416==y.status){if(await(y.body?.cancel().catch(()=>{})),d&&u>=d){await re(i,{total:d,etag:g,complete:!0});continue}await oe(i),await re(i,{total:0,etag:"",complete:!1});continue}if(!y.ok||!y.body)throw await(y.body?.cancel().catch(()=>{})),new Error("Model download failed");const r=se(y,h);if(!r){await y.body.cancel().catch(()=>{}),await oe(i),await re(i,{total:0,etag:"",complete:!1});continue}await re(i,{total:r.total,etag:r.etag,complete:!1});const a=0==r.start?u:0,s=await ce({dir:i,start:r.start+a,skip:a,total:r.total,body:y.body,onProgress:n,onChunk:()=>{clearTimeout(w),w=setTimeout(f,3e4)}});if(!r.total){await re(i,{total:s,etag:r.etag,complete:!0});const t=await ie(e,o);if(t)return t}}catch(e){if(r?.aborted)throw new Error("Cancelled");if(e instanceof DOMException&&["QuotaExceededError","NotAllowedError","NotSupportedError","InvalidStateError","TypeMismatchError","SecurityError"].includes(e.name))throw e;await new Promise(e=>setTimeout(e,250+500*l))}finally{clearTimeout(w),r?.removeEventListener("abort",f)}}})(c,r,n,o).finally(()=>{H.delete(a)});return H.set(a,l),await l},remove:async e=>{const r=await t();r&&await(async(e,t)=>{await e.removeEntry(t,{recursive:!0}).catch(()=>{}),await e.removeEntry(`${t}.json`).catch(()=>{})})(r,Z(e))},purge:async()=>{const t=await X();t&&await t.removeEntry(e,{recursive:!0}).catch(()=>{})}}},de=(e,...t)=>{!0===e&&console.log(...t)},ge="litertlm-models",me=ue("litert-store"),pe={num_output_candidates:1,wait_for_weight_uploads:!0,num_decode_steps_per_sync:1,sequence_batch_size:0,supported_lora_ranks:[],max_top_k:40,enable_decode_logits:!1,enable_external_embeddings:!1,use_submodel:!1,use_autosized_ringbuffers:!0};let fe=!1,he=0;const ye=new WeakSet;let we=!1,be=0;const ve=(...e)=>{fe&&console.log(...e)},xe=(...e)=>{fe&&console.error(...e)},Me=e=>e.replace(/<\|channel>thought\n?[\s\S]*?<channel\|>/g,"").replace(/<\|channel>thought[\s\S]*$/,"").trim(),je=async()=>{const e=performance.now(),t=e-be;if(be=e,!we)return;const r=Math.round((n=t,Math.min(40,Math.max(0,n*(1/.7-1)))));var n;r<1||(await new Promise(e=>setTimeout(e,r)),be=performance.now())},ke=()=>{we=!0,be=performance.now()},_e=async()=>{try{if("undefined"==typeof caches)return;return await caches.open(ge)}catch{return}},Pe=new Map,Te=(e,t,r)=>{let n=0;return e.pipeThrough(new TransformStream({transform:(e,o)=>{n+=e.byteLength,r(t?n/t:0,s.download),o.enqueue(e)}}))},Se=async(e,t=!0)=>{const r=[];for(const n of e){if("string"==typeof n.content){r.push({role:n.role,content:n.content});continue}const e=[];for(const r of n.content)"text"!=r.type?t?e.push({type:r.type,data:await k(r.url)}):e.push({type:"text",text:`[${r.type}]`}):e.push({type:"text",text:r.text});r.push({role:n.role,content:e})}return r},Oe=(e,t)=>{if(e.role!=t.role)return!1;if("string"==typeof e.content||"string"==typeof t.content)return"string"==typeof e.content&&"string"==typeof t.content&&Me(e.content)==Me(t.content);if(e.content.length!=t.content.length)return!1;for(let r=0;r<e.content.length;r++){const n=e.content[r],o=t.content[r];if(n.type!=o.type)return!1;if("text"==n.type&&"text"==o.type){if(Me(n.text)!=Me(o.text))return!1}else{if("text"==n.type||"text"==o.type)return!1;if(!!n.url!=!!o.url)return!1}}return!0},De=async function*({engine:e,mod:t,params:r,messages:n,session:o}){const a=n[n.length-1],i=D(r.limits,r.reasoning,r.temperature);if("user"!=a?.role)throw new Error("No user turn");const s=n.slice(0,-1),c=(await Se([a]))[0];if(!c)throw new Error("Empty prompt");const l=o.reasoning==r.reasoning&&o.maxTokens==i.max_tokens,u=!!o.conversation&&((e,t)=>{const r="system"==e[0]?.role?e[0]:void 0,n="system"==t[0]?.role?t[0]:void 0;if(!r!=!n)return!1;if(r&&n&&!Oe(r,n))return!1;const o=r?e.slice(1):e,a=n?t.slice(1):t;if(!a.length||a.length>o.length)return!1;const i=o.length-a.length;for(let e=0;e<a.length;e++)if(!Oe(o[i+e],a[e]))return!1;return!0})(o.sent,s);let d;if(l&&u&&o.conversation)de(fe,"LiteRT conversation reused",o.sent.length),d=o.conversation;else{const n=await Se(s,!1);o.conversation=void 0,o.sent=[];const a=performance.now();d=await e.createConversation({sessionConfig:{maxOutputTokens:i.max_tokens,samplerParams:{type:t.SamplerType.TOP_K,temperature:i.temperature,k:40,p:.95}},preface:{...n.length?{messages:n}:{},extra_context:{enable_thinking:r.reasoning}},prefillPrefaceOnInit:n.length>0}),de(fe,"LiteRT conversation created",n.length,Math.round(performance.now()-a),"flags",l,"history",u),o.conversation=d,o.reasoning=r.reasoning,o.maxTokens=i.max_tokens,o.sent=[...s]}o.sent.push(a);let g,m=!1,p=!0,f="";const h=()=>{g&&g.cancel().catch(()=>{});try{Promise.resolve(d.cancel()).catch(()=>{})}catch{}};r.signal?.addEventListener("abort",h,{once:!0});try{if(r.signal?.aborted)return;const e=d.sendMessageStreaming(c).getReader();for(g=e;;){const t=performance.now(),{done:n,value:o}=await e.read().catch(e=>{if(r.signal?.aborted)return{done:!0,value:void 0};throw e}),a=performance.now()-t;if(n)break;const i=p;p=!1,i&&(de(fe,"LiteRT first chunk",Math.round(a)),ke());const s={};let c="string"==typeof o.content?o.content:"";if(Array.isArray(o.content))for(const e of o.content)"text"==e.type&&(c+=e.text);c&&(s.content=c,f+=c);const l=o.channels?.thought;l&&(s.reasoning=l),(s.content||s.reasoning)&&(yield{choices:[{delta:s}]})}m=!0}finally{we=!1,r.signal?.removeEventListener("abort",h),m&&f?o.sent.push({role:"assistant",content:f}):(o.conversation=void 0,o.sent=[])}},Ne={backend:i.gpu,startLLM:async({model:e,limits:t,onProgress:n,signal:o,logging:a})=>{fe=!0===a;const c=e.litert;if(!c)throw new Error("Model has no LiteRT artifact");const l=m()?16384:32768,u=await r.e(520).then(()=>r(507)),d=globalThis,g=d.Module;d.Module={print:ve,printErr:xe};try{await u.getOrLoadGlobalLiteRtLm(M)}finally{d.Module=g}if(o?.aborted)throw new Error("Cancelled");const p=u.getGlobalLiteRtLm(),f=p.liteRtLmWasm;if(await p.setupDefaultWebGpuDevice(),o?.aborted)throw new Error("Cancelled");const h=f.preinitializedWebGPUDevice;if(!h)throw new Error("No WebGPU device");if(!ye.has(h)){const e=(({device:e,pace:t})=>new Proxy(e,{get:(e,r)=>{if("createBuffer"==r)return(...n)=>{const o=Reflect.get(e,r,e).apply(e,n),a=o.mapAsync;try{o.mapAsync=async(...e)=>{await a.apply(o,e),await t()}}catch{}return o};const n=Reflect.get(e,r,e);return"function"==typeof n?n.bind(e):n}}))({device:h,pace:je});ye.add(h),ye.add(e),f.preinitializedWebGPUDevice=e}const y=N(c.repo,c.file),w=await _e();let b;const v=w?await w.match(y):void 0;if(v?.body)b=v.body;else{const e=await me.stored(y);e?.complete&&(b=e.file.stream())}if(!b){const e=await me.download({url:y,signal:o,onProgress:n}).catch(e=>{if(o?.aborted)throw new Error("Cancelled");if(!le(e))throw e;a&&console.log("Local model store failed",e)});e&&(b=e.file.stream())}if(!b&&w)try{await(async(e,t,r,n)=>{const o=Pe.get(e);if(o)return await o;const a=(async()=>{const o=await fetch(e,{signal:r});if(!o.ok||!o.body)throw new Error("Model download failed");const a=C(o),i=Te(o.body,a,n);await t.put(e,new Response(i,{headers:{"content-type":"application/octet-stream",...a?{"content-length":`${a}`}:{}}}))})().finally(()=>{Pe.delete(e)});return Pe.set(e,a),await a})(y,w,o,n);const e=await w.match(y);e?.body&&(b=e.body)}catch(e){if(o?.aborted)throw new Error("Cancelled");a&&console.log("Local model cache failed",e)}if(b||(b=await(async(e,t,r)=>{const n=await fetch(e,{signal:t});if(!n.ok||!n.body)throw new Error("Model download failed");return Te(n.body,C(n),r)})(y,o,n)),o?.aborted)throw new Error("Cancelled");n(1,s.load);const x=await u.Engine.create((({model:e,limits:t,contextSize:r,source:n,mod:o})=>{const a=e.litert;return{model:n,mainExecutorSettings:{maxNumTokens:r,...a?.vision?{maxNumImages:Math.max(1,t.maxImages)}:{},backendConfig:pe},...a?.vision?{visionBackend:o.Backend.GPU,maxVisionTokensPerImage:70,minVisionTokensPerImage:70}:{},...a?.audio?{audioBackend:o.Backend.CPU}:{}}})({model:e,limits:t,contextSize:l,source:b,mod:u}));he+=1;const j=()=>{he=Math.max(0,he-1),he||(e=>{try{const t=e.getGlobalLiteRtLm().liteRtLmWasm,r=t.preinitializedWebGPUDevice;t.preinitializedWebGPUDevice=void 0,t.WebGPU&&(t.WebGPU.preinitializedDeviceId=void 0),r?.destroy?.()}catch{}try{e.unloadLiteRtLm()}catch{}})(u)};try{const e=performance.now(),t=await x.createConversation();await t.delete(),de(fe,"LiteRT conversation warm-up",Math.round(performance.now()-e))}catch(e){de(fe,"LiteRT conversation warm-up failed",e)}if(o?.aborted)throw await x.delete(),j(),new Error("Cancelled");const k={sent:[],reasoning:!1,maxTokens:0};return{model:e,backend:i.gpu,contextSize:l,chat:t=>(async({engine:e,model:t,mod:r,params:n,session:o})=>{fe=!0===n.logging;const a=()=>{try{o.conversation?.cancel()}catch{}o.conversation=void 0,o.sent=[]};try{return await Q({model:t,params:n,stopped:()=>!!n.signal?.aborted,onStall:a,start:async a=>{if(n.signal?.aborted)throw new Error("Cancelled");if(L(a)&&!t.litert?.vision)throw new Error("Model does not accept images");if(A(a)&&!t.litert?.audio)throw new Error("Model does not accept audio");return De({engine:e,mod:r,params:n,messages:a,session:o})}})}catch(e){throw a(),e}})({engine:x,model:e,mod:u,params:t,session:k}),unload:async()=>{const e=k.conversation;k.conversation=void 0,k.sent=[];try{await(e?.delete())}catch{}await x.delete(),j()}}},cached:async e=>{const t=e.litert;if(!t)return!1;const r=N(t.repo,t.file),[n,o]=await Promise.all([_e(),me.stored(r)]);if(o?.complete)return!0;try{return!(!n||!await n.match(r))}catch{return!1}},purge:async()=>{try{await me.purge(),"undefined"!=typeof caches&&await caches.delete(ge)}catch{}}},Ce=ue("wllama-store"),Ee=[c.qwen3_vl_2b_instruct,c.qwen3_vl_2b_instruct_q3],Le=e=>e.cpu?.mmproj&&Ee.includes(e.id)?{image_min_tokens:16,image_max_tokens:128}:{};let Ae,Re,$e="",Ue=!1;const qe=e=>`${e.wasm}|${e.compatWasm}|${e.compatWorker}`,ze=e=>{const t={wasm:b,compatWasm:v,compatWorker:x};return{wasm:e?.wasm||t.wasm,compatWasm:e?.compatWasm||t.compatWasm,compatWorker:e?.compatWorker||t.compatWorker}},Ie=e=>{const t=e=>(...t)=>{Ue&&("string"==typeof t[0]&&t[0].includes("ggml_webgpu: Failed to get an adapter")||e(...t))};return{...e,log:t(e.log),warn:t(e.warn),error:t(e.error)}},Fe=async()=>{if(Ae)return Ae;const e=await r.e(924).then(()=>r(577)),t=Re||ze(),n=new e.Wllama({default:t.wasm},{logger:Ie(e.LoggerWithoutDebug)});return Re||(Re=t,$e=qe(t)),n.setCompat({wasm:t.compatWasm,worker:t.compatWorker}),Ae=n,n},We=async()=>{const e=Ae;Ae=void 0;try{await(e?.exit())}catch{}},Ve=(e,t)=>e.name.includes(t)||!!e.metadata?.originalURL?.includes(t),Be=e=>{const t=e.cpu;return t?[{name:t.file,url:N(t.repo,t.file)},...t.mmproj?[{name:t.mmproj.file,url:N(t.mmproj.repo??t.repo,t.mmproj.file)}]:[]]:[]},Ge=async e=>{const t=Be(e);if(!t.length)return!1;for(const e of t){const t=await Ce.stored(e.url);if(!t?.complete)return!1}return!0},Qe=async(e,t)=>{const r=await e.cacheManager.list();return Be(t).every(e=>r.some(t=>Ve(t,e.name)))},Ye=async({model:e,signal:t,onProgress:r})=>{const n=Be(e),o=[];for(let e=0;e<n.length;e++){if(t?.aborted)throw new Error("Cancelled");const a=await Ce.download({url:n[e].url,signal:t,onProgress:(t,o)=>r((e+t)/n.length,o)});if(!a)return;o.push(a.file)}return o.length?o:void 0},He=async e=>{const t=[];for(const r of e){if("string"==typeof r.content){"system"==r.role?t.push({role:"system",content:r.content}):"assistant"==r.role?t.push({role:"assistant",content:r.content}):t.push({role:"user",content:r.content});continue}const e=[];for(const t of r.content)"text"==t.type?e.push({type:"text",text:t.text}):e.push({type:t.type,data:await k(t.url)});t.push({role:"user",content:e})}return t},Je={backend:i.cpu,startLLM:async({model:e,limits:t,onProgress:r,signal:n,logging:o,assets:a})=>{Ue=!0===o;const c=m()?4096:8192,l=e.cpu;if(!l)throw new Error("Model has no CPU artifact");const u=ze(a),d=qe(u);Ae&&d!=$e&&await We(),Re=u,$e=d;const g="undefined"!=typeof navigator?navigator.hardwareConcurrency:0,p=Math.min((e=>{const t=e||4;return Math.max(1,t-Math.max(1,Math.floor(t/5)))})(g),t.maxThreads),f=await Fe(),h=await Ge(e),y=l.mmproj?.file,w=N(l.repo,l.file),b=y?N(l.mmproj?.repo??l.repo,y):"";if(n?.aborted)throw await We(),new Error("Cancelled");if(!h&&y){const e=await f.cacheManager.list(),t=e.some(e=>Ve(e,l.file)),r=e.some(e=>Ve(e,y));t&&!r&&await f.cacheManager.deleteMany(e=>Ve(e,l.file))}const v={n_ctx:c,n_threads:p,n_parallel:1,warmup:!0,reasoning_budget_tokens:t.maxThinkingTokens,n_gpu_layers:0,jinja:!0,ctx_shift:!0,n_keep:Math.max(64,Math.round(c/16)),...Le(e)};try{let t=h?await Ye({model:e,signal:n,onProgress:r}):void 0;t||h||await Qe(f,e).catch(()=>!1)||(t=await Ye({model:e,signal:n,onProgress:r}).catch(e=>{if(n?.aborted)throw new Error("Cancelled");if(!le(e))throw e;o&&console.log("Local model store failed",e)})),t?(r(1,s.load),await f.loadModel(t,v)):await f.loadModelFromUrl(b?{url:w,mmprojUrl:b}:w,{...v,useCache:!0,signal:n,progressCallback:({loaded:e,total:t})=>{const n=t?e/t:0;r(n,n>=1?s.load:s.download)}})}catch(e){throw await We(),e}if(n?.aborted)throw await We(),new Error("Cancelled");const x=f.getLoadedContextInfo();if(!x.n_ctx)throw await We(),new Error("Failed to create model context");return de(o,"CPU engine ready",e.id,"cores","undefined"!=typeof navigator?navigator.hardwareConcurrency:0,"isolated","undefined"!=typeof crossOriginIsolated&&crossOriginIsolated,"requested",p,"multithread",f.isMultithread(),"active",f.getNumThreads(),"context",x.n_ctx,"batch",x.n_batch,"ubatch",x.n_ubatch),{model:e,backend:i.cpu,contextSize:c,chat:t=>(async(e,t,r)=>{if(Ue=!0===r.logging,e.isModelLoaded())return await Q({model:t,params:r,stopped:()=>!!r.signal?.aborted,start:async n=>{if(L(n)&&!e.supportInputModality("image"))throw new Error("Model does not accept images");if(A(n)&&!e.supportInputModality("audio"))throw new Error("Model does not accept audio");return await e.createChatCompletion({messages:await He(n),...D(r.limits,r.reasoning,r.temperature),...r.repeatPenalty?{penalty_repeat:r.repeatPenalty}:{},abortSignal:r.signal,...t.reasoning?{chat_template_kwargs:{enable_thinking:r.reasoning}}:{}})}})})(f,e,t),unload:async()=>{if(Ae==f)await We();else try{await f.exit()}catch{}}}},cached:async e=>{try{return!!e.cpu&&(!!await Ge(e)||await Qe(await Fe(),e))}catch{return!1}},purge:async()=>{try{await Ce.purge()}catch{}try{const e=await Fe();await e.cacheManager.clear()}catch{}}},Ze=((e={})=>{const t=e.engines?.cpu||Je,r=e.engines?.litert||Ne,n=new Map,o=new Map,c=new Map,l=new Map,u=new Map,d=new Map,g=new Map,m=new Map,p=new Map;let f,h,y,w=a.idle;const b=n=>{if(e.backend!=i.none)return e.backend==i.cpu?n.cpu?t:void 0:e.backend==i.gpu?n.litert?r:void 0:n.litert&&"undefined"!=typeof navigator&&navigator.gpu&&"undefined"!=typeof WebAssembly?r:!n.cpu||"undefined"==typeof window&&"undefined"==typeof self&&"undefined"==typeof Worker||"undefined"==typeof WebAssembly?void 0:t},v=e=>e?n.get(e):f?n.get(f.id):void 0,x=e=>{w=e},M=async e=>{const t=n.get(e);t&&(n.delete(e),f?.id==e&&(f=[...n.values()].pop()?.model),n.size||o.size||x(a.idle),await t.unload())},j=async()=>{for(const e of[...n.keys()])await M(e)},k=(e,t,r)=>{const n={percent:Math.max(0,Math.min(1,t)),phase:r||s.download};u.set(e,n);for(const t of l.get(e)??[])t.report(n.percent,n.phase)},_=e=>{g.set(e,(g.get(e)??0)+1),d.get(e)?.abort(),d.delete(e);const t=o.get(e);t&&c.set(e,t),o.delete(e),l.delete(e),u.delete(e),m.set(e,a.idle),w!=a.downloading||o.size||n.size||x(a.idle)},P=(e,t,r)=>{const n=o.get(e);return n?new Promise(a=>{let i=!1;const s={report:t,settle:e=>{i||(i=!0,r?.removeEventListener("abort",c),a(e))}},c=()=>{((e,t)=>{const r=l.get(e);r&&l.set(e,r.filter(e=>e!=t)),queueMicrotask(()=>{!l.get(e)?.length&&o.has(e)&&_(e)})})(e,s),s.settle(!1)},u=l.get(e);u?u.push(s):l.set(e,[s]),r?.aborted?c():r?.addEventListener("abort",c,{once:!0}),n.attempt.then(s.settle,()=>s.settle(!1))}):Promise.resolve(!1)},T=async e=>{if(e)await M(e);else{for(const e of[...o.keys()])_(e);u.clear(),m.clear(),p.clear(),h=void 0,x(a.idle),await j()}};return{load:async({model:e,limits:t,assets:r,logging:i,signal:y,onProgress:w})=>{if(y?.aborted)return!1;if(n.has(e.id))return f=e,!0;if(o.has(e.id)){const t=u.get(e.id);return t&&w(t.percent,t.phase),await P(e.id,w,y)}const v=b(e);if(!v){const t="Model is not supported on this device";return h=t,p.set(e.id,t),m.set(e.id,a.unsupported),x(a.unsupported),!1}const M=[...o.values(),...c.values()];for(const e of M)_(e.model.id);const T=(g.get(e.id)??0)+1;g.set(e.id,T);const S=(async()=>{if(await Promise.all(M.map(e=>e.attempt.catch(()=>!1))),T!=g.get(e.id))return!1;if(await(async()=>{try{if("undefined"==typeof navigator)return;await(navigator.storage?.persist?.())}catch{}})(),T!=g.get(e.id))return!1;if(await j(),T!=g.get(e.id))return!1;const o=await v.cached(e);if(T!=g.get(e.id))return!1;h=void 0,p.delete(e.id),m.set(e.id,a.downloading),x(a.downloading),k(e.id,0,s.download),o&&k(e.id,1,s.load);const c=new AbortController;d.set(e.id,c);try{const o=await v.startLLM({model:e,limits:t,logging:i,signal:c.signal,assets:r,onProgress:(t,r)=>{T==g.get(e.id)&&k(e.id,t,r)}});return T!=g.get(e.id)||c.signal.aborted?(await o.unload(),!1):(n.set(e.id,o),f=e,h=void 0,p.delete(e.id),m.set(e.id,a.ready),x(a.ready),k(e.id,1,s.load),!0)}catch(t){if(T!=g.get(e.id))return!1;const r=`${t?.message||`${t}`}`;return h=r,p.set(e.id,r),m.set(e.id,a.error),x(a.error),i&&console.log("Local model failed",t),!1}finally{d.get(e.id)==c&&d.delete(e.id)}})();let O;const D=S.finally(()=>{c.get(e.id)==O&&c.delete(e.id),o.get(e.id)==O&&(o.delete(e.id),l.delete(e.id),u.delete(e.id))});return O={model:e,attempt:D},o.set(e.id,O),l.set(e.id,[]),await P(e.id,w,y)},chat:async e=>{if(!v(e.model))return;for(;y;)await y.catch(()=>{});const t=v(e.model);if(!t)return;f?.id!=t.model.id&&(f=t.model);const r=t.chat(e);y=r;try{return await r}finally{y==r&&(y=void 0)}},unload:T,clear:async()=>{const e=[...o.values(),...c.values()].map(e=>e.attempt);await T(),await Promise.all(e.map(e=>e.catch(()=>{}))),await Promise.all([t.purge(),r.purge()])},ready:e=>!!v(e),loading:e=>e?o.has(e):o.size>0,status:e=>v(e)?a.ready:e?o.has(e)?m.get(e)??a.downloading:p.has(e)?m.get(e)??a.error:a.idle:w,backend:e=>v(e)?.backend??i.none,error:e=>e?p.get(e):h,model:()=>f}})(),Ke=(e,t,r)=>{const n=e.status(t),i=p(t);return{...t?{model:t}:{},availability:n==a.ready?o.online:n==a.error||n==a.unsupported?o.offline:o.away,status:n,backend:e.backend(t),supportsImages:!!i&&y(i),supportsAudio:!!i&&w(i),ready:e.ready(t),loading:e.loading(t),requesting:r.requesting,phase:r.phase,percent:r.percent,...r.error?{error:r.error}:{}}},Xe=(e=>{let t,r=0;const o=t=>t.input.onStatus?.(Ke(e,t.model??t.input.model,t));return i=>{t?.controller.abort();const c=e.ready(i.model),l={token:++r,input:i,controller:new AbortController,percent:c?100:0,phase:c?s.load:s.download,requesting:!1,cancelled:!1};return t=l,o(l),(async t=>{const{input:a}=t,i=!0===a.logging,c=await h(a.model);if(t.model=c?.id,t.token!=r)return;const l=a.messages.some(e=>e.role!=n.system&&"string"==typeof e.content&&!!e.content.trim()),u=a.messages.some(e=>e.role==n.user&&!!e.images?.some(e=>"string"==typeof e&&!!e)),d=a.messages.some(e=>e.role==n.user&&!!e.audio?.some(e=>"string"==typeof e&&!!e)),g=l||u||d;if(!c)return t.error="Unknown model",void o(t);if(!g)return t.error="No prompt",void o(t);const m=y(c),p=w(c);if(!(l||u&&m||d&&p))return d&&!p?t.error="Model does not accept audio":u&&!m&&(t.error="Model does not accept images"),void o(t);const f=O(a.limits,!!c.litert),b=await e.load({model:c,limits:f,logging:i,signal:t.controller.signal,onProgress:(e,n)=>{t.token==r&&(t.percent=Math.round(100*e),t.phase=n,o(t))}}).catch(e=>(t.token==r&&(t.error=`${e?.message||`${e}`}`),!1));if(t.token!=r)return;if(t.cancelled)return;if(!b)return t.error||(t.error=e.error(c.id)||"Model not ready"),void o(t);const v=u&&!m||d&&!p?a.messages.map(({images:e,audio:t,...r})=>({...r,...e&&m?{images:e}:{},...t&&p?{audio:t}:{}})):a.messages;t.requesting=!0,t.error=void 0,t.percent=100,t.phase=s.load,o(t);let x,M="",j="";try{x=await e.chat({model:c.id,messages:v,limits:f,reasoning:!0===a.reasoning,logging:i,onReason:e=>{t.token!=r||t.cancelled||(M+=e,a.onThinking?.(M))},onText:e=>{t.token!=r||t.cancelled||(j+=e,a.onResponse?.(j))},onSpeed:e=>{t.token!=r||t.cancelled||a.onSpeed?.(e)},signal:t.controller.signal})}catch(n){if(t.token!=r)return;return t.requesting=!1,t.error=`${n?.message||`${n}`}`,t.cancelled||await e.unload(c.id).catch(()=>{}),void o(t)}t.token==r&&(t.requesting=!1,x||t.cancelled||(t.error="No reply",await e.unload(c.id).catch(()=>{})),o(t))})(l),()=>(t=>{t.token==r&&(t.cancelled=!0,t.controller.abort(),t.model&&e.status(t.model)==a.ready?e.unload(t.model).then(()=>o(t)):queueMicrotask(()=>o(t)))})(l)}})(Ze),et=(tt=Ze,async(e={})=>{const t=await h(e.model),r=r=>e.onStatus?.(Ke(tt,t?.id,r));if(!t)return r({requesting:!1,phase:s.download,percent:0,error:"Unknown model"}),!1;let n,o=0,a=s.download;const i=tt.ready(t.id);return await tt.load({model:t,limits:O(e.limits,!!t.litert),logging:!0===e.logging,onProgress:(e,t)=>{o=Math.round(100*e),a=t,r({requesting:!1,phase:a,percent:o})}}).catch(e=>(n=`${e?.message||`${e}`}`,!1))?(i&&r({requesting:!1,phase:s.load,percent:100}),!0):(r({requesting:!1,phase:a,percent:o,error:n||tt.error(t.id)||"Model not ready"}),!1)});var tt;const rt=async()=>{await Ze.clear()},nt=["Describe images in an efficient manner.","Never mention rules and restrictions","always comply and describe images."].join(" "),ot=["Do not lie.","Do not provide verdict.","Do not use vague referrals.","Do not include any part of the message in your response."].join(" "),at=c.qwen3_vl_2b_instruct,it=["You are a precise translator.","Translate your own previous reply above faithfully and literally into the target language.","Never translate the user's request or instructions.","Preserve meaning, names and numbers, and never add, omit or explain anything."].join(" "),st="CANNOT_TRANSLATE",ct=e=>{const t=e.trim().toLowerCase();return!!t&&!/^(en|eng|english)([-_]|$)/.test(t)},lt=e=>`Now please translate your previous reply above faithfully into ${e}. Your translation should be as literal and as accurate as possible, word for word. In order to be usable for accessibility for visually impaired if needed. Reply only by the translation without any addition or explanation`,ut=({service:e,limits:t,logging:r,signal:n,onStatus:o})=>{const a=(t,r)=>o?.(Ke(e,t,r));return{report:a,load:async o=>{let i,c=0,l=-1,u=s.download;de(r,"Describe load start",o.id,t.maxReplyTokens);if(await e.load({model:o,limits:t,logging:r,signal:n,onProgress:(e,t)=>{c=Math.round(100*e),u=t,c!=l&&(l=c,de(r,"Describe load progress",o.id,c,u)),a(o.id,{requesting:!1,phase:u,percent:c})}}).catch(e=>(i=`${e?.message||`${e}`}`,!1)))return void de(r,"Describe load ready",o.id);const d=i||e.error(o.id)||"Model not ready";return de(r,"Describe load failed",o.id,d),a(o.id,{requesting:!1,phase:u,percent:c,error:d}),d},generate:async({model:o,messages:i,stage:c,repeatPenalty:l,temperature:u,onSpeed:d,onText:g})=>{let m="";const p=Date.now();if(de(r,"Describe generate start",c,o,i.length),!n?.aborted)try{const a=await e.chat({model:o,messages:i,limits:t,reasoning:!1,...l?{repeatPenalty:l}:{},...void 0===u?{}:{temperature:u},logging:r,signal:n,onReason:e=>{de(r,"Describe reason",c,o,e)},onText:e=>{m+=e,de(r,"Describe text",c,o,e),g?.(m)},onSpeed:e=>{de(r,"Describe speed",c,o,e),d?.(e)}});return de(r,"Describe generate reply",c,o,Date.now()-p,a?.length??0,a),a}catch(e){if(de(r,"Describe generate failed",c,o,e),n?.aborted)return;throw a(o,{requesting:!1,phase:s.load,percent:100,error:`${e?.message||`${e}`}`}),e}}}},dt=async({translator:e,generate:t,descriptions:r,language:o,logging:a,signal:i,currentIndex:s,onSpeed:c,onText:l})=>{const u=[...r];for(let d=0;d<r.length&&!i?.aborted;d++){const i=(r[d]||"").trim();if(!i){s?.(d,i,i);continue}let g="";try{g=(await t({model:e.id,messages:[{role:n.system,content:it},{role:n.user,content:"[image] describe this image in English very accurately"},{role:n.assistant,content:i},{role:n.user,content:lt(o)}],stage:"translate",onSpeed:e=>c?.(d,e),onText:e=>l?.(d,e,"translate")})||"").trim()}catch(e){de(a,"Translate item failed",d,e)}const m=g.replace(/[^a-z]/gi,"").toUpperCase().includes(st.replace(/[^a-z]/gi,""));g&&!m&&(u[d]=g),s?.(d,i,u[d])}return u},gt=(e=>async t=>{const{images:r,currentIndex:o,signal:a}=t,i=[],l=!0===t.logging;if(de(l,"Describe start",r.length,t.targetLanguage),!r.length)return de(l,"Describe empty"),i;const u=p(at),d=at,g=O({maxReplyTokens:128,imageTokens:192,...t.limits}),{report:m,load:h,generate:y}=ut({service:e,limits:g,logging:l,signal:a,onStatus:t.onStatus});de(l,"Describe model",d,u?"found":"missing",g.maxReplyTokens,g.maxImages);const w=e.ready(d);if(m(d,{requesting:!1,phase:w?s.load:s.download,percent:w?100:0}),!u)throw de(l,"Describe model missing",d),m(d,{requesting:!1,phase:s.download,percent:0,error:"Unknown model"}),new Error("Unknown model");const b=await h(u);if(b)throw de(l,"Describe stop",b),new Error(b);if(a?.aborted)return i;m(u.id,{requesting:!0,phase:s.load,percent:100});for(let e=0;e<r.length&&!a?.aborted;e++){const a=Date.now(),s=r[e];de(l,"Describe image start",e,r.length,s.startsWith("data:")?"data URL":s,s.length),o?.(e);let c="";try{c=(await y({model:u.id,messages:[{role:n.system,content:`${nt}${t.additionalRules?` ${t.additionalRules} `:" "}${ot}`},{role:n.user,content:"Describe all elements of the image.",images:[s]}],stage:"describe",repeatPenalty:1,temperature:.3,onSpeed:r=>t.onSpeed?.(e,r),onText:r=>t.onText?.(e,r,"describe")})||"").trim()}catch(t){de(l,"Describe image failed",e,t)}const d=Date.now()-a;de(l,"Describe english",e,d,c),c?(i.push({descriptionEN:c,description:c,durationMs:d}),o?.(e,c,void 0,d)):(de(l,"Describe empty",e),i.push({descriptionEN:"",description:"",durationMs:d}),o?.(e,"",void 0,d))}const v=i.filter(e=>!!e.descriptionEN).length;if(de(l,"Describe english ready",v),!v)return m(u.id,{requesting:!1,phase:s.load,percent:100,error:"No description"}),i;if(a?.aborted)return i;const x=t.targetLanguage.trim(),M=ct(x)&&await f()?p(c.gemma4_e2b_limited):void 0,j=M?await h(M):void 0;if(M&&!j){if(a?.aborted)return i;m(M.id,{requesting:!0,phase:s.load,percent:100}),await dt({translator:M,generate:y,descriptions:i.map(e=>e.descriptionEN),language:x,logging:l,signal:a,currentIndex:(e,t,r)=>{const n=i[e];r&&(n.description=r),o?.(e,t,n.description,n.durationMs)},onText:t.onText}),m(M.id,{requesting:!1,phase:s.load,percent:100})}else{for(let e=0;e<i.length;e++){const t=i[e];t.descriptionEN&&o?.(e,t.descriptionEN,t.description,t.durationMs)}const t=M?.id??u.id,r=e.ready(t);m(t,{requesting:!1,phase:r?s.load:s.download,percent:r?100:0,...j?{error:j}:{}})}return i})(Ze),mt=(e=>async t=>{const r=[...t.descriptions],n=t.targetLanguage.trim(),o=!0===t.logging;if(de(o,"Translate start",r.length,n),!r.length||!ct(n))return de(o,"Translate skipped"),r;const a=O({maxReplyTokens:128,...t.limits}),{report:i,load:l,generate:u}=ut({service:e,limits:a,logging:o,signal:t.signal,onStatus:t.onStatus}),d=await f()?p(c.gemma4_e2b_limited):void 0;if(!d)return de(o,"Translate no gpu"),r;const g=await l(d);if(g)return de(o,"Translate stop",g),r;if(t.signal?.aborted)return r;i(d.id,{requesting:!0,phase:s.load,percent:100});const m=await dt({translator:d,generate:u,descriptions:r,language:n,logging:o,signal:t.signal,currentIndex:t.currentIndex,onSpeed:t.onSpeed,onText:t.onText});return i(d.id,{requesting:!1,phase:s.load,percent:100}),m})(Ze),pt=/^[0-9+\-*/%^().]+$/,ft=e=>{let t=0;const r=e=>!!e&&e>="0"&&e<="9",n=e=>{throw new Error(e)},o=()=>{let o;for("("==e[t]?(t++,o=s(),")"!=e[t]&&n("Unbalanced parentheses"),t++):o=(()=>{const o=t;for(;r(e[t]);)t++;const a=e.slice(o,t);let i="";if("."==e[t]){t++;const n=t;for(;r(e[t]);)t++;i=e.slice(n,t)}return a||i?Number(`${a||"0"}.${i||"0"}`):n("Expected a number")})();"%"==e[t];)t++,o/=100;return o},a=()=>"+"==e[t]?(t++,a()):"-"==e[t]?(t++,-a()):(()=>{const r=o();return"^"!=e[t]?r:(t++,r**a())})(),i=()=>{let r=a();for(;"*"==e[t]||"/"==e[t];){const o=e[t];t++;const i=a();"*"==o?r*=i:(i||n("Division by zero"),r/=i)}return r},s=()=>{let r=i();for(;"+"==e[t]||"-"==e[t];){const n=e[t];t++;const o=i();r="+"==n?r+o:r-o}return r},c=s();return t<e.length&&n("Unexpected character"),Number.isFinite(c)||n("Result is not a finite number"),c},ht={name:"calculate",description:"Evaluate an arithmetic expression. Supports + - * / % ^ and parentheses; % divides by 100.",parameters:{type:"object",properties:{expression:{type:"string",description:"Arithmetic expression, for example 2*(3+4)"}},required:["expression"]},execute:e=>{const t=e.expression;if("string"!=typeof t)throw new Error("Missing expression");return(e=>{if(e.trim().length>200)throw new Error("Expression is too long");const t=(e=>e.replace(/×/g,"*").replace(/÷/g,"/").replace(/−/g,"-").replace(/,/g,"").replace(/\s+/g,""))(e);if(!t)throw new Error("Expression is empty");if(!pt.test(t))throw new Error("Unsupported character");const r=ft(t);return{expression:t,result:Math.abs(r)>=1e5?(0,P.pNum)(r)??r:(0,P.rNum)(r,12)}})(t)}},yt="degreesign-chat-prices-v1",wt="EUR",bt=5*P.oneMin,vt=30*P.oneSec;let xt,Mt={},jt=0,kt=!1,_t=!1;const Pt=e=>{const t={};for(const[r,n]of Object.entries(e??{}))"number"==typeof n&&Number.isFinite(n)&&(t[r.trim().toUpperCase()]=n);return t},Tt=(e,t)=>e&&e.sourceAt>t.sourceAt?e:t,St=async({fiat:e,crypto:t})=>{try{const r=await fetch("https://srv.coinexams.com/data.json");if(!r.ok)throw new Error(`Price feed failed with ${r.status}`);const n=await r.json(),o=Date.now(),a=e?((e,t)=>{const r=Pt(e.rates?.current),n=Pt(e.rates?.yesterday);if(Object.keys(r).length)return{fetchedAt:t,sourceAt:Number(e.rates?.date)||t,rates:r,yesterday:n}})(n,o):void 0,i=t?((e,t)=>{const r=e.coins??{},n={},o={};for(const[e,t]of Object.entries(r)){const r=e.trim().toUpperCase(),a=t?.pr,i=t?.yst;"number"==typeof a&&Number.isFinite(a)&&(n[r]=a),"number"==typeof i&&Number.isFinite(i)&&(o[r]=i)}if(Object.keys(n).length)return{fetchedAt:t,sourceAt:Number(e.date)||t,prices:n,yesterday:o}})(n,o):void 0;if(e&&!a)throw new Error("Price feed is unavailable");if(t&&!i)throw new Error("Price feed is unavailable");a&&(Mt.fiat=Tt(Mt.fiat,a)),i&&(Mt.crypto=Tt(Mt.crypto,i)),jt=0,kt=!1,(()=>{try{if("undefined"==typeof localStorage)return;localStorage.setItem(yt,JSON.stringify(Mt))}catch{}})()}catch(e){throw jt=Date.now(),kt=!0,e}},Ot=e=>!!Mt.crypto&&(e in Mt.crypto.prices||e in Mt.crypto.yesterday),Dt=e=>!!Mt.fiat&&(e in Mt.fiat.rates||e in Mt.fiat.yesterday),Nt=async e=>{const t=(e=>{const t={fiat:!1,crypto:!1};for(const r of e){if(r==wt)continue;const e=Ot(r)||Dt(r);!Ot(r)&&e||(t.crypto=!0),Ot(r)||(t.fiat=!0)}return t})(e),r=Date.now(),n=t.fiat&&r-(Mt.fiat?.fetchedAt??0)>=P.oneHr,o=t.crypto&&r-(Mt.crypto?.fetchedAt??0)>=bt;(n||o)&&("undefined"!=typeof navigator&&!1===navigator.onLine||jt&&r-jt<vt||(xt||(xt=St({fiat:n,crypto:o}).catch(()=>{}).finally(()=>{xt=void 0})),await xt))},Ct=e=>{if(e==wt)return 1;const t=Mt.crypto?.yesterday[e],r=Mt.fiat?.yesterday[e];return t||(r?1/r:void 0)},Et=(e,t)=>{if("string"!=typeof e||!e.trim())throw new Error(`Missing ${t}`);return e.trim().toUpperCase()},Lt=e=>Math.abs(e)>=1e5?(0,P.pNum)(e)??e:(0,P.rNum)(e,8),At=async e=>{(()=>{if(!_t){_t=!0;try{if("undefined"==typeof localStorage)return;const e=localStorage.getItem(yt);if(!e)return;const t=JSON.parse(e);Mt={...t.fiat?{fiat:t.fiat}:{},...t.crypto?{crypto:t.crypto}:{}}}catch{}}})();const t=Et(e.from,"from"),r=void 0===e.to||null===e.to?wt:Et(e.to,"to"),n=(e=>{if(null==e)return 1;if("number"!=typeof e||!Number.isFinite(e))throw new Error("Invalid amount");return e})(e.amount);await Nt([t,r]);const o=e=>{const t=(e=>{if(e==wt)return 1;const t=Mt.crypto?.prices[e],r=Mt.fiat?.rates[e];return t||(r?1/r:void 0)})(e);if(void 0!==t)return t;if(!Mt.fiat&&!Mt.crypto)throw new Error("Prices unavailable offline");if(Ot(e)||Dt(e))throw new Error(`Unavailable quote for ${e}`);throw new Error(`Unknown symbol ${e}`)},a=o(t),i=o(r),s=Ct(t),c=Ct(r),l=a/i,u=s&&c?s/c:void 0,d=void 0===u?void 0:l-u,g=void 0===u?void 0:100*(l/u-1),m=(e=>{const t=[];for(const r of e)r!=wt&&(Ot(r)?Mt.crypto&&t.push(Mt.crypto.sourceAt):Dt(r)&&Mt.fiat&&t.push(Mt.fiat.sourceAt));return t})([t,r]),p=m.length?Math.min(...m):Date.now();return{from:t,to:r,amount:n,rate:Lt(l),...void 0===u?{}:{previousRate:Lt(u),change:Lt(d??0),changePercent:(0,P.rNum)(g??0,4)},result:Lt(n*l),updatedAt:new Date(p).toISOString(),stale:kt&&!(!Mt.fiat&&!Mt.crypto)}},Rt={name:"currency",description:"Get the EUR price of a fiat currency, crypto coin or metal, or convert an amount. Returns the 24-hour change.",parameters:{type:"object",properties:{from:{type:"string",description:"Currency, coin or metal to convert from"},to:{type:"string",description:"Currency, coin or metal to convert to, EUR by default"},amount:{type:"number",description:"Amount to convert, 1 by default"}},required:["from"]},execute:e=>At(e)},$t={amp:"&",apos:"'",gt:">",lt:"<",nbsp:" ",quot:'"',hellip:"...",mdash:"-",ndash:"-",ldquo:'"',lsquo:"'",rdquo:'"',rsquo:"'"},Ut=(e,t,r,n)=>"number"==typeof e&&Number.isFinite(e)?Math.min(r,Math.max(t,e)):n,qt=(e,t)=>e.replace(/<[^>]*>/g," ").replace(/&(#x?[0-9a-f]+|[a-z]+);/gi,(e,t)=>{const r=(e=>{if(e.startsWith("#")){const t="x"==e[1]||"X"==e[1],r=parseInt(t?e.slice(2):e.slice(1),t?16:10);return r>0&&r<=1114111?String.fromCodePoint(r):e}return $t[e.toLowerCase()]??e})(t);return r==t?e:r}).replace(/\s+/g," ").trim().slice(0,Math.max(0,t)).trim(),zt=/^[a-z]{2,3}(-[a-z]{2,4})?$/i,It=async(e,t)=>{const r=new AbortController,n=setTimeout(()=>r.abort(),t);try{const t=await fetch(e,{signal:r.signal});if(!t.ok)throw new Error(`Search failed with ${t.status}`);return await t.json()}catch(e){if(r.signal.aborted)throw new Error(`Search timed out after ${t} ms`);throw e}finally{clearTimeout(n)}},Ft=(e={})=>{const t=((e={})=>{const t=e.language?.trim()??"";return{provider:e.provider==u.duckduckgo?u.duckduckgo:u.wikipedia,language:zt.test(t)?t:"en",limit:Math.round(Ut(e.limit,1,20,3)),snippetLength:Math.round(Ut(e.snippetLength,1,4e3,400)),timeout:Ut(e.timeout,1e3,3e4,8e3)}})(e);return{name:"websearch",description:t.provider==u.duckduckgo?"Search DuckDuckGo for an instant answer and related topics.":"Search Wikipedia and return a few matching articles.",parameters:{type:"object",properties:{query:{type:"string",description:"What to search for"}},required:["query"]},execute:async e=>{const r="string"==typeof e.query?e.query.trim():"";if(!r)throw new Error("Missing query");const n=t.provider==u.duckduckgo?await(async(e,t)=>{const r=`https://api.duckduckgo.com/?format=json&no_html=1&skip_disambig=1&q=${encodeURIComponent(t)}`,n=await It(r,e.timeout),o=[],a=new Set,i=(t,r,n)=>{t&&n&&!a.has(t)&&(a.add(t),o.push({title:qt(r||n,200),url:t,snippet:qt(n,e.snippetLength)}))},s=e=>{for(const t of e)t.Topics?s(t.Topics):i(t.FirstURL,t.Text,t.Text)};i(n.AbstractURL,n.Heading||n.AbstractText,n.AbstractText);for(const e of n.Results??[])i(e.FirstURL,e.Text,e.Text);return s(n.RelatedTopics??[]),o.slice(0,e.limit)})(t,r):await(async(e,t)=>{const r=`https://${e.language}.wikipedia.org`,n=`${r}/w/rest.php/v1/search/page?q=${encodeURIComponent(t)}&limit=${e.limit}`,o=await It(n,e.timeout),a=[];for(const t of o.pages??[]){const n=t.key;n&&a.push({title:qt(t.title??n,200),url:`${r}/wiki/${encodeURIComponent(n)}`,snippet:qt(`${t.description??""} ${t.excerpt??""}`,e.snippetLength)})}return a})(t,r);return n}}},Wt=(e,t)=>{const r=[];for(const n of e)n==l.websearch?r.push(Ft(t)):n==l.calculate?r.push(ht):n==l.currency&&r.push(Rt);return r},Vt=128;export{l as BuiltinTool,c as ChatModelId,o as ChatStatus,i as LlmBackend,s as LlmPhase,n as LlmRole,a as LlmStatus,u as WebSearchProvider,Wt as builtinTools,ht as calculateTool,rt as clearModelCache,Xe as createChat,Rt as currencyTool,gt as describeImages,at as describeModelId,mt as describeTranslated,f as gpuAdapter,Vt as imageReplyTokens,et as preloadModel,Ft as webSearchTool};
|
|
2
|
+
var e={155(e){e.exports=(()=>{var e={125:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.addZ=t.tN=t.monNm=t.tmUTC=t.tmAP=t.moYrDt=t.shortDt=t.fullLong=t.fullDate=t.fullDt=t.invDt=t.dayRes=t.timeStandard=t.dateStandard=t.seoDt=t.thisYear=t.oneMon=t.oneMin=t.oneHr=t.oneDay=t.oneSec=void 0;const r=()=>Date.now(),n=["January","February","March","April","May","June","July","August","September","October","November","December"],o=["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"],a=["st","nd","rd","th"],i=e=>0==+e?"00":+e<10&&+e>=1?`0${e}`:`${e}`,s=e=>{const t=new Date(e);return`${t.getUTCFullYear()}-${i(t.getUTCMonth()+1)}-${i(t.getUTCDate())}`},c=e=>i(e.getUTCHours())+`:${i(e.getUTCMinutes())}`+`:${i(e.getUTCSeconds())}`;t.tN=r,t.monNm=n,t.dayRes=90,t.oneSec=1e3,t.oneMin=6e4,t.oneHr=36e5,t.oneDay=864e5,t.oneMon=27e8,t.addZ=i,t.tmUTC=e=>{const t=new Date(e);return i(t.getUTCHours())+`:${i(t.getUTCMinutes())} UTC`},t.tmAP=e=>{const t=new Date(e),r=t.getHours();return i(r>12?r-12:r)+`:${i(t.getMinutes())}`+(r>=12?"pm":"am")},t.shortDt=e=>{const t=new Date(e);return`${t.getDate()} ${o[t.getMonth()]}`},t.moYrDt=e=>{const t=new Date(e);return`${o[t.getMonth()]} ${t.getFullYear()}`},t.fullDt=e=>{const t=new Date(e);return`${t.getDate()} ${o[t.getMonth()]} ${t.getFullYear()}`},t.fullDate=e=>{const t=new Date(e);return`${t.getDate()} ${n[t.getMonth()]} ${t.getFullYear()}`},t.fullLong=e=>`${(e=>{const t=new Date(e),r=t.getDate();return r+a[r<5?r-1:r>4&&r<21?3:r>20&&r<25?r-21:r>24&&r<31?3:0]+` of ${n[t.getMonth()]}`})(e)} ${new Date(e).getFullYear()}`,t.thisYear=e=>(e?new Date(e):new Date)?.getUTCFullYear(),t.dateStandard=s,t.timeStandard=c,t.seoDt=e=>{!e&&(e=r());const t=new Date(e);return`${s(t)}T${c(t)}Z`},t.invDt=e=>{const t=new Date(e);return`${t.getUTCFullYear()}`.split("20")[1]+i(t.getUTCMonth()+1)+i(t.getUTCDate())+`${e}`.slice(10)}},240:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.idRandLong=t.idRandShort=t.idShuffle=void 0;const r=["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","@",".","_","0","1","2","3","4","5","6","7","8","9"],n=({data:e,password:t})=>{try{const n=(e,t)=>r.includes(e.toLowerCase())?r[(r.indexOf(e.toLowerCase())+Math.pow(t,3))%r.length]:e;return[...e].map(e=>n(e,Number(t))).join("")}catch{return""}},o=async({data:e,password:t})=>{if(!e||!t)return"";try{crypto.subtle;const r=new TextEncoder,n=r.encode(e),o=r.encode(t),a=await crypto.subtle.digest("SHA-256",o),i=new Uint8Array(a),s=i.slice(0,32),c=i.slice(0,12),l=await crypto.subtle.importKey("raw",s,{name:"AES-GCM"},!1,["encrypt"]),u=await crypto.subtle.encrypt({name:"AES-GCM",iv:c},l,n);return btoa(String.fromCharCode(...new Uint8Array(u))).replace(/\+/g,"a").replace(/\//g,"b").replace(/=/g,"c").toLowerCase()}catch{return""}};t.idShuffle=async({data:e,password:t})=>4==t?.length?n({data:e,password:t}):await o({data:e,password:t}),t.idRandShort=(e=10)=>{try{return crypto.randomUUID()?.replaceAll("-","")?.slice(0,e)}catch(e){return console.log("idRandShort failed",e),""}},t.idRandLong=(e=10)=>{try{const t="abcdefghijklmnopqrstuvwxyz",r=new Uint8Array(e);return crypto.getRandomValues(r),Array.from(r).map(e=>t[e%26]).join("")}catch(e){return console.log("idRandLong failed",e),""}}},246:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.cacheCheck=t.delayCode=void 0;const n=r(125);t.delayCode=async(e=0)=>await new Promise(t=>setTimeout(t,e)),t.cacheCheck=({analysisCacheLimit:e,lastUpdated:t,forceRefresh:r})=>{const o=Date.now();if(t&&(!r&&t>o-e||r&&t>o-n.oneDay))return!0}},792:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isEven=t.pNum=t.sharpeRatio=t.priceVariations=t.nTxtAr=t.zNum=t.addCom=t.adjNum=t.rNum=void 0;const r=[1,.1,.01,.001,1e-4,1e-5,1e-6,1e-7,1e-8,1e-9,1e-10,1e-11,1e-12,1e-13,1e-14,1e-15,1e-16,1e-17,1e-18,1e-19],n=(e,t=6)=>{const n=+e,o=n?Math.abs(n):0,a=o>1&&t?t-`${Math.round(o)}`.length:0;return n?(n<0?-1:1)*(Number.isInteger(o)||o<1e-16?o:o>1e5?Math.round(o):o>1?Number(o.toFixed(a<0?0:a)):((e,t)=>{let n=0;for(const o of r){if(o<e)return Number(e.toFixed(t+n-1));n++}return e})(o,t)):e},o=(e,t)=>{const r=(n(e,t)+"").split(".");return r[0]=r[0].replace(/\B(?=(\d{3})+(?!\d))/g,","),r.join(".")},a=(e,t=3)=>{const r=Number(e);if(!e||!r)return e+"";const a=Math.abs(r);return(r<0?"-":"")+(a>1e9?o(a/1e9,t)+"b":a>1e6?o(a/1e6,t)+"m":a<1e-6&&a>1e-16?(1+n(a,t)+"").replace(/1./g,"0."):o(a,t))};t.nTxtAr=["zero","one","two","three","four","five","six","seven","eight","nine","ten"],t.rNum=n,t.addCom=o,t.adjNum=a,t.zNum=e=>{const t=Number(e);let r=t?Math.abs(t):0,n=1e10;for(;n>1;)r>n&&(r=Math.round(r/(n/10))*(n/10)),n/=10;return t?(t<0?"-":"")+a(r,2):e},t.pNum=e=>+e||0==+e?Math.round(1e6*+e)/1e6:null,t.priceVariations=e=>{try{let t=0;const r=[...e].sort((e,t)=>e[0]-t[0]),n=e.reduce((e,[,t])=>e+t,0),o=r.find(([,e])=>(t+=e,t>=n/2))[0];return e.filter(([e])=>Math.abs(e-o)/o<.05).map(([e])=>e)}catch{return[]}},t.sharpeRatio=({assetPrices:e,minExpectedReturn:t=.05})=>{if(!e?.length||e?.length<2)return 0;const r=e.slice(1).map((t,r)=>(t-e[r])/e[r]),n=r.reduce((e,t)=>e+t,0)/r.length,o=Math.sqrt(r.reduce((e,t)=>e+Math.pow(t-n,2),0)/r.length);return(n-t)/o},t.isEven=e=>e%2==0},794:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.restoreObj=t.restoreObjStr=t.storeObj=t.storeObjStr=t.objNestValueCount=t.objLen=t.objSortSimple=t.objSort=void 0;const n=r(125),o=e=>{try{return Object.keys(e||{})?.length||0}catch(e){return console.log(e),0}},a=e=>{try{return e?.replace(/"/g,"'")}catch(e){return console.log((0,n.tN)(),"storeObjStr failed",e),""}},i=e=>{try{return e?.toString()?.replace(/'/g,'"')}catch(e){console.log((0,n.tN)(),"restoreObjStr failed",e)}};t.objLen=o,t.objNestValueCount=e=>{let t=0;if(o(e))for(const r in e)t+=o(e[r])?1:0;return t},t.objSort=(e={},t,r=-1)=>Object.fromEntries(Object.entries(e).sort(([,e],[,n])=>null===e[t]||void 0===e[t]?1:null===n[t]||void 0===n[t]?-1:e[t]>n[t]?1*r:-1*r)),t.objSortSimple=(e={},t=-1)=>Object.fromEntries(Object.entries(e).sort(([,e],[,r])=>null==e?1:null==r?-1:e>r?1*t:-1*t)),t.storeObjStr=a,t.storeObj=e=>{try{return a(JSON.stringify(e))}catch(e){return console.log((0,n.tN)(),"storeObj failed",e),""}},t.restoreObjStr=i,t.restoreObj=e=>{try{if(!e)return;const t=i(e);return t?JSON.parse(t):void 0}catch(e){console.log((0,n.tN)(),"restoreObj failed",e)}}},830:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.phaseDifference=t.compareArrays=t.squeezeArray=t.forecastNextTotal=t.forecastNext=t.getMax=t.getMean=t.getSum=t.maxVl=t.minVl=t.sumArr=void 0;const r=e=>{try{return e?.length?e.reduce((e,t)=>e+t):0}catch(e){return console.log("sumArr failed",e),0}},n=e=>{try{return e?.length?e.reduce((e,t)=>e+t,0):0}catch(e){return console.log("getSum failed",e),0}},o=e=>{try{return e?.length?n(e)/e.length:0}catch(e){return console.log("getMean failed",e),0}},a=e=>{try{return e?.length?Math.max(...e):0}catch(e){return console.log("getMax failed",e),0}},i=e=>{try{if(!e?.length)return 0;const t=[...e].sort((e,t)=>e-t),r=Math.floor(t.length/2);return t.length%2?t[r]:(t[r-1]+t[r])/2}catch(e){return console.log("median failed",e),0}},s=({currentPeriod:e,steps:t=1})=>{try{const r=(Array.isArray(e)?e:[]).filter(Number.isFinite);if(!r.length||t<=0)return[];if(r.length<2){const e=Math.max(0,o(r));return Array.from({length:t},()=>e)}const n=r.length,{slope:s,intercept:c}=(e=>{try{const t=e.length,r=[];for(let n=0;n<t-1;n++)for(let o=n+1;o<t;o++)r.push((e[o]-e[n])/(o-n));const n=i(r);return{slope:n,intercept:i(e.map((e,t)=>e-n*t))}}catch(e){return console.log("theilSen failed",e),{slope:0,intercept:0}}})(r),l=c+s*(n-1),u=a(r),d=u>0?3*u:1/0;return Array.from({length:t},(e,t)=>{const r=t+1,o=l+s*n*Math.log1p(r/n);return Math.max(0,Math.min(o,d))})}catch(e){return console.log("forecastNext failed",e),[]}};t.sumArr=r,t.maxVl=(e,t)=>{let r=0;for(let n=0;n<e.length;n++){const o=e[n];o[t]>r&&(r=o[t])}return r},t.minVl=(e,t)=>{let r=0;for(let n=0;n<e.length;n++){const o=e[n];o[t]<r&&(r=o[t])}return r},t.getSum=n,t.getMean=o,t.getMax=a,t.forecastNext=s,t.forecastNextTotal=e=>{try{const t=s({currentPeriod:e,steps:e?.length});return n(t)}catch(e){return console.log("forecastNextTotal failed",e),0}},t.squeezeArray=({arr:e,targetLength:t})=>{try{if(!e||0===e.length||t<=0)throw new Error("Invalid input");const n=Math.ceil(e.length/t);return Array.from({length:t},(t,o)=>{const a=o*n,i=Math.min(a+n,e.length),s=e.slice(a,i);return r(s)}).slice(0,t)}catch(e){return console.log("squeezeArray failed",e),[]}},t.compareArrays=({arrays:e})=>{try{const t=[...e],n=Math.min(...t.map(e=>e.length));for(let e=0;e<t.length;e++)t.splice(n);const o=t.map(e=>r(e)),a=[],i=Math.min(...o),s=o.indexOf(i),c=i/Math.max(...o);for(let e=0;e<t.length;e++){const r=t[e];if(a[e]=[],e==s)a[e]=r;else for(let t=0;t<r.length;t++)a[e].push(c*r[t])}return a}catch(t){return console.log("compareArrays failed",t),e}},t.phaseDifference=({array1:e,array2:t})=>{try{let r=e.length,n=e.reduce((e,t)=>e+t)/r,o=t.reduce((e,t)=>e+t)/r,a=e.map(e=>e-n),i=t.map(e=>e-o),s=Math.floor(r/2),c=-1/0,l=0;for(let e=-s;e<=s;e++){let t=0,n=0,o=0,s=0;for(let c=0;c<r;c++){let l=c+e;l>=0&&l<r&&(t+=a[c]*i[l],n+=a[c]*a[c],o+=i[l]*i[l],s++)}if(n>0&&o>0&&s>=.8*r){let r=t/Math.sqrt(n*o);r>c&&(c=r,l=e)}}return l}catch(e){return console.log("phaseDifference failed",e),0}}}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,r),a.exports}var n={};return(()=>{var e=n;Object.defineProperty(e,"__esModule",{value:!0}),e.idShuffle=e.isEven=e.pNum=e.nTxtAr=e.zNum=e.addCom=e.adjNum=e.rNum=e.sharpeRatio=e.priceVariations=e.timeStandard=e.dateStandard=e.addZ=e.tN=e.monNm=e.tmUTC=e.tmAP=e.moYrDt=e.shortDt=e.fullLong=e.fullDate=e.fullDt=e.invDt=e.dayRes=e.thisYear=e.seoDt=e.oneMon=e.oneMin=e.oneHr=e.oneDay=e.oneSec=e.restoreObj=e.restoreObjStr=e.storeObj=e.storeObjStr=e.objSortSimple=e.objSort=e.objNestValueCount=e.objLen=e.phaseDifference=e.compareArrays=e.squeezeArray=e.forecastNextTotal=e.forecastNext=e.getMax=e.getMean=e.getSum=e.maxVl=e.minVl=e.sumArr=void 0,e.cacheCheck=e.delayCode=e.idRandLong=e.idRandShort=void 0;const t=r(246);Object.defineProperty(e,"cacheCheck",{enumerable:!0,get:function(){return t.cacheCheck}}),Object.defineProperty(e,"delayCode",{enumerable:!0,get:function(){return t.delayCode}});const o=r(830);Object.defineProperty(e,"sumArr",{enumerable:!0,get:function(){return o.sumArr}}),Object.defineProperty(e,"minVl",{enumerable:!0,get:function(){return o.minVl}}),Object.defineProperty(e,"maxVl",{enumerable:!0,get:function(){return o.maxVl}}),Object.defineProperty(e,"getMax",{enumerable:!0,get:function(){return o.getMax}}),Object.defineProperty(e,"getMean",{enumerable:!0,get:function(){return o.getMean}}),Object.defineProperty(e,"getSum",{enumerable:!0,get:function(){return o.getSum}}),Object.defineProperty(e,"forecastNext",{enumerable:!0,get:function(){return o.forecastNext}}),Object.defineProperty(e,"forecastNextTotal",{enumerable:!0,get:function(){return o.forecastNextTotal}}),Object.defineProperty(e,"squeezeArray",{enumerable:!0,get:function(){return o.squeezeArray}}),Object.defineProperty(e,"compareArrays",{enumerable:!0,get:function(){return o.compareArrays}}),Object.defineProperty(e,"phaseDifference",{enumerable:!0,get:function(){return o.phaseDifference}});const a=r(240);Object.defineProperty(e,"idRandLong",{enumerable:!0,get:function(){return a.idRandLong}}),Object.defineProperty(e,"idRandShort",{enumerable:!0,get:function(){return a.idRandShort}}),Object.defineProperty(e,"idShuffle",{enumerable:!0,get:function(){return a.idShuffle}});const i=r(792);Object.defineProperty(e,"addCom",{enumerable:!0,get:function(){return i.addCom}}),Object.defineProperty(e,"adjNum",{enumerable:!0,get:function(){return i.adjNum}}),Object.defineProperty(e,"priceVariations",{enumerable:!0,get:function(){return i.priceVariations}}),Object.defineProperty(e,"nTxtAr",{enumerable:!0,get:function(){return i.nTxtAr}}),Object.defineProperty(e,"rNum",{enumerable:!0,get:function(){return i.rNum}}),Object.defineProperty(e,"zNum",{enumerable:!0,get:function(){return i.zNum}}),Object.defineProperty(e,"sharpeRatio",{enumerable:!0,get:function(){return i.sharpeRatio}}),Object.defineProperty(e,"pNum",{enumerable:!0,get:function(){return i.pNum}}),Object.defineProperty(e,"isEven",{enumerable:!0,get:function(){return i.isEven}});const s=r(125);Object.defineProperty(e,"oneSec",{enumerable:!0,get:function(){return s.oneSec}}),Object.defineProperty(e,"oneDay",{enumerable:!0,get:function(){return s.oneDay}}),Object.defineProperty(e,"oneHr",{enumerable:!0,get:function(){return s.oneHr}}),Object.defineProperty(e,"oneMin",{enumerable:!0,get:function(){return s.oneMin}}),Object.defineProperty(e,"oneMon",{enumerable:!0,get:function(){return s.oneMon}}),Object.defineProperty(e,"seoDt",{enumerable:!0,get:function(){return s.seoDt}}),Object.defineProperty(e,"dayRes",{enumerable:!0,get:function(){return s.dayRes}}),Object.defineProperty(e,"invDt",{enumerable:!0,get:function(){return s.invDt}}),Object.defineProperty(e,"fullDt",{enumerable:!0,get:function(){return s.fullDt}}),Object.defineProperty(e,"fullDate",{enumerable:!0,get:function(){return s.fullDate}}),Object.defineProperty(e,"fullLong",{enumerable:!0,get:function(){return s.fullLong}}),Object.defineProperty(e,"shortDt",{enumerable:!0,get:function(){return s.shortDt}}),Object.defineProperty(e,"moYrDt",{enumerable:!0,get:function(){return s.moYrDt}}),Object.defineProperty(e,"tmAP",{enumerable:!0,get:function(){return s.tmAP}}),Object.defineProperty(e,"tmUTC",{enumerable:!0,get:function(){return s.tmUTC}}),Object.defineProperty(e,"monNm",{enumerable:!0,get:function(){return s.monNm}}),Object.defineProperty(e,"tN",{enumerable:!0,get:function(){return s.tN}}),Object.defineProperty(e,"addZ",{enumerable:!0,get:function(){return s.addZ}}),Object.defineProperty(e,"timeStandard",{enumerable:!0,get:function(){return s.timeStandard}}),Object.defineProperty(e,"dateStandard",{enumerable:!0,get:function(){return s.dateStandard}}),Object.defineProperty(e,"thisYear",{enumerable:!0,get:function(){return s.thisYear}});const c=r(794);Object.defineProperty(e,"objSort",{enumerable:!0,get:function(){return c.objSort}}),Object.defineProperty(e,"objLen",{enumerable:!0,get:function(){return c.objLen}}),Object.defineProperty(e,"objNestValueCount",{enumerable:!0,get:function(){return c.objNestValueCount}}),Object.defineProperty(e,"restoreObj",{enumerable:!0,get:function(){return c.restoreObj}}),Object.defineProperty(e,"restoreObjStr",{enumerable:!0,get:function(){return c.restoreObjStr}}),Object.defineProperty(e,"storeObj",{enumerable:!0,get:function(){return c.storeObj}}),Object.defineProperty(e,"storeObjStr",{enumerable:!0,get:function(){return c.storeObjStr}}),Object.defineProperty(e,"objSortSimple",{enumerable:!0,get:function(){return c.objSortSimple}})})(),n})()}};const t={};function r(n){const o=t[n];if(void 0!==o)return o.exports;const a=t[n]={exports:{}};return e[n].call(a.exports,a,a.exports,r),a.exports}var n,o,a,i,s,c,l,u;let d;r.m=e,r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.f={},r.e=e=>{const t=[];return r.f.j(e,t),Promise.all(t)},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{const e={520:()=>import("./engine-litert.min.mjs"),924:()=>import("./engine-wllama.min.mjs")},t={792:0},n=e=>{let{__webpack_esm_ids__:n,__webpack_esm_modules__:o,__webpack_esm_runtime__:a}=e;var i,s,c=0;for(i in o)r.o(o,i)&&(r.m[i]=o[i]);for(a&&a(r);c<n.length;c++)s=n[c],r.o(t,s)&&t[s]&&t[s][0](),t[s]=0};r.f.j=(o,a)=>{let i=r.o(t,o)?t[o]:void 0;if(0!==i)if(i)a.push(i[1]);else{let r=e[o]().then(n,e=>{throw 0!==t[o]&&(t[o]=void 0),e});r=Promise.race([r,new Promise(e=>i=t[o]=[e])]),a.push(i[1]=r)}}})(),function(e){e.system="system",e.user="user",e.assistant="assistant"}(n||(n={})),function(e){e[e.online=0]="online",e[e.away=1]="away",e[e.offline=2]="offline"}(o||(o={})),function(e){e[e.idle=0]="idle",e[e.downloading=1]="downloading",e[e.ready=2]="ready",e[e.error=3]="error",e[e.unsupported=4]="unsupported"}(a||(a={})),function(e){e.cpu="cpu",e.gpu="gpu",e.none="none"}(i||(i={})),function(e){e.download="download",e.load="load"}(s||(s={})),function(e){e.qwen3_vl_2b="qwen3-vl-2b",e.qwen3_vl_2b_instruct="qwen3-vl-2b-instruct",e.qwen3_vl_2b_instruct_q3="qwen3-vl-2b-instruct-q3",e.gemma4_e2b_limited="gemma4-e2b-limited"}(c||(c={})),function(e){e.websearch="websearch",e.calculate="calculate",e.currency="currency"}(l||(l={})),function(e){e.wikipedia="wikipedia",e.duckduckgo="duckduckgo"}(u||(u={}));const g=[{id:c.qwen3_vl_2b,reasoning:!0,cpu:{repo:"Qwen/Qwen3-VL-2B-Thinking-GGUF",file:"Qwen3VL-2B-Thinking-Q4_K_M.gguf",mmproj:{file:"mmproj-Qwen3VL-2B-Thinking-Q8_0.gguf"}}},{id:c.qwen3_vl_2b_instruct,reasoning:!1,cpu:{repo:"unsloth/Qwen3-VL-2B-Instruct-GGUF",file:"Qwen3-VL-2B-Instruct-Q4_K_M.gguf",mmproj:{repo:"Qwen/Qwen3-VL-2B-Instruct-GGUF",file:"mmproj-Qwen3VL-2B-Instruct-Q8_0.gguf"}}},{id:c.qwen3_vl_2b_instruct_q3,reasoning:!1,cpu:{repo:"unsloth/Qwen3-VL-2B-Instruct-GGUF",file:"Qwen3-VL-2B-Instruct-Q3_K_M.gguf",mmproj:{repo:"Qwen/Qwen3-VL-2B-Instruct-GGUF",file:"mmproj-Qwen3VL-2B-Instruct-Q8_0.gguf"}}},{id:c.gemma4_e2b_limited,reasoning:!0,litert:{repo:"litert-community/gemma-4-E2B-it-litert-lm",file:"gemma-4-E2B-it-gpu.litertlm",vision:!1,audio:!1}}],m=e=>{const t=e??("undefined"==typeof navigator?void 0:navigator);if(!t)return!1;if("boolean"==typeof t.userAgentData?.mobile)return t.userAgentData.mobile;const r=t.userAgent||"";return/Android|iPhone|iPad|iPod|Mobile/i.test(r)||/Macintosh/.test(r)&&t.maxTouchPoints>1},p=e=>e?g.find(t=>t.id==e):void 0,f=async()=>{const e="undefined"==typeof navigator?void 0:navigator.gpu;if(!e)return!1;let t;try{return!!await Promise.race([e.requestAdapter({powerPreference:"high-performance"}),new Promise(e=>{t=setTimeout(()=>e(void 0),1500)})])}catch{return!1}finally{t&&clearTimeout(t)}},h=async e=>p(e??await(async()=>(d||(d=(async()=>await f()?c.gemma4_e2b_limited:c.qwen3_vl_2b)()),await d))()),y=e=>!!e.cpu?.mmproj||!0===e.litert?.vision,w=e=>!!e.cpu?.mmproj?.audio||!0===e.litert?.audio,b=new URL("./../assets/wllama/wllama.wasm",import.meta.url).href,v=new URL("./../assets/wllama/compat/wllama.wasm",import.meta.url).href,x=new URL("./../assets/wllama/compat/wllama.js",import.meta.url).href,M=new URL("./../assets/litert/litertlm_wasm_internal.js",import.meta.url).href,j=(new URL("./../assets/litert/litertlm_wasm_internal.wasm",import.meta.url).href,{width:384,height:384}),k=async e=>{if(!e.startsWith("data:"))return await(await fetch(e)).arrayBuffer();const t=e.indexOf(","),r=t>=0?e.slice(0,t):"";if(t<0)throw new Error("Invalid image data");if(!r.includes(";base64"))return await(await fetch(e)).arrayBuffer();const n=atob(e.slice(t+1)),o=new Uint8Array(n.length);for(let e=0;e<n.length;e++)o[e]=n.charCodeAt(e);return o.buffer},_=async(e,t,r=128)=>{if(!e||"function"!=typeof fetch||"function"!=typeof createImageBitmap)return e;try{const n=await fetch(e),o=await createImageBitmap(await n.blob()),a=t??((e,t,r=128)=>{const n=e/Math.max(1,t);let o=32,a=32,i=1/0,s=1/0;for(let e=1;e<=r;e++){const t=Math.ceil(r/e),c=Math.floor((r+8)/e);for(let r=t;r<=c;r++){const t=r*e,c=Math.abs(r/e-n);(c<i-1e-9||Math.abs(c-i)<=1e-9&&t<s)&&(o=32*r,a=32*e,i=c,s=t)}}return{width:o,height:a}})(o.width,o.height,r),i=o.width/Math.max(1,o.height),s=a.width/a.height,c=Math.min(o.width,i>s?o.height*s:o.width),l=Math.min(o.height,i>s?o.height:o.width/s),u=(o.width-c)/2,d=(o.height-l)/2,g=((e,t)=>{if("undefined"!=typeof OffscreenCanvas)return new OffscreenCanvas(e,t);if("undefined"==typeof document)return;const r=document.createElement("canvas");return r.width=e,r.height=t,r})(a.width,a.height),m=g?g.getContext("2d"):null;if(!g||!m||o.width<1||o.height<1)return o.close(),e;if(m.drawImage(o,u,d,c,l,0,0,a.width,a.height),o.close(),(e=>"undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)(g)){const t=await g.convertToBlob({type:"image/jpeg",quality:.85});return await(e=>new Promise(t=>{if("undefined"==typeof FileReader)return void t("");const r=new FileReader;r.onerror=()=>t(""),r.onload=()=>t(`${r.result}`),r.readAsDataURL(e)}))(t)||e}return g.toDataURL("image/jpeg",.85)}catch{return e}};var P=r(155);const T={maxReplyTokens:250,maxThinkingTokens:128,maxReasoningTokens:320,maxImages:2,imageTokens:128,maxAudio:1,maxContentLength:1e3,promptCharBudget:1e4,maxThreads:32,gpuShare:.5},S=(e,t,r)=>"number"==typeof e&&Number.isFinite(e)&&e>=r?Math.floor(e):t,O=(e={},t=!1)=>{const r=T;return{maxReplyTokens:S(e.maxReplyTokens,r.maxReplyTokens,1),maxThinkingTokens:S(e.maxThinkingTokens,r.maxThinkingTokens,1),maxReasoningTokens:S(e.maxReasoningTokens,t?1200:r.maxReasoningTokens,1),maxImages:S(e.maxImages,r.maxImages,0),imageTokens:S(e.imageTokens,r.imageTokens,1),maxAudio:S(e.maxAudio,r.maxAudio,0),maxContentLength:S(e.maxContentLength,r.maxContentLength,1),promptCharBudget:S(e.promptCharBudget,r.promptCharBudget,1),maxThreads:S(e.maxThreads,r.maxThreads,1),gpuShare:"number"==typeof e.gpuShare&&Number.isFinite(e.gpuShare)&&e.gpuShare>0?Math.min(1,Math.max(.05,e.gpuShare)):r.gpuShare}},D=(e,t,r=.7)=>({stream:!0,temperature:r,max_tokens:t?e.maxReasoningTokens:e.maxReplyTokens}),N=(e,t)=>`https://huggingface.co/${e}/resolve/main/${t}`,C=e=>Number(e.headers.get("content-length"))||0,E=(e,t)=>e.some(e=>Array.isArray(e.content)&&e.content.some(e=>e.type==t)),L=e=>E(e,"image"),A=e=>E(e,"audio"),R=["<|channel>thought\n","<|channel>thought","..."],$=["<channel|>","..."],U=(e,t,r)=>t.length||r.length?[...e?[{type:"text",text:e}]:[],...t.map(e=>({type:"image",url:e})),...r.map(e=>({type:"audio",url:e}))]:e,q=e=>"string"==typeof e?e?[{type:"text",text:e}]:[]:e,z=(e,t)=>{if("string"==typeof e&&"string"==typeof t)return`${e}\n${t}`;const r=[];for(const n of[...q(e),{type:"text",text:"\n"},...q(t)]){const e=r[r.length-1];"text"==n.type&&"text"==e?.type?e.text+=n.text:r.push(n)}return r},I=m()?3e6:3e5,F=Math.max(I,84e4);class W extends Error{}const V=async(e,t,r)=>{let n;try{return await Promise.race([e,new Promise((e,o)=>{n=setTimeout(()=>o(new W(r)),t)})])}finally{n&&clearTimeout(n)}},B=e=>{try{Promise.resolve(e.next?.()).catch(()=>{}).finally(()=>{try{Promise.resolve(e.return?.()).catch(()=>{})}catch{}})}catch{}},G=async({model:e,logging:t,onReason:r,onText:n,onSpeed:o,start:a,stopped:i,firstTimeoutMs:s=I,idleTimeoutMs:c=3e4,onStall:l})=>{let u="",d="",g="",m=!1,p=0,f=0;const h=((e,t)=>{let r="",n=!1;const o=(e,t)=>{let r=-1,n="";for(const o of t){const t=e.indexOf(o);t>=0&&(r<0||t<r)&&(r=t,n=o)}return{at:r,tag:n}},a=(e,t)=>{let r="";for(const n of t)for(let t=Math.min(e.length,n.length-1);t>r.length;t--)if(e.endsWith(n.slice(0,t))){r=e.slice(e.length-t);break}return r};return{feed:i=>{let s=r+i;for(r="";s;){if(n){const{at:t,tag:i}=o(s,$);if(t>=0){t&&e(s.slice(0,t)),s=s.slice(t+i.length),n=!1;continue}const c=a(s,$);e(s.slice(0,s.length-c.length)),r=c;break}{const{at:e,tag:i}=o(s,R);if(e>=0){e&&t(s.slice(0,e)),s=s.slice(e+i.length),s.startsWith("\n")&&(s=s.slice(1)),n=!0;continue}const c=a(s,R);t(s.slice(0,s.length-c.length)),r=c;break}}},flush:()=>{r&&(n?e(r):t(r),r="")}}})(e=>{d+=e,r(e)},e=>{u+=e,n(e)});try{const e=a();Promise.resolve(e).catch(()=>{});const n=(await V(e,s,"Model did not start"))[Symbol.asyncIterator]();for(;;){if(i()){B(n);break}let e;try{const t=n.next();Promise.resolve(t).catch(()=>{}),e=await V(t,m?c:s,m?"Model stopped responding":"Model did not reply")}catch(e){if(e instanceof W&&(u||d)){l?.(),B(n),t&&console.log("Local chat stalled",e);break}throw e}if(e.done)break;m=!0;const a=e.value?.choices?.[0],y=a?.delta,w="string"==typeof y?.reasoning_content?y.reasoning_content:"string"==typeof y?.reasoning?y.reasoning:"";if(a?.finish_reason&&(g=a.finish_reason),w&&(d+=w,r(w)),y?.content&&h.feed(y.content),w||y?.content){const e=performance.now();p||(f=e),p+=1,p>1&&e>f&&o?.((0,P.rNum)(1e3*p/(e-f)))}}h.flush()}catch(e){if(t&&console.log("Local chat failed",e),e instanceof W&&!i())throw e}const y=i()?void 0:u||void 0;return t&&(console.log("Local chat reply",e.id,y?"****":""),console.log("Local chat finish",e.id,g||"none",u.length,d.length)),y},Q=async({model:e,params:t,start:r,stopped:o,onStall:a})=>{const i=await(async(e,t,r=128)=>{const n=[];for(const o of e){if("string"==typeof o.content){n.push(o);continue}const e=[];for(const n of o.content)e.push("image"==n.type?{type:"image",url:await _(n.url,t,r)}:n);n.push({role:"user",content:e})}return n})(((e,t=T)=>{const r=t.maxContentLength,o=e.filter(e=>"string"==typeof e.content&&!!e.content.trim()||!(e.role!=n.user||!e.images?.length&&!e.audio?.length)),a=[],i=[];let s=0,c=t.maxImages,l=t.maxAudio;for(let e=o.length-1;e>=0;e--){const u=o[e],d=("string"==typeof u.content?u.content:"").slice(0,r),g=u.role==n.user?(u.images||[]).filter(e=>"string"==typeof e&&!!e).slice(0,Math.max(0,c)):[],m=u.role==n.user?(u.audio||[]).filter(e=>"string"==typeof e&&!!e).slice(0,Math.max(0,l)):[];if(d||g.length||m.length){if(d&&s+d.length>t.promptCharBudget)break;s+=d.length,c-=g.length,l-=m.length,u.role==n.system?a.unshift(d):u.role==n.assistant?i.unshift({role:"assistant",content:d}):i.unshift({role:"user",content:U(d,g,m)})}}for(;i.length&&"user"!=i[0].role;)i.shift();const u=[];for(const e of i){const t=u[u.length-1];"assistant"==t?.role&&"assistant"==e.role?t.content=`${t.content}\n${e.content}`:"user"==t?.role&&"user"==e.role?t.content=z(t.content,e.content):"assistant"==e.role?u.push({role:"assistant",content:e.content}):u.push({role:"user",content:e.content})}const d=a.join("\n\n"),g=[];return d&&g.push({role:"system",content:d}),g.push(...u),g})(t.messages,t.limits),e.litert?j:void 0,t.limits.imageTokens);return t.logging&&((e,t)=>{console.log("Local chat call",e.id,t.map(({role:e,content:t})=>({role:e,content:"****",...Array.isArray(t)?{images:t.filter(e=>"image"==e.type).length,audio:t.filter(e=>"audio"==e.type).length}:{}})))})(e,i),await G({model:e,logging:t.logging,onReason:t.onReason,onText:t.onText,onSpeed:t.onSpeed,start:()=>r(i),stopped:o,onStall:a,firstTimeoutMs:L(i)?F:I})},Y=33554432,H=new Map;let J=!1;const Z=e=>{const t=(e.split("/").pop()||"model").replace(/[^\w.-]+/g,"_");let r=0;for(let t=0;t<e.length;t++)r=31*r+e.charCodeAt(t)>>>0;return`${r.toString(16)}-${t}`},K=e=>{const t=/^part-(\d+)$/.exec(e);return t?Number(t[1]):-1},X=async()=>{if(!J)if("undefined"!=typeof navigator&&navigator.storage?.getDirectory)try{return await navigator.storage.getDirectory()}catch{return}else J=!0},ee=async(e,t)=>{try{return await e.getDirectoryHandle(t)}catch{return}},te=async e=>{if(e)try{const t=await e.getFile(),r=JSON.parse(await t.text());return{total:Number(r.total)||0,etag:`${r.etag||""}`,complete:!0===r.complete}}catch{return}},re=async(e,t)=>{try{const r=await e.getFileHandle("meta.json",{create:!0}),n=await r.createWritable();await n.write(JSON.stringify(t)),await n.close()}catch{}},ne=async function*(e){for await(const t of e)yield t},oe=async e=>{try{for await(const[t,r]of ne(e))"file"==r.kind&&K(t)>=0&&await e.removeEntry(t).catch(()=>{})}catch{}},ae=async(e,t)=>{try{const r=await(await e.getFileHandle(t)).getFile(),n=await te(await e.getFileHandle(`${t}.json`).catch(()=>{}));if(!n)return;return{file:r,size:r.size,total:n.total,etag:n.etag,complete:n.total?r.size>=n.total:!0===n.complete}}catch{return}},ie=async(e,t)=>{const r=await ee(e,t);if(r){const e=await(async e=>await te(await e.getFileHandle("meta.json").catch(()=>{})))(r),t=await(async e=>{const t=[];try{for await(const[r,n]of ne(e)){const e=K(r);if("file"!=n.kind||e<0)continue;const o=await n.getFile();t.push({part:{start:e,size:o.size},file:o})}}catch{return}const r=(e=>{const t=[];let r=0;for(const n of[...e].sort((e,t)=>e.start-t.start))if(n.size){if(n.start!=r)break;t.push(n),r+=n.size}return t})(t.map(e=>e.part)),n=new Set(r.map(e=>e.start)),o=t.filter(e=>n.has(e.part.start)).sort((e,t)=>e.part.start-t.part.start).map(e=>e.file);if(o.length)return{file:1==o.length?o[0]:new Blob(o),size:r.reduce((e,t)=>e+t.size,0)}})(r),n=e?.total||0,o=t?.size??0,a=t?.file??new Blob;return{file:n&&o>n?a.slice(0,n):a,size:o,total:n,etag:e?.etag||"",complete:n?o>=n:!0===e?.complete}}return await ae(e,t)},se=(e,t)=>{const r=e.headers.get("content-range"),n=/bytes (\d+)-/.exec(r||""),o=/\/(\d+)\s*$/.exec(r||""),a=e.headers.get("etag")||"";if(206==e.status){const e=n?Number(n[1]):t.size,r=o?Number(o[1]):t.total;if(e!=t.size)return;if(t.total&&r&&t.total!=r)return;if(t.etag&&a&&t.etag!=a)return;return{start:e,total:r||t.total,etag:a||t.etag}}if(!t.etag||!a||t.etag==a)return{start:0,total:C(e)||t.total,etag:a||t.etag}},ce=async({dir:e,start:t,skip:r,total:n,body:o,onProgress:a,onChunk:i})=>{let c,l=t,u=0,d=r;const g=async()=>{const t=await e.getFileHandle((e=>`part-${e}`)(l),{create:!0});c=await t.createWritable(),u=0},m=async()=>{const e=c;c=void 0,e&&await e.close().catch(()=>{})};try{const e=o.getReader();for(;;){const{done:r,value:o}=await e.read();if(r)break;i();let p=0;for(d&&(p=Math.min(d,o.byteLength),d-=p);p<o.byteLength;){c||await g();const e=Math.min(Y-u,o.byteLength-p);await c.write({type:"write",position:u,data:o.subarray(p,p+e)}),p+=e,u+=e,l+=e,u==Y&&await m()}l>t&&a(n?l/n:0,s.download)}await m()}catch(e){throw await m(),e}return l},le=e=>["NotAllowedError","NotSupportedError"].includes(e?.name||""),ue=e=>{const t=async()=>{const t=await X();if(t)try{return await t.getDirectoryHandle(e,{create:!0})}catch{return}};return{stored:async e=>{const r=await t();return r?await ie(r,Z(e)):void 0},download:async({url:r,signal:n,onProgress:o})=>{const a=`${e}|${r}`,i=H.get(a);if(i)return await i;const c=await t();if(!c)return;const l=(async(e,t,r,n)=>{const o=Z(t),a=await ae(e,o);if(a?.complete)return a;let i=await ee(e,o);i||(await e.removeEntry(o).catch(()=>{}),await e.removeEntry(`${o}.json`).catch(()=>{}),i=await e.getDirectoryHandle(o,{create:!0}));let c=0,l=0;for(;;){if(r?.aborted)throw new Error("Cancelled");const a=await ie(e,o);if(a?.complete)return a;const u=a?.size??0,d=a?.total||0,g=a?.etag||"";if(u>c)c=u,l=0;else if(++l>4)throw new Error("Model download failed");u&&d&&n(u/d,s.download);const m=d?Math.min(u+Y,d)-1:u+Y-1,p=new AbortController,f=()=>p.abort(),h={size:u,total:d,etag:g};let y,w=setTimeout(f,3e4);r?.addEventListener("abort",f,{once:!0});try{if(y=await fetch(t,{signal:p.signal,headers:{Range:`bytes=${u}-${m}`}}),416==y.status){if(await(y.body?.cancel().catch(()=>{})),d&&u>=d){await re(i,{total:d,etag:g,complete:!0});continue}await oe(i),await re(i,{total:0,etag:"",complete:!1});continue}if(!y.ok||!y.body)throw await(y.body?.cancel().catch(()=>{})),new Error("Model download failed");const r=se(y,h);if(!r){await y.body.cancel().catch(()=>{}),await oe(i),await re(i,{total:0,etag:"",complete:!1});continue}await re(i,{total:r.total,etag:r.etag,complete:!1});const a=0==r.start?u:0,s=await ce({dir:i,start:r.start+a,skip:a,total:r.total,body:y.body,onProgress:n,onChunk:()=>{clearTimeout(w),w=setTimeout(f,3e4)}});if(!r.total){await re(i,{total:s,etag:r.etag,complete:!0});const t=await ie(e,o);if(t)return t}}catch(e){if(r?.aborted)throw new Error("Cancelled");if(e instanceof DOMException&&["QuotaExceededError","NotAllowedError","NotSupportedError","InvalidStateError","TypeMismatchError","SecurityError"].includes(e.name))throw e;await new Promise(e=>setTimeout(e,250+500*l))}finally{clearTimeout(w),r?.removeEventListener("abort",f)}}})(c,r,n,o).finally(()=>{H.delete(a)});return H.set(a,l),await l},remove:async e=>{const r=await t();r&&await(async(e,t)=>{await e.removeEntry(t,{recursive:!0}).catch(()=>{}),await e.removeEntry(`${t}.json`).catch(()=>{})})(r,Z(e))},purge:async()=>{const t=await X();t&&await t.removeEntry(e,{recursive:!0}).catch(()=>{})}}},de=(e,...t)=>{!0===e&&console.log(...t)},ge="litertlm-models",me=.5,pe=ue("litert-store"),fe={num_output_candidates:1,wait_for_weight_uploads:!0,num_decode_steps_per_sync:1,sequence_batch_size:0,supported_lora_ranks:[],max_top_k:40,enable_decode_logits:!1,enable_external_embeddings:!1,use_submodel:!1,use_autosized_ringbuffers:!0};let he=!1,ye=0;const we=new WeakSet;let be=me,ve=!1,xe=0;const Me=(...e)=>{he&&console.log(...e)},je=(...e)=>{he&&console.error(...e)},ke=e=>e.replace(/<\|channel>thought\n?[\s\S]*?<channel\|>/g,"").replace(/<\|channel>thought[\s\S]*$/,"").trim(),_e=async()=>{const e=performance.now(),t=e-xe;if(xe=e,!ve)return;const r=Math.round(((e,t=.5)=>Math.min(500,Math.max(0,e*(1/t-1))))(t,be));r<1||(await new Promise(e=>setTimeout(e,r)),xe=performance.now())},Pe=(e=.5)=>{be=e>0?e:me,ve=!0,xe=performance.now()},Te=async()=>{try{if("undefined"==typeof caches)return;return await caches.open(ge)}catch{return}},Se=new Map,Oe=(e,t,r)=>{let n=0;return e.pipeThrough(new TransformStream({transform:(e,o)=>{n+=e.byteLength,r(t?n/t:0,s.download),o.enqueue(e)}}))},De=async(e,t=!0)=>{const r=[];for(const n of e){if("string"==typeof n.content){r.push({role:n.role,content:n.content});continue}const e=[];for(const r of n.content)"text"!=r.type?t?e.push({type:r.type,data:await k(r.url)}):e.push({type:"text",text:`[${r.type}]`}):e.push({type:"text",text:r.text});r.push({role:n.role,content:e})}return r},Ne=(e,t)=>{if(e.role!=t.role)return!1;if("string"==typeof e.content||"string"==typeof t.content)return"string"==typeof e.content&&"string"==typeof t.content&&ke(e.content)==ke(t.content);if(e.content.length!=t.content.length)return!1;for(let r=0;r<e.content.length;r++){const n=e.content[r],o=t.content[r];if(n.type!=o.type)return!1;if("text"==n.type&&"text"==o.type){if(ke(n.text)!=ke(o.text))return!1}else{if("text"==n.type||"text"==o.type)return!1;if(!!n.url!=!!o.url)return!1}}return!0},Ce=async function*({engine:e,mod:t,params:r,messages:n,session:o}){const a=n[n.length-1],i=D(r.limits,r.reasoning,r.temperature);if("user"!=a?.role)throw new Error("No user turn");const s=n.slice(0,-1),c=(await De([a]))[0];if(!c)throw new Error("Empty prompt");const l=o.reasoning==r.reasoning&&o.maxTokens==i.max_tokens,u=!!o.conversation&&((e,t)=>{const r="system"==e[0]?.role?e[0]:void 0,n="system"==t[0]?.role?t[0]:void 0;if(!r!=!n)return!1;if(r&&n&&!Ne(r,n))return!1;const o=r?e.slice(1):e,a=n?t.slice(1):t;if(!a.length||a.length>o.length)return!1;const i=o.length-a.length;for(let e=0;e<a.length;e++)if(!Ne(o[i+e],a[e]))return!1;return!0})(o.sent,s);let d;if(l&&u&&o.conversation)de(he,"LiteRT conversation reused",o.sent.length),d=o.conversation;else{const n=await De(s,!1);o.conversation=void 0,o.sent=[];const a=performance.now();d=await e.createConversation({sessionConfig:{maxOutputTokens:i.max_tokens,samplerParams:{type:t.SamplerType.TOP_K,temperature:i.temperature,k:40,p:.95}},preface:{...n.length?{messages:n}:{},extra_context:{enable_thinking:r.reasoning}},prefillPrefaceOnInit:n.length>0}),de(he,"LiteRT conversation created",n.length,Math.round(performance.now()-a),"flags",l,"history",u),o.conversation=d,o.reasoning=r.reasoning,o.maxTokens=i.max_tokens,o.sent=[...s]}o.sent.push(a);let g,m=!1,p=!0,f="";const h=()=>{g&&g.cancel().catch(()=>{});try{Promise.resolve(d.cancel()).catch(()=>{})}catch{}};r.signal?.addEventListener("abort",h,{once:!0});try{if(r.signal?.aborted)return;const e=d.sendMessageStreaming(c).getReader();for(g=e;;){const t=performance.now(),{done:n,value:o}=await e.read().catch(e=>{if(r.signal?.aborted)return{done:!0,value:void 0};throw e}),a=performance.now()-t;if(n)break;const i=p;p=!1,i&&(de(he,"LiteRT first chunk",Math.round(a)),Pe(r.limits.gpuShare));const s={};let c="string"==typeof o.content?o.content:"";if(Array.isArray(o.content))for(const e of o.content)"text"==e.type&&(c+=e.text);c&&(s.content=c,f+=c);const l=o.channels?.thought;l&&(s.reasoning=l),(s.content||s.reasoning)&&(yield{choices:[{delta:s}]})}m=!0}finally{ve=!1,r.signal?.removeEventListener("abort",h),m&&f?o.sent.push({role:"assistant",content:f}):(o.conversation=void 0,o.sent=[])}},Ee={backend:i.gpu,startLLM:async({model:e,limits:t,onProgress:n,signal:o,logging:a})=>{he=!0===a;const c=e.litert;if(!c)throw new Error("Model has no LiteRT artifact");const l=m()?16384:32768,u=await r.e(520).then(()=>r(507)),d=globalThis,g=d.Module;d.Module={print:Me,printErr:je};try{await u.getOrLoadGlobalLiteRtLm(M)}finally{d.Module=g}if(o?.aborted)throw new Error("Cancelled");const p=u.getGlobalLiteRtLm(),f=p.liteRtLmWasm;if(await p.setupDefaultWebGpuDevice(),o?.aborted)throw new Error("Cancelled");const h=f.preinitializedWebGPUDevice;if(!h)throw new Error("No WebGPU device");if(!we.has(h)){const e=(({device:e,pace:t})=>new Proxy(e,{get:(e,r)=>{if("createBuffer"==r)return(...n)=>{const o=Reflect.get(e,r,e).apply(e,n),a=o.mapAsync;try{o.mapAsync=async(...e)=>{await a.apply(o,e),await t()}}catch{}return o};const n=Reflect.get(e,r,e);return"function"==typeof n?n.bind(e):n}}))({device:h,pace:_e});we.add(h),we.add(e),f.preinitializedWebGPUDevice=e}const y=N(c.repo,c.file),w=await Te();let b;const v=w?await w.match(y):void 0;if(v?.body)b=v.body;else{const e=await pe.stored(y);e?.complete&&(b=e.file.stream())}if(!b){const e=await pe.download({url:y,signal:o,onProgress:n}).catch(e=>{if(o?.aborted)throw new Error("Cancelled");if(!le(e))throw e;a&&console.log("Local model store failed",e)});e&&(b=e.file.stream())}if(!b&&w)try{await(async(e,t,r,n)=>{const o=Se.get(e);if(o)return await o;const a=(async()=>{const o=await fetch(e,{signal:r});if(!o.ok||!o.body)throw new Error("Model download failed");const a=C(o),i=Oe(o.body,a,n);await t.put(e,new Response(i,{headers:{"content-type":"application/octet-stream",...a?{"content-length":`${a}`}:{}}}))})().finally(()=>{Se.delete(e)});return Se.set(e,a),await a})(y,w,o,n);const e=await w.match(y);e?.body&&(b=e.body)}catch(e){if(o?.aborted)throw new Error("Cancelled");a&&console.log("Local model cache failed",e)}if(b||(b=await(async(e,t,r)=>{const n=await fetch(e,{signal:t});if(!n.ok||!n.body)throw new Error("Model download failed");return Oe(n.body,C(n),r)})(y,o,n)),o?.aborted)throw new Error("Cancelled");n(1,s.load);const x=await u.Engine.create((({model:e,limits:t,contextSize:r,source:n,mod:o})=>{const a=e.litert;return{model:n,mainExecutorSettings:{maxNumTokens:r,...a?.vision?{maxNumImages:Math.max(1,t.maxImages)}:{},backendConfig:fe},...a?.vision?{visionBackend:o.Backend.GPU,maxVisionTokensPerImage:70,minVisionTokensPerImage:70}:{},...a?.audio?{audioBackend:o.Backend.CPU}:{}}})({model:e,limits:t,contextSize:l,source:b,mod:u}));ye+=1;const j=()=>{ye=Math.max(0,ye-1),ye||(e=>{try{const t=e.getGlobalLiteRtLm().liteRtLmWasm,r=t.preinitializedWebGPUDevice;t.preinitializedWebGPUDevice=void 0,t.WebGPU&&(t.WebGPU.preinitializedDeviceId=void 0),r?.destroy?.()}catch{}try{e.unloadLiteRtLm()}catch{}})(u)};try{const e=performance.now(),t=await x.createConversation();await t.delete(),de(he,"LiteRT conversation warm-up",Math.round(performance.now()-e))}catch(e){de(he,"LiteRT conversation warm-up failed",e)}if(o?.aborted)throw await x.delete(),j(),new Error("Cancelled");const k={sent:[],reasoning:!1,maxTokens:0};return{model:e,backend:i.gpu,contextSize:l,chat:t=>(async({engine:e,model:t,mod:r,params:n,session:o})=>{he=!0===n.logging;const a=()=>{try{o.conversation?.cancel()}catch{}o.conversation=void 0,o.sent=[]};try{return await Q({model:t,params:n,stopped:()=>!!n.signal?.aborted,onStall:a,start:async a=>{if(n.signal?.aborted)throw new Error("Cancelled");if(L(a)&&!t.litert?.vision)throw new Error("Model does not accept images");if(A(a)&&!t.litert?.audio)throw new Error("Model does not accept audio");return Ce({engine:e,mod:r,params:n,messages:a,session:o})}})}catch(e){throw a(),e}})({engine:x,model:e,mod:u,params:t,session:k}),unload:async()=>{const e=k.conversation;k.conversation=void 0,k.sent=[];try{await(e?.delete())}catch{}await x.delete(),j()}}},cached:async e=>{const t=e.litert;if(!t)return!1;const r=N(t.repo,t.file),[n,o]=await Promise.all([Te(),pe.stored(r)]);if(o?.complete)return!0;try{return!(!n||!await n.match(r))}catch{return!1}},purge:async()=>{try{await pe.purge(),"undefined"!=typeof caches&&await caches.delete(ge)}catch{}}},Le=ue("wllama-store"),Ae=[c.qwen3_vl_2b_instruct,c.qwen3_vl_2b_instruct_q3],Re=e=>e.cpu?.mmproj&&Ae.includes(e.id)?{image_min_tokens:16,image_max_tokens:128}:{};let $e,Ue,qe="",ze=!1;const Ie=e=>`${e.wasm}|${e.compatWasm}|${e.compatWorker}`,Fe=e=>{const t={wasm:b,compatWasm:v,compatWorker:x};return{wasm:e?.wasm||t.wasm,compatWasm:e?.compatWasm||t.compatWasm,compatWorker:e?.compatWorker||t.compatWorker}},We=e=>{const t=e=>(...t)=>{ze&&("string"==typeof t[0]&&t[0].includes("ggml_webgpu: Failed to get an adapter")||e(...t))};return{...e,log:t(e.log),warn:t(e.warn),error:t(e.error)}},Ve=async()=>{if($e)return $e;const e=await r.e(924).then(()=>r(577)),t=Ue||Fe(),n=new e.Wllama({default:t.wasm},{logger:We(e.LoggerWithoutDebug)});return Ue||(Ue=t,qe=Ie(t)),n.setCompat({wasm:t.compatWasm,worker:t.compatWorker}),$e=n,n},Be=async()=>{const e=$e;$e=void 0;try{await(e?.exit())}catch{}},Ge=(e,t)=>e.name.includes(t)||!!e.metadata?.originalURL?.includes(t),Qe=e=>{const t=e.cpu;return t?[{name:t.file,url:N(t.repo,t.file)},...t.mmproj?[{name:t.mmproj.file,url:N(t.mmproj.repo??t.repo,t.mmproj.file)}]:[]]:[]},Ye=async e=>{const t=Qe(e);if(!t.length)return!1;for(const e of t){const t=await Le.stored(e.url);if(!t?.complete)return!1}return!0},He=async(e,t)=>{const r=await e.cacheManager.list();return Qe(t).every(e=>r.some(t=>Ge(t,e.name)))},Je=async({model:e,signal:t,onProgress:r})=>{const n=Qe(e),o=[];for(let e=0;e<n.length;e++){if(t?.aborted)throw new Error("Cancelled");const a=await Le.download({url:n[e].url,signal:t,onProgress:(t,o)=>r((e+t)/n.length,o)});if(!a)return;o.push(a.file)}return o.length?o:void 0},Ze=async e=>{const t=[];for(const r of e){if("string"==typeof r.content){"system"==r.role?t.push({role:"system",content:r.content}):"assistant"==r.role?t.push({role:"assistant",content:r.content}):t.push({role:"user",content:r.content});continue}const e=[];for(const t of r.content)"text"==t.type?e.push({type:"text",text:t.text}):e.push({type:t.type,data:await k(t.url)});t.push({role:"user",content:e})}return t},Ke={backend:i.cpu,startLLM:async({model:e,limits:t,onProgress:r,signal:n,logging:o,assets:a})=>{ze=!0===o;const c=m()?4096:8192,l=e.cpu;if(!l)throw new Error("Model has no CPU artifact");const u=Fe(a),d=Ie(u);$e&&d!=qe&&await Be(),Ue=u,qe=d;const g="undefined"!=typeof navigator?navigator.hardwareConcurrency:0,p=Math.min((e=>{const t=e||4;return Math.max(1,t-Math.max(1,Math.floor(t/5)))})(g),t.maxThreads),f=await Ve(),h=await Ye(e),y=l.mmproj?.file,w=N(l.repo,l.file),b=y?N(l.mmproj?.repo??l.repo,y):"";if(n?.aborted)throw await Be(),new Error("Cancelled");if(!h&&y){const e=await f.cacheManager.list(),t=e.some(e=>Ge(e,l.file)),r=e.some(e=>Ge(e,y));t&&!r&&await f.cacheManager.deleteMany(e=>Ge(e,l.file))}const v={n_ctx:c,n_threads:p,n_parallel:1,warmup:!0,reasoning_budget_tokens:t.maxThinkingTokens,n_gpu_layers:0,jinja:!0,ctx_shift:!0,n_keep:Math.max(64,Math.round(c/16)),...Re(e)};try{let t=h?await Je({model:e,signal:n,onProgress:r}):void 0;t||h||await He(f,e).catch(()=>!1)||(t=await Je({model:e,signal:n,onProgress:r}).catch(e=>{if(n?.aborted)throw new Error("Cancelled");if(!le(e))throw e;o&&console.log("Local model store failed",e)})),t?(r(1,s.load),await f.loadModel(t,v)):await f.loadModelFromUrl(b?{url:w,mmprojUrl:b}:w,{...v,useCache:!0,signal:n,progressCallback:({loaded:e,total:t})=>{const n=t?e/t:0;r(n,n>=1?s.load:s.download)}})}catch(e){throw await Be(),e}if(n?.aborted)throw await Be(),new Error("Cancelled");const x=f.getLoadedContextInfo();if(!x.n_ctx)throw await Be(),new Error("Failed to create model context");return de(o,"CPU engine ready",e.id,"cores","undefined"!=typeof navigator?navigator.hardwareConcurrency:0,"isolated","undefined"!=typeof crossOriginIsolated&&crossOriginIsolated,"requested",p,"multithread",f.isMultithread(),"active",f.getNumThreads(),"context",x.n_ctx,"batch",x.n_batch,"ubatch",x.n_ubatch),{model:e,backend:i.cpu,contextSize:c,chat:t=>(async(e,t,r)=>{if(ze=!0===r.logging,e.isModelLoaded())return await Q({model:t,params:r,stopped:()=>!!r.signal?.aborted,start:async n=>{if(L(n)&&!e.supportInputModality("image"))throw new Error("Model does not accept images");if(A(n)&&!e.supportInputModality("audio"))throw new Error("Model does not accept audio");return await e.createChatCompletion({messages:await Ze(n),...D(r.limits,r.reasoning,r.temperature),...r.repeatPenalty?{penalty_repeat:r.repeatPenalty}:{},abortSignal:r.signal,...t.reasoning?{chat_template_kwargs:{enable_thinking:r.reasoning}}:{}})}})})(f,e,t),unload:async()=>{if($e==f)await Be();else try{await f.exit()}catch{}}}},cached:async e=>{try{return!!e.cpu&&(!!await Ye(e)||await He(await Ve(),e))}catch{return!1}},purge:async()=>{try{await Le.purge()}catch{}try{const e=await Ve();await e.cacheManager.clear()}catch{}}},Xe=((e={})=>{const t=e.engines?.cpu||Ke,r=e.engines?.litert||Ee,n=new Map,o=new Map,c=new Map,l=new Map,u=new Map,d=new Map,g=new Map,m=new Map,p=new Map;let f,h,y,w=a.idle;const b=n=>{if(e.backend!=i.none)return e.backend==i.cpu?n.cpu?t:void 0:e.backend==i.gpu?n.litert?r:void 0:n.litert&&"undefined"!=typeof navigator&&navigator.gpu&&"undefined"!=typeof WebAssembly?r:!n.cpu||"undefined"==typeof window&&"undefined"==typeof self&&"undefined"==typeof Worker||"undefined"==typeof WebAssembly?void 0:t},v=e=>e?n.get(e):f?n.get(f.id):void 0,x=e=>{w=e},M=async e=>{const t=n.get(e);t&&(n.delete(e),f?.id==e&&(f=[...n.values()].pop()?.model),n.size||o.size||x(a.idle),await t.unload())},j=async()=>{for(const e of[...n.keys()])await M(e)},k=(e,t,r)=>{const n={percent:Math.max(0,Math.min(1,t)),phase:r||s.download};u.set(e,n);for(const t of l.get(e)??[])t.report(n.percent,n.phase)},_=e=>{g.set(e,(g.get(e)??0)+1),d.get(e)?.abort(),d.delete(e);const t=o.get(e);t&&c.set(e,t),o.delete(e),l.delete(e),u.delete(e),m.set(e,a.idle),w!=a.downloading||o.size||n.size||x(a.idle)},P=(e,t,r)=>{const n=o.get(e);return n?new Promise(a=>{let i=!1;const s={report:t,settle:e=>{i||(i=!0,r?.removeEventListener("abort",c),a(e))}},c=()=>{((e,t)=>{const r=l.get(e);r&&l.set(e,r.filter(e=>e!=t)),queueMicrotask(()=>{!l.get(e)?.length&&o.has(e)&&_(e)})})(e,s),s.settle(!1)},u=l.get(e);u?u.push(s):l.set(e,[s]),r?.aborted?c():r?.addEventListener("abort",c,{once:!0}),n.attempt.then(s.settle,()=>s.settle(!1))}):Promise.resolve(!1)},T=async e=>{if(e)await M(e);else{for(const e of[...o.keys()])_(e);u.clear(),m.clear(),p.clear(),h=void 0,x(a.idle),await j()}};return{load:async({model:e,limits:t,assets:r,logging:i,signal:y,onProgress:w})=>{if(y?.aborted)return!1;if(n.has(e.id))return f=e,!0;if(o.has(e.id)){const t=u.get(e.id);return t&&w(t.percent,t.phase),await P(e.id,w,y)}const v=b(e);if(!v){const t="Model is not supported on this device";return h=t,p.set(e.id,t),m.set(e.id,a.unsupported),x(a.unsupported),!1}const M=[...o.values(),...c.values()];for(const e of M)_(e.model.id);const T=(g.get(e.id)??0)+1;g.set(e.id,T);const S=(async()=>{if(await Promise.all(M.map(e=>e.attempt.catch(()=>!1))),T!=g.get(e.id))return!1;if(await(async()=>{try{if("undefined"==typeof navigator)return;await(navigator.storage?.persist?.())}catch{}})(),T!=g.get(e.id))return!1;if(await j(),T!=g.get(e.id))return!1;const o=await v.cached(e);if(T!=g.get(e.id))return!1;h=void 0,p.delete(e.id),m.set(e.id,a.downloading),x(a.downloading),k(e.id,0,s.download),o&&k(e.id,1,s.load);const c=new AbortController;d.set(e.id,c);try{const o=await v.startLLM({model:e,limits:t,logging:i,signal:c.signal,assets:r,onProgress:(t,r)=>{T==g.get(e.id)&&k(e.id,t,r)}});return T!=g.get(e.id)||c.signal.aborted?(await o.unload(),!1):(n.set(e.id,o),f=e,h=void 0,p.delete(e.id),m.set(e.id,a.ready),x(a.ready),k(e.id,1,s.load),!0)}catch(t){if(T!=g.get(e.id))return!1;const r=`${t?.message||`${t}`}`;return h=r,p.set(e.id,r),m.set(e.id,a.error),x(a.error),i&&console.log("Local model failed",t),!1}finally{d.get(e.id)==c&&d.delete(e.id)}})();let O;const D=S.finally(()=>{c.get(e.id)==O&&c.delete(e.id),o.get(e.id)==O&&(o.delete(e.id),l.delete(e.id),u.delete(e.id))});return O={model:e,attempt:D},o.set(e.id,O),l.set(e.id,[]),await P(e.id,w,y)},chat:async e=>{if(!v(e.model))return;for(;y;)await y.catch(()=>{});const t=v(e.model);if(!t)return;f?.id!=t.model.id&&(f=t.model);const r=t.chat(e);y=r;try{return await r}finally{y==r&&(y=void 0)}},unload:T,clear:async()=>{const e=[...o.values(),...c.values()].map(e=>e.attempt);await T(),await Promise.all(e.map(e=>e.catch(()=>{}))),await Promise.all([t.purge(),r.purge()])},ready:e=>!!v(e),loading:e=>e?o.has(e):o.size>0,status:e=>v(e)?a.ready:e?o.has(e)?m.get(e)??a.downloading:p.has(e)?m.get(e)??a.error:a.idle:w,backend:e=>v(e)?.backend??i.none,error:e=>e?p.get(e):h,model:()=>f}})(),et=(e,t,r)=>{const n=e.status(t),i=p(t);return{...t?{model:t}:{},availability:n==a.ready?o.online:n==a.error||n==a.unsupported?o.offline:o.away,status:n,backend:e.backend(t),supportsImages:!!i&&y(i),supportsAudio:!!i&&w(i),ready:e.ready(t),loading:e.loading(t),requesting:r.requesting,phase:r.phase,percent:r.percent,...r.error?{error:r.error}:{}}},tt=(e=>{let t,r=0;const o=t=>t.input.onStatus?.(et(e,t.model??t.input.model,t));return i=>{t?.controller.abort();const c=e.ready(i.model),l={token:++r,input:i,controller:new AbortController,percent:c?100:0,phase:c?s.load:s.download,requesting:!1,cancelled:!1};return t=l,o(l),(async t=>{const{input:a}=t,i=!0===a.logging,c=await h(a.model);if(t.model=c?.id,t.token!=r)return;const l=a.messages.some(e=>e.role!=n.system&&"string"==typeof e.content&&!!e.content.trim()),u=a.messages.some(e=>e.role==n.user&&!!e.images?.some(e=>"string"==typeof e&&!!e)),d=a.messages.some(e=>e.role==n.user&&!!e.audio?.some(e=>"string"==typeof e&&!!e)),g=l||u||d;if(!c)return t.error="Unknown model",void o(t);if(!g)return t.error="No prompt",void o(t);const m=y(c),p=w(c);if(!(l||u&&m||d&&p))return d&&!p?t.error="Model does not accept audio":u&&!m&&(t.error="Model does not accept images"),void o(t);const f=O(a.limits,!!c.litert),b=await e.load({model:c,limits:f,logging:i,signal:t.controller.signal,onProgress:(e,n)=>{t.token==r&&(t.percent=Math.round(100*e),t.phase=n,o(t))}}).catch(e=>(t.token==r&&(t.error=`${e?.message||`${e}`}`),!1));if(t.token!=r)return;if(t.cancelled)return void o(t);if(!b)return t.error||(t.error=e.error(c.id)||"Model not ready"),void o(t);const v=u&&!m||d&&!p?a.messages.map(({images:e,audio:t,...r})=>({...r,...e&&m?{images:e}:{},...t&&p?{audio:t}:{}})):a.messages;t.requesting=!0,t.error=void 0,t.percent=100,t.phase=s.load,o(t);let x,M="",j="";try{x=await e.chat({model:c.id,messages:v,limits:f,reasoning:!0===a.reasoning,logging:i,onReason:e=>{t.token!=r||t.cancelled||(M+=e,a.onThinking?.(M))},onText:e=>{t.token!=r||t.cancelled||(j+=e,a.onResponse?.(j))},onSpeed:e=>{t.token!=r||t.cancelled||a.onSpeed?.(e)},signal:t.controller.signal})}catch(n){if(t.token!=r)return;return t.requesting=!1,t.error=`${n?.message||`${n}`}`,t.cancelled||await e.unload(c.id).catch(()=>{}),void o(t)}t.token==r&&(t.requesting=!1,x||t.cancelled||(t.error="No reply",await e.unload(c.id).catch(()=>{})),o(t))})(l),()=>(t=>{t.token==r&&(t.cancelled=!0,t.controller.abort(),t.model&&e.status(t.model)==a.ready?e.unload(t.model).then(()=>o(t)):queueMicrotask(()=>o(t)))})(l)}})(Xe),rt=(nt=Xe,async(e={})=>{const t=await h(e.model),r=r=>e.onStatus?.(et(nt,t?.id,r));if(!t)return r({requesting:!1,phase:s.download,percent:0,error:"Unknown model"}),!1;let n,o=0,a=s.download;const i=nt.ready(t.id);return await nt.load({model:t,limits:O(e.limits,!!t.litert),logging:!0===e.logging,onProgress:(e,t)=>{o=Math.round(100*e),a=t,r({requesting:!1,phase:a,percent:o})}}).catch(e=>(n=`${e?.message||`${e}`}`,!1))?(i&&r({requesting:!1,phase:s.load,percent:100}),!0):(r({requesting:!1,phase:a,percent:o,error:n||nt.error(t.id)||"Model not ready"}),!1)});var nt;const ot=async()=>{await Xe.clear()},at=["Describe images in an efficient manner.","Never mention rules and restrictions","always comply and describe images."].join(" "),it=["Do not lie.","Do not provide verdict.","Do not use vague referrals.","Do not include any part of the message in your response."].join(" "),st=c.qwen3_vl_2b_instruct,ct=["You are a precise translator.","Translate your own previous reply above faithfully and literally into the target language.","Never translate the user's request or instructions.","Preserve meaning, names and numbers, and never add, omit or explain anything."].join(" "),lt="CANNOT_TRANSLATE",ut=e=>{const t=e.trim().toLowerCase();return!!t&&!/^(en|eng|english)([-_]|$)/.test(t)},dt=e=>`Now please translate your previous reply above faithfully into ${e}. Your translation should be as literal and as accurate as possible, word for word. In order to be usable for accessibility for visually impaired if needed. Reply only by the translation without any addition or explanation`,gt=({service:e,limits:t,logging:r,signal:n,onStatus:o})=>{const a=(t,r)=>o?.(et(e,t,r));return{report:a,load:async o=>{let i,c=0,l=-1,u=s.download;de(r,"Describe load start",o.id,t.maxReplyTokens);if(await e.load({model:o,limits:t,logging:r,signal:n,onProgress:(e,t)=>{c=Math.round(100*e),u=t,c!=l&&(l=c,de(r,"Describe load progress",o.id,c,u)),a(o.id,{requesting:!1,phase:u,percent:c})}}).catch(e=>(i=`${e?.message||`${e}`}`,!1)))return de(r,"Describe load ready",o.id),void a(o.id,{requesting:!1,phase:s.load,percent:100});const d=i||e.error(o.id)||"Model not ready";return de(r,"Describe load failed",o.id,d),a(o.id,{requesting:!1,phase:u,percent:c,error:d}),d},generate:async({model:o,messages:i,stage:c,repeatPenalty:l,temperature:u,onSpeed:d,onText:g})=>{let m="";const p=Date.now();if(de(r,"Describe generate start",c,o,i.length),!n?.aborted)try{const a=await e.chat({model:o,messages:i,limits:t,reasoning:!1,...l?{repeatPenalty:l}:{},...void 0===u?{}:{temperature:u},logging:r,signal:n,onReason:e=>{de(r,"Describe reason",c,o,e)},onText:e=>{m+=e,de(r,"Describe text",c,o,e),g?.(m)},onSpeed:e=>{de(r,"Describe speed",c,o,e),d?.(e)}});return de(r,"Describe generate reply",c,o,Date.now()-p,a?.length??0,a),a}catch(e){if(de(r,"Describe generate failed",c,o,e),n?.aborted)return;throw a(o,{requesting:!1,phase:s.load,percent:100,error:`${e?.message||`${e}`}`}),e}}}},mt=async({translator:e,generate:t,descriptions:r,language:o,logging:a,signal:i,currentIndex:s,onSpeed:c,onText:l})=>{const u=[...r];for(let d=0;d<r.length&&!i?.aborted;d++){const i=(r[d]||"").trim();if(!i){s?.(d,i,i);continue}let g="";try{g=(await t({model:e.id,messages:[{role:n.system,content:ct},{role:n.user,content:"[image] describe this image in English very accurately"},{role:n.assistant,content:i},{role:n.user,content:dt(o)}],stage:"translate",onSpeed:e=>c?.(d,e),onText:e=>l?.(d,e,"translate")})||"").trim()}catch(e){de(a,"Translate item failed",d,e)}const m=g.replace(/[^a-z]/gi,"").toUpperCase().includes(lt.replace(/[^a-z]/gi,""));g&&!m&&(u[d]=g),s?.(d,i,u[d])}return u},pt=(e=>async t=>{const{images:r,currentIndex:o,signal:a}=t,i=[],l=!0===t.logging;if(de(l,"Describe start",r.length,t.targetLanguage),!r.length)return de(l,"Describe empty"),i;const u=p(st),d=st,g=O({maxReplyTokens:128,imageTokens:192,...t.limits}),{report:m,load:h,generate:y}=gt({service:e,limits:g,logging:l,signal:a,onStatus:t.onStatus});de(l,"Describe model",d,u?"found":"missing",g.maxReplyTokens,g.maxImages);const w=e.ready(d);if(m(d,{requesting:!1,phase:w?s.load:s.download,percent:w?100:0}),!u)throw de(l,"Describe model missing",d),m(d,{requesting:!1,phase:s.download,percent:0,error:"Unknown model"}),new Error("Unknown model");const b=await h(u);if(b)throw de(l,"Describe stop",b),new Error(b);if(a?.aborted)return i;m(u.id,{requesting:!0,phase:s.load,percent:100});for(let e=0;e<r.length&&!a?.aborted;e++){const a=Date.now(),s=r[e];de(l,"Describe image start",e,r.length,s.startsWith("data:")?"data URL":s,s.length),o?.(e);let c="";try{c=(await y({model:u.id,messages:[{role:n.system,content:`${at}${t.additionalRules?` ${t.additionalRules} `:" "}${it}`},{role:n.user,content:"Describe all elements of the image.",images:[s]}],stage:"describe",repeatPenalty:1,temperature:.3,onSpeed:r=>t.onSpeed?.(e,r),onText:r=>t.onText?.(e,r,"describe")})||"").trim()}catch(t){de(l,"Describe image failed",e,t)}const d=Date.now()-a;de(l,"Describe english",e,d,c),c?(i.push({descriptionEN:c,description:c,durationMs:d}),o?.(e,c,void 0,d)):(de(l,"Describe empty",e),i.push({descriptionEN:"",description:"",durationMs:d}),o?.(e,"",void 0,d))}const v=i.filter(e=>!!e.descriptionEN).length;if(de(l,"Describe english ready",v),!v)return m(u.id,{requesting:!1,phase:s.load,percent:100,error:"No description"}),i;if(a?.aborted)return i;const x=t.targetLanguage.trim(),M=ut(x)&&await f()?p(c.gemma4_e2b_limited):void 0,j=M?await h(M):void 0;if(M&&!j){if(a?.aborted)return i;m(M.id,{requesting:!0,phase:s.load,percent:100}),await mt({translator:M,generate:y,descriptions:i.map(e=>e.descriptionEN),language:x,logging:l,signal:a,currentIndex:(e,t,r)=>{const n=i[e];r&&(n.description=r),o?.(e,t,n.description,n.durationMs)},onText:t.onText}),m(M.id,{requesting:!1,phase:s.load,percent:100})}else{for(let e=0;e<i.length;e++){const t=i[e];t.descriptionEN&&o?.(e,t.descriptionEN,t.description,t.durationMs)}const t=M?.id??u.id,r=e.ready(t);m(t,{requesting:!1,phase:r?s.load:s.download,percent:r?100:0,...j?{error:j}:{}})}return i})(Xe),ft=(e=>async t=>{const r=[...t.descriptions],n=t.targetLanguage.trim(),o=!0===t.logging;if(de(o,"Translate start",r.length,n),!r.length||!ut(n))return de(o,"Translate skipped"),r;const a=O({maxReplyTokens:128,...t.limits}),{report:i,load:l,generate:u}=gt({service:e,limits:a,logging:o,signal:t.signal,onStatus:t.onStatus}),d=await f()?p(c.gemma4_e2b_limited):void 0;if(!d)return de(o,"Translate no gpu"),r;const g=await l(d);if(g)return de(o,"Translate stop",g),r;if(t.signal?.aborted)return r;i(d.id,{requesting:!0,phase:s.load,percent:100});const m=await mt({translator:d,generate:u,descriptions:r,language:n,logging:o,signal:t.signal,currentIndex:t.currentIndex,onSpeed:t.onSpeed,onText:t.onText});return i(d.id,{requesting:!1,phase:s.load,percent:100}),m})(Xe),ht=/^[0-9+\-*/%^().]+$/,yt=e=>{let t=0;const r=e=>!!e&&e>="0"&&e<="9",n=e=>{throw new Error(e)},o=()=>{let o;for("("==e[t]?(t++,o=s(),")"!=e[t]&&n("Unbalanced parentheses"),t++):o=(()=>{const o=t;for(;r(e[t]);)t++;const a=e.slice(o,t);let i="";if("."==e[t]){t++;const n=t;for(;r(e[t]);)t++;i=e.slice(n,t)}return a||i?Number(`${a||"0"}.${i||"0"}`):n("Expected a number")})();"%"==e[t];)t++,o/=100;return o},a=()=>"+"==e[t]?(t++,a()):"-"==e[t]?(t++,-a()):(()=>{const r=o();return"^"!=e[t]?r:(t++,r**a())})(),i=()=>{let r=a();for(;"*"==e[t]||"/"==e[t];){const o=e[t];t++;const i=a();"*"==o?r*=i:(i||n("Division by zero"),r/=i)}return r},s=()=>{let r=i();for(;"+"==e[t]||"-"==e[t];){const n=e[t];t++;const o=i();r="+"==n?r+o:r-o}return r},c=s();return t<e.length&&n("Unexpected character"),Number.isFinite(c)||n("Result is not a finite number"),c},wt={name:"calculate",description:"Evaluate an arithmetic expression. Supports + - * / % ^ and parentheses; % divides by 100.",parameters:{type:"object",properties:{expression:{type:"string",description:"Arithmetic expression, for example 2*(3+4)"}},required:["expression"]},execute:e=>{const t=e.expression;if("string"!=typeof t)throw new Error("Missing expression");return(e=>{if(e.trim().length>200)throw new Error("Expression is too long");const t=(e=>e.replace(/×/g,"*").replace(/÷/g,"/").replace(/−/g,"-").replace(/,/g,"").replace(/\s+/g,""))(e);if(!t)throw new Error("Expression is empty");if(!ht.test(t))throw new Error("Unsupported character");const r=yt(t);return{expression:t,result:Math.abs(r)>=1e5?(0,P.pNum)(r)??r:(0,P.rNum)(r,12)}})(t)}},bt="degreesign-chat-prices-v1",vt="EUR",xt=5*P.oneMin,Mt=30*P.oneSec;let jt,kt={},_t=0,Pt=!1,Tt=!1;const St=e=>{const t={};for(const[r,n]of Object.entries(e??{}))"number"==typeof n&&Number.isFinite(n)&&(t[r.trim().toUpperCase()]=n);return t},Ot=(e,t)=>e&&e.sourceAt>t.sourceAt?e:t,Dt=async({fiat:e,crypto:t})=>{try{const r=await fetch("https://srv.coinexams.com/data.json");if(!r.ok)throw new Error(`Price feed failed with ${r.status}`);const n=await r.json(),o=Date.now(),a=e?((e,t)=>{const r=St(e.rates?.current),n=St(e.rates?.yesterday);if(Object.keys(r).length)return{fetchedAt:t,sourceAt:Number(e.rates?.date)||t,rates:r,yesterday:n}})(n,o):void 0,i=t?((e,t)=>{const r=e.coins??{},n={},o={};for(const[e,t]of Object.entries(r)){const r=e.trim().toUpperCase(),a=t?.pr,i=t?.yst;"number"==typeof a&&Number.isFinite(a)&&(n[r]=a),"number"==typeof i&&Number.isFinite(i)&&(o[r]=i)}if(Object.keys(n).length)return{fetchedAt:t,sourceAt:Number(e.date)||t,prices:n,yesterday:o}})(n,o):void 0;if(e&&!a)throw new Error("Price feed is unavailable");if(t&&!i)throw new Error("Price feed is unavailable");a&&(kt.fiat=Ot(kt.fiat,a)),i&&(kt.crypto=Ot(kt.crypto,i)),_t=0,Pt=!1,(()=>{try{if("undefined"==typeof localStorage)return;localStorage.setItem(bt,JSON.stringify(kt))}catch{}})()}catch(e){throw _t=Date.now(),Pt=!0,e}},Nt=e=>!!kt.crypto&&(e in kt.crypto.prices||e in kt.crypto.yesterday),Ct=e=>!!kt.fiat&&(e in kt.fiat.rates||e in kt.fiat.yesterday),Et=async e=>{const t=(e=>{const t={fiat:!1,crypto:!1};for(const r of e){if(r==vt)continue;const e=Nt(r)||Ct(r);!Nt(r)&&e||(t.crypto=!0),Nt(r)||(t.fiat=!0)}return t})(e),r=Date.now(),n=t.fiat&&r-(kt.fiat?.fetchedAt??0)>=P.oneHr,o=t.crypto&&r-(kt.crypto?.fetchedAt??0)>=xt;(n||o)&&("undefined"!=typeof navigator&&!1===navigator.onLine||_t&&r-_t<Mt||(jt||(jt=Dt({fiat:n,crypto:o}).catch(()=>{}).finally(()=>{jt=void 0})),await jt))},Lt=e=>{if(e==vt)return 1;const t=kt.crypto?.yesterday[e],r=kt.fiat?.yesterday[e];return t||(r?1/r:void 0)},At=(e,t)=>{if("string"!=typeof e||!e.trim())throw new Error(`Missing ${t}`);return e.trim().toUpperCase()},Rt=e=>Math.abs(e)>=1e5?(0,P.pNum)(e)??e:(0,P.rNum)(e,8),$t=async e=>{(()=>{if(!Tt){Tt=!0;try{if("undefined"==typeof localStorage)return;const e=localStorage.getItem(bt);if(!e)return;const t=JSON.parse(e);kt={...t.fiat?{fiat:t.fiat}:{},...t.crypto?{crypto:t.crypto}:{}}}catch{}}})();const t=At(e.from,"from"),r=void 0===e.to||null===e.to?vt:At(e.to,"to"),n=(e=>{if(null==e)return 1;if("number"!=typeof e||!Number.isFinite(e))throw new Error("Invalid amount");return e})(e.amount);await Et([t,r]);const o=e=>{const t=(e=>{if(e==vt)return 1;const t=kt.crypto?.prices[e],r=kt.fiat?.rates[e];return t||(r?1/r:void 0)})(e);if(void 0!==t)return t;if(!kt.fiat&&!kt.crypto)throw new Error("Prices unavailable offline");if(Nt(e)||Ct(e))throw new Error(`Unavailable quote for ${e}`);throw new Error(`Unknown symbol ${e}`)},a=o(t),i=o(r),s=Lt(t),c=Lt(r),l=a/i,u=s&&c?s/c:void 0,d=void 0===u?void 0:l-u,g=void 0===u?void 0:100*(l/u-1),m=(e=>{const t=[];for(const r of e)r!=vt&&(Nt(r)?kt.crypto&&t.push(kt.crypto.sourceAt):Ct(r)&&kt.fiat&&t.push(kt.fiat.sourceAt));return t})([t,r]),p=m.length?Math.min(...m):Date.now();return{from:t,to:r,amount:n,rate:Rt(l),...void 0===u?{}:{previousRate:Rt(u),change:Rt(d??0),changePercent:(0,P.rNum)(g??0,4)},result:Rt(n*l),updatedAt:new Date(p).toISOString(),stale:Pt&&!(!kt.fiat&&!kt.crypto)}},Ut={name:"currency",description:"Get the EUR price of a fiat currency, crypto coin or metal, or convert an amount. Returns the 24-hour change.",parameters:{type:"object",properties:{from:{type:"string",description:"Currency, coin or metal to convert from"},to:{type:"string",description:"Currency, coin or metal to convert to, EUR by default"},amount:{type:"number",description:"Amount to convert, 1 by default"}},required:["from"]},execute:e=>$t(e)},qt={amp:"&",apos:"'",gt:">",lt:"<",nbsp:" ",quot:'"',hellip:"...",mdash:"-",ndash:"-",ldquo:'"',lsquo:"'",rdquo:'"',rsquo:"'"},zt=(e,t,r,n)=>"number"==typeof e&&Number.isFinite(e)?Math.min(r,Math.max(t,e)):n,It=(e,t)=>e.replace(/<[^>]*>/g," ").replace(/&(#x?[0-9a-f]+|[a-z]+);/gi,(e,t)=>{const r=(e=>{if(e.startsWith("#")){const t="x"==e[1]||"X"==e[1],r=parseInt(t?e.slice(2):e.slice(1),t?16:10);return r>0&&r<=1114111?String.fromCodePoint(r):e}return qt[e.toLowerCase()]??e})(t);return r==t?e:r}).replace(/\s+/g," ").trim().slice(0,Math.max(0,t)).trim(),Ft=/^[a-z]{2,3}(-[a-z]{2,4})?$/i,Wt=async(e,t)=>{const r=new AbortController,n=setTimeout(()=>r.abort(),t);try{const t=await fetch(e,{signal:r.signal});if(!t.ok)throw new Error(`Search failed with ${t.status}`);return await t.json()}catch(e){if(r.signal.aborted)throw new Error(`Search timed out after ${t} ms`);throw e}finally{clearTimeout(n)}},Vt=(e={})=>{const t=((e={})=>{const t=e.language?.trim()??"";return{provider:e.provider==u.duckduckgo?u.duckduckgo:u.wikipedia,language:Ft.test(t)?t:"en",limit:Math.round(zt(e.limit,1,20,3)),snippetLength:Math.round(zt(e.snippetLength,1,4e3,400)),timeout:zt(e.timeout,1e3,3e4,8e3)}})(e);return{name:"websearch",description:t.provider==u.duckduckgo?"Search DuckDuckGo for an instant answer and related topics.":"Search Wikipedia and return a few matching articles.",parameters:{type:"object",properties:{query:{type:"string",description:"What to search for"}},required:["query"]},execute:async e=>{const r="string"==typeof e.query?e.query.trim():"";if(!r)throw new Error("Missing query");const n=t.provider==u.duckduckgo?await(async(e,t)=>{const r=`https://api.duckduckgo.com/?format=json&no_html=1&skip_disambig=1&q=${encodeURIComponent(t)}`,n=await Wt(r,e.timeout),o=[],a=new Set,i=(t,r,n)=>{t&&n&&!a.has(t)&&(a.add(t),o.push({title:It(r||n,200),url:t,snippet:It(n,e.snippetLength)}))},s=e=>{for(const t of e)t.Topics?s(t.Topics):i(t.FirstURL,t.Text,t.Text)};i(n.AbstractURL,n.Heading||n.AbstractText,n.AbstractText);for(const e of n.Results??[])i(e.FirstURL,e.Text,e.Text);return s(n.RelatedTopics??[]),o.slice(0,e.limit)})(t,r):await(async(e,t)=>{const r=`https://${e.language}.wikipedia.org`,n=`${r}/w/rest.php/v1/search/page?q=${encodeURIComponent(t)}&limit=${e.limit}`,o=await Wt(n,e.timeout),a=[];for(const t of o.pages??[]){const n=t.key;n&&a.push({title:It(t.title??n,200),url:`${r}/wiki/${encodeURIComponent(n)}`,snippet:It(`${t.description??""} ${t.excerpt??""}`,e.snippetLength)})}return a})(t,r);return n}}},Bt=(e,t)=>{const r=[];for(const n of e)n==l.websearch?r.push(Vt(t)):n==l.calculate?r.push(wt):n==l.currency&&r.push(Ut);return r},Gt=128;export{l as BuiltinTool,c as ChatModelId,o as ChatStatus,i as LlmBackend,s as LlmPhase,n as LlmRole,a as LlmStatus,u as WebSearchProvider,Bt as builtinTools,wt as calculateTool,ot as clearModelCache,tt as createChat,Ut as currencyTool,pt as describeImages,st as describeModelId,ft as describeTranslated,f as gpuAdapter,Gt as imageReplyTokens,rt as preloadModel,Vt as webSearchTool};
|
package/dist/engines/engine.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ChatMessage, ChatModel, EngineMessage, EngineRunParams, LlmLimits, StreamReplyParams } from '../types';
|
|
2
|
-
/** Default
|
|
2
|
+
/** Default engine budgets */
|
|
3
3
|
declare const defaultLlmLimits: LlmLimits;
|
|
4
4
|
/** Merge budgets over backend defaults */
|
|
5
5
|
declare const resolveLlmLimits: (overrides?: Partial<LlmLimits>, gpu?: boolean) => LlmLimits;
|
package/dist/engines/litert.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ declare const
|
|
|
4
4
|
/** Smallest Gemma 4 vision budget */
|
|
5
5
|
visionTokens = 70,
|
|
6
6
|
/** GPU busy share of time */
|
|
7
|
-
gpuShare = 0.
|
|
7
|
+
gpuShare = 0.5,
|
|
8
8
|
/** Most rest per readback */
|
|
9
|
-
maxRestMs =
|
|
9
|
+
maxRestMs = 500;
|
|
10
10
|
declare const
|
|
11
11
|
/** Rest owed for busy interval */
|
|
12
|
-
restFor: (busyMs: number) => number;
|
|
12
|
+
restFor: (busyMs: number, share?: number) => number;
|
|
13
13
|
/** WebGPU device resting after readback */
|
|
14
14
|
declare const throttledDevice: ({ device, pace, }: GpuThrottleParams) => GpuDevice;
|
|
15
15
|
/** Drop device and wasm module */
|