@degreesign/chat 0.6.2 → 0.7.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 +34 -167
- package/dist/browser/chat.min.mjs +1 -1
- package/dist/engines/litert.d.ts +3 -22
- package/dist/index.d.ts +1 -0
- package/dist/models.d.ts +2 -4
- package/dist/node/chat.node.min.js +1 -1
- package/dist/node/chat.node.min.mjs +1 -1
- package/dist/tools/index.d.ts +6 -7
- package/dist/types.d.ts +16 -68
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,8 +40,6 @@ package loads one model, streams one reply and reports status.
|
|
|
40
40
|
capped by the prompt budgets.
|
|
41
41
|
- Audio: a user turn can carry an audio URL, sent only to a model with audio
|
|
42
42
|
support and capped by the prompt budgets.
|
|
43
|
-
- Tools: the model may call Web search, arithmetic and currency built-ins, plus
|
|
44
|
-
any tool the host supplies, in the same reply.
|
|
45
43
|
- Reusable: the loaded model stays in memory for the next call.
|
|
46
44
|
- Typed: written in TypeScript with declarations for every export.
|
|
47
45
|
- Portable: importing and calling works in browsers, workers, React and Node.
|
|
@@ -61,11 +59,11 @@ yarn add @degreesign/chat
|
|
|
61
59
|
pnpm add @degreesign/chat
|
|
62
60
|
```
|
|
63
61
|
|
|
64
|
-
`@wllama/wllama`, `@wllama/wllama-compat
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
`@wllama/wllama`, `@wllama/wllama-compat` and `@litert-lm/core` are build-time
|
|
63
|
+
dependencies. The engines are bundled into the published build as dynamic
|
|
64
|
+
chunks and their wasm assets ship beside them, so a consumer installs nothing
|
|
65
|
+
extra and resolves no engine import. Only the model weights are downloaded at
|
|
66
|
+
runtime.
|
|
69
67
|
|
|
70
68
|
The build emits:
|
|
71
69
|
|
|
@@ -241,12 +239,6 @@ requested model is already loaded, no download or load happens.
|
|
|
241
239
|
| `onResponse` | Receives the accumulated reply text as it streams. Required. |
|
|
242
240
|
| `onSpeed?` | Receives the current generation speed in tokens per second. |
|
|
243
241
|
| `onStatus?` | Receives a `ChatStatusSnapshot` on every state change. |
|
|
244
|
-
| `builtins?` | Built-in tools to attach, all three by default; `false` attaches none. |
|
|
245
|
-
| `websearch?` | `WebSearchConfig` for the built-in search, provider, language and limits. |
|
|
246
|
-
| `tools?` | Extra `ChatTool` entries, appended after the built-ins. |
|
|
247
|
-
| `onToolCall?` | Receives a `ChatToolCall` before a tool runs. |
|
|
248
|
-
| `onToolResult?` | Receives a `ChatToolResult` when a tool returns or throws. |
|
|
249
|
-
| `maxToolRounds?` | Ceiling on tool rounds in one reply, default 4, clamped 1 to 25. |
|
|
250
242
|
|
|
251
243
|
Without `model` the package picks the GPU build when the browser provides a
|
|
252
244
|
WebGPU adapter and the CPU build when it does not. The budget defaults are 250
|
|
@@ -294,143 +286,33 @@ on failure. A preload owns no cancel function; a new load replaces it.
|
|
|
294
286
|
|
|
295
287
|
## Tools
|
|
296
288
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
inside the one `createChat` call. Qwen3-VL 2B and the CPU engine never receive
|
|
300
|
-
tools: `ChatStatusSnapshot.supportsTools` reports `false` there, the built-ins
|
|
301
|
-
are dropped and a host tool ends the call with `Model does not accept tools`.
|
|
302
|
-
|
|
303
|
-
Three built-ins ship and all three attach by default:
|
|
304
|
-
|
|
305
|
-
| `BuiltinTool` | What it does |
|
|
306
|
-
| ------------- | ------------ |
|
|
307
|
-
| `websearch` | Searches Wikipedia by default, or DuckDuckGo, and returns a few hits. |
|
|
308
|
-
| `calculate` | Evaluates an arithmetic expression with a safe parser. |
|
|
309
|
-
| `currency` | Quotes and converts fiat, crypto and metals with the 24-hour change. |
|
|
289
|
+
Three built-in tools ship as descriptors. They are not connected to the model:
|
|
290
|
+
the package never declares a tool to an engine and never runs one by itself.
|
|
310
291
|
|
|
311
292
|
```ts
|
|
312
|
-
import {
|
|
293
|
+
import { builtinTools, BuiltinTool } from '@degreesign/chat';
|
|
313
294
|
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
// all three by default; narrow or disable them here
|
|
317
|
-
builtins: [BuiltinTool.calculate, BuiltinTool.currency],
|
|
318
|
-
websearch: { provider: WebSearchProvider.wikipedia, language: "en", limit: 3 },
|
|
319
|
-
onToolCall: (call) => renderToolStart(call),
|
|
320
|
-
onToolResult: (result) => renderToolEnd(result),
|
|
321
|
-
onResponse: (text) => renderReply(text),
|
|
322
|
-
});
|
|
295
|
+
const [calculation] = builtinTools([BuiltinTool.calculate]);
|
|
296
|
+
const answer = await calculation.execute({ expression: `6*7` });
|
|
323
297
|
```
|
|
324
298
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
`
|
|
332
|
-
|
|
333
|
-
conversation.
|
|
299
|
+
| Export | Description |
|
|
300
|
+
| ------ | ----------- |
|
|
301
|
+
| `builtinTools(names, config?)` | Returns the requested tools in the order given. |
|
|
302
|
+
| `calculateTool` | Evaluates an arithmetic expression, fully local. |
|
|
303
|
+
| `currencyTool` | Converts between fiat, metals and coins through the CoinExams feed. |
|
|
304
|
+
| `webSearchTool(config?)` | Searches Wikipedia by default, or DuckDuckGo. |
|
|
305
|
+
| `BuiltinTool` | `websearch`, `calculate` or `currency`. |
|
|
306
|
+
| `WebSearchProvider` | `wikipedia` or `duckduckgo`. |
|
|
334
307
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
messages,
|
|
340
|
-
tools: [
|
|
341
|
-
{
|
|
342
|
-
name: "lookup_order",
|
|
343
|
-
description: "Read one order from the shop.",
|
|
344
|
-
parameters: {
|
|
345
|
-
type: "object",
|
|
346
|
-
properties: {
|
|
347
|
-
id: { type: "string", description: "Order id" },
|
|
348
|
-
},
|
|
349
|
-
required: ["id"],
|
|
350
|
-
},
|
|
351
|
-
execute: async ({ id }) => await shop.order(String(id)),
|
|
352
|
-
},
|
|
353
|
-
],
|
|
354
|
-
onToolCall: (call) => renderToolStart(call),
|
|
355
|
-
onToolResult: (result) => renderToolEnd(result),
|
|
356
|
-
onResponse: (text) => renderReply(text),
|
|
357
|
-
});
|
|
358
|
-
```
|
|
308
|
+
Each tool has `name`, `description`, `parameters` (`ChatToolSchema`) and
|
|
309
|
+
`execute(args)`, which returns a JSON-safe `ChatToolValue` or throws. `ChatTool`
|
|
310
|
+
is that whole shape, and `ChatToolCall` / `ChatToolResult` describe a call and
|
|
311
|
+
its outcome for a host that records them.
|
|
359
312
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
- `execute` receives the parsed arguments and may return a value or a promise.
|
|
364
|
-
A thrown error becomes a tool error the model reads, and `onToolResult`
|
|
365
|
-
receives `error`.
|
|
366
|
-
- Tools and callbacks are captured when the conversation is created. Rebuilding
|
|
367
|
-
the array with the same functions and declarations reuses the conversation;
|
|
368
|
-
changing a declaration or a function opens a new one and pays one history
|
|
369
|
-
prefill.
|
|
370
|
-
- The package cannot abort a running `execute`. A cancel stops generation and
|
|
371
|
-
discards its result.
|
|
372
|
-
- The package neither clamps nor times out a host result. Keep it small: three
|
|
373
|
-
declarations already cost roughly 200 to 250 of the 4096 context tokens.
|
|
374
|
-
|
|
375
|
-
### Search
|
|
376
|
-
|
|
377
|
-
`websearch` sends one query and returns a short list of `title`, `url` and
|
|
378
|
-
`snippet`.
|
|
379
|
-
|
|
380
|
-
| `WebSearchConfig` | Default | Meaning |
|
|
381
|
-
| ----------------- | ------- | ------- |
|
|
382
|
-
| `provider` | Wikipedia | `WebSearchProvider.wikipedia` or `.duckduckgo`. |
|
|
383
|
-
| `language` | `en` | Wikipedia edition, two or three letters plus an optional region. |
|
|
384
|
-
| `limit` | 3 | Hits asked of the provider, clamped 1 to 20. |
|
|
385
|
-
| `snippetLength` | 400 | Characters kept per snippet. |
|
|
386
|
-
| `timeout` | 8000 | Request budget in milliseconds. |
|
|
387
|
-
|
|
388
|
-
Wikipedia is the default because its REST search has CORS `*`, no key and a
|
|
389
|
-
predictable result shape. DuckDuckGo returns an instant answer and related
|
|
390
|
-
topics, and many queries have neither, so it can return an empty list. Both
|
|
391
|
-
endpoints are public and keyless.
|
|
392
|
-
|
|
393
|
-
### Calculator
|
|
394
|
-
|
|
395
|
-
`calculate` accepts `+`, `-`, `*`, `/`, `%`, `^` and parentheses, and returns
|
|
396
|
-
`{ expression, result }`.
|
|
397
|
-
|
|
398
|
-
- `×`, `÷` and `−` are normalized, and thousands commas and spaces are removed.
|
|
399
|
-
- No implicit multiplication: write `2*(3+4)`.
|
|
400
|
-
- No functions: use `^0.5` for a square root.
|
|
401
|
-
- `%` is a postfix division by 100, so `200*15%` is 30 and `200+10%` is 200.1.
|
|
402
|
-
- Unbalanced parentheses, division by zero, an unknown character, an expression
|
|
403
|
-
over 200 characters and a non-finite result are errors.
|
|
404
|
-
- The parser is hand written. The package never uses `eval` or `new Function`.
|
|
405
|
-
|
|
406
|
-
### Currency
|
|
407
|
-
|
|
408
|
-
`currency` reads one public price file published by [CoinExams](https://coinexams.com)
|
|
409
|
-
and answers from it.
|
|
410
|
-
|
|
411
|
-
- Every rate is quoted against `EUR`, which is always 1.
|
|
412
|
-
- Fiat and metals come from the fiat section. Crypto comes from the coin
|
|
413
|
-
section, which wins when a symbol appears in both.
|
|
414
|
-
- Metals are `XAU`, `XAG`, `XPT` and `XPD`, quoted per gram. A zero or missing
|
|
415
|
-
quote is unavailable.
|
|
416
|
-
- Arguments are `from` (required), `to` (default `EUR`) and `amount` (default 1).
|
|
417
|
-
- A result carries `from`, `to`, `amount`, `rate`, `result`, `updatedAt` and
|
|
418
|
-
`stale`, plus `previousRate`, `change` and `changePercent` when the feed has a
|
|
419
|
-
24-hour value for both symbols.
|
|
420
|
-
|
|
421
|
-
The feed is cached on the device under `degreesign-chat-prices-v1` in
|
|
422
|
-
`localStorage`. Fiat and metals refresh at most hourly, crypto at most every
|
|
423
|
-
five minutes, and concurrent calls share one fetch. A failed refresh keeps the
|
|
424
|
-
previous snapshot, serves it with `stale: true` and waits 30 seconds before the
|
|
425
|
-
next attempt. `navigator.onLine === false` skips the fetch and serves the cache.
|
|
426
|
-
With no cache and no network the tool reports `Prices unavailable offline`.
|
|
427
|
-
|
|
428
|
-
### Privacy
|
|
429
|
-
|
|
430
|
-
Search sends the model's query to the chosen provider, and currency fetches the
|
|
431
|
-
public price file. Nothing else leaves the device, and no key is sent. To keep a
|
|
432
|
-
call fully local, pass `builtins: [BuiltinTool.calculate]`, which computes on
|
|
433
|
-
device.
|
|
313
|
+
`webSearchTool` takes `WebSearchConfig`: `provider`, a Wikipedia `language`
|
|
314
|
+
edition, `limit` results, `snippetLength` and a `timeout` in milliseconds. The
|
|
315
|
+
search and currency tools fetch over the network; `calculate` does not.
|
|
434
316
|
|
|
435
317
|
## Status
|
|
436
318
|
|
|
@@ -443,7 +325,6 @@ device.
|
|
|
443
325
|
| `backend` | `LlmBackend.cpu`, `.gpu` or `.none`. |
|
|
444
326
|
| `supportsImages` | Whether the requested model accepts images. |
|
|
445
327
|
| `supportsAudio` | Whether the requested model accepts audio. |
|
|
446
|
-
| `supportsTools` | Whether the requested model accepts tool declarations. |
|
|
447
328
|
| `ready` | Whether a model is loaded and accepts a reply. |
|
|
448
329
|
| `loading` | Whether a download or load is in flight. |
|
|
449
330
|
| `requesting` | Whether a reply is streaming right now. |
|
|
@@ -458,12 +339,6 @@ A stream that never produces its first chunk ends with an error after 180
|
|
|
458
339
|
seconds instead of waiting forever. Once a chunk has arrived, 30 seconds of
|
|
459
340
|
silence ends the stream and keeps the text already delivered.
|
|
460
341
|
|
|
461
|
-
A lost WebGPU device is rebuilt once: the package drops the dead engine and its
|
|
462
|
-
device, reloads the LiteRT wasm, retries the turn on the next smaller context
|
|
463
|
-
window (4096, 2048, 1024) and reports the reply normally. When no rebuild is
|
|
464
|
-
possible the runtime ends as `error` with `backend: none`, so the host can fall
|
|
465
|
-
back to the CPU model.
|
|
466
|
-
|
|
467
342
|
## Logging
|
|
468
343
|
|
|
469
344
|
Console output stays off by default. Pass `logging: true` in a call to receive
|
|
@@ -473,10 +348,10 @@ without it goes quiet again.
|
|
|
473
348
|
|
|
474
349
|
## Models
|
|
475
350
|
|
|
476
|
-
| `ChatModelId` | Name | Reasoning | Images | Audio |
|
|
477
|
-
| ------------- | ---- | --------- | ------ | ----- |
|
|
478
|
-
| `qwen3_vl_2b` | Qwen3-VL 2B | Yes | Yes | No |
|
|
479
|
-
| `gemma4_e2b` | Gemma 4 E2B | Yes | Desktop | Desktop |
|
|
351
|
+
| `ChatModelId` | Name | Reasoning | Images | Audio | CPU | WebGPU |
|
|
352
|
+
| ------------- | ---- | --------- | ------ | ----- | --- | ------ |
|
|
353
|
+
| `qwen3_vl_2b` | Qwen3-VL 2B | Yes | Yes | No | Yes | No |
|
|
354
|
+
| `gemma4_e2b` | Gemma 4 E2B | Yes | Desktop | Desktop | No | Yes |
|
|
480
355
|
|
|
481
356
|
A phone or tablet asking for Gemma gets the browser build,
|
|
482
357
|
`gemma-4-E2B-it-gpu.litertlm`, which is text only. It has no vision or audio
|
|
@@ -684,16 +559,9 @@ const useReply = () => {
|
|
|
684
559
|
| `ChatStatusSnapshot` | Availability, engine status, backend, progress and request state. |
|
|
685
560
|
| `LlmLimits` | Token, prompt, image, audio and thread budgets, all overridable. |
|
|
686
561
|
| `WllamaAssets` | Wasm, compat wasm and compat worker URLs. |
|
|
687
|
-
| `ChatTool` | One tool: `name`, `description`, `parameters` and `execute`. |
|
|
688
|
-
| `ChatToolSchema` | The JSON-schema subset a tool parameter declares. |
|
|
689
|
-
| `ChatToolValue` | A JSON-safe argument or result value. |
|
|
690
|
-
| `ChatToolCall` | One model call: `id`, `name` and parsed `arguments`. |
|
|
691
|
-
| `ChatToolResult` | A finished call, with `result` or `error`. |
|
|
692
|
-
| `WebSearchConfig` | Provider, language, limit, snippet length and timeout. |
|
|
693
|
-
| `WebSearchResult` | One hit: `title`, `url` and `snippet`. |
|
|
694
562
|
|
|
695
563
|
The public enums are `ChatModelId`, `LlmRole`, `ChatStatus`, `LlmStatus`,
|
|
696
|
-
`LlmBackend
|
|
564
|
+
`LlmBackend` and `LlmPhase`.
|
|
697
565
|
|
|
698
566
|
## Architecture
|
|
699
567
|
|
|
@@ -741,11 +609,10 @@ includes no server component.
|
|
|
741
609
|
|
|
742
610
|
### Does it have runtime dependencies?
|
|
743
611
|
|
|
744
|
-
No runtime dependencies. `@wllama/wllama`, `@wllama/wllama-compat
|
|
745
|
-
`@litert-lm/core`
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
they use.
|
|
612
|
+
No runtime dependencies. `@wllama/wllama`, `@wllama/wllama-compat` and
|
|
613
|
+
`@litert-lm/core` are build-time dependencies, bundled into the dynamic engine
|
|
614
|
+
chunks and their wasm assets, so consumers resolve no engine import and
|
|
615
|
+
download no engine code beyond the chunk they use.
|
|
749
616
|
|
|
750
617
|
### Where are the models stored?
|
|
751
618
|
|
|
@@ -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.gemma4_e2b="gemma4-e2b"}(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 f=[{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.gemma4_e2b,reasoning:!0,litert:{repo:"litert-community/gemma-4-E2B-it-litert-lm",file:"gemma-4-E2B-it.litertlm",vision:!0,audio:!0,tools:!0,web:{file:"gemma-4-E2B-it-gpu.litertlm",vision:!1,audio:!1,tools:!0}}}],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,t=m())=>{const r=e.litert;if(r)return t&&r.web?r.web:{file:r.file,vision:r.vision,audio:r.audio,tools:r.tools}},g=e=>e?f.find(t=>t.id==e):void 0,h=async()=>(d||(d=(async()=>(await(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)}})()?f.find(e=>!!e.litert):f.find(e=>!!e.cpu))?.id)()),await d),y=async e=>g(e||await h()),w=(e,t=m())=>!!e.cpu?.mmproj||!0===p(e,t)?.vision,b=(e,t=m())=>!!e.cpu?.mmproj?.audio||!0===p(e,t)?.audio,v=(e,t=m())=>!0===p(e,t)?.tools,x=new URL("./../assets/wllama/wllama.wasm",import.meta.url).href,j=new URL("./../assets/wllama/compat/wllama.wasm",import.meta.url).href,M=new URL("./../assets/wllama/compat/wllama.js",import.meta.url).href,k=new URL("./../assets/litert/litertlm_wasm_internal.js",import.meta.url).href,P=(new URL("./../assets/litert/litertlm_wasm_internal.wasm",import.meta.url).href,288),T=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},O=async e=>{if(!e||"function"!=typeof fetch||"function"!=typeof createImageBitmap)return e;try{const t=await fetch(e),r=await createImageBitmap(await t.blob()),n=Math.min(r.width,r.height),o=Math.floor((r.width-n)/2),a=Math.floor((r.height-n)/2),i=((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})(P,P),s=i?i.getContext("2d"):null;if(!i||!s||n<1)return r.close(),e;if(s.drawImage(r,o,a,n,n,0,0,P,P),r.close(),(e=>"undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)(i)){const t=await i.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 i.toDataURL("image/jpeg",.85)}catch{return e}},S={maxReplyTokens:250,maxThinkingTokens:128,maxReasoningTokens:320,maxImages:2,maxAudio:1,maxContentLength:1e3,promptCharBudget:1e4,maxThreads:6},C=(e,t,r)=>"number"==typeof e&&Number.isFinite(e)&&e>=r?Math.floor(e):t,N=(e={},t=!1)=>{const r=S;return{maxReplyTokens:C(e.maxReplyTokens,r.maxReplyTokens,1),maxThinkingTokens:C(e.maxThinkingTokens,r.maxThinkingTokens,1),maxReasoningTokens:C(e.maxReasoningTokens,t?1200:r.maxReasoningTokens,1),maxImages:C(e.maxImages,r.maxImages,0),maxAudio:C(e.maxAudio,r.maxAudio,0),maxContentLength:C(e.maxContentLength,r.maxContentLength,1),promptCharBudget:C(e.promptCharBudget,r.promptCharBudget,1),maxThreads:C(e.maxThreads,r.maxThreads,1)}},E=(e,t)=>({stream:!0,temperature:.7,max_tokens:t?e.maxReasoningTokens:e.maxReplyTokens}),_=(e,t)=>`https://huggingface.co/${e}/resolve/main/${t}`,A=e=>Number(e.headers.get("content-length"))||0,D=(e,t)=>e.some(e=>Array.isArray(e.content)&&e.content.some(e=>e.type==t)),L=e=>D(e,"image"),R=e=>D(e,"audio"),$=["<|channel>thought\n","<|channel>thought","..."],U=["<channel|>","..."],q=(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,z=e=>"string"==typeof e?e?[{type:"text",text:e}]:[]:e,F=(e,t)=>{if("string"==typeof e&&"string"==typeof t)return`${e}\n${t}`;const r=[];for(const n of[...z(e),{type:"text",text:"\n"},...z(t)]){const e=r[r.length-1];"text"==n.type&&"text"==e?.type?e.text+=n.text:r.push(n)}return r};class I extends Error{}const W=async(e,t,r)=>{let n;try{return await Promise.race([e,new Promise((e,o)=>{n=setTimeout(()=>o(new I(r)),t)})])}finally{n&&clearTimeout(n)}},V=e=>{try{Promise.resolve(e.return?.()).catch(()=>{})}catch{}},B=async({model:e,logging:t,onReason:r,onText:n,onSpeed:o,start:a,stopped:i,firstTimeoutMs:s=18e4,idleTimeoutMs:c=3e4,onStall:l})=>{let u="",d="",f="",m=!1,p=0,g=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,U);if(t>=0){t&&e(s.slice(0,t)),s=s.slice(t+i.length),n=!1;continue}const c=a(s,U);e(s.slice(0,s.length-c.length)),r=c;break}{const{at:e,tag:i}=o(s,$);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,$);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=(await W(a(),s,"Model did not start"))[Symbol.asyncIterator]();for(;;){if(i()){V(e);break}let n;try{n=await W(e.next(),m?c:s,m?"Model stopped responding":"Model did not reply")}catch(r){if(r instanceof I&&(u||d)){l?.(),V(e),t&&console.log("Local chat stalled",r);break}throw r}if(n.done)break;m=!0;const a=n.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&&(f=a.finish_reason),w&&(d+=w,r(w)),y?.content&&h.feed(y.content),w||y?.content){const e=performance.now();p||(g=e),p+=1,p>1&&e>g&&o?.(1e3*p/(e-g))}}h.flush()}catch(e){if(t&&console.log("Local chat failed",e),!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,f||"none",u.length,d.length)),y},H=async({model:e,params:t,start:r,stopped:o,onStall:a})=>{const i=await(async e=>{const t=[];for(const r of e){if("string"==typeof r.content){t.push(r);continue}const e=[];for(const t of r.content)e.push("image"==t.type?{type:"image",url:await O(t.url)}:t);t.push({role:"user",content:e})}return t})(((e,t=S)=>{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),f=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||f.length||m.length){if(d&&s+d.length>t.promptCharBudget)break;s+=d.length,c-=f.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:q(d,f,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=F(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"),f=[];return d&&f.push({role:"system",content:d}),f.push(...u),f})(t.messages,t.limits));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 B({model:e,logging:t.logging,onReason:t.onReason,onText:t.onText,onSpeed:t.onSpeed,start:()=>r(i),stopped:o,onStall:a})},Y=33554432,G=new Map;let J=!1;const Q=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}`},Z=e=>{const t=/^part-(\d+)$/.exec(e);return t?Number(t[1]):-1},K=async()=>{if(!J)if("undefined"!=typeof navigator&&navigator.storage?.getDirectory)try{return await navigator.storage.getDirectory()}catch{return}else J=!0},X=async(e,t)=>{try{return await e.getDirectoryHandle(t)}catch{return}},ee=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}},te=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{}},re=async function*(e){for await(const t of e)yield t},ne=async e=>{try{for await(const[t,r]of re(e))"file"==r.kind&&Z(t)>=0&&await e.removeEntry(t).catch(()=>{})}catch{}},oe=async(e,t)=>{try{const r=await(await e.getFileHandle(t)).getFile(),n=await ee(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}},ae=async(e,t)=>{const r=await X(e,t);if(r){const e=await(async e=>await ee(await e.getFileHandle("meta.json").catch(()=>{})))(r),t=await(async e=>{const t=[];try{for await(const[r,n]of re(e)){const e=Z(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 oe(e,t)},ie=(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:A(e)||t.total,etag:a||t.etag}},se=async({dir:e,start:t,skip:r,total:n,body:o,onProgress:a,onChunk:i})=>{let c,l=t,u=0,d=r;const f=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 f();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},ce=e=>["NotAllowedError","NotSupportedError"].includes(e?.name||""),le=e=>{const t=async()=>{const t=await K();if(t)try{return await t.getDirectoryHandle(e,{create:!0})}catch{return}};return{stored:async e=>{const r=await t();return r?await ae(r,Q(e)):void 0},download:async({url:r,signal:n,onProgress:o})=>{const a=`${e}|${r}`,i=G.get(a);if(i)return await i;const c=await t();if(!c)return;const l=(async(e,t,r,n)=>{const o=Q(t),a=await oe(e,o);if(a?.complete)return a;let i=await X(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 ae(e,o);if(a?.complete)return a;const u=a?.size??0,d=a?.total||0,f=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,g=()=>p.abort(),h={size:u,total:d,etag:f};let y,w=setTimeout(g,3e4);r?.addEventListener("abort",g,{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 te(i,{total:d,etag:f,complete:!0});continue}await ne(i),await te(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=ie(y,h);if(!r){await y.body.cancel().catch(()=>{}),await ne(i),await te(i,{total:0,etag:"",complete:!1});continue}await te(i,{total:r.total,etag:r.etag,complete:!1});const a=0==r.start?u:0,s=await se({dir:i,start:r.start+a,skip:a,total:r.total,body:y.body,onProgress:n,onChunk:()=>{clearTimeout(w),w=setTimeout(g,3e4)}});if(!r.total){await te(i,{total:s,etag:r.etag,complete:!0});const t=await ae(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",g)}}})(c,r,n,o).finally(()=>{G.delete(a)});return G.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,Q(e))},purge:async()=>{const t=await K();t&&await t.removeEntry(e,{recursive:!0}).catch(()=>{})}}},ue="litertlm-models",de=[4096,2048,1024],fe=le("litert-store"),me={num_output_candidates:1,wait_for_weight_uploads:!0,num_decode_steps_per_sync:3,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 pe=!1;const ge=(...e)=>{pe&&console.log(...e)},he=(...e)=>{pe&&console.error(...e)},ye=e=>{const t=e.mod.getGlobalLiteRtLm().liteRtLmWasm.preinitializedWebGPUDevice;e.device=t,e.lost=!1,t&&t.lost.then(()=>{e.device==t&&(e.lost=!0)})},we=async()=>{try{if("undefined"==typeof caches)return;return await caches.open(ue)}catch{return}},be=async e=>{const t=globalThis,r=t.Module;t.Module={print:ge,printErr:he};try{await e.getOrLoadGlobalLiteRtLm(k)}finally{t.Module=r}},ve=new Map,xe=(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)}}))},je=async({url:e,signal:t,onProgress:r})=>{const n=await we();let o;const a=n?await n.match(e):void 0;if(a?.body)o=a.body;else{const t=await fe.stored(e);t?.complete&&(o=t.file.stream())}if(!o){const n=await fe.download({url:e,signal:t,onProgress:r}).catch(e=>{if(t?.aborted)throw new Error("Cancelled");if(!ce(e))throw e;pe&&console.log("Local model store failed",e)});n&&(o=n.file.stream())}if(!o&&n)try{await(async(e,t,r,n)=>{const o=ve.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=A(o),i=xe(o.body,a,n);await t.put(e,new Response(i,{headers:{"content-type":"application/octet-stream",...a?{"content-length":`${a}`}:{}}}))})().finally(()=>{ve.delete(e)});return ve.set(e,a),await a})(e,n,t,r);const a=await n.match(e);a?.body&&(o=a.body)}catch(e){if(t?.aborted)throw new Error("Cancelled");pe&&console.log("Local model cache failed",e)}return o||(o=await(async(e,t,r)=>{const n=await fetch(e,{signal:t});if(!n.ok||!n.body)throw new Error("Model download failed");return xe(n.body,A(n),r)})(e,t,r)),o},Me=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 T(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},ke=(e,t)=>{if(e.role!=t.role)return!1;if("string"==typeof e.content||"string"==typeof t.content)return e.content==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(n.text!=o.text)return!1}else if(("image"==n.type&&"image"==o.type||"audio"==n.type&&"audio"==o.type)&&n.url!=o.url)return!1}return!0},Pe=e=>({type:"function",function:{name:e.name,...void 0===e.description?{}:{description:e.description},...void 0===e.parameters?{}:{parameters:e.parameters}},execute:e.execute}),Te=async function*({engine:e,mod:t,params:r,messages:n,session:o}){const a=n[n.length-1],i=E(r.limits,r.reasoning),s=r.tools??[];if("user"!=a?.role)throw new Error("No user turn");const c=n.slice(0,-1),l=(await Me([a]))[0];if(!l)throw new Error("Empty prompt");const u=!!o.conversation&&o.reasoning==r.reasoning&&o.maxTokens==i.max_tokens&&((e=[],t=[])=>{if(e.length!=t.length)return!1;for(let r=0;r<e.length;r++){const n=e[r],o=t[r];if(n.name!=o.name)return!1;if(n.description!=o.description)return!1;if(n.execute!==o.execute)return!1;if(JSON.stringify(n.parameters)!=JSON.stringify(o.parameters))return!1}return!0})(o.tools,s)&&((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&&!ke(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(!ke(o[i+e],a[e]))return!1;return!0})(o.sent,c);let d;if(u&&o.conversation)d=o.conversation;else{const n=await Me(c,!1);o.conversation=void 0,o.sent=[];const a={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};d=s.length?new t.AutoToolChat({engine:e,config:a,tools:s.map(Pe),recurringToolCallLimit:(f=r.maxToolRounds,"number"==typeof f&&Number.isFinite(f)?Math.min(25,Math.max(1,Math.floor(f))):4),onToolProgress:e=>((e,t)=>{const r={id:t.id,name:t.name,arguments:t.arguments};"started"!=t.status?"completed"==t.status?e.onToolResult?.({...r,result:t.result}):e.onToolResult?.({...r,error:t.error||"Tool failed"}):e.onToolCall?.(r)})(r,e)}):await e.createConversation(a),o.conversation=d,o.reasoning=r.reasoning,o.maxTokens=i.max_tokens,o.tools=[...s],o.sent=[...c]}var f;o.sent.push(a);let m,p=!1,g="";const h=()=>{m&&m.cancel().catch(()=>{});try{d.cancel()}catch{}};r.signal?.addEventListener("abort",h,{once:!0});try{if(r.signal?.aborted)return;const e=d.sendMessageStreaming(l).getReader();for(m=e;;){const{done:t,value:r}=await e.read();if(t)break;const n={};let o="string"==typeof r.content?r.content:"";if(Array.isArray(r.content))for(const e of r.content)"text"==e.type&&(o+=e.text);o&&(n.content=o,g+=o);const a=r.channels?.thought;a&&(n.reasoning=a),(n.content||n.reasoning)&&(yield{choices:[{delta:n}]})}p=!0}finally{r.signal?.removeEventListener("abort",h),p&&g?o.sent.push({role:"assistant",content:g}):(o.conversation=void 0,o.sent=[])}},Oe=({model:e,limits:t,source:r,mod:n,contextTokens:o=4096})=>{const a=p(e);return{model:r,mainExecutorSettings:{maxNumTokens:o,...a?.vision?{maxNumImages:Math.max(1,t.maxImages)}:{},backendConfig:me},...a?.vision?{visionBackend:n.Backend.GPU,maxVisionTokensPerImage:70,minVisionTokensPerImage:70}:{},...a?.audio?{audioBackend:n.Backend.CPU}:{}}},Se=async(e,t,r)=>{if(e.contextStep>=de.length-1)throw new Error("The graphics device was lost");try{await e.engine.delete()}catch{}e.mod.unloadLiteRtLm(),await be(e.mod),await e.mod.getGlobalLiteRtLm().setupDefaultWebGpuDevice(),e.contextStep+=1,e.engine=await e.mod.Engine.create(Oe({model:t,limits:r,source:await e.reopen(),mod:e.mod,contextTokens:de[e.contextStep]})),ye(e)},Ce={backend:i.gpu,startLLM:async({model:e,limits:t,onProgress:n,signal:o,logging:a})=>{pe=!0===a;const c=e.litert,l=p(e);if(!c||!l)throw new Error("Model has no LiteRT artifact");const u=await r.e(520).then(()=>r(507));if(await be(u),o?.aborted)throw new Error("Cancelled");const d=_(c.repo,l.file),f=await je({url:d,signal:o,onProgress:n});if(o?.aborted)throw new Error("Cancelled");n(1,s.load);const m=u.getGlobalLiteRtLm();m.liteRtLmWasm.preinitializedWebGPUDevice||await m.setupDefaultWebGpuDevice();const g={engine:await u.Engine.create(Oe({model:e,limits:t,source:f,mod:u})),mod:u,lost:!1,contextStep:0,reopen:()=>je({url:d,onProgress:()=>{}})};if(ye(g),o?.aborted)throw await g.engine.delete(),new Error("Cancelled");const h={sent:[],reasoning:!1,maxTokens:0};return{model:e,backend:i.gpu,contextSize:de[g.contextStep],chat:t=>(async({gpu:e,model:t,params:r,session:n})=>{pe=!0===r.logging;const o=()=>!!r.signal?.aborted,a=()=>{try{n.conversation?.cancel()}catch{}n.conversation=void 0,n.sent=[],n.tools=void 0},i=async()=>{try{return await H({model:t,params:r,stopped:o,onStall:a,start:async a=>{if(o())throw new Error("Cancelled");const i=p(t);if(L(a)&&!i?.vision)throw new Error("Model does not accept images");if(R(a)&&!i?.audio)throw new Error("Model does not accept audio");if(r.tools?.length&&!i?.tools)throw new Error("Model does not accept tools");return Te({engine:e.engine,mod:e.mod,params:r,messages:a,session:n})}})}catch(e){throw a(),e}};let s;try{s=await i()}catch(t){if(!e.lost&&!(e=>/device.*lost|lost.*device|vkQueueSubmit|device.*destroyed|aborted/i.test(`${e?.message||e}`))(t))throw t;e.lost=!0}return!e.lost||o()?s:(r.onRestart?.(),a(),await Se(e,t,r.limits),await i())})({gpu:g,model:e,params:t,session:h}),fatal:()=>g.lost,unload:async()=>{h.conversation=void 0,h.sent=[],h.tools=void 0;try{await g.engine.delete()}catch{}}}},cached:async e=>{const t=e.litert,r=p(e);if(!t||!r)return!1;const n=_(t.repo,r.file),[o,a]=await Promise.all([we(),fe.stored(n)]);if(a?.complete)return!0;try{return!(!o||!await o.match(n))}catch{return!1}},hasCache:async()=>{try{for(const e of f){const t=e.litert,r=p(e);if(!t||!r)continue;if(await fe.stored(_(t.repo,r.file)))return!0}const e=await we();return!!e&&(await e.keys()).length>0}catch{return!1}},remove:async e=>{try{const t=e.litert,r=p(e);if(!t||!r)return;const n=_(t.repo,r.file),o=await we();await fe.remove(n),o&&await o.delete(n)}catch{}},purge:async()=>{try{await fe.purge(),"undefined"!=typeof caches&&await caches.delete(ue)}catch{}}},Ne=le("wllama-store");let Ee,_e,Ae="",De=!1;const Le=e=>`${e.wasm}|${e.compatWasm}|${e.compatWorker}`,Re=e=>{const t={wasm:x,compatWasm:j,compatWorker:M};return{wasm:e?.wasm||t.wasm,compatWasm:e?.compatWasm||t.compatWasm,compatWorker:e?.compatWorker||t.compatWorker}},$e=e=>{const t=e=>(...t)=>{De&&("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)}},Ue=async()=>{if(Ee)return Ee;const e=await r.e(924).then(()=>r(577)),t=_e||Re(),n=new e.Wllama({default:t.wasm},{logger:$e(e.LoggerWithoutDebug)});return _e||(_e=t,Ae=Le(t)),n.setCompat({wasm:t.compatWasm,worker:t.compatWorker}),Ee=n,n},qe=async()=>{const e=Ee;Ee=void 0;try{await(e?.exit())}catch{}},ze=(e,t)=>e.name.includes(t)||!!e.metadata?.originalURL?.includes(t),Fe=e=>{const t=e.cpu;return t?[{name:t.file,url:_(t.repo,t.file)},...t.mmproj?[{name:t.mmproj.file,url:_(t.repo,t.mmproj.file)}]:[]]:[]},Ie=async e=>{const t=Fe(e);if(!t.length)return!1;for(const e of t){const t=await Ne.stored(e.url);if(!t?.complete)return!1}return!0},We=async(e,t)=>{const r=await e.cacheManager.list();return Fe(t).every(e=>r.some(t=>ze(t,e.name)))},Ve=async({model:e,signal:t,onProgress:r})=>{const n=Fe(e),o=[];for(let e=0;e<n.length;e++){if(t?.aborted)throw new Error("Cancelled");const a=await Ne.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},Be=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 T(t.url)});t.push({role:"user",content:e})}return t},He={backend:i.cpu,startLLM:async({model:e,limits:t,onProgress:r,signal:n,logging:o,assets:a})=>{De=!0===o;const c=m()?4096:8192,l=e.cpu;if(!l)throw new Error("Model has no CPU artifact");const u=Re(a),d=Le(u);Ee&&d!=Ae&&await qe(),_e=u,Ae=d;const f=(p="undefined"!=typeof navigator&&navigator.hardwareConcurrency||4,g=l.mmproj?Math.min(t.maxThreads,2):t.maxThreads,Math.max(1,Math.min(Math.max(2,Math.min(8,(p||4)-1)),g)));var p,g;const h=await Ue(),y=await Ie(e),w=l.mmproj?.file,b=_(l.repo,l.file),v=w?_(l.repo,w):"";if(n?.aborted)throw await qe(),new Error("Cancelled");if(!y&&w){const e=await h.cacheManager.list(),t=e.some(e=>ze(e,l.file)),r=e.some(e=>ze(e,w));t&&!r&&await h.cacheManager.deleteMany(e=>ze(e,l.file))}const x={n_ctx:c,n_threads:f,reasoning_budget_tokens:t.maxThinkingTokens,n_gpu_layers:0,jinja:!0};try{let t=y?await Ve({model:e,signal:n,onProgress:r}):void 0;t||y||await We(h,e).catch(()=>!1)||(t=await Ve({model:e,signal:n,onProgress:r}).catch(e=>{if(n?.aborted)throw new Error("Cancelled");if(!ce(e))throw e;o&&console.log("Local model store failed",e)})),t?(r(1,s.load),await h.loadModel(t,x)):await h.loadModelFromUrl(v?{url:b,mmprojUrl:v}:b,{...x,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 qe(),e}if(n?.aborted)throw await qe(),new Error("Cancelled");if(!h.getLoadedContextInfo().n_ctx)throw await qe(),new Error("Failed to create model context");return{model:e,backend:i.cpu,contextSize:c,chat:t=>(async(e,t,r)=>{if(De=!0===r.logging,e.isModelLoaded())return await H({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(R(n)&&!e.supportInputModality("audio"))throw new Error("Model does not accept audio");return await e.createChatCompletion({messages:await Be(n),...E(r.limits,r.reasoning),abortSignal:r.signal,...t.reasoning?{chat_template_kwargs:{enable_thinking:r.reasoning}}:{}})}})})(h,e,t),unload:async()=>{if(Ee==h)await qe();else try{await h.exit()}catch{}}}},cached:async e=>{try{return!!e.cpu&&(!!await Ie(e)||await We(await Ue(),e))}catch{return!1}},hasCache:async()=>{try{for(const e of f.flatMap(e=>Fe(e)))if(await Ne.stored(e.url))return!0;const e=await Ue();return(await e.cacheManager.list()).length>0}catch{return!1}},remove:async e=>{const t=Fe(e);try{for(const e of t)await Ne.remove(e.url)}catch{}try{const e=await Ue();await e.cacheManager.deleteMany(e=>t.some(t=>ze(e,t.name)))}catch{}},purge:async()=>{try{await Ne.purge()}catch{}try{const e=await Ue();await e.cacheManager.clear()}catch{}}},Ye=((e={})=>{const t=e.engines?.cpu||He,r=e.engines?.litert||Ce;let n,o,c,l,u,d,m,p,g=i.none,h=a.idle,y=[],w=0,b={percent:0,phase:s.download};const v=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},x=(e,t)=>{b={percent:Math.max(0,Math.min(1,e)),phase:t||s.download};for(const e of[...y])e.report(b.percent,b.phase)},j=e=>{h=e},M=()=>{w++,d?.abort(),d=void 0,u=void 0,h==a.downloading&&j(a.idle)},k=(e,t)=>{const r=l;return r?new Promise(n=>{let o=!1;const a={report:e,settle:e=>{o||(o=!0,t?.removeEventListener("abort",i),n(e))}},i=()=>{(e=>{y=y.filter(t=>t!=e),queueMicrotask(()=>{!y.length&&l&&M()})})(a),a.settle(!1)};y.push(a),t?.aborted?i():t?.addEventListener("abort",i,{once:!0}),r.then(a.settle,()=>a.settle(!1))}):Promise.resolve(!1)},P=()=>h==a.ready&&!!n&&!!o,T=async()=>{const e=n;M(),n=void 0,o=void 0,c=void 0,j(a.idle),await(e?.unload())};return{load:async({model:e,limits:t,assets:r,logging:i,signal:p,onProgress:h})=>{if(p?.aborted)return!1;if(P()&&o?.id==e.id)return!0;if(l&&u==e.id)return h(b.percent,b.phase),await k(h,p);l&&(M(),y=[],await l.catch(()=>!1));const T=++w,O=(async()=>{await(async()=>{try{if("undefined"==typeof navigator)return;await(navigator.storage?.persist?.())}catch{}})();const l=v(e);if(T!=w)return!1;if(!l)return m="Model is not supported on this device",j(a.unsupported),!1;if(await(async(e,t)=>{if(o&&o.id!=e.id){const e=o,t=c,r=n;n=void 0,o=void 0,c=void 0,await(r?.unload()),await(t?.remove(e))}if(await t.hasCache())for(const r of f)r.id!=e.id&&v(r)==t&&await t.remove(r)})(e,l),T!=w)return!1;const u=await l.cached(e);if(T!=w)return!1;m=void 0,j(a.downloading),x(0,s.download),u&&x(1,s.load);const p=new AbortController;d=p;try{const u=await l.startLLM({model:e,limits:t,logging:i,signal:p.signal,assets:r,onProgress:(e,t)=>{T==w&&x(e,t)}});return T!=w||p.signal.aborted?(await u.unload(),!1):(n=u,o=e,c=l,g=l.backend,m=void 0,j(a.ready),x(1,s.load),!0)}catch(e){return T!=w||(n=void 0,o=void 0,c=void 0,m=`${e?.message||`${e}`}`,i&&console.log("Local model failed",e),j(a.error)),!1}finally{d==p&&(d=void 0)}})().finally(()=>{l==O&&(l=void 0,u=void 0,y=[])});return l=O,u=e.id,await k(h,p)},chat:async e=>{if(!P()||!n)return;for(;p;)await p.catch(()=>{});if(!P()||!n)return;const t=n,r=t.chat(e);p=r;try{return await r}catch(e){throw t.fatal?.()&&n==t&&(await T(),g=i.none,m=`${e?.message||`${e}`}`,j(a.error)),e}finally{p==r&&(p=void 0)}},unload:T,ready:P,loading:()=>!P()&&h==a.downloading,status:()=>h,backend:()=>g,error:()=>m,model:()=>o}})();var Ge=r(155);const Je=/^[0-9+\-*/%^().]+$/,Qe=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},Ze={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(!Je.test(t))throw new Error("Unsupported character");const r=Qe(t);return{expression:t,result:Math.abs(r)>=1e5?(0,Ge.pNum)(r)??r:(0,Ge.rNum)(r,12)}})(t)}},Ke="degreesign-chat-prices-v1",Xe="EUR",et=5*Ge.oneMin,tt=30*Ge.oneSec;let rt,nt={},ot=0,at=!1,it=!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},ct=(e,t)=>e&&e.sourceAt>t.sourceAt?e:t,lt=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&&(nt.fiat=ct(nt.fiat,a)),i&&(nt.crypto=ct(nt.crypto,i)),ot=0,at=!1,(()=>{try{if("undefined"==typeof localStorage)return;localStorage.setItem(Ke,JSON.stringify(nt))}catch{}})()}catch(e){throw ot=Date.now(),at=!0,e}},ut=e=>!!nt.crypto&&(e in nt.crypto.prices||e in nt.crypto.yesterday),dt=e=>!!nt.fiat&&(e in nt.fiat.rates||e in nt.fiat.yesterday),ft=async e=>{const t=(e=>{const t={fiat:!1,crypto:!1};for(const r of e){if(r==Xe)continue;const e=ut(r)||dt(r);!ut(r)&&e||(t.crypto=!0),ut(r)||(t.fiat=!0)}return t})(e),r=Date.now(),n=t.fiat&&r-(nt.fiat?.fetchedAt??0)>=Ge.oneHr,o=t.crypto&&r-(nt.crypto?.fetchedAt??0)>=et;(n||o)&&("undefined"!=typeof navigator&&!1===navigator.onLine||ot&&r-ot<tt||(rt||(rt=lt({fiat:n,crypto:o}).catch(()=>{}).finally(()=>{rt=void 0})),await rt))},mt=e=>{if(e==Xe)return 1;const t=nt.crypto?.yesterday[e],r=nt.fiat?.yesterday[e];return t||(r?1/r:void 0)},pt=(e,t)=>{if("string"!=typeof e||!e.trim())throw new Error(`Missing ${t}`);return e.trim().toUpperCase()},gt=e=>Math.abs(e)>=1e5?(0,Ge.pNum)(e)??e:(0,Ge.rNum)(e,8),ht=async e=>{(()=>{if(!it){it=!0;try{if("undefined"==typeof localStorage)return;const e=localStorage.getItem(Ke);if(!e)return;const t=JSON.parse(e);nt={...t.fiat?{fiat:t.fiat}:{},...t.crypto?{crypto:t.crypto}:{}}}catch{}}})();const t=pt(e.from,"from"),r=void 0===e.to||null===e.to?Xe:pt(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 ft([t,r]);const o=e=>{const t=(e=>{if(e==Xe)return 1;const t=nt.crypto?.prices[e],r=nt.fiat?.rates[e];return t||(r?1/r:void 0)})(e);if(void 0!==t)return t;if(!nt.fiat&&!nt.crypto)throw new Error("Prices unavailable offline");if(ut(e)||dt(e))throw new Error(`Unavailable quote for ${e}`);throw new Error(`Unknown symbol ${e}`)},a=o(t),i=o(r),s=mt(t),c=mt(r),l=a/i,u=s&&c?s/c:void 0,d=void 0===u?void 0:l-u,f=void 0===u?void 0:100*(l/u-1),m=(e=>{const t=[];for(const r of e)r!=Xe&&(ut(r)?nt.crypto&&t.push(nt.crypto.sourceAt):dt(r)&&nt.fiat&&t.push(nt.fiat.sourceAt));return t})([t,r]),p=m.length?Math.min(...m):Date.now();return{from:t,to:r,amount:n,rate:gt(l),...void 0===u?{}:{previousRate:gt(u),change:gt(d??0),changePercent:(0,Ge.rNum)(f??0,4)},result:gt(n*l),updatedAt:new Date(p).toISOString(),stale:at&&!(!nt.fiat&&!nt.crypto)}},yt={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=>ht(e)},wt={amp:"&",apos:"'",gt:">",lt:"<",nbsp:" ",quot:'"',hellip:"...",mdash:"-",ndash:"-",ldquo:'"',lsquo:"'",rdquo:'"',rsquo:"'"},bt=(e,t,r,n)=>"number"==typeof e&&Number.isFinite(e)?Math.min(r,Math.max(t,e)):n,vt=(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 wt[e.toLowerCase()]??e})(t);return r==t?e:r}).replace(/\s+/g," ").trim().slice(0,Math.max(0,t)).trim(),xt=/^[a-z]{2,3}(-[a-z]{2,4})?$/i,jt=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)}},Mt=(e={})=>{const t=((e={})=>{const t=e.language?.trim()??"";return{provider:e.provider==u.duckduckgo?u.duckduckgo:u.wikipedia,language:xt.test(t)?t:"en",limit:Math.round(bt(e.limit,1,20,3)),snippetLength:Math.round(bt(e.snippetLength,1,4e3,400)),timeout:bt(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 jt(r,e.timeout),o=[],a=new Set,i=(t,r,n)=>{t&&n&&!a.has(t)&&(a.add(t),o.push({title:vt(r||n,200),url:t,snippet:vt(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 jt(n,e.timeout),a=[];for(const t of o.pages??[]){const n=t.key;n&&a.push({title:vt(t.title??n,200),url:`${r}/wiki/${encodeURIComponent(n)}`,snippet:vt(`${t.description??""} ${t.excerpt??""}`,e.snippetLength)})}return a})(t,r);return n}}},kt=[l.websearch,l.calculate,l.currency],Pt=e=>{const t=e.tools??[],r=!1===e.builtins?[]:e.builtins??kt,n=new Set,o=[];for(const e of t){if(n.has(e.name))throw new Error(`Duplicate tool name ${e.name}`);n.add(e.name)}for(const t of((e,t)=>{const r=[];for(const n of e)n==l.websearch?r.push(Mt(t)):n==l.calculate?r.push(Ze):n==l.currency&&r.push(yt);return r})(r,e.websearch))n.has(t.name)||o.push(t);return o.push(...t),{tools:o,explicit:t.length>0}},Tt=(e,t,r)=>{const n=e.status(),i=g(t);return{availability:n==a.ready?o.online:n==a.error||n==a.unsupported?o.offline:o.away,status:n,backend:e.backend(),supportsImages:!!i&&w(i),supportsAudio:!!i&&b(i),supportsTools:!!i&&v(i),ready:e.ready(),loading:e.loading(),requesting:r.requesting,phase:r.phase,percent:r.percent,...r.error?{error:r.error}:{}}},Ot=(e=>{let t,r=0;const o=t=>t.input.onStatus?.(Tt(e,t.model??t.input.model,t));return i=>{t?.controller.abort();const c={token:++r,input:i,controller:new AbortController,percent:e.ready()?100:0,phase:e.ready()?s.load:s.download,requesting:!1,cancelled:!1};return t=c,o(c),(async t=>{const{input:a}=t,i=!0===a.logging,c=await y(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)),f=l||u||d;if(!c)return t.error="Unknown model",void o(t);if(!f)return t.error="No prompt",void o(t);const m=w(c),p=b(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);let g;try{g=Pt(a)}catch(e){return t.error=`${e?.message||`${e}`}`,void o(t)}const h=v(c);if(!h&&g.explicit)return t.error="Model does not accept tools",void o(t);const x=h?g.tools:[],j=N(a.limits,!!c.litert),M=await e.load({model:c,limits:j,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(!M)return t.error||(t.error=e.error()||"Model not ready"),void o(t);const k=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 P,T="",O="";try{P=await e.chat({messages:k,limits:j,reasoning:!0===a.reasoning,logging:i,...x.length?{tools:x}:{},...void 0===a.maxToolRounds?{}:{maxToolRounds:a.maxToolRounds},onToolCall:e=>{t.token!=r||t.cancelled||a.onToolCall?.(e)},onToolResult:e=>{t.token!=r||t.cancelled||a.onToolResult?.(e)},onReason:e=>{t.token!=r||t.cancelled||(T+=e,a.onThinking?.(T))},onText:e=>{t.token!=r||t.cancelled||(O+=e,a.onResponse?.(O))},onRestart:()=>{T="",O="",a.onThinking?.(T),a.onResponse?.(O)},onSpeed:e=>{t.token!=r||t.cancelled||a.onSpeed?.(e)},signal:t.controller.signal})}catch(e){if(t.token!=r)return;return t.requesting=!1,t.error=`${e?.message||`${e}`}`,void o(t)}t.token==r&&(t.requesting=!1,P||t.cancelled||(t.error="No reply"),o(t))})(c),()=>(t=>{t.token==r&&(t.cancelled=!0,t.controller.abort(),e.status()!=a.ready?queueMicrotask(()=>o(t)):e.unload().then(()=>o(t)))})(c)}})(Ye),St=(Ct=Ye,async(e={})=>{const t=await y(e.model),r=r=>e.onStatus?.(Tt(Ct,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=Ct.ready()&&Ct.model()?.id==t.id;return await Ct.load({model:t,limits:N(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||Ct.error()||"Model not ready"}),!1)});var Ct;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,Ot as createChat,St as preloadModel};
|
|
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.gemma4_e2b="gemma4-e2b"}(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 f=[{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.gemma4_e2b,reasoning:!0,litert:{repo:"litert-community/gemma-4-E2B-it-litert-lm",file:"gemma-4-E2B-it.litertlm",vision:!0,audio:!0,web:{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},g=(e,t=m())=>{const r=e.litert;if(r)return t&&r.web?r.web:{file:r.file,vision:r.vision,audio:r.audio}},p=e=>e?f.find(t=>t.id==e):void 0,h=async()=>(d||(d=(async()=>(await(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)}})()?f.find(e=>!!e.litert):f.find(e=>!!e.cpu))?.id)()),await d),y=async e=>p(e||await h()),w=(e,t=m())=>!!e.cpu?.mmproj||!0===g(e,t)?.vision,b=(e,t=m())=>!!e.cpu?.mmproj?.audio||!0===g(e,t)?.audio,v=new URL("./../assets/wllama/wllama.wasm",import.meta.url).href,x=new URL("./../assets/wllama/compat/wllama.wasm",import.meta.url).href,j=new URL("./../assets/wllama/compat/wllama.js",import.meta.url).href,M=new URL("./../assets/litert/litertlm_wasm_internal.js",import.meta.url).href,k=(new URL("./../assets/litert/litertlm_wasm_internal.wasm",import.meta.url).href,288),O=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},P=async e=>{if(!e||"function"!=typeof fetch||"function"!=typeof createImageBitmap)return e;try{const t=await fetch(e),r=await createImageBitmap(await t.blob()),n=Math.min(r.width,r.height),o=Math.floor((r.width-n)/2),a=Math.floor((r.height-n)/2),i=((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})(k,k),s=i?i.getContext("2d"):null;if(!i||!s||n<1)return r.close(),e;if(s.drawImage(r,o,a,n,n,0,0,k,k),r.close(),(e=>"undefined"!=typeof OffscreenCanvas&&e instanceof OffscreenCanvas)(i)){const t=await i.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 i.toDataURL("image/jpeg",.85)}catch{return e}},S={maxReplyTokens:250,maxThinkingTokens:128,maxReasoningTokens:320,maxImages:2,maxAudio:1,maxContentLength:1e3,promptCharBudget:1e4,maxThreads:6},C=(e,t,r)=>"number"==typeof e&&Number.isFinite(e)&&e>=r?Math.floor(e):t,T=(e={},t=!1)=>{const r=S;return{maxReplyTokens:C(e.maxReplyTokens,r.maxReplyTokens,1),maxThinkingTokens:C(e.maxThinkingTokens,r.maxThinkingTokens,1),maxReasoningTokens:C(e.maxReasoningTokens,t?1200:r.maxReasoningTokens,1),maxImages:C(e.maxImages,r.maxImages,0),maxAudio:C(e.maxAudio,r.maxAudio,0),maxContentLength:C(e.maxContentLength,r.maxContentLength,1),promptCharBudget:C(e.promptCharBudget,r.promptCharBudget,1),maxThreads:C(e.maxThreads,r.maxThreads,1)}},N=(e,t)=>({stream:!0,temperature:.7,max_tokens:t?e.maxReasoningTokens:e.maxReplyTokens}),E=(e,t)=>`https://huggingface.co/${e}/resolve/main/${t}`,_=e=>Number(e.headers.get("content-length"))||0,A=(e,t)=>e.some(e=>Array.isArray(e.content)&&e.content.some(e=>e.type==t)),D=e=>A(e,"image"),L=e=>A(e,"audio"),$=["<|channel>thought\n","<|channel>thought","..."],R=["<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};class F extends Error{}const I=async(e,t,r)=>{let n;try{return await Promise.race([e,new Promise((e,o)=>{n=setTimeout(()=>o(new F(r)),t)})])}finally{n&&clearTimeout(n)}},V=e=>{try{Promise.resolve(e.return?.()).catch(()=>{})}catch{}},W=async({model:e,logging:t,onReason:r,onText:n,onSpeed:o,start:a,stopped:i,firstTimeoutMs:s=18e4,idleTimeoutMs:c=3e4,onStall:l})=>{let u="",d="",f="",m=!1,g=0,p=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,R);if(t>=0){t&&e(s.slice(0,t)),s=s.slice(t+i.length),n=!1;continue}const c=a(s,R);e(s.slice(0,s.length-c.length)),r=c;break}{const{at:e,tag:i}=o(s,$);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,$);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=(await I(a(),s,"Model did not start"))[Symbol.asyncIterator]();for(;;){if(i()){V(e);break}let n;try{n=await I(e.next(),m?c:s,m?"Model stopped responding":"Model did not reply")}catch(r){if(r instanceof F&&(u||d)){l?.(),V(e),t&&console.log("Local chat stalled",r);break}throw r}if(n.done)break;m=!0;const a=n.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&&(f=a.finish_reason),w&&(d+=w,r(w)),y?.content&&h.feed(y.content),w||y?.content){const e=performance.now();g||(p=e),g+=1,g>1&&e>p&&o?.(1e3*g/(e-p))}}h.flush()}catch(e){if(t&&console.log("Local chat failed",e),e instanceof F&&!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,f||"none",u.length,d.length)),y},B=async({model:e,params:t,start:r,stopped:o,onStall:a})=>{const i=await(async e=>{const t=[];for(const r of e){if("string"==typeof r.content){t.push(r);continue}const e=[];for(const t of r.content)e.push("image"==t.type?{type:"image",url:await P(t.url)}:t);t.push({role:"user",content:e})}return t})(((e,t=S)=>{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),f=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||f.length||m.length){if(d&&s+d.length>t.promptCharBudget)break;s+=d.length,c-=f.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,f,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"),f=[];return d&&f.push({role:"system",content:d}),f.push(...u),f})(t.messages,t.limits));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 W({model:e,logging:t.logging,onReason:t.onReason,onText:t.onText,onSpeed:t.onSpeed,start:()=>r(i),stopped:o,onStall:a})},H=33554432,Y=new Map;let J=!1;const G=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}`},Q=e=>{const t=/^part-(\d+)$/.exec(e);return t?Number(t[1]):-1},Z=async()=>{if(!J)if("undefined"!=typeof navigator&&navigator.storage?.getDirectory)try{return await navigator.storage.getDirectory()}catch{return}else J=!0},K=async(e,t)=>{try{return await e.getDirectoryHandle(t)}catch{return}},X=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}},ee=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{}},te=async function*(e){for await(const t of e)yield t},re=async e=>{try{for await(const[t,r]of te(e))"file"==r.kind&&Q(t)>=0&&await e.removeEntry(t).catch(()=>{})}catch{}},ne=async(e,t)=>{try{const r=await(await e.getFileHandle(t)).getFile(),n=await X(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}},oe=async(e,t)=>{const r=await K(e,t);if(r){const e=await(async e=>await X(await e.getFileHandle("meta.json").catch(()=>{})))(r),t=await(async e=>{const t=[];try{for await(const[r,n]of te(e)){const e=Q(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 ne(e,t)},ae=(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:_(e)||t.total,etag:a||t.etag}},ie=async({dir:e,start:t,skip:r,total:n,body:o,onProgress:a,onChunk:i})=>{let c,l=t,u=0,d=r;const f=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 g=0;for(d&&(g=Math.min(d,o.byteLength),d-=g);g<o.byteLength;){c||await f();const e=Math.min(H-u,o.byteLength-g);await c.write({type:"write",position:u,data:o.subarray(g,g+e)}),g+=e,u+=e,l+=e,u==H&&await m()}l>t&&a(n?l/n:0,s.download)}await m()}catch(e){throw await m(),e}return l},se=e=>["NotAllowedError","NotSupportedError"].includes(e?.name||""),ce=e=>{const t=async()=>{const t=await Z();if(t)try{return await t.getDirectoryHandle(e,{create:!0})}catch{return}};return{stored:async e=>{const r=await t();return r?await oe(r,G(e)):void 0},download:async({url:r,signal:n,onProgress:o})=>{const a=`${e}|${r}`,i=Y.get(a);if(i)return await i;const c=await t();if(!c)return;const l=(async(e,t,r,n)=>{const o=G(t),a=await ne(e,o);if(a?.complete)return a;let i=await K(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 oe(e,o);if(a?.complete)return a;const u=a?.size??0,d=a?.total||0,f=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+H,d)-1:u+H-1,g=new AbortController,p=()=>g.abort(),h={size:u,total:d,etag:f};let y,w=setTimeout(p,3e4);r?.addEventListener("abort",p,{once:!0});try{if(y=await fetch(t,{signal:g.signal,headers:{Range:`bytes=${u}-${m}`}}),416==y.status){if(await(y.body?.cancel().catch(()=>{})),d&&u>=d){await ee(i,{total:d,etag:f,complete:!0});continue}await re(i),await ee(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=ae(y,h);if(!r){await y.body.cancel().catch(()=>{}),await re(i),await ee(i,{total:0,etag:"",complete:!1});continue}await ee(i,{total:r.total,etag:r.etag,complete:!1});const a=0==r.start?u:0,s=await ie({dir:i,start:r.start+a,skip:a,total:r.total,body:y.body,onProgress:n,onChunk:()=>{clearTimeout(w),w=setTimeout(p,3e4)}});if(!r.total){await ee(i,{total:s,etag:r.etag,complete:!0});const t=await oe(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",p)}}})(c,r,n,o).finally(()=>{Y.delete(a)});return Y.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,G(e))},purge:async()=>{const t=await Z();t&&await t.removeEntry(e,{recursive:!0}).catch(()=>{})}}},le="litertlm-models",ue=ce("litert-store"),de={num_output_candidates:1,wait_for_weight_uploads:!0,num_decode_steps_per_sync:3,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;const me=(...e)=>{fe&&console.log(...e)},ge=(...e)=>{fe&&console.error(...e)},pe=async()=>{try{if("undefined"==typeof caches)return;return await caches.open(le)}catch{return}},he=new Map,ye=(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)}}))},we=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 O(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},be=(e,t)=>{if(e.role!=t.role)return!1;if("string"==typeof e.content||"string"==typeof t.content)return e.content==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(n.text!=o.text)return!1}else if(("image"==n.type&&"image"==o.type||"audio"==n.type&&"audio"==o.type)&&n.url!=o.url)return!1}return!0},ve=async function*({engine:e,mod:t,params:r,messages:n,session:o}){const a=n[n.length-1],i=N(r.limits,r.reasoning);if("user"!=a?.role)throw new Error("No user turn");const s=n.slice(0,-1),c=(await we([a]))[0];if(!c)throw new Error("Empty prompt");const l=!!o.conversation&&o.reasoning==r.reasoning&&o.maxTokens==i.max_tokens&&((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&&!be(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(!be(o[i+e],a[e]))return!1;return!0})(o.sent,s);let u;if(l&&o.conversation)u=o.conversation;else{const n=await we(s,!1);o.conversation=void 0,o.sent=[],u=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}),o.conversation=u,o.reasoning=r.reasoning,o.maxTokens=i.max_tokens,o.sent=[...s]}o.sent.push(a);let d,f=!1,m="";const g=()=>{d&&d.cancel().catch(()=>{});try{u.cancel()}catch{}};r.signal?.addEventListener("abort",g,{once:!0});try{if(r.signal?.aborted)return;const e=u.sendMessageStreaming(c).getReader();for(d=e;;){const{done:t,value:r}=await e.read();if(t)break;const n={};let o="string"==typeof r.content?r.content:"";if(Array.isArray(r.content))for(const e of r.content)"text"==e.type&&(o+=e.text);o&&(n.content=o,m+=o);const a=r.channels?.thought;a&&(n.reasoning=a),(n.content||n.reasoning)&&(yield{choices:[{delta:n}]})}f=!0}finally{r.signal?.removeEventListener("abort",g),f&&m?o.sent.push({role:"assistant",content:m}):(o.conversation=void 0,o.sent=[])}},xe={backend:i.gpu,startLLM:async({model:e,limits:t,onProgress:n,signal:o,logging:a})=>{fe=!0===a;const c=e.litert,l=g(e);if(!c||!l)throw new Error("Model has no LiteRT artifact");const u=await r.e(520).then(()=>r(507)),d=globalThis,f=d.Module;d.Module={print:me,printErr:ge};try{await u.getOrLoadGlobalLiteRtLm(M)}finally{d.Module=f}if(o?.aborted)throw new Error("Cancelled");const m=E(c.repo,l.file),p=await pe();let h;const y=p?await p.match(m):void 0;if(y?.body)h=y.body;else{const e=await ue.stored(m);e?.complete&&(h=e.file.stream())}if(!h){const e=await ue.download({url:m,signal:o,onProgress:n}).catch(e=>{if(o?.aborted)throw new Error("Cancelled");if(!se(e))throw e;a&&console.log("Local model store failed",e)});e&&(h=e.file.stream())}if(!h&&p)try{await(async(e,t,r,n)=>{const o=he.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=_(o),i=ye(o.body,a,n);await t.put(e,new Response(i,{headers:{"content-type":"application/octet-stream",...a?{"content-length":`${a}`}:{}}}))})().finally(()=>{he.delete(e)});return he.set(e,a),await a})(m,p,o,n);const e=await p.match(m);e?.body&&(h=e.body)}catch(e){if(o?.aborted)throw new Error("Cancelled");a&&console.log("Local model cache failed",e)}if(h||(h=await(async(e,t,r)=>{const n=await fetch(e,{signal:t});if(!n.ok||!n.body)throw new Error("Model download failed");return ye(n.body,_(n),r)})(m,o,n)),o?.aborted)throw new Error("Cancelled");n(1,s.load);const w=await u.Engine.create((({model:e,limits:t,source:r,mod:n})=>{const o=g(e);return{model:r,mainExecutorSettings:{maxNumTokens:4096,...o?.vision?{maxNumImages:Math.max(1,t.maxImages)}:{},backendConfig:de},...o?.vision?{visionBackend:n.Backend.GPU,maxVisionTokensPerImage:70,minVisionTokensPerImage:70}:{},...o?.audio?{audioBackend:n.Backend.CPU}:{}}})({model:e,limits:t,source:h,mod:u}));if(o?.aborted)throw await w.delete(),new Error("Cancelled");const b={sent:[],reasoning:!1,maxTokens:0};return{model:e,backend:i.gpu,contextSize:4096,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 B({model:t,params:n,stopped:()=>!!n.signal?.aborted,onStall:a,start:async a=>{if(n.signal?.aborted)throw new Error("Cancelled");const i=g(t);if(D(a)&&!i?.vision)throw new Error("Model does not accept images");if(L(a)&&!i?.audio)throw new Error("Model does not accept audio");return ve({engine:e,mod:r,params:n,messages:a,session:o})}})}catch(e){throw a(),e}})({engine:w,model:e,mod:u,params:t,session:b}),unload:async()=>{b.conversation=void 0,b.sent=[],await w.delete()}}},cached:async e=>{const t=e.litert,r=g(e);if(!t||!r)return!1;const n=E(t.repo,r.file),[o,a]=await Promise.all([pe(),ue.stored(n)]);if(a?.complete)return!0;try{return!(!o||!await o.match(n))}catch{return!1}},hasCache:async()=>{try{for(const e of f){const t=e.litert,r=g(e);if(!t||!r)continue;if(await ue.stored(E(t.repo,r.file)))return!0}const e=await pe();return!!e&&(await e.keys()).length>0}catch{return!1}},remove:async e=>{try{const t=e.litert,r=g(e);if(!t||!r)return;const n=E(t.repo,r.file),o=await pe();await ue.remove(n),o&&await o.delete(n)}catch{}},purge:async()=>{try{await ue.purge(),"undefined"!=typeof caches&&await caches.delete(le)}catch{}}},je=ce("wllama-store");let Me,ke,Oe="",Pe=!1;const Se=e=>`${e.wasm}|${e.compatWasm}|${e.compatWorker}`,Ce=e=>{const t={wasm:v,compatWasm:x,compatWorker:j};return{wasm:e?.wasm||t.wasm,compatWasm:e?.compatWasm||t.compatWasm,compatWorker:e?.compatWorker||t.compatWorker}},Te=e=>{const t=e=>(...t)=>{Pe&&("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)}},Ne=async()=>{if(Me)return Me;const e=await r.e(924).then(()=>r(577)),t=ke||Ce(),n=new e.Wllama({default:t.wasm},{logger:Te(e.LoggerWithoutDebug)});return ke||(ke=t,Oe=Se(t)),n.setCompat({wasm:t.compatWasm,worker:t.compatWorker}),Me=n,n},Ee=async()=>{const e=Me;Me=void 0;try{await(e?.exit())}catch{}},_e=(e,t)=>e.name.includes(t)||!!e.metadata?.originalURL?.includes(t),Ae=e=>{const t=e.cpu;return t?[{name:t.file,url:E(t.repo,t.file)},...t.mmproj?[{name:t.mmproj.file,url:E(t.repo,t.mmproj.file)}]:[]]:[]},De=async e=>{const t=Ae(e);if(!t.length)return!1;for(const e of t){const t=await je.stored(e.url);if(!t?.complete)return!1}return!0},Le=async(e,t)=>{const r=await e.cacheManager.list();return Ae(t).every(e=>r.some(t=>_e(t,e.name)))},$e=async({model:e,signal:t,onProgress:r})=>{const n=Ae(e),o=[];for(let e=0;e<n.length;e++){if(t?.aborted)throw new Error("Cancelled");const a=await je.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},Re=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 O(t.url)});t.push({role:"user",content:e})}return t},Ue={backend:i.cpu,startLLM:async({model:e,limits:t,onProgress:r,signal:n,logging:o,assets:a})=>{Pe=!0===o;const c=m()?4096:8192,l=e.cpu;if(!l)throw new Error("Model has no CPU artifact");const u=Ce(a),d=Se(u);Me&&d!=Oe&&await Ee(),ke=u,Oe=d;const f=(g="undefined"!=typeof navigator&&navigator.hardwareConcurrency||4,p=l.mmproj?Math.min(t.maxThreads,2):t.maxThreads,Math.max(1,Math.min(Math.max(2,Math.min(8,(g||4)-1)),p)));var g,p;const h=await Ne(),y=await De(e),w=l.mmproj?.file,b=E(l.repo,l.file),v=w?E(l.repo,w):"";if(n?.aborted)throw await Ee(),new Error("Cancelled");if(!y&&w){const e=await h.cacheManager.list(),t=e.some(e=>_e(e,l.file)),r=e.some(e=>_e(e,w));t&&!r&&await h.cacheManager.deleteMany(e=>_e(e,l.file))}const x={n_ctx:c,n_threads:f,reasoning_budget_tokens:t.maxThinkingTokens,n_gpu_layers:0,jinja:!0};try{let t=y?await $e({model:e,signal:n,onProgress:r}):void 0;t||y||await Le(h,e).catch(()=>!1)||(t=await $e({model:e,signal:n,onProgress:r}).catch(e=>{if(n?.aborted)throw new Error("Cancelled");if(!se(e))throw e;o&&console.log("Local model store failed",e)})),t?(r(1,s.load),await h.loadModel(t,x)):await h.loadModelFromUrl(v?{url:b,mmprojUrl:v}:b,{...x,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 Ee(),e}if(n?.aborted)throw await Ee(),new Error("Cancelled");if(!h.getLoadedContextInfo().n_ctx)throw await Ee(),new Error("Failed to create model context");return{model:e,backend:i.cpu,contextSize:c,chat:t=>(async(e,t,r)=>{if(Pe=!0===r.logging,e.isModelLoaded())return await B({model:t,params:r,stopped:()=>!!r.signal?.aborted,start:async n=>{if(D(n)&&!e.supportInputModality("image"))throw new Error("Model does not accept images");if(L(n)&&!e.supportInputModality("audio"))throw new Error("Model does not accept audio");return await e.createChatCompletion({messages:await Re(n),...N(r.limits,r.reasoning),abortSignal:r.signal,...t.reasoning?{chat_template_kwargs:{enable_thinking:r.reasoning}}:{}})}})})(h,e,t),unload:async()=>{if(Me==h)await Ee();else try{await h.exit()}catch{}}}},cached:async e=>{try{return!!e.cpu&&(!!await De(e)||await Le(await Ne(),e))}catch{return!1}},hasCache:async()=>{try{for(const e of f.flatMap(e=>Ae(e)))if(await je.stored(e.url))return!0;const e=await Ne();return(await e.cacheManager.list()).length>0}catch{return!1}},remove:async e=>{const t=Ae(e);try{for(const e of t)await je.remove(e.url)}catch{}try{const e=await Ne();await e.cacheManager.deleteMany(e=>t.some(t=>_e(e,t.name)))}catch{}},purge:async()=>{try{await je.purge()}catch{}try{const e=await Ne();await e.cacheManager.clear()}catch{}}},qe=((e={})=>{const t=e.engines?.cpu||Ue,r=e.engines?.litert||xe;let n,o,c,l,u,d,m,g,p=i.none,h=a.idle,y=[],w=0,b={percent:0,phase:s.download};const v=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},x=(e,t)=>{b={percent:Math.max(0,Math.min(1,e)),phase:t||s.download};for(const e of[...y])e.report(b.percent,b.phase)},j=e=>{h=e},M=()=>{w++,d?.abort(),d=void 0,u=void 0,h==a.downloading&&j(a.idle)},k=(e,t)=>{const r=l;return r?new Promise(n=>{let o=!1;const a={report:e,settle:e=>{o||(o=!0,t?.removeEventListener("abort",i),n(e))}},i=()=>{(e=>{y=y.filter(t=>t!=e),queueMicrotask(()=>{!y.length&&l&&M()})})(a),a.settle(!1)};y.push(a),t?.aborted?i():t?.addEventListener("abort",i,{once:!0}),r.then(a.settle,()=>a.settle(!1))}):Promise.resolve(!1)},O=()=>h==a.ready&&!!n&&!!o;return{load:async({model:e,limits:t,assets:r,logging:i,signal:g,onProgress:h})=>{if(g?.aborted)return!1;if(O()&&o?.id==e.id)return!0;if(l&&u==e.id)return h(b.percent,b.phase),await k(h,g);l&&(M(),y=[],await l.catch(()=>!1));const P=++w,S=(async()=>{await(async()=>{try{if("undefined"==typeof navigator)return;await(navigator.storage?.persist?.())}catch{}})();const l=v(e);if(P!=w)return!1;if(!l)return m="Model is not supported on this device",j(a.unsupported),!1;if(await(async(e,t)=>{if(o&&o.id!=e.id){const e=o,t=c,r=n;n=void 0,o=void 0,c=void 0,await(r?.unload()),await(t?.remove(e))}if(await t.hasCache())for(const r of f)r.id!=e.id&&v(r)==t&&await t.remove(r)})(e,l),P!=w)return!1;const u=await l.cached(e);if(P!=w)return!1;m=void 0,j(a.downloading),x(0,s.download),u&&x(1,s.load);const g=new AbortController;d=g;try{const u=await l.startLLM({model:e,limits:t,logging:i,signal:g.signal,assets:r,onProgress:(e,t)=>{P==w&&x(e,t)}});return P!=w||g.signal.aborted?(await u.unload(),!1):(n=u,o=e,c=l,p=l.backend,m=void 0,j(a.ready),x(1,s.load),!0)}catch(e){return P!=w||(n=void 0,o=void 0,c=void 0,m=`${e?.message||`${e}`}`,i&&console.log("Local model failed",e),j(a.error)),!1}finally{d==g&&(d=void 0)}})().finally(()=>{l==S&&(l=void 0,u=void 0,y=[])});return l=S,u=e.id,await k(h,g)},chat:async e=>{if(!O()||!n)return;for(;g;)await g.catch(()=>{});if(!O()||!n)return;const t=n.chat(e);g=t;try{return await t}finally{g==t&&(g=void 0)}},unload:async()=>{const e=n;M(),n=void 0,o=void 0,c=void 0,j(a.idle),await(e?.unload())},ready:O,loading:()=>!O()&&h==a.downloading,status:()=>h,backend:()=>p,error:()=>m,model:()=>o}})(),ze=(e,t,r)=>{const n=e.status(),i=p(t);return{availability:n==a.ready?o.online:n==a.error||n==a.unsupported?o.offline:o.away,status:n,backend:e.backend(),supportsImages:!!i&&w(i),supportsAudio:!!i&&b(i),ready:e.ready(),loading:e.loading(),requesting:r.requesting,phase:r.phase,percent:r.percent,...r.error?{error:r.error}:{}}},Fe=(e=>{let t,r=0;const o=t=>t.input.onStatus?.(ze(e,t.model??t.input.model,t));return i=>{t?.controller.abort();const c={token:++r,input:i,controller:new AbortController,percent:e.ready()?100:0,phase:e.ready()?s.load:s.download,requesting:!1,cancelled:!1};return t=c,o(c),(async t=>{const{input:a}=t,i=!0===a.logging,c=await y(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)),f=l||u||d;if(!c)return t.error="Unknown model",void o(t);if(!f)return t.error="No prompt",void o(t);const m=w(c),g=b(c);if(!(l||u&&m||d&&g))return d&&!g?t.error="Model does not accept audio":u&&!m&&(t.error="Model does not accept images"),void o(t);const p=T(a.limits,!!c.litert),h=await e.load({model:c,limits:p,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(!h)return t.error||(t.error=e.error()||"Model not ready"),void o(t);const v=u&&!m||d&&!g?a.messages.map(({images:e,audio:t,...r})=>({...r,...e&&m?{images:e}:{},...t&&g?{audio:t}:{}})):a.messages;t.requesting=!0,t.error=void 0,t.percent=100,t.phase=s.load,o(t);let x,j="",M="";try{x=await e.chat({messages:v,limits:p,reasoning:!0===a.reasoning,logging:i,onReason:e=>{t.token!=r||t.cancelled||(j+=e,a.onThinking?.(j))},onText:e=>{t.token!=r||t.cancelled||(M+=e,a.onResponse?.(M))},onSpeed:e=>{t.token!=r||t.cancelled||a.onSpeed?.(e)},signal:t.controller.signal})}catch(e){if(t.token!=r)return;return t.requesting=!1,t.error=`${e?.message||`${e}`}`,void o(t)}t.token==r&&(t.requesting=!1,x||t.cancelled||(t.error="No reply"),o(t))})(c),()=>(t=>{t.token==r&&(t.cancelled=!0,t.controller.abort(),e.status()!=a.ready?queueMicrotask(()=>o(t)):e.unload().then(()=>o(t)))})(c)}})(qe),Ie=(Ve=qe,async(e={})=>{const t=await y(e.model),r=r=>e.onStatus?.(ze(Ve,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=Ve.ready()&&Ve.model()?.id==t.id;return await Ve.load({model:t,limits:T(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||Ve.error()||"Model not ready"}),!1)});var Ve,We=r(155);const Be=/^[0-9+\-*/%^().]+$/,He=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},Ye={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(!Be.test(t))throw new Error("Unsupported character");const r=He(t);return{expression:t,result:Math.abs(r)>=1e5?(0,We.pNum)(r)??r:(0,We.rNum)(r,12)}})(t)}},Je="degreesign-chat-prices-v1",Ge="EUR",Qe=5*We.oneMin,Ze=30*We.oneSec;let Ke,Xe={},et=0,tt=!1,rt=!1;const nt=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,at=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=nt(e.rates?.current),n=nt(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&&(Xe.fiat=ot(Xe.fiat,a)),i&&(Xe.crypto=ot(Xe.crypto,i)),et=0,tt=!1,(()=>{try{if("undefined"==typeof localStorage)return;localStorage.setItem(Je,JSON.stringify(Xe))}catch{}})()}catch(e){throw et=Date.now(),tt=!0,e}},it=e=>!!Xe.crypto&&(e in Xe.crypto.prices||e in Xe.crypto.yesterday),st=e=>!!Xe.fiat&&(e in Xe.fiat.rates||e in Xe.fiat.yesterday),ct=async e=>{const t=(e=>{const t={fiat:!1,crypto:!1};for(const r of e){if(r==Ge)continue;const e=it(r)||st(r);!it(r)&&e||(t.crypto=!0),it(r)||(t.fiat=!0)}return t})(e),r=Date.now(),n=t.fiat&&r-(Xe.fiat?.fetchedAt??0)>=We.oneHr,o=t.crypto&&r-(Xe.crypto?.fetchedAt??0)>=Qe;(n||o)&&("undefined"!=typeof navigator&&!1===navigator.onLine||et&&r-et<Ze||(Ke||(Ke=at({fiat:n,crypto:o}).catch(()=>{}).finally(()=>{Ke=void 0})),await Ke))},lt=e=>{if(e==Ge)return 1;const t=Xe.crypto?.yesterday[e],r=Xe.fiat?.yesterday[e];return t||(r?1/r:void 0)},ut=(e,t)=>{if("string"!=typeof e||!e.trim())throw new Error(`Missing ${t}`);return e.trim().toUpperCase()},dt=e=>Math.abs(e)>=1e5?(0,We.pNum)(e)??e:(0,We.rNum)(e,8),ft=async e=>{(()=>{if(!rt){rt=!0;try{if("undefined"==typeof localStorage)return;const e=localStorage.getItem(Je);if(!e)return;const t=JSON.parse(e);Xe={...t.fiat?{fiat:t.fiat}:{},...t.crypto?{crypto:t.crypto}:{}}}catch{}}})();const t=ut(e.from,"from"),r=void 0===e.to||null===e.to?Ge:ut(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 ct([t,r]);const o=e=>{const t=(e=>{if(e==Ge)return 1;const t=Xe.crypto?.prices[e],r=Xe.fiat?.rates[e];return t||(r?1/r:void 0)})(e);if(void 0!==t)return t;if(!Xe.fiat&&!Xe.crypto)throw new Error("Prices unavailable offline");if(it(e)||st(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,f=void 0===u?void 0:100*(l/u-1),m=(e=>{const t=[];for(const r of e)r!=Ge&&(it(r)?Xe.crypto&&t.push(Xe.crypto.sourceAt):st(r)&&Xe.fiat&&t.push(Xe.fiat.sourceAt));return t})([t,r]),g=m.length?Math.min(...m):Date.now();return{from:t,to:r,amount:n,rate:dt(l),...void 0===u?{}:{previousRate:dt(u),change:dt(d??0),changePercent:(0,We.rNum)(f??0,4)},result:dt(n*l),updatedAt:new Date(g).toISOString(),stale:tt&&!(!Xe.fiat&&!Xe.crypto)}},mt={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=>ft(e)},gt={amp:"&",apos:"'",gt:">",lt:"<",nbsp:" ",quot:'"',hellip:"...",mdash:"-",ndash:"-",ldquo:'"',lsquo:"'",rdquo:'"',rsquo:"'"},pt=(e,t,r,n)=>"number"==typeof e&&Number.isFinite(e)?Math.min(r,Math.max(t,e)):n,ht=(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 gt[e.toLowerCase()]??e})(t);return r==t?e:r}).replace(/\s+/g," ").trim().slice(0,Math.max(0,t)).trim(),yt=/^[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)}},bt=(e={})=>{const t=((e={})=>{const t=e.language?.trim()??"";return{provider:e.provider==u.duckduckgo?u.duckduckgo:u.wikipedia,language:yt.test(t)?t:"en",limit:Math.round(pt(e.limit,1,20,3)),snippetLength:Math.round(pt(e.snippetLength,1,4e3,400)),timeout:pt(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:ht(r||n,200),url:t,snippet:ht(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:ht(t.title??n,200),url:`${r}/wiki/${encodeURIComponent(n)}`,snippet:ht(`${t.description??""} ${t.excerpt??""}`,e.snippetLength)})}return a})(t,r);return n}}},vt=(e,t)=>{const r=[];for(const n of e)n==l.websearch?r.push(bt(t)):n==l.calculate?r.push(Ye):n==l.currency&&r.push(mt);return r};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,vt as builtinTools,Ye as calculateTool,Fe as createChat,mt as currencyTool,Ie as preloadModel,bt as webSearchTool};
|
package/dist/engines/litert.d.ts
CHANGED
|
@@ -1,35 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ChatModel, ChatTool, EngineChunk, EngineMessage, LitertChatParams, LitertGpu, LitertMessage, LitertSettings, LitertSettingsParams, LlmEngine, LlmLimits, StartLlmParams, StreamLitertParams } from '../types';
|
|
1
|
+
import type { EngineChunk, EngineMessage, LitertMessage, LitertSettings, LitertSettingsParams, LlmEngine, StartLlmParams, StreamLitertParams } from '../types';
|
|
3
2
|
declare const
|
|
4
3
|
/** Smallest Gemma 4 vision budget in tokens */
|
|
5
4
|
visionTokens = 70;
|
|
6
|
-
/** Watch the live device, marking the engine dead when it is lost */
|
|
7
|
-
declare const watchDevice: (gpu: LitertGpu) => void;
|
|
8
5
|
/** Fetch one model file into the cache, once per URL */
|
|
9
6
|
declare const cacheModel: (url: string, cache: Cache, signal: AbortSignal | undefined, onProgress: StartLlmParams[`onProgress`]) => Promise<void>;
|
|
10
|
-
/** Open the model file, from a store, the cache or the network */
|
|
11
|
-
declare const openSource: ({ url, signal, onProgress, }: {
|
|
12
|
-
url: string;
|
|
13
|
-
signal?: AbortSignal;
|
|
14
|
-
onProgress: StartLlmParams[`onProgress`];
|
|
15
|
-
}) => Promise<ReadableStream<Uint8Array>>;
|
|
16
7
|
/** Map built messages to LiteRT turns */
|
|
17
8
|
declare const toLitertMessages: (messages: EngineMessage[], keepMedia?: boolean) => Promise<LitertMessage[]>;
|
|
18
9
|
/** Whether the live conversation already holds the incoming history */
|
|
19
10
|
declare const continuesHistory: (sent: EngineMessage[], history: EngineMessage[]) => boolean;
|
|
20
|
-
/** Clamp the tool round budget of one reply */
|
|
21
|
-
declare const toolRounds: (value?: number) => number;
|
|
22
|
-
/** Map one host or built-in tool to the engine tool shape */
|
|
23
|
-
declare const engineTool: (tool: ChatTool) => ToolWithImplementation;
|
|
24
|
-
/** Whether two lists declare the same tools and the same functions */
|
|
25
|
-
declare const sameTools: (first?: ChatTool[], next?: ChatTool[]) => boolean;
|
|
26
11
|
/** Stream one LiteRT reply as engine chunks */
|
|
27
12
|
declare const streamLitert: ({ engine, mod, params, messages, session, }: StreamLitertParams) => AsyncGenerator<EngineChunk>;
|
|
28
|
-
/** Stream one reply on a started GPU runtime */
|
|
29
|
-
declare const chatOn: ({ gpu, model, params, session, }: LitertChatParams) => Promise<string | undefined>;
|
|
30
13
|
/** Build one engine settings object with the small vision budget */
|
|
31
|
-
declare const litertSettings: ({ model, limits, source, mod,
|
|
32
|
-
/** Rebuild the engine on a fresh device after a loss */
|
|
33
|
-
declare const rebuildGpu: (gpu: LitertGpu, model: ChatModel, limits: LlmLimits) => Promise<void>;
|
|
14
|
+
declare const litertSettings: ({ model, limits, source, mod, }: LitertSettingsParams) => LitertSettings;
|
|
34
15
|
declare const litertEngine: LlmEngine;
|
|
35
|
-
export { cacheModel,
|
|
16
|
+
export { cacheModel, continuesHistory, litertEngine, litertSettings, streamLitert, toLitertMessages, visionTokens, };
|