Humuhumu33 commited on
Commit
666a78d
·
verified ·
1 Parent(s): 89dc30e

Remove orphaned old-layout files (_shared vendor dup + old diagnostics)

Browse files
Files changed (49) hide show
  1. _shared/voice/vendor/kokoro/kokoro.js +0 -1
  2. _shared/voice/vendor/kokoro/phonemizer.js +0 -0
  3. _shared/voice/vendor/kokoro/stub.js +0 -6
  4. _shared/voice/vendor/kokoro/transformers/ort-wasm-simd-threaded.jsep.mjs +0 -125
  5. _shared/voice/vendor/kokoro/transformers/ort-wasm-simd-threaded.jsep.wasm +0 -3
  6. _shared/voice/vendor/kokoro/transformers/transformers.js +0 -0
  7. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/config.json +0 -3
  8. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/tokenizer.json +0 -175
  9. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/tokenizer_config.json +0 -6
  10. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/af_bella.bin +0 -3
  11. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/af_heart.bin +0 -3
  12. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/af_nicole.bin +0 -3
  13. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/am_fenrir.bin +0 -3
  14. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/am_michael.bin +0 -3
  15. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/am_puck.bin +0 -3
  16. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/bf_emma.bin +0 -3
  17. _shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/bm_george.bin +0 -3
  18. _shared/voice/vendor/models/onnx-community/silero-vad/onnx/model.onnx +0 -3
  19. _shared/voice/vendor/models/onnx-community/silero-vad/onnx/model_quantized.onnx +0 -3
  20. _shared/voice/vendor/transformers/ort-wasm-simd-threaded.jsep.wasm +0 -3
  21. _shared/voice/vendor/transformers/transformers.js +0 -0
  22. _shared/voice/vendor/transformers/transformers.mjs +0 -0
  23. blake3-gpu-parallel.html +0 -145
  24. blake3-gpu-test.html +0 -195
  25. core/agents.js +0 -74
  26. core/backend.js +0 -23
  27. core/code-tools.js +0 -130
  28. core/keymap.js +0 -29
  29. core/mcp.js +0 -144
  30. core/mcphub.js +0 -107
  31. core/memory.js +0 -69
  32. core/presets.js +0 -54
  33. core/promptsLib.js +0 -109
  34. core/q-brain-fast.mjs +0 -153
  35. core/schema.js +0 -85
  36. core/semantic-witness.mjs +0 -33
  37. core/skills.js +0 -92
  38. core/state.js +0 -39
  39. core/store.js +0 -185
  40. core/tools.js +0 -112
  41. gemv-bench.html +0 -183
  42. gpu-blake3.mjs +0 -107
  43. holo-blake3.mjs +0 -128
  44. holo-gpu-device.mjs +0 -27
  45. kernel-profile.html +0 -147
  46. q-chat.html +0 -120
  47. rb-bench.html +0 -130
  48. roofline.html +0 -126
  49. style.css +0 -28
_shared/voice/vendor/kokoro/kokoro.js DELETED
@@ -1 +0,0 @@
1
- import{StyleTextToSpeech2Model as e,AutoTokenizer as a,Tensor as t,RawAudio as r,env as n}from"@huggingface/transformers";import{phonemize as l}from"phonemizer";import s from"path";import i from"fs/promises";function o(e){if(e.includes("."))return e;if(e.includes(":")){let[a,t]=e.split(":").map(Number);return 0===t?`${a} o'clock`:t<10?`${a} oh ${t}`:`${a} ${t}`}let a=parseInt(e.slice(0,4),10);if(a<1100||a%1e3<10)return e;let t=e.slice(0,2),r=parseInt(e.slice(2,4),10),n=e.endsWith("s")?"s":"";if(a%1e3>=100&&a%1e3<=999){if(0===r)return`${t} hundred${n}`;if(r<10)return`${t} oh ${r}${n}`}return`${t} ${r}${n}`}function c(e){const a="$"===e[0]?"dollar":"pound";if(isNaN(Number(e.slice(1))))return`${e.slice(1)} ${a}s`;if(!e.includes(".")){let t="1"===e.slice(1)?"":"s";return`${e.slice(1)} ${a}${t}`}const[t,r]=e.slice(1).split("."),n=parseInt(r.padEnd(2,"0"),10);return`${t} ${a}${"1"===t?"":"s"} and ${n} ${"$"===e[0]?1===n?"cent":"cents":1===n?"penny":"pence"}`}function g(e){let[a,t]=e.split(".");return`${a} point ${t.split("").join(" ")}`}const u=new RegExp(`(\\s*[${d=';:,.!?¡¿—…"«»“”(){}[]',d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}]+\\s*)+`,"g");var d;async function m(e,a="a",t=!0){t&&(e=function(e){return e.replace(/[‘’]/g,"'").replace(/«/g,"“").replace(/»/g,"”").replace(/[“”]/g,'"').replace(/\(/g,"«").replace(/\)/g,"»").replace(/、/g,", ").replace(/。/g,". ").replace(/!/g,"! ").replace(/,/g,", ").replace(/:/g,": ").replace(/;/g,"; ").replace(/?/g,"? ").replace(/[^\S \n]/g," ").replace(/ +/," ").replace(/(?<=\n) +(?=\n)/g,"").replace(/\bD[Rr]\.(?= [A-Z])/g,"Doctor").replace(/\b(?:Mr\.|MR\.(?= [A-Z]))/g,"Mister").replace(/\b(?:Ms\.|MS\.(?= [A-Z]))/g,"Miss").replace(/\b(?:Mrs\.|MRS\.(?= [A-Z]))/g,"Mrs").replace(/\betc\.(?! [A-Z])/gi,"etc").replace(/\b(y)eah?\b/gi,"$1e'a").replace(/\d*\.\d+|\b\d{4}s?\b|(?<!:)\b(?:[1-9]|1[0-2]):[0-5]\d\b(?!:)/g,o).replace(/(?<=\d),(?=\d)/g,"").replace(/[$£]\d+(?:\.\d+)?(?: hundred| thousand| (?:[bm]|tr)illion)*\b|[$£]\d+\.\d\d?\b/gi,c).replace(/\d*\.\d+/g,g).replace(/(?<=\d)-(?=\d)/g," to ").replace(/(?<=\d)S/g," S").replace(/(?<=[BCDFGHJ-NP-TV-Z])'?s\b/g,"'S").replace(/(?<=X')S\b/g,"s").replace(/(?:[A-Za-z]\.){2,} [a-z]/g,(e=>e.replace(/\./g,"-"))).replace(/(?<=[A-Z])\.(?=[A-Z])/gi,"-").trim()}(e));const r=function(e,a){const t=[];let r=0;for(const n of e.matchAll(a)){const a=n[0];r<n.index&&t.push({match:!1,text:e.slice(r,n.index)}),a.length>0&&t.push({match:!0,text:a}),r=n.index+a.length}return r<e.length&&t.push({match:!1,text:e.slice(r)}),t}(e,u),n="a"===a?"en-us":"en",s=(await Promise.all(r.map((async({match:e,text:a})=>e?a:(await l(a,n)).join(" "))))).join("");let i=s.replace(/kəkˈoːɹoʊ/g,"kˈoʊkəɹoʊ").replace(/kəkˈɔːɹəʊ/g,"kˈəʊkəɹəʊ").replace(/ʲ/g,"j").replace(/r/g,"ɹ").replace(/x/g,"k").replace(/ɬ/g,"l").replace(/(?<=[a-zɹː])(?=hˈʌndɹɪd)/g," ").replace(/ z(?=[;:,.!?¡¿—…"«»“” ]|$)/g,"z");return"a"===a&&(i=i.replace(/(?<=nˈaɪn)ti(?!ː)/g,"di")),i.trim()}function p(e,a=!0){return".!?…。?!".includes(e)||a&&"\n"===e}function f(e,a){let t=a;for(;t<e.length&&!/\s/.test(e[t]);)++t;return e.substring(a,t)}const h=new Set(["mr","mrs","ms","dr","prof","sr","jr","sgt","col","gen","rep","sen","gov","lt","maj","capt","st","mt","etc","co","inc","ltd","dept","vs","p","pg","jan","feb","mar","apr","jun","jul","aug","sep","sept","oct","nov","dec","sun","mon","tu","tue","tues","wed","th","thu","thur","thurs","fri","sat"]);function _(e){return e=e.replace(/['’]s$/i,"").replace(/\.+$/,""),h.has(e.toLowerCase())}const v=new Map([[")","("],["]","["],["}","{"],["》","《"],["〉","〈"],["›","‹"],["»","«"],["〉","〈"],["」","「"],["』","『"],["〕","〔"],["】","【"]]),b=new Set(v.values());function y(e,a,t,r){if('"'===e||"'"===e){if("'"===e&&t>0&&t<r.length-1&&/[A-Za-z]/.test(r[t-1])&&/[A-Za-z]/.test(r[t+1]))return;return void(a.length&&a.at(-1)===e?a.pop():a.push(e))}if(b.has(e))return void a.push(e);const n=v.get(e);n&&a.length&&a.at(-1)===n&&a.pop()}class w{constructor(){this._buffer="",this._sentences=[],this._resolver=null,this._closed=!1}push(...e){for(const a of e)this._buffer+=a,this._process()}close(){if(this._closed)throw new Error("Stream is already closed.");this._closed=!0,this.flush()}flush(){const e=this._buffer.trim();e.length>0&&this._sentences.push(e),this._buffer="",this._resolve()}_resolve(){this._resolver&&(this._resolver(),this._resolver=null)}_process(){let e=0;const a=this._buffer,t=a.length;let r=0,n=[];const l=e=>{let r=e;for(;r+1<t&&p(a[r+1],!1);)++r;for(;r+1<t&&(n=a[r+1],"\"')]}」』".includes(n));)++r;var n;let l=r+1;for(;l<t&&/\s/.test(a[l]);)++l;return{end:r,nextNonSpace:l}};for(;r<t;){const s=a[r];if(y(s,n,r,a),0===n.length&&p(s)){const n=a.slice(e,r);if(/(^|\n)\d+$/.test(n)){++r;continue}const{end:i,nextNonSpace:o}=l(r);if(r===o-1&&"\n"!==s){++r;continue}if(o===t)break;let c=r-1;for(;c>=0&&/\S/.test(a[c]);)c--;c=Math.max(e,c+1);const g=f(a,c);if(!g){++r;continue}if((/https?[,:]\/\//.test(g)||g.includes("@"))&&!p(g.at(-1))){r=c+g.length;continue}if(_(g)){++r;continue}if(/^([A-Za-z]\.)+$/.test(g)&&o<t&&/[A-Z]/.test(a[o])){++r;continue}if("."===s&&o<t&&/[a-z]/.test(a[o])){++r;continue}const u=a.substring(e,i+1).trim();if("..."===u||"…"===u){++r;continue}u&&this._sentences.push(u),r=e=i+1}else++r}this._buffer=a.substring(e),this._sentences.length>0&&this._resolve()}async*[Symbol.asyncIterator](){if(this._resolver)throw new Error("Another iterator is already active.");for(;;)if(this._sentences.length>0)yield this._sentences.shift();else{if(this._closed)break;await new Promise((e=>{this._resolver=e}))}}[Symbol.iterator](){this.flush();const e=this._sentences[Symbol.iterator]();return this._sentences=[],e}get sentences(){return this._sentences}}const $=Object.freeze({af_heart:{name:"Heart",language:"en-us",gender:"Female",traits:"❤️",targetQuality:"A",overallGrade:"A"},af_alloy:{name:"Alloy",language:"en-us",gender:"Female",targetQuality:"B",overallGrade:"C"},af_aoede:{name:"Aoede",language:"en-us",gender:"Female",targetQuality:"B",overallGrade:"C+"},af_bella:{name:"Bella",language:"en-us",gender:"Female",traits:"🔥",targetQuality:"A",overallGrade:"A-"},af_jessica:{name:"Jessica",language:"en-us",gender:"Female",targetQuality:"C",overallGrade:"D"},af_kore:{name:"Kore",language:"en-us",gender:"Female",targetQuality:"B",overallGrade:"C+"},af_nicole:{name:"Nicole",language:"en-us",gender:"Female",traits:"🎧",targetQuality:"B",overallGrade:"B-"},af_nova:{name:"Nova",language:"en-us",gender:"Female",targetQuality:"B",overallGrade:"C"},af_river:{name:"River",language:"en-us",gender:"Female",targetQuality:"C",overallGrade:"D"},af_sarah:{name:"Sarah",language:"en-us",gender:"Female",targetQuality:"B",overallGrade:"C+"},af_sky:{name:"Sky",language:"en-us",gender:"Female",targetQuality:"B",overallGrade:"C-"},am_adam:{name:"Adam",language:"en-us",gender:"Male",targetQuality:"D",overallGrade:"F+"},am_echo:{name:"Echo",language:"en-us",gender:"Male",targetQuality:"C",overallGrade:"D"},am_eric:{name:"Eric",language:"en-us",gender:"Male",targetQuality:"C",overallGrade:"D"},am_fenrir:{name:"Fenrir",language:"en-us",gender:"Male",targetQuality:"B",overallGrade:"C+"},am_liam:{name:"Liam",language:"en-us",gender:"Male",targetQuality:"C",overallGrade:"D"},am_michael:{name:"Michael",language:"en-us",gender:"Male",targetQuality:"B",overallGrade:"C+"},am_onyx:{name:"Onyx",language:"en-us",gender:"Male",targetQuality:"C",overallGrade:"D"},am_puck:{name:"Puck",language:"en-us",gender:"Male",targetQuality:"B",overallGrade:"C+"},am_santa:{name:"Santa",language:"en-us",gender:"Male",targetQuality:"C",overallGrade:"D-"},bf_emma:{name:"Emma",language:"en-gb",gender:"Female",traits:"🚺",targetQuality:"B",overallGrade:"B-"},bf_isabella:{name:"Isabella",language:"en-gb",gender:"Female",targetQuality:"B",overallGrade:"C"},bm_george:{name:"George",language:"en-gb",gender:"Male",targetQuality:"B",overallGrade:"C"},bm_lewis:{name:"Lewis",language:"en-gb",gender:"Male",targetQuality:"C",overallGrade:"D+"},bf_alice:{name:"Alice",language:"en-gb",gender:"Female",traits:"🚺",targetQuality:"C",overallGrade:"D"},bf_lily:{name:"Lily",language:"en-gb",gender:"Female",traits:"🚺",targetQuality:"C",overallGrade:"D"},bm_daniel:{name:"Daniel",language:"en-gb",gender:"Male",traits:"🚹",targetQuality:"C",overallGrade:"D"},bm_fable:{name:"Fable",language:"en-gb",gender:"Male",traits:"🚹",targetQuality:"B",overallGrade:"C"}});const G=new Map;async function k(e){if(G.has(e))return G.get(e);const a=new Float32Array(await async function(e){if(i&&Object.hasOwn(i,"readFile")){const a="undefined"!=typeof __dirname?__dirname:import.meta.dirname,t=s.resolve(a,`../voices/${e}.bin`),{buffer:r}=await i.readFile(t);return r}const a=`https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX/resolve/main/voices/${e}.bin`;let t;try{t=await caches.open("kokoro-voices");const e=await t.match(a);if(e)return await e.arrayBuffer()}catch(e){console.warn("Unable to open cache",e)}const r=await fetch(a),n=await r.arrayBuffer();if(t)try{await t.put(a,new Response(n,{headers:r.headers}))}catch(e){console.warn("Unable to cache file",e)}return n}(e));return G.set(e,a),a}class M{constructor(e,a){this.model=e,this.tokenizer=a}static async from_pretrained(t,{dtype:r="fp32",device:n=null,progress_callback:l=null}={}){const s=e.from_pretrained(t,{progress_callback:l,dtype:r,device:n}),i=a.from_pretrained(t,{progress_callback:l}),o=await Promise.all([s,i]);return new M(...o)}get voices(){return $}list_voices(){console.table($)}_validate_voice(e){if(!$.hasOwnProperty(e))throw console.error(`Voice "${e}" not found. Available voices:`),console.table($),new Error(`Voice "${e}" not found. Should be one of: ${Object.keys($).join(", ")}.`);return e.at(0)}async generate(e,{voice:a="af_heart",speed:t=1}={}){const r=this._validate_voice(a),n=await m(e,r),{input_ids:l}=this.tokenizer(n,{truncation:!0});return this.generate_from_ids(l,{voice:a,speed:t})}async generate_from_ids(e,{voice:a="af_heart",speed:n=1}={}){const l=256*Math.min(Math.max(e.dims.at(-1)-2,0),509),s=(await k(a)).slice(l,l+256),i={input_ids:e,style:new t("float32",s,[1,256]),speed:new t("float32",[n],[1])},{waveform:o}=await this.model(i);return new r(o.data,24e3)}async*stream(e,{voice:a="af_heart",speed:t=1,split_pattern:r=null}={}){const n=this._validate_voice(a);let l;if(e instanceof w)l=e;else{if("string"!=typeof e)throw new Error("Invalid input type. Expected string or TextSplitterStream.");{l=new w;const a=r?e.split(r).map((e=>e.trim())).filter((e=>e.length>0)):[e];l.push(...a)}}for await(const e of l){const r=await m(e,n),{input_ids:l}=this.tokenizer(r,{truncation:!0}),s=await this.generate_from_ids(l,{voice:a,speed:t});yield{text:e,phonemes:r,audio:s}}}}const Q={set wasmPaths(e){n.backends.onnx.wasm.wasmPaths=e},get wasmPaths(){return n.backends.onnx.wasm.wasmPaths}};export{M as KokoroTTS,w as TextSplitterStream,Q as env};
 
 
_shared/voice/vendor/kokoro/phonemizer.js DELETED
The diff for this file is too large to render. See raw diff
 
_shared/voice/vendor/kokoro/stub.js DELETED
@@ -1,6 +0,0 @@
1
- // browser stub for node built-ins kokoro-js imports but doesn't use client-side.
2
- export const join = (...a) => a.join('/');
3
- export const resolve = (...a) => a.join('/');
4
- export const dirname = (p) => String(p).replace(/\/[^/]*$/, '');
5
- export const readFile = async () => { throw new Error('fs unavailable in browser'); };
6
- export default {};
 
 
 
 
 
 
 
_shared/voice/vendor/kokoro/transformers/ort-wasm-simd-threaded.jsep.mjs DELETED
@@ -1,125 +0,0 @@
1
- var ortWasmThreaded = (() => {
2
- var _scriptName = import.meta.url;
3
-
4
- return (
5
- async function(moduleArg = {}) {
6
- var moduleRtn;
7
-
8
- var e=moduleArg,aa,ca,da=new Promise((a,b)=>{aa=a;ca=b}),ea="object"==typeof window,k="undefined"!=typeof WorkerGlobalScope,n="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node&&"renderer"!=process.type,q=k&&self.name?.startsWith("em-pthread");if(n){const {createRequire:a}=await import("module");var require=a(import.meta.url),fa=require("worker_threads");global.Worker=fa.Worker;q=(k=!fa.oc)&&"em-pthread"==fa.workerData}
9
- e.mountExternalData=(a,b)=>{a.startsWith("./")&&(a=a.substring(2));(e.Eb||(e.Eb=new Map)).set(a,b)};e.unmountExternalData=()=>{delete e.Eb};var SharedArrayBuffer=globalThis.SharedArrayBuffer??(new WebAssembly.Memory({initial:0,maximum:0,pc:!0})).buffer.constructor;
10
- const ha=a=>async(...b)=>{try{if(e.Fb)throw Error("Session already started");const c=e.Fb={dc:b[0],errors:[]},d=await a(...b);if(e.Fb!==c)throw Error("Session mismatch");e.Jb?.flush();const f=c.errors;if(0<f.length){let g=await Promise.all(f);g=g.filter(h=>h);if(0<g.length)throw Error(g.join("\n"));}return d}finally{e.Fb=null}};
11
- e.jsepInit=(a,b)=>{if("webgpu"===a){[e.Jb,e.Ub,e.Yb,e.Kb,e.Xb,e.jb,e.Zb,e.ac,e.Vb,e.Wb,e.$b]=b;const c=e.Jb;e.jsepRegisterBuffer=(d,f,g,h)=>c.registerBuffer(d,f,g,h);e.jsepGetBuffer=d=>c.getBuffer(d);e.jsepCreateDownloader=(d,f,g)=>c.createDownloader(d,f,g);e.jsepOnCreateSession=d=>{c.onCreateSession(d)};e.jsepOnReleaseSession=d=>{c.onReleaseSession(d)};e.jsepOnRunStart=d=>c.onRunStart(d);e.bc=(d,f)=>{c.upload(d,f)}}else if("webnn"===a){const c=b[0];[e.nc,e.Nb,e.webnnEnsureTensor,e.Ob,e.webnnDownloadTensor]=
12
- b.slice(1);e.webnnReleaseTensorId=e.Nb;e.webnnUploadTensor=e.Ob;e.webnnOnRunStart=d=>c.onRunStart(d);e.webnnOnRunEnd=c.onRunEnd.bind(c);e.webnnRegisterMLContext=(d,f)=>{c.registerMLContext(d,f)};e.webnnOnReleaseSession=d=>{c.onReleaseSession(d)};e.webnnCreateMLTensorDownloader=(d,f)=>c.createMLTensorDownloader(d,f);e.webnnRegisterMLTensor=(d,f,g,h)=>c.registerMLTensor(d,f,g,h);e.webnnCreateMLContext=d=>c.createMLContext(d);e.webnnRegisterMLConstant=(d,f,g,h,l,m)=>c.registerMLConstant(d,f,g,h,l,e.Eb,
13
- m);e.webnnRegisterGraphInput=c.registerGraphInput.bind(c);e.webnnIsGraphInput=c.isGraphInput.bind(c);e.webnnCreateTemporaryTensor=c.createTemporaryTensor.bind(c);e.webnnIsInt64Supported=c.isInt64Supported.bind(c)}};
14
- let ja=()=>{const a=(b,c,d)=>(...f)=>{const g=t,h=c?.();f=b(...f);const l=c?.();h!==l&&(b=l,d(h),c=d=null);return t!=g?ia():f};(b=>{for(const c of b)e[c]=a(e[c],()=>e[c],d=>e[c]=d)})(["_OrtAppendExecutionProvider","_OrtCreateSession","_OrtRun","_OrtRunWithBinding","_OrtBindInput"]);"undefined"!==typeof ha&&(e._OrtRun=ha(e._OrtRun),e._OrtRunWithBinding=ha(e._OrtRunWithBinding));ja=void 0};e.asyncInit=()=>{ja?.()};var ka=Object.assign({},e),la="./this.program",ma=(a,b)=>{throw b;},v="",na,oa;
15
- if(n){var fs=require("fs"),pa=require("path");import.meta.url.startsWith("data:")||(v=pa.dirname(require("url").fileURLToPath(import.meta.url))+"/");oa=a=>{a=qa(a)?new URL(a):a;return fs.readFileSync(a)};na=async a=>{a=qa(a)?new URL(a):a;return fs.readFileSync(a,void 0)};!e.thisProgram&&1<process.argv.length&&(la=process.argv[1].replace(/\\/g,"/"));process.argv.slice(2);ma=(a,b)=>{process.exitCode=a;throw b;}}else if(ea||k)k?v=self.location.href:"undefined"!=typeof document&&
16
- document.currentScript&&(v=document.currentScript.src),_scriptName&&(v=_scriptName),v.startsWith("blob:")?v="":v=v.slice(0,v.replace(/[?#].*/,"").lastIndexOf("/")+1),n||(k&&(oa=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),na=async a=>{if(qa(a))return new Promise((c,d)=>{var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?c(f.response):d(f.status)};
17
- f.onerror=d;f.send(null)});var b=await fetch(a,{credentials:"same-origin"});if(b.ok)return b.arrayBuffer();throw Error(b.status+" : "+b.url);});var ra=console.log.bind(console),sa=console.error.bind(console);n&&(ra=(...a)=>fs.writeSync(1,a.join(" ")+"\n"),sa=(...a)=>fs.writeSync(2,a.join(" ")+"\n"));var ta=ra,x=sa;Object.assign(e,ka);ka=null;var ua=e.wasmBinary,z,va,A=!1,wa,B,xa,ya,za,Aa,Ba,Ca,C,Da,Ea,qa=a=>a.startsWith("file://");function D(){z.buffer!=B.buffer&&E();return B}
18
- function F(){z.buffer!=B.buffer&&E();return xa}function G(){z.buffer!=B.buffer&&E();return ya}function Fa(){z.buffer!=B.buffer&&E();return za}function H(){z.buffer!=B.buffer&&E();return Aa}function I(){z.buffer!=B.buffer&&E();return Ba}function Ga(){z.buffer!=B.buffer&&E();return Ca}function J(){z.buffer!=B.buffer&&E();return Ea}
19
- if(q){var Ha;if(n){var Ia=fa.parentPort;Ia.on("message",b=>onmessage({data:b}));Object.assign(globalThis,{self:global,postMessage:b=>Ia.postMessage(b)})}var Ja=!1;x=function(...b){b=b.join(" ");n?fs.writeSync(2,b+"\n"):console.error(b)};self.alert=function(...b){postMessage({Bb:"alert",text:b.join(" "),ic:Ka()})};self.onunhandledrejection=b=>{throw b.reason||b;};function a(b){try{var c=b.data,d=c.Bb;if("load"===d){let f=[];self.onmessage=g=>f.push(g);self.startWorker=()=>{postMessage({Bb:"loaded"});
20
- for(let g of f)a(g);self.onmessage=a};for(const g of c.Rb)if(!e[g]||e[g].proxy)e[g]=(...h)=>{postMessage({Bb:"callHandler",Qb:g,args:h})},"print"==g&&(ta=e[g]),"printErr"==g&&(x=e[g]);z=c.kc;E();Ha(c.lc)}else if("run"===d){La(c.Ab);Ma(c.Ab,0,0,1,0,0);Na();Oa(c.Ab);Ja||(Pa(),Ja=!0);try{Qa(c.fc,c.Hb)}catch(f){if("unwind"!=f)throw f;}}else"setimmediate"!==c.target&&("checkMailbox"===d?Ja&&Ra():d&&(x(`worker: received unknown command ${d}`),x(c)))}catch(f){throw Sa(),f;}}self.onmessage=a}
21
- function E(){var a=z.buffer;e.HEAP8=B=new Int8Array(a);e.HEAP16=ya=new Int16Array(a);e.HEAPU8=xa=new Uint8Array(a);e.HEAPU16=za=new Uint16Array(a);e.HEAP32=Aa=new Int32Array(a);e.HEAPU32=Ba=new Uint32Array(a);e.HEAPF32=Ca=new Float32Array(a);e.HEAPF64=Ea=new Float64Array(a);e.HEAP64=C=new BigInt64Array(a);e.HEAPU64=Da=new BigUint64Array(a)}q||(z=new WebAssembly.Memory({initial:256,maximum:65536,shared:!0}),E());function Ta(){q?startWorker(e):K.Ca()}var Ua=0,Va=null;
22
- function Wa(){Ua--;if(0==Ua&&Va){var a=Va;Va=null;a()}}function L(a){a="Aborted("+a+")";x(a);A=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ca(a);throw a;}var Xa;async function Ya(a){if(!ua)try{var b=await na(a);return new Uint8Array(b)}catch{}if(a==Xa&&ua)a=new Uint8Array(ua);else if(oa)a=oa(a);else throw"both async and sync fetching of the wasm failed";return a}
23
- async function Za(a,b){try{var c=await Ya(a);return await WebAssembly.instantiate(c,b)}catch(d){x(`failed to asynchronously prepare wasm: ${d}`),L(d)}}async function $a(a){var b=Xa;if(!ua&&"function"==typeof WebAssembly.instantiateStreaming&&!qa(b)&&!n)try{var c=fetch(b,{credentials:"same-origin"});return await WebAssembly.instantiateStreaming(c,a)}catch(d){x(`wasm streaming compile failed: ${d}`),x("falling back to ArrayBuffer instantiation")}return Za(b,a)}
24
- function ab(){bb={L:cb,Aa:db,b:eb,$:fb,A:gb,pa:hb,X:ib,Z:jb,qa:kb,na:lb,ga:mb,ma:nb,J:ob,Y:pb,V:qb,oa:rb,W:sb,va:tb,E:ub,Q:vb,O:wb,D:xb,u:yb,r:zb,P:Ab,z:Bb,R:Cb,ja:Db,T:Eb,aa:Fb,M:Gb,F:Hb,ia:Oa,sa:Ib,t:Jb,Ba:Kb,w:Lb,o:Mb,l:Nb,c:Ob,n:Pb,j:Qb,v:Rb,p:Sb,f:Tb,s:Ub,m:Vb,e:Wb,k:Xb,i:Yb,g:Zb,d:$b,da:ac,ea:bc,fa:cc,ba:dc,ca:ec,N:fc,xa:gc,ua:hc,h:ic,C:jc,G:kc,ta:lc,x:mc,ra:nc,U:oc,q:pc,y:qc,K:rc,S:sc,za:tc,ya:uc,ka:vc,la:wc,_:xc,B:yc,I:zc,ha:Ac,H:Bc,a:z,wa:Cc};return{a:bb}}
25
- var Dc={829644:(a,b,c,d,f)=>{if("undefined"==typeof e||!e.Eb)return 1;a=M(Number(a>>>0));a.startsWith("./")&&(a=a.substring(2));a=e.Eb.get(a);if(!a)return 2;b=Number(b>>>0);c=Number(c>>>0);d=Number(d>>>0);if(b+c>a.byteLength)return 3;try{const g=a.subarray(b,b+c);switch(f){case 0:F().set(g,d>>>0);break;case 1:e.mc?e.mc(d,g):e.bc(d,g);break;default:return 4}return 0}catch{return 4}},830468:(a,b,c)=>{e.Ob(a,F().subarray(b>>>0,b+c>>>0))},830532:()=>e.nc(),830574:a=>{e.Nb(a)},830611:()=>{e.Vb()},830642:()=>
26
- {e.Wb()},830671:()=>{e.$b()},830696:a=>e.Ub(a),830729:a=>e.Yb(a),830761:(a,b,c)=>{e.Kb(Number(a),Number(b),Number(c),!0)},830824:(a,b,c)=>{e.Kb(Number(a),Number(b),Number(c))},830881:()=>"undefined"!==typeof wasmOffsetConverter,830938:a=>{e.jb("Abs",a,void 0)},830989:a=>{e.jb("Neg",a,void 0)},831040:a=>{e.jb("Floor",a,void 0)},831093:a=>{e.jb("Ceil",a,void 0)},831145:a=>{e.jb("Reciprocal",a,void 0)},831203:a=>{e.jb("Sqrt",a,void 0)},831255:a=>{e.jb("Exp",a,void 0)},831306:a=>{e.jb("Erf",a,void 0)},
27
- 831357:a=>{e.jb("Sigmoid",a,void 0)},831412:(a,b,c)=>{e.jb("HardSigmoid",a,{alpha:b,beta:c})},831491:a=>{e.jb("Log",a,void 0)},831542:a=>{e.jb("Sin",a,void 0)},831593:a=>{e.jb("Cos",a,void 0)},831644:a=>{e.jb("Tan",a,void 0)},831695:a=>{e.jb("Asin",a,void 0)},831747:a=>{e.jb("Acos",a,void 0)},831799:a=>{e.jb("Atan",a,void 0)},831851:a=>{e.jb("Sinh",a,void 0)},831903:a=>{e.jb("Cosh",a,void 0)},831955:a=>{e.jb("Asinh",a,void 0)},832008:a=>{e.jb("Acosh",a,void 0)},832061:a=>{e.jb("Atanh",a,void 0)},
28
- 832114:a=>{e.jb("Tanh",a,void 0)},832166:a=>{e.jb("Not",a,void 0)},832217:(a,b,c)=>{e.jb("Clip",a,{min:b,max:c})},832286:a=>{e.jb("Clip",a,void 0)},832338:(a,b)=>{e.jb("Elu",a,{alpha:b})},832396:a=>{e.jb("Gelu",a,void 0)},832448:a=>{e.jb("Relu",a,void 0)},832500:(a,b)=>{e.jb("LeakyRelu",a,{alpha:b})},832564:(a,b)=>{e.jb("ThresholdedRelu",a,{alpha:b})},832634:(a,b)=>{e.jb("Cast",a,{to:b})},832692:a=>{e.jb("Add",a,void 0)},832743:a=>{e.jb("Sub",a,void 0)},832794:a=>{e.jb("Mul",a,void 0)},832845:a=>
29
- {e.jb("Div",a,void 0)},832896:a=>{e.jb("Pow",a,void 0)},832947:a=>{e.jb("Equal",a,void 0)},833E3:a=>{e.jb("Greater",a,void 0)},833055:a=>{e.jb("GreaterOrEqual",a,void 0)},833117:a=>{e.jb("Less",a,void 0)},833169:a=>{e.jb("LessOrEqual",a,void 0)},833228:(a,b,c,d,f)=>{e.jb("ReduceMean",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},833403:(a,b,c,d,f)=>{e.jb("ReduceMax",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>
30
- 0,Number(f)>>>0)):[]})},833577:(a,b,c,d,f)=>{e.jb("ReduceMin",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},833751:(a,b,c,d,f)=>{e.jb("ReduceProd",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},833926:(a,b,c,d,f)=>{e.jb("ReduceSum",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},834100:(a,b,c,d,f)=>{e.jb("ReduceL1",a,{keepDims:!!b,
31
- noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},834273:(a,b,c,d,f)=>{e.jb("ReduceL2",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},834446:(a,b,c,d,f)=>{e.jb("ReduceLogSum",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},834623:(a,b,c,d,f)=>{e.jb("ReduceSumSquare",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>
32
- 0,Number(f)>>>0)):[]})},834803:(a,b,c,d,f)=>{e.jb("ReduceLogSumExp",a,{keepDims:!!b,noopWithEmptyAxes:!!c,axes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},834983:a=>{e.jb("Where",a,void 0)},835036:(a,b,c)=>{e.jb("Transpose",a,{perm:b?Array.from(H().subarray(Number(b)>>>0,Number(c)>>>0)):[]})},835160:(a,b,c,d)=>{e.jb("DepthToSpace",a,{blocksize:b,mode:M(c),format:d?"NHWC":"NCHW"})},835293:(a,b,c,d)=>{e.jb("DepthToSpace",a,{blocksize:b,mode:M(c),format:d?"NHWC":"NCHW"})},835426:(a,
33
- b,c,d,f,g,h,l,m,p,r,u,w,y,ba)=>{e.jb("ConvTranspose",a,{format:m?"NHWC":"NCHW",autoPad:b,dilations:[c],group:d,kernelShape:[f],pads:[g,h],strides:[l],wIsConst:()=>!!D()[p>>>0],outputPadding:r?Array.from(H().subarray(Number(r)>>>0,Number(u)>>>0)):[],outputShape:w?Array.from(H().subarray(Number(w)>>>0,Number(y)>>>0)):[],activation:M(ba)})},835859:(a,b,c,d,f,g,h,l,m,p,r,u,w,y)=>{e.jb("ConvTranspose",a,{format:l?"NHWC":"NCHW",autoPad:b,dilations:Array.from(H().subarray(Number(c)>>>0,(Number(c)>>>0)+2>>>
34
- 0)),group:d,kernelShape:Array.from(H().subarray(Number(f)>>>0,(Number(f)>>>0)+2>>>0)),pads:Array.from(H().subarray(Number(g)>>>0,(Number(g)>>>0)+4>>>0)),strides:Array.from(H().subarray(Number(h)>>>0,(Number(h)>>>0)+2>>>0)),wIsConst:()=>!!D()[m>>>0],outputPadding:p?Array.from(H().subarray(Number(p)>>>0,Number(r)>>>0)):[],outputShape:u?Array.from(H().subarray(Number(u)>>>0,Number(w)>>>0)):[],activation:M(y)})},836520:(a,b,c,d,f,g,h,l,m,p,r,u,w,y,ba)=>{e.jb("ConvTranspose",a,{format:m?"NHWC":"NCHW",
35
- autoPad:b,dilations:[c],group:d,kernelShape:[f],pads:[g,h],strides:[l],wIsConst:()=>!!D()[p>>>0],outputPadding:r?Array.from(H().subarray(Number(r)>>>0,Number(u)>>>0)):[],outputShape:w?Array.from(H().subarray(Number(w)>>>0,Number(y)>>>0)):[],activation:M(ba)})},836953:(a,b,c,d,f,g,h,l,m,p,r,u,w,y)=>{e.jb("ConvTranspose",a,{format:l?"NHWC":"NCHW",autoPad:b,dilations:Array.from(H().subarray(Number(c)>>>0,(Number(c)>>>0)+2>>>0)),group:d,kernelShape:Array.from(H().subarray(Number(f)>>>0,(Number(f)>>>0)+
36
- 2>>>0)),pads:Array.from(H().subarray(Number(g)>>>0,(Number(g)>>>0)+4>>>0)),strides:Array.from(H().subarray(Number(h)>>>0,(Number(h)>>>0)+2>>>0)),wIsConst:()=>!!D()[m>>>0],outputPadding:p?Array.from(H().subarray(Number(p)>>>0,Number(r)>>>0)):[],outputShape:u?Array.from(H().subarray(Number(u)>>>0,Number(w)>>>0)):[],activation:M(y)})},837614:(a,b)=>{e.jb("GlobalAveragePool",a,{format:b?"NHWC":"NCHW"})},837705:(a,b,c,d,f,g,h,l,m,p,r,u,w,y)=>{e.jb("AveragePool",a,{format:y?"NHWC":"NCHW",auto_pad:b,ceil_mode:c,
37
- count_include_pad:d,storage_order:f,dilations:g?Array.from(H().subarray(Number(g)>>>0,Number(h)>>>0)):[],kernel_shape:l?Array.from(H().subarray(Number(l)>>>0,Number(m)>>>0)):[],pads:p?Array.from(H().subarray(Number(p)>>>0,Number(r)>>>0)):[],strides:u?Array.from(H().subarray(Number(u)>>>0,Number(w)>>>0)):[]})},838184:(a,b)=>{e.jb("GlobalAveragePool",a,{format:b?"NHWC":"NCHW"})},838275:(a,b,c,d,f,g,h,l,m,p,r,u,w,y)=>{e.jb("AveragePool",a,{format:y?"NHWC":"NCHW",auto_pad:b,ceil_mode:c,count_include_pad:d,
38
- storage_order:f,dilations:g?Array.from(H().subarray(Number(g)>>>0,Number(h)>>>0)):[],kernel_shape:l?Array.from(H().subarray(Number(l)>>>0,Number(m)>>>0)):[],pads:p?Array.from(H().subarray(Number(p)>>>0,Number(r)>>>0)):[],strides:u?Array.from(H().subarray(Number(u)>>>0,Number(w)>>>0)):[]})},838754:(a,b)=>{e.jb("GlobalMaxPool",a,{format:b?"NHWC":"NCHW"})},838841:(a,b,c,d,f,g,h,l,m,p,r,u,w,y)=>{e.jb("MaxPool",a,{format:y?"NHWC":"NCHW",auto_pad:b,ceil_mode:c,count_include_pad:d,storage_order:f,dilations:g?
39
- Array.from(H().subarray(Number(g)>>>0,Number(h)>>>0)):[],kernel_shape:l?Array.from(H().subarray(Number(l)>>>0,Number(m)>>>0)):[],pads:p?Array.from(H().subarray(Number(p)>>>0,Number(r)>>>0)):[],strides:u?Array.from(H().subarray(Number(u)>>>0,Number(w)>>>0)):[]})},839316:(a,b)=>{e.jb("GlobalMaxPool",a,{format:b?"NHWC":"NCHW"})},839403:(a,b,c,d,f,g,h,l,m,p,r,u,w,y)=>{e.jb("MaxPool",a,{format:y?"NHWC":"NCHW",auto_pad:b,ceil_mode:c,count_include_pad:d,storage_order:f,dilations:g?Array.from(H().subarray(Number(g)>>>
40
- 0,Number(h)>>>0)):[],kernel_shape:l?Array.from(H().subarray(Number(l)>>>0,Number(m)>>>0)):[],pads:p?Array.from(H().subarray(Number(p)>>>0,Number(r)>>>0)):[],strides:u?Array.from(H().subarray(Number(u)>>>0,Number(w)>>>0)):[]})},839878:(a,b,c,d,f)=>{e.jb("Gemm",a,{alpha:b,beta:c,transA:d,transB:f})},839982:a=>{e.jb("MatMul",a,void 0)},840036:(a,b,c,d)=>{e.jb("ArgMax",a,{keepDims:!!b,selectLastIndex:!!c,axis:d})},840144:(a,b,c,d)=>{e.jb("ArgMin",a,{keepDims:!!b,selectLastIndex:!!c,axis:d})},840252:(a,
41
- b)=>{e.jb("Softmax",a,{axis:b})},840315:(a,b)=>{e.jb("Concat",a,{axis:b})},840375:(a,b,c,d,f)=>{e.jb("Split",a,{axis:b,numOutputs:c,splitSizes:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},840531:a=>{e.jb("Expand",a,void 0)},840585:(a,b)=>{e.jb("Gather",a,{axis:Number(b)})},840656:(a,b)=>{e.jb("GatherElements",a,{axis:Number(b)})},840735:(a,b)=>{e.jb("GatherND",a,{batch_dims:Number(b)})},840814:(a,b,c,d,f,g,h,l,m,p,r)=>{e.jb("Resize",a,{antialias:b,axes:c?Array.from(H().subarray(Number(c)>>>
42
- 0,Number(d)>>>0)):[],coordinateTransformMode:M(f),cubicCoeffA:g,excludeOutside:h,extrapolationValue:l,keepAspectRatioPolicy:M(m),mode:M(p),nearestMode:M(r)})},841176:(a,b,c,d,f,g,h)=>{e.jb("Slice",a,{starts:b?Array.from(H().subarray(Number(b)>>>0,Number(c)>>>0)):[],ends:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[],axes:g?Array.from(H().subarray(Number(g)>>>0,Number(h)>>>0)):[]})},841440:a=>{e.jb("Tile",a,void 0)},841492:(a,b,c)=>{e.jb("InstanceNormalization",a,{epsilon:b,format:c?"NHWC":
43
- "NCHW"})},841606:(a,b,c)=>{e.jb("InstanceNormalization",a,{epsilon:b,format:c?"NHWC":"NCHW"})},841720:a=>{e.jb("Range",a,void 0)},841773:(a,b)=>{e.jb("Einsum",a,{equation:M(b)})},841854:(a,b,c,d,f)=>{e.jb("Pad",a,{mode:b,value:c,pads:d?Array.from(H().subarray(Number(d)>>>0,Number(f)>>>0)):[]})},841997:(a,b,c,d,f,g)=>{e.jb("BatchNormalization",a,{epsilon:b,momentum:c,spatial:!!f,trainingMode:!!d,format:g?"NHWC":"NCHW"})},842166:(a,b,c,d,f,g)=>{e.jb("BatchNormalization",a,{epsilon:b,momentum:c,spatial:!!f,
44
- trainingMode:!!d,format:g?"NHWC":"NCHW"})},842335:(a,b,c)=>{e.jb("CumSum",a,{exclusive:Number(b),reverse:Number(c)})},842432:(a,b,c)=>{e.jb("DequantizeLinear",a,{axis:b,blockSize:c})},842522:(a,b,c,d,f)=>{e.jb("GridSample",a,{align_corners:b,mode:M(c),padding_mode:M(d),format:f?"NHWC":"NCHW"})},842692:(a,b,c,d,f)=>{e.jb("GridSample",a,{align_corners:b,mode:M(c),padding_mode:M(d),format:f?"NHWC":"NCHW"})},842862:(a,b)=>{e.jb("ScatterND",a,{reduction:M(b)})},842947:(a,b,c,d,f,g,h,l,m)=>{e.jb("Attention",
45
- a,{numHeads:b,isUnidirectional:c,maskFilterValue:d,scale:f,doRotary:g,qkvHiddenSizes:h?Array.from(H().subarray(Number(l)>>>0,Number(l)+h>>>0)):[],pastPresentShareBuffer:!!m})},843219:a=>{e.jb("BiasAdd",a,void 0)},843274:a=>{e.jb("BiasSplitGelu",a,void 0)},843335:a=>{e.jb("FastGelu",a,void 0)},843391:(a,b,c,d,f,g,h,l,m,p,r,u,w,y,ba,Vd)=>{e.jb("Conv",a,{format:u?"NHWC":"NCHW",auto_pad:b,dilations:c?Array.from(H().subarray(Number(c)>>>0,Number(d)>>>0)):[],group:f,kernel_shape:g?Array.from(H().subarray(Number(g)>>>
46
- 0,Number(h)>>>0)):[],pads:l?Array.from(H().subarray(Number(l)>>>0,Number(m)>>>0)):[],strides:p?Array.from(H().subarray(Number(p)>>>0,Number(r)>>>0)):[],w_is_const:()=>!!D()[Number(w)>>>0],activation:M(y),activation_params:ba?Array.from(Ga().subarray(Number(ba)>>>0,Number(Vd)>>>0)):[]})},843975:a=>{e.jb("Gelu",a,void 0)},844027:(a,b,c,d,f,g,h,l,m)=>{e.jb("GroupQueryAttention",a,{numHeads:b,kvNumHeads:c,scale:d,softcap:f,doRotary:g,rotaryInterleaved:h,smoothSoftmax:l,localWindowSize:m})},844244:(a,
47
- b,c,d)=>{e.jb("LayerNormalization",a,{axis:b,epsilon:c,simplified:!!d})},844355:(a,b,c,d)=>{e.jb("LayerNormalization",a,{axis:b,epsilon:c,simplified:!!d})},844466:(a,b,c,d,f,g)=>{e.jb("MatMulNBits",a,{k:b,n:c,accuracyLevel:d,bits:f,blockSize:g})},844593:(a,b,c,d,f,g)=>{e.jb("MultiHeadAttention",a,{numHeads:b,isUnidirectional:c,maskFilterValue:d,scale:f,doRotary:g})},844752:(a,b)=>{e.jb("QuickGelu",a,{alpha:b})},844816:(a,b,c,d,f)=>{e.jb("RotaryEmbedding",a,{interleaved:!!b,numHeads:c,rotaryEmbeddingDim:d,
48
- scale:f})},844955:(a,b,c)=>{e.jb("SkipLayerNormalization",a,{epsilon:b,simplified:!!c})},845057:(a,b,c)=>{e.jb("SkipLayerNormalization",a,{epsilon:b,simplified:!!c})},845159:(a,b,c,d)=>{e.jb("GatherBlockQuantized",a,{gatherAxis:b,quantizeAxis:c,blockSize:d})},845280:a=>{e.Zb(a)},845314:(a,b)=>e.ac(Number(a),Number(b),e.Fb.dc,e.Fb.errors)};function db(a,b,c){return Ec(async()=>{await e.Xb(Number(a),Number(b),Number(c))})}function cb(){return"undefined"!==typeof wasmOffsetConverter}
49
- class Fc{name="ExitStatus";constructor(a){this.message=`Program terminated with exit(${a})`;this.status=a}}
50
- var Gc=a=>{a.terminate();a.onmessage=()=>{}},Hc=[],Lc=a=>{0==N.length&&(Ic(),Jc(N[0]));var b=N.pop();if(!b)return 6;Kc.push(b);O[a.Ab]=b;b.Ab=a.Ab;var c={Bb:"run",fc:a.ec,Hb:a.Hb,Ab:a.Ab};n&&b.unref();b.postMessage(c,a.Mb);return 0},P=0,Q=(a,b,...c)=>{for(var d=2*c.length,f=Mc(),g=Nc(8*d),h=g>>>3,l=0;l<c.length;l++){var m=c[l];"bigint"==typeof m?(C[h+2*l]=1n,C[h+2*l+1]=m):(C[h+2*l]=0n,J()[h+2*l+1>>>0]=m)}a=Oc(a,0,d,g,b);Pc(f);return a};
51
- function Cc(a){if(q)return Q(0,1,a);wa=a;if(!(0<P)){for(var b of Kc)Gc(b);for(b of N)Gc(b);N=[];Kc=[];O={};A=!0}ma(a,new Fc(a))}function Qc(a){if(q)return Q(1,0,a);xc(a)}var xc=a=>{wa=a;if(q)throw Qc(a),"unwind";Cc(a)},N=[],Kc=[],Rc=[],O={};function Sc(){for(var a=e.numThreads-1;a--;)Ic();Hc.unshift(()=>{Ua++;Tc(()=>Wa())})}var Vc=a=>{var b=a.Ab;delete O[b];N.push(a);Kc.splice(Kc.indexOf(a),1);a.Ab=0;Uc(b)};function Na(){Rc.forEach(a=>a())}
52
- var Jc=a=>new Promise(b=>{a.onmessage=g=>{g=g.data;var h=g.Bb;if(g.Gb&&g.Gb!=Ka()){var l=O[g.Gb];l?l.postMessage(g,g.Mb):x(`Internal error! Worker sent a message "${h}" to target pthread ${g.Gb}, but that thread no longer exists!`)}else if("checkMailbox"===h)Ra();else if("spawnThread"===h)Lc(g);else if("cleanupThread"===h)Vc(O[g.hc]);else if("loaded"===h)a.loaded=!0,n&&!a.Ab&&a.unref(),b(a);else if("alert"===h)alert(`Thread ${g.ic}: ${g.text}`);else if("setimmediate"===g.target)a.postMessage(g);else if("callHandler"===
53
- h)e[g.Qb](...g.args);else h&&x(`worker sent an unknown command ${h}`)};a.onerror=g=>{x(`${"worker sent an error!"} ${g.filename}:${g.lineno}: ${g.message}`);throw g;};n&&(a.on("message",g=>a.onmessage({data:g})),a.on("error",g=>a.onerror(g)));var c=[],d=[],f;for(f of d)e.propertyIsEnumerable(f)&&c.push(f);a.postMessage({Bb:"load",Rb:c,kc:z,lc:va})});function Tc(a){q?a():Promise.all(N.map(Jc)).then(a)}
54
- function Ic(){var a=new Worker(new URL(import.meta.url),{type:"module",workerData:"em-pthread",name:"em-pthread"});N.push(a)}var La=a=>{E();var b=I()[a+52>>>2>>>0];a=I()[a+56>>>2>>>0];Wc(b,b-a);Pc(b)},Qa=(a,b)=>{P=0;a=Xc(a,b);0<P?wa=a:Yc(a)};class Zc{constructor(a){this.Ib=a-24}}var $c=0,ad=0;function eb(a,b,c){a>>>=0;var d=new Zc(a);b>>>=0;c>>>=0;I()[d.Ib+16>>>2>>>0]=0;I()[d.Ib+4>>>2>>>0]=b;I()[d.Ib+8>>>2>>>0]=c;$c=a;ad++;throw $c;}
55
- function bd(a,b,c,d){return q?Q(2,1,a,b,c,d):fb(a,b,c,d)}function fb(a,b,c,d){a>>>=0;b>>>=0;c>>>=0;d>>>=0;if("undefined"==typeof SharedArrayBuffer)return 6;var f=[];if(q&&0===f.length)return bd(a,b,c,d);a={ec:c,Ab:a,Hb:d,Mb:f};return q?(a.Bb="spawnThread",postMessage(a,f),0):Lc(a)}
56
- var cd="undefined"!=typeof TextDecoder?new TextDecoder:void 0,dd=(a,b=0,c=NaN)=>{b>>>=0;var d=b+c;for(c=b;a[c]&&!(c>=d);)++c;if(16<c-b&&a.buffer&&cd)return cd.decode(a.buffer instanceof ArrayBuffer?a.subarray(b,c):a.slice(b,c));for(d="";b<c;){var f=a[b++];if(f&128){var g=a[b++]&63;if(192==(f&224))d+=String.fromCharCode((f&31)<<6|g);else{var h=a[b++]&63;f=224==(f&240)?(f&15)<<12|g<<6|h:(f&7)<<18|g<<12|h<<6|a[b++]&63;65536>f?d+=String.fromCharCode(f):(f-=65536,d+=String.fromCharCode(55296|f>>10,56320|
57
- f&1023))}}else d+=String.fromCharCode(f)}return d},M=(a,b)=>(a>>>=0)?dd(F(),a,b):"";function gb(a,b,c){return q?Q(3,1,a,b,c):0}function hb(a,b){if(q)return Q(4,1,a,b)}
58
- var ed=a=>{for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);127>=d?b++:2047>=d?b+=2:55296<=d&&57343>=d?(b+=4,++c):b+=3}return b},fd=(a,b,c)=>{var d=F();b>>>=0;if(0<c){var f=b;c=b+c-1;for(var g=0;g<a.length;++g){var h=a.charCodeAt(g);if(55296<=h&&57343>=h){var l=a.charCodeAt(++g);h=65536+((h&1023)<<10)|l&1023}if(127>=h){if(b>=c)break;d[b++>>>0]=h}else{if(2047>=h){if(b+1>=c)break;d[b++>>>0]=192|h>>6}else{if(65535>=h){if(b+2>=c)break;d[b++>>>0]=224|h>>12}else{if(b+3>=c)break;d[b++>>>0]=240|h>>18;
59
- d[b++>>>0]=128|h>>12&63}d[b++>>>0]=128|h>>6&63}d[b++>>>0]=128|h&63}}d[b>>>0]=0;a=b-f}else a=0;return a};function ib(a,b){if(q)return Q(5,1,a,b)}function jb(a,b,c){if(q)return Q(6,1,a,b,c)}function kb(a,b,c){return q?Q(7,1,a,b,c):0}function lb(a,b){if(q)return Q(8,1,a,b)}function mb(a,b,c){if(q)return Q(9,1,a,b,c)}function nb(a,b,c,d){if(q)return Q(10,1,a,b,c,d)}function ob(a,b,c,d){if(q)return Q(11,1,a,b,c,d)}function pb(a,b,c,d){if(q)return Q(12,1,a,b,c,d)}function qb(a){if(q)return Q(13,1,a)}
60
- function rb(a,b){if(q)return Q(14,1,a,b)}function sb(a,b,c){if(q)return Q(15,1,a,b,c)}var tb=()=>L(""),gd,R=a=>{for(var b="";F()[a>>>0];)b+=gd[F()[a++>>>0]];return b},hd={},jd={},kd={},S;function ld(a,b,c={}){var d=b.name;if(!a)throw new S(`type "${d}" must have a positive integer typeid pointer`);if(jd.hasOwnProperty(a)){if(c.Sb)return;throw new S(`Cannot register type '${d}' twice`);}jd[a]=b;delete kd[a];hd.hasOwnProperty(a)&&(b=hd[a],delete hd[a],b.forEach(f=>f()))}
61
- function T(a,b,c={}){return ld(a,b,c)}var md=(a,b,c)=>{switch(b){case 1:return c?d=>D()[d>>>0]:d=>F()[d>>>0];case 2:return c?d=>G()[d>>>1>>>0]:d=>Fa()[d>>>1>>>0];case 4:return c?d=>H()[d>>>2>>>0]:d=>I()[d>>>2>>>0];case 8:return c?d=>C[d>>>3]:d=>Da[d>>>3];default:throw new TypeError(`invalid integer width (${b}): ${a}`);}};
62
- function ub(a,b,c){a>>>=0;c>>>=0;b=R(b>>>0);T(a,{name:b,fromWireType:d=>d,toWireType:function(d,f){if("bigint"!=typeof f&&"number"!=typeof f)throw null===f?f="null":(d=typeof f,f="object"===d||"array"===d||"function"===d?f.toString():""+f),new TypeError(`Cannot convert "${f}" to ${this.name}`);"number"==typeof f&&(f=BigInt(f));return f},Cb:U,readValueFromPointer:md(b,c,-1==b.indexOf("u")),Db:null})}var U=8;
63
- function vb(a,b,c,d){a>>>=0;b=R(b>>>0);T(a,{name:b,fromWireType:function(f){return!!f},toWireType:function(f,g){return g?c:d},Cb:U,readValueFromPointer:function(f){return this.fromWireType(F()[f>>>0])},Db:null})}var nd=[],V=[];function Ob(a){a>>>=0;9<a&&0===--V[a+1]&&(V[a]=void 0,nd.push(a))}
64
- var W=a=>{if(!a)throw new S("Cannot use deleted val. handle = "+a);return V[a]},X=a=>{switch(a){case void 0:return 2;case null:return 4;case !0:return 6;case !1:return 8;default:const b=nd.pop()||V.length;V[b]=a;V[b+1]=1;return b}};function od(a){return this.fromWireType(I()[a>>>2>>>0])}var pd={name:"emscripten::val",fromWireType:a=>{var b=W(a);Ob(a);return b},toWireType:(a,b)=>X(b),Cb:U,readValueFromPointer:od,Db:null};function wb(a){return T(a>>>0,pd)}
65
- var qd=(a,b)=>{switch(b){case 4:return function(c){return this.fromWireType(Ga()[c>>>2>>>0])};case 8:return function(c){return this.fromWireType(J()[c>>>3>>>0])};default:throw new TypeError(`invalid float width (${b}): ${a}`);}};function xb(a,b,c){a>>>=0;c>>>=0;b=R(b>>>0);T(a,{name:b,fromWireType:d=>d,toWireType:(d,f)=>f,Cb:U,readValueFromPointer:qd(b,c),Db:null})}
66
- function yb(a,b,c,d,f){a>>>=0;c>>>=0;b=R(b>>>0);-1===f&&(f=4294967295);f=l=>l;if(0===d){var g=32-8*c;f=l=>l<<g>>>g}var h=b.includes("unsigned")?function(l,m){return m>>>0}:function(l,m){return m};T(a,{name:b,fromWireType:f,toWireType:h,Cb:U,readValueFromPointer:md(b,c,0!==d),Db:null})}
67
- function zb(a,b,c){function d(g){var h=I()[g>>>2>>>0];g=I()[g+4>>>2>>>0];return new f(D().buffer,g,h)}a>>>=0;var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,BigInt64Array,BigUint64Array][b];c=R(c>>>0);T(a,{name:c,fromWireType:d,Cb:U,readValueFromPointer:d},{Sb:!0})}
68
- function Ab(a,b){a>>>=0;b=R(b>>>0);T(a,{name:b,fromWireType:function(c){for(var d=I()[c>>>2>>>0],f=c+4,g,h=f,l=0;l<=d;++l){var m=f+l;if(l==d||0==F()[m>>>0])h=M(h,m-h),void 0===g?g=h:(g+=String.fromCharCode(0),g+=h),h=m+1}Y(c);return g},toWireType:function(c,d){d instanceof ArrayBuffer&&(d=new Uint8Array(d));var f="string"==typeof d;if(!(f||d instanceof Uint8Array||d instanceof Uint8ClampedArray||d instanceof Int8Array))throw new S("Cannot pass non-string to std::string");var g=f?ed(d):d.length;var h=
69
- rd(4+g+1),l=h+4;I()[h>>>2>>>0]=g;if(f)fd(d,l,g+1);else if(f)for(f=0;f<g;++f){var m=d.charCodeAt(f);if(255<m)throw Y(h),new S("String has UTF-16 code units that do not fit in 8 bits");F()[l+f>>>0]=m}else for(f=0;f<g;++f)F()[l+f>>>0]=d[f];null!==c&&c.push(Y,h);return h},Cb:U,readValueFromPointer:od,Db(c){Y(c)}})}
70
- var sd="undefined"!=typeof TextDecoder?new TextDecoder("utf-16le"):void 0,td=(a,b)=>{var c=a>>1;for(var d=c+b/2;!(c>=d)&&Fa()[c>>>0];)++c;c<<=1;if(32<c-a&&sd)return sd.decode(F().slice(a,c));c="";for(d=0;!(d>=b/2);++d){var f=G()[a+2*d>>>1>>>0];if(0==f)break;c+=String.fromCharCode(f)}return c},ud=(a,b,c)=>{c??=2147483647;if(2>c)return 0;c-=2;var d=b;c=c<2*a.length?c/2:a.length;for(var f=0;f<c;++f){var g=a.charCodeAt(f);G()[b>>>1>>>0]=g;b+=2}G()[b>>>1>>>0]=0;return b-d},vd=a=>2*a.length,wd=(a,b)=>{for(var c=
71
- 0,d="";!(c>=b/4);){var f=H()[a+4*c>>>2>>>0];if(0==f)break;++c;65536<=f?(f-=65536,d+=String.fromCharCode(55296|f>>10,56320|f&1023)):d+=String.fromCharCode(f)}return d},xd=(a,b,c)=>{b>>>=0;c??=2147483647;if(4>c)return 0;var d=b;c=d+c-4;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var h=a.charCodeAt(++f);g=65536+((g&1023)<<10)|h&1023}H()[b>>>2>>>0]=g;b+=4;if(b+4>c)break}H()[b>>>2>>>0]=0;return b-d},yd=a=>{for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);55296<=d&&57343>=
72
- d&&++c;b+=4}return b};
73
- function Bb(a,b,c){a>>>=0;b>>>=0;c>>>=0;c=R(c);if(2===b){var d=td;var f=ud;var g=vd;var h=l=>Fa()[l>>>1>>>0]}else 4===b&&(d=wd,f=xd,g=yd,h=l=>I()[l>>>2>>>0]);T(a,{name:c,fromWireType:l=>{for(var m=I()[l>>>2>>>0],p,r=l+4,u=0;u<=m;++u){var w=l+4+u*b;if(u==m||0==h(w))r=d(r,w-r),void 0===p?p=r:(p+=String.fromCharCode(0),p+=r),r=w+b}Y(l);return p},toWireType:(l,m)=>{if("string"!=typeof m)throw new S(`Cannot pass non-string to C++ string type ${c}`);var p=g(m),r=rd(4+p+b);I()[r>>>2>>>0]=p/b;f(m,r+4,p+b);
74
- null!==l&&l.push(Y,r);return r},Cb:U,readValueFromPointer:od,Db(l){Y(l)}})}function Cb(a,b){a>>>=0;b=R(b>>>0);T(a,{Tb:!0,name:b,Cb:0,fromWireType:()=>{},toWireType:()=>{}})}function Db(a){Ma(a>>>0,!k,1,!ea,131072,!1);Na()}var zd=a=>{if(!A)try{if(a(),!(0<P))try{q?Yc(wa):xc(wa)}catch(b){b instanceof Fc||"unwind"==b||ma(1,b)}}catch(b){b instanceof Fc||"unwind"==b||ma(1,b)}};
75
- function Oa(a){a>>>=0;"function"===typeof Atomics.jc&&(Atomics.jc(H(),a>>>2,a).value.then(Ra),a+=128,Atomics.store(H(),a>>>2,1))}var Ra=()=>{var a=Ka();a&&(Oa(a),zd(Ad))};function Eb(a,b){a>>>=0;a==b>>>0?setTimeout(Ra):q?postMessage({Gb:a,Bb:"checkMailbox"}):(a=O[a])&&a.postMessage({Bb:"checkMailbox"})}var Bd=[];function Fb(a,b,c,d,f){b>>>=0;d/=2;Bd.length=d;c=f>>>0>>>3;for(f=0;f<d;f++)Bd[f]=C[c+2*f]?C[c+2*f+1]:J()[c+2*f+1>>>0];return(b?Dc[b]:Cd[a])(...Bd)}var Gb=()=>{P=0};
76
- function Hb(a){a>>>=0;q?postMessage({Bb:"cleanupThread",hc:a}):Vc(O[a])}function Ib(a){n&&O[a>>>0].ref()}var Ed=(a,b)=>{var c=jd[a];if(void 0===c)throw a=Dd(a),c=R(a),Y(a),new S(`${b} has unknown type ${c}`);return c},Fd=(a,b,c)=>{var d=[];a=a.toWireType(d,c);d.length&&(I()[b>>>2>>>0]=X(d));return a};function Jb(a,b,c){b>>>=0;c>>>=0;a=W(a>>>0);b=Ed(b,"emval::as");return Fd(b,c,a)}function Kb(a,b){b>>>=0;a=W(a>>>0);b=Ed(b,"emval::as");return b.toWireType(null,a)}var Gd=a=>{try{a()}catch(b){L(b)}};
77
- function Hd(){var a=K,b={};for(let [c,d]of Object.entries(a))b[c]="function"==typeof d?(...f)=>{Id.push(c);try{return d(...f)}finally{A||(Id.pop(),t&&1===Z&&0===Id.length&&(Z=0,P+=1,Gd(Jd),"undefined"!=typeof Fibers&&Fibers.rc()))}}:d;return b}var Z=0,t=null,Kd=0,Id=[],Ld={},Md={},Nd=0,Od=null,Pd=[];function ia(){return new Promise((a,b)=>{Od={resolve:a,reject:b}})}
78
- function Qd(){var a=rd(65548),b=a+12;I()[a>>>2>>>0]=b;I()[a+4>>>2>>>0]=b+65536;b=Id[0];var c=Ld[b];void 0===c&&(c=Nd++,Ld[b]=c,Md[c]=b);b=c;H()[a+8>>>2>>>0]=b;return a}function Rd(){var a=H()[t+8>>>2>>>0];a=K[Md[a]];--P;return a()}
79
- function Sd(a){if(!A){if(0===Z){var b=!1,c=!1;a((d=0)=>{if(!A&&(Kd=d,b=!0,c)){Z=2;Gd(()=>Td(t));"undefined"!=typeof MainLoop&&MainLoop.Pb&&MainLoop.resume();d=!1;try{var f=Rd()}catch(l){f=l,d=!0}var g=!1;if(!t){var h=Od;h&&(Od=null,(d?h.reject:h.resolve)(f),g=!0)}if(d&&!g)throw f;}});c=!0;b||(Z=1,t=Qd(),"undefined"!=typeof MainLoop&&MainLoop.Pb&&MainLoop.pause(),Gd(()=>Ud(t)))}else 2===Z?(Z=0,Gd(Wd),Y(t),t=null,Pd.forEach(zd)):L(`invalid state: ${Z}`);return Kd}}
80
- function Ec(a){return Sd(b=>{a().then(b)})}function Lb(a){a>>>=0;return Ec(async()=>{var b=await W(a);return X(b)})}var Xd=[];function Mb(a,b,c,d){c>>>=0;d>>>=0;a=Xd[a>>>0];b=W(b>>>0);return a(null,b,c,d)}var Yd={},Zd=a=>{var b=Yd[a];return void 0===b?R(a):b};function Nb(a,b,c,d,f){c>>>=0;d>>>=0;f>>>=0;a=Xd[a>>>0];b=W(b>>>0);c=Zd(c);return a(b,b[c],d,f)}var $d=()=>"object"==typeof globalThis?globalThis:Function("return this")();
81
- function Pb(a){a>>>=0;if(0===a)return X($d());a=Zd(a);return X($d()[a])}var ae=a=>{var b=Xd.length;Xd.push(a);return b},be=(a,b)=>{for(var c=Array(a),d=0;d<a;++d)c[d]=Ed(I()[b+4*d>>>2>>>0],"parameter "+d);return c},ce=(a,b)=>Object.defineProperty(b,"name",{value:a});
82
- function de(a){var b=Function;if(!(b instanceof Function))throw new TypeError(`new_ called with constructor type ${typeof b} which is not a function`);var c=ce(b.name||"unknownFunctionName",function(){});c.prototype=b.prototype;c=new c;a=b.apply(c,a);return a instanceof Object?a:c}
83
- function Qb(a,b,c){b=be(a,b>>>0);var d=b.shift();a--;var f="return function (obj, func, destructorsRef, args) {\n",g=0,h=[];0===c&&h.push("obj");for(var l=["retType"],m=[d],p=0;p<a;++p)h.push("arg"+p),l.push("argType"+p),m.push(b[p]),f+=` var arg${p} = argType${p}.readValueFromPointer(args${g?"+"+g:""});\n`,g+=b[p].Cb;f+=` var rv = ${1===c?"new func":"func.call"}(${h.join(", ")});\n`;d.Tb||(l.push("emval_returnValue"),m.push(Fd),f+=" return emval_returnValue(retType, destructorsRef, rv);\n");l.push(f+
84
- "};\n");a=de(l)(...m);c=`methodCaller<(${b.map(r=>r.name).join(", ")}) => ${d.name}>`;return ae(ce(c,a))}function Rb(a){a=Zd(a>>>0);return X(e[a])}function Sb(a,b){b>>>=0;a=W(a>>>0);b=W(b);return X(a[b])}function Tb(a){a>>>=0;9<a&&(V[a+1]+=1)}function Ub(){return X([])}function Vb(a){a=W(a>>>0);for(var b=Array(a.length),c=0;c<a.length;c++)b[c]=a[c];return X(b)}function Wb(a){return X(Zd(a>>>0))}function Xb(){return X({})}
85
- function Yb(a){a>>>=0;for(var b=W(a);b.length;){var c=b.pop();b.pop()(c)}Ob(a)}function Zb(a,b,c){b>>>=0;c>>>=0;a=W(a>>>0);b=W(b);c=W(c);a[b]=c}function $b(a,b){b>>>=0;a=Ed(a>>>0,"_emval_take_value");a=a.readValueFromPointer(b);return X(a)}
86
- function ac(a,b){a=-9007199254740992>a||9007199254740992<a?NaN:Number(a);b>>>=0;a=new Date(1E3*a);H()[b>>>2>>>0]=a.getUTCSeconds();H()[b+4>>>2>>>0]=a.getUTCMinutes();H()[b+8>>>2>>>0]=a.getUTCHours();H()[b+12>>>2>>>0]=a.getUTCDate();H()[b+16>>>2>>>0]=a.getUTCMonth();H()[b+20>>>2>>>0]=a.getUTCFullYear()-1900;H()[b+24>>>2>>>0]=a.getUTCDay();a=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0;H()[b+28>>>2>>>0]=a}
87
- var ee=a=>0===a%4&&(0!==a%100||0===a%400),fe=[0,31,60,91,121,152,182,213,244,274,305,335],ge=[0,31,59,90,120,151,181,212,243,273,304,334];
88
- function bc(a,b){a=-9007199254740992>a||9007199254740992<a?NaN:Number(a);b>>>=0;a=new Date(1E3*a);H()[b>>>2>>>0]=a.getSeconds();H()[b+4>>>2>>>0]=a.getMinutes();H()[b+8>>>2>>>0]=a.getHours();H()[b+12>>>2>>>0]=a.getDate();H()[b+16>>>2>>>0]=a.getMonth();H()[b+20>>>2>>>0]=a.getFullYear()-1900;H()[b+24>>>2>>>0]=a.getDay();var c=(ee(a.getFullYear())?fe:ge)[a.getMonth()]+a.getDate()-1|0;H()[b+28>>>2>>>0]=c;H()[b+36>>>2>>>0]=-(60*a.getTimezoneOffset());c=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();
89
- var d=(new Date(a.getFullYear(),0,1)).getTimezoneOffset();a=(c!=d&&a.getTimezoneOffset()==Math.min(d,c))|0;H()[b+32>>>2>>>0]=a}
90
- function cc(a){a>>>=0;var b=new Date(H()[a+20>>>2>>>0]+1900,H()[a+16>>>2>>>0],H()[a+12>>>2>>>0],H()[a+8>>>2>>>0],H()[a+4>>>2>>>0],H()[a>>>2>>>0],0),c=H()[a+32>>>2>>>0],d=b.getTimezoneOffset(),f=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),g=(new Date(b.getFullYear(),0,1)).getTimezoneOffset(),h=Math.min(g,f);0>c?H()[a+32>>>2>>>0]=Number(f!=g&&h==d):0<c!=(h==d)&&(f=Math.max(g,f),b.setTime(b.getTime()+6E4*((0<c?h:f)-d)));H()[a+24>>>2>>>0]=b.getDay();c=(ee(b.getFullYear())?fe:ge)[b.getMonth()]+
91
- b.getDate()-1|0;H()[a+28>>>2>>>0]=c;H()[a>>>2>>>0]=b.getSeconds();H()[a+4>>>2>>>0]=b.getMinutes();H()[a+8>>>2>>>0]=b.getHours();H()[a+12>>>2>>>0]=b.getDate();H()[a+16>>>2>>>0]=b.getMonth();H()[a+20>>>2>>>0]=b.getYear();a=b.getTime();return BigInt(isNaN(a)?-1:a/1E3)}function dc(a,b,c,d,f,g,h){return q?Q(16,1,a,b,c,d,f,g,h):-52}function ec(a,b,c,d,f,g){if(q)return Q(17,1,a,b,c,d,f,g)}var he={},pc=()=>performance.timeOrigin+performance.now();
92
- function fc(a,b){if(q)return Q(18,1,a,b);he[a]&&(clearTimeout(he[a].id),delete he[a]);if(!b)return 0;var c=setTimeout(()=>{delete he[a];zd(()=>ie(a,performance.timeOrigin+performance.now()))},b);he[a]={id:c,qc:b};return 0}
93
- function gc(a,b,c,d){a>>>=0;b>>>=0;c>>>=0;d>>>=0;var f=(new Date).getFullYear(),g=(new Date(f,0,1)).getTimezoneOffset();f=(new Date(f,6,1)).getTimezoneOffset();var h=Math.max(g,f);I()[a>>>2>>>0]=60*h;H()[b>>>2>>>0]=Number(g!=f);b=l=>{var m=Math.abs(l);return`UTC${0<=l?"-":"+"}${String(Math.floor(m/60)).padStart(2,"0")}${String(m%60).padStart(2,"0")}`};a=b(g);b=b(f);f<g?(fd(a,c,17),fd(b,d,17)):(fd(a,d,17),fd(b,c,17))}var lc=()=>Date.now(),je=1;
94
- function hc(a,b,c){if(!(0<=a&&3>=a))return 28;if(0===a)a=Date.now();else if(je)a=performance.timeOrigin+performance.now();else return 52;C[c>>>0>>>3]=BigInt(Math.round(1E6*a));return 0}var ke=[],le=(a,b)=>{ke.length=0;for(var c;c=F()[a++>>>0];){var d=105!=c;d&=112!=c;b+=d&&b%8?4:0;ke.push(112==c?I()[b>>>2>>>0]:106==c?C[b>>>3]:105==c?H()[b>>>2>>>0]:J()[b>>>3>>>0]);b+=d?8:4}return ke};function ic(a,b,c){a>>>=0;b=le(b>>>0,c>>>0);return Dc[a](...b)}
95
- function jc(a,b,c){a>>>=0;b=le(b>>>0,c>>>0);return Dc[a](...b)}var kc=()=>{};function mc(a,b){return x(M(a>>>0,b>>>0))}var nc=()=>{P+=1;throw"unwind";};function oc(){return 4294901760}var qc=()=>n?require("os").cpus().length:navigator.hardwareConcurrency;function rc(){L("Cannot use emscripten_pc_get_function without -sUSE_OFFSET_CONVERTER");return 0}
96
- function sc(a){a>>>=0;var b=F().length;if(a<=b||4294901760<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);a:{d=(Math.min(4294901760,65536*Math.ceil(Math.max(a,d)/65536))-z.buffer.byteLength+65535)/65536|0;try{z.grow(d);E();var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1}var me=()=>{L("Cannot use convertFrameToPC (needed by __builtin_return_address) without -sUSE_OFFSET_CONVERTER");return 0},ne={},oe=a=>{a.forEach(b=>{var c=me();c&&(ne[c]=b)})};
97
- function tc(){var a=Error().stack.toString().split("\n");"Error"==a[0]&&a.shift();oe(a);ne.Lb=me();ne.cc=a;return ne.Lb}function uc(a,b,c){a>>>=0;b>>>=0;if(ne.Lb==a)var d=ne.cc;else d=Error().stack.toString().split("\n"),"Error"==d[0]&&d.shift(),oe(d);for(var f=3;d[f]&&me()!=a;)++f;for(a=0;a<c&&d[a+f];++a)H()[b+4*a>>>2>>>0]=me();return a}
98
- var pe={},re=()=>{if(!qe){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:la||"./this.program"},b;for(b in pe)void 0===pe[b]?delete a[b]:a[b]=pe[b];var c=[];for(b in a)c.push(`${b}=${a[b]}`);qe=c}return qe},qe;
99
- function vc(a,b){if(q)return Q(19,1,a,b);a>>>=0;b>>>=0;var c=0;re().forEach((d,f)=>{var g=b+c;f=I()[a+4*f>>>2>>>0]=g;for(g=0;g<d.length;++g)D()[f++>>>0]=d.charCodeAt(g);D()[f>>>0]=0;c+=d.length+1});return 0}function wc(a,b){if(q)return Q(20,1,a,b);a>>>=0;b>>>=0;var c=re();I()[a>>>2>>>0]=c.length;var d=0;c.forEach(f=>d+=f.length+1);I()[b>>>2>>>0]=d;return 0}function yc(a){return q?Q(21,1,a):52}function zc(a,b,c,d){return q?Q(22,1,a,b,c,d):52}function Ac(a,b,c,d){return q?Q(23,1,a,b,c,d):70}
100
- var se=[null,[],[]];function Bc(a,b,c,d){if(q)return Q(24,1,a,b,c,d);b>>>=0;c>>>=0;d>>>=0;for(var f=0,g=0;g<c;g++){var h=I()[b>>>2>>>0],l=I()[b+4>>>2>>>0];b+=8;for(var m=0;m<l;m++){var p=F()[h+m>>>0],r=se[a];0===p||10===p?((1===a?ta:x)(dd(r)),r.length=0):r.push(p)}f+=l}I()[d>>>2>>>0]=f;return 0}q||Sc();for(var te=Array(256),ue=0;256>ue;++ue)te[ue]=String.fromCharCode(ue);gd=te;S=e.BindingError=class extends Error{constructor(a){super(a);this.name="BindingError"}};
101
- e.InternalError=class extends Error{constructor(a){super(a);this.name="InternalError"}};V.push(0,1,void 0,1,null,1,!0,1,!1,1);e.count_emval_handles=()=>V.length/2-5-nd.length;var Cd=[Cc,Qc,bd,gb,hb,ib,jb,kb,lb,mb,nb,ob,pb,qb,rb,sb,dc,ec,fc,vc,wc,yc,zc,Ac,Bc],bb,K;
102
- (async function(){function a(d,f){K=d.exports;K=Hd();K=ve();Rc.push(K.ib);va=f;Wa();return K}Ua++;var b=ab();if(e.instantiateWasm)return new Promise(d=>{e.instantiateWasm(b,(f,g)=>{a(f,g);d(f.exports)})});if(q)return new Promise(d=>{Ha=f=>{var g=new WebAssembly.Instance(f,ab());d(a(g,f))}});Xa??=e.locateFile?e.locateFile?e.locateFile("ort-wasm-simd-threaded.jsep.wasm",v):v+"ort-wasm-simd-threaded.jsep.wasm":(new URL("ort-wasm-simd-threaded.jsep.wasm",import.meta.url)).href;try{var c=await $a(b);
103
- return a(c.instance,c.module)}catch(d){return ca(d),Promise.reject(d)}})();var Dd=a=>(Dd=K.Da)(a),Pa=()=>(Pa=K.Ea)();e._OrtInit=(a,b)=>(e._OrtInit=K.Fa)(a,b);e._OrtGetLastError=(a,b)=>(e._OrtGetLastError=K.Ga)(a,b);e._OrtCreateSessionOptions=(a,b,c,d,f,g,h,l,m,p)=>(e._OrtCreateSessionOptions=K.Ha)(a,b,c,d,f,g,h,l,m,p);e._OrtAppendExecutionProvider=(a,b,c,d,f)=>(e._OrtAppendExecutionProvider=K.Ia)(a,b,c,d,f);e._OrtAddFreeDimensionOverride=(a,b,c)=>(e._OrtAddFreeDimensionOverride=K.Ja)(a,b,c);
104
- e._OrtAddSessionConfigEntry=(a,b,c)=>(e._OrtAddSessionConfigEntry=K.Ka)(a,b,c);e._OrtReleaseSessionOptions=a=>(e._OrtReleaseSessionOptions=K.La)(a);e._OrtCreateSession=(a,b,c)=>(e._OrtCreateSession=K.Ma)(a,b,c);e._OrtReleaseSession=a=>(e._OrtReleaseSession=K.Na)(a);e._OrtGetInputOutputCount=(a,b,c)=>(e._OrtGetInputOutputCount=K.Oa)(a,b,c);e._OrtGetInputOutputMetadata=(a,b,c,d)=>(e._OrtGetInputOutputMetadata=K.Pa)(a,b,c,d);e._OrtFree=a=>(e._OrtFree=K.Qa)(a);
105
- e._OrtCreateTensor=(a,b,c,d,f,g)=>(e._OrtCreateTensor=K.Ra)(a,b,c,d,f,g);e._OrtGetTensorData=(a,b,c,d,f)=>(e._OrtGetTensorData=K.Sa)(a,b,c,d,f);e._OrtReleaseTensor=a=>(e._OrtReleaseTensor=K.Ta)(a);e._OrtCreateRunOptions=(a,b,c,d)=>(e._OrtCreateRunOptions=K.Ua)(a,b,c,d);e._OrtAddRunConfigEntry=(a,b,c)=>(e._OrtAddRunConfigEntry=K.Va)(a,b,c);e._OrtReleaseRunOptions=a=>(e._OrtReleaseRunOptions=K.Wa)(a);e._OrtCreateBinding=a=>(e._OrtCreateBinding=K.Xa)(a);
106
- e._OrtBindInput=(a,b,c)=>(e._OrtBindInput=K.Ya)(a,b,c);e._OrtBindOutput=(a,b,c,d)=>(e._OrtBindOutput=K.Za)(a,b,c,d);e._OrtClearBoundOutputs=a=>(e._OrtClearBoundOutputs=K._a)(a);e._OrtReleaseBinding=a=>(e._OrtReleaseBinding=K.$a)(a);e._OrtRunWithBinding=(a,b,c,d,f)=>(e._OrtRunWithBinding=K.ab)(a,b,c,d,f);e._OrtRun=(a,b,c,d,f,g,h,l)=>(e._OrtRun=K.bb)(a,b,c,d,f,g,h,l);e._OrtEndProfiling=a=>(e._OrtEndProfiling=K.cb)(a);e._JsepOutput=(a,b,c)=>(e._JsepOutput=K.db)(a,b,c);
107
- e._JsepGetNodeName=a=>(e._JsepGetNodeName=K.eb)(a);
108
- var Ka=()=>(Ka=K.fb)(),Y=e._free=a=>(Y=e._free=K.gb)(a),rd=e._malloc=a=>(rd=e._malloc=K.hb)(a),Ma=(a,b,c,d,f,g)=>(Ma=K.kb)(a,b,c,d,f,g),Sa=()=>(Sa=K.lb)(),Oc=(a,b,c,d,f)=>(Oc=K.mb)(a,b,c,d,f),Uc=a=>(Uc=K.nb)(a),Yc=a=>(Yc=K.ob)(a),ie=(a,b)=>(ie=K.pb)(a,b),Ad=()=>(Ad=K.qb)(),Wc=(a,b)=>(Wc=K.rb)(a,b),Pc=a=>(Pc=K.sb)(a),Nc=a=>(Nc=K.tb)(a),Mc=()=>(Mc=K.ub)(),Xc=e.dynCall_ii=(a,b)=>(Xc=e.dynCall_ii=K.vb)(a,b),Ud=a=>(Ud=K.wb)(a),Jd=()=>(Jd=K.xb)(),Td=a=>(Td=K.yb)(a),Wd=()=>(Wd=K.zb)();
109
- function ve(){var a=K;a=Object.assign({},a);var b=d=>f=>d(f)>>>0,c=d=>()=>d()>>>0;a.Da=b(a.Da);a.fb=c(a.fb);a.hb=b(a.hb);a.tb=b(a.tb);a.ub=c(a.ub);a.__cxa_get_exception_ptr=b(a.__cxa_get_exception_ptr);return a}e.stackSave=()=>Mc();e.stackRestore=a=>Pc(a);e.stackAlloc=a=>Nc(a);
110
- e.setValue=function(a,b,c="i8"){c.endsWith("*")&&(c="*");switch(c){case "i1":D()[a>>>0]=b;break;case "i8":D()[a>>>0]=b;break;case "i16":G()[a>>>1>>>0]=b;break;case "i32":H()[a>>>2>>>0]=b;break;case "i64":C[a>>>3]=BigInt(b);break;case "float":Ga()[a>>>2>>>0]=b;break;case "double":J()[a>>>3>>>0]=b;break;case "*":I()[a>>>2>>>0]=b;break;default:L(`invalid type for setValue: ${c}`)}};
111
- e.getValue=function(a,b="i8"){b.endsWith("*")&&(b="*");switch(b){case "i1":return D()[a>>>0];case "i8":return D()[a>>>0];case "i16":return G()[a>>>1>>>0];case "i32":return H()[a>>>2>>>0];case "i64":return C[a>>>3];case "float":return Ga()[a>>>2>>>0];case "double":return J()[a>>>3>>>0];case "*":return I()[a>>>2>>>0];default:L(`invalid type for getValue: ${b}`)}};e.UTF8ToString=M;e.stringToUTF8=fd;e.lengthBytesUTF8=ed;
112
- function we(){if(0<Ua)Va=we;else if(q)aa(e),Ta();else{for(;0<Hc.length;)Hc.shift()(e);0<Ua?Va=we:(e.calledRun=!0,A||(Ta(),aa(e)))}}we();e.PTR_SIZE=4;moduleRtn=da;
113
-
114
-
115
- return moduleRtn;
116
- }
117
- );
118
- })();
119
- export default ortWasmThreaded;
120
- var isPthread = globalThis.self?.name?.startsWith('em-pthread');
121
- var isNode = typeof globalThis.process?.versions?.node == 'string';
122
- if (isNode) isPthread = (await import('worker_threads')).workerData === 'em-pthread';
123
-
124
- // When running as a pthread, construct a new instance on startup
125
- isPthread && ortWasmThreaded();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_shared/voice/vendor/kokoro/transformers/ort-wasm-simd-threaded.jsep.wasm DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c46655e8a94afc45338d4cb2b840475f88e5012d524509916e505079c00bfa39
3
- size 21596019
 
 
 
 
_shared/voice/vendor/kokoro/transformers/transformers.js DELETED
The diff for this file is too large to render. See raw diff
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/config.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "model_type": "style_text_to_speech_2"
3
- }
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/tokenizer.json DELETED
@@ -1,175 +0,0 @@
1
- {
2
- "version": "1.0",
3
- "truncation": null,
4
- "padding": null,
5
- "added_tokens": [],
6
- "normalizer": {
7
- "type": "Replace",
8
- "pattern": {
9
- "Regex": "[^$;:,.!?\u2014\u2026\"()\u201c\u201d \u0303\u02a3\u02a5\u02a6\u02a8\u1d5d\uab67AIOQSTWY\u1d4aabcdefhijklmnopqrstuvwxyz\u0251\u0250\u0252\u00e6\u03b2\u0254\u0255\u00e7\u0256\u00f0\u02a4\u0259\u025a\u025b\u025c\u025f\u0261\u0265\u0268\u026a\u029d\u026f\u0270\u014b\u0273\u0272\u0274\u00f8\u0278\u03b8\u0153\u0279\u027e\u027b\u0281\u027d\u0282\u0283\u0288\u02a7\u028a\u028b\u028c\u0263\u0264\u03c7\u028e\u0292\u0294\u02c8\u02cc\u02d0\u02b0\u02b2\u2193\u2192\u2197\u2198\u1d7b]"
10
- },
11
- "content": ""
12
- },
13
- "pre_tokenizer": {
14
- "type": "Split",
15
- "pattern": {
16
- "Regex": ""
17
- },
18
- "behavior": "Isolated",
19
- "invert": false
20
- },
21
- "post_processor": {
22
- "type": "TemplateProcessing",
23
- "single": [
24
- {
25
- "SpecialToken": {
26
- "id": "$",
27
- "type_id": 0
28
- }
29
- },
30
- {
31
- "Sequence": {
32
- "id": "A",
33
- "type_id": 0
34
- }
35
- },
36
- {
37
- "SpecialToken": {
38
- "id": "$",
39
- "type_id": 0
40
- }
41
- }
42
- ],
43
- "special_tokens": {
44
- "$": {
45
- "id": "$",
46
- "ids": [
47
- 0
48
- ],
49
- "tokens": [
50
- "$"
51
- ]
52
- }
53
- }
54
- },
55
- "decoder": null,
56
- "model": {
57
- "vocab": {
58
- "$": 0,
59
- ";": 1,
60
- ":": 2,
61
- ",": 3,
62
- ".": 4,
63
- "!": 5,
64
- "?": 6,
65
- "\u2014": 9,
66
- "\u2026": 10,
67
- "\"": 11,
68
- "(": 12,
69
- ")": 13,
70
- "\u201c": 14,
71
- "\u201d": 15,
72
- " ": 16,
73
- "\u0303": 17,
74
- "\u02a3": 18,
75
- "\u02a5": 19,
76
- "\u02a6": 20,
77
- "\u02a8": 21,
78
- "\u1d5d": 22,
79
- "\uab67": 23,
80
- "A": 24,
81
- "I": 25,
82
- "O": 31,
83
- "Q": 33,
84
- "S": 35,
85
- "T": 36,
86
- "W": 39,
87
- "Y": 41,
88
- "\u1d4a": 42,
89
- "a": 43,
90
- "b": 44,
91
- "c": 45,
92
- "d": 46,
93
- "e": 47,
94
- "f": 48,
95
- "h": 50,
96
- "i": 51,
97
- "j": 52,
98
- "k": 53,
99
- "l": 54,
100
- "m": 55,
101
- "n": 56,
102
- "o": 57,
103
- "p": 58,
104
- "q": 59,
105
- "r": 60,
106
- "s": 61,
107
- "t": 62,
108
- "u": 63,
109
- "v": 64,
110
- "w": 65,
111
- "x": 66,
112
- "y": 67,
113
- "z": 68,
114
- "\u0251": 69,
115
- "\u0250": 70,
116
- "\u0252": 71,
117
- "\u00e6": 72,
118
- "\u03b2": 75,
119
- "\u0254": 76,
120
- "\u0255": 77,
121
- "\u00e7": 78,
122
- "\u0256": 80,
123
- "\u00f0": 81,
124
- "\u02a4": 82,
125
- "\u0259": 83,
126
- "\u025a": 85,
127
- "\u025b": 86,
128
- "\u025c": 87,
129
- "\u025f": 90,
130
- "\u0261": 92,
131
- "\u0265": 99,
132
- "\u0268": 101,
133
- "\u026a": 102,
134
- "\u029d": 103,
135
- "\u026f": 110,
136
- "\u0270": 111,
137
- "\u014b": 112,
138
- "\u0273": 113,
139
- "\u0272": 114,
140
- "\u0274": 115,
141
- "\u00f8": 116,
142
- "\u0278": 118,
143
- "\u03b8": 119,
144
- "\u0153": 120,
145
- "\u0279": 123,
146
- "\u027e": 125,
147
- "\u027b": 126,
148
- "\u0281": 128,
149
- "\u027d": 129,
150
- "\u0282": 130,
151
- "\u0283": 131,
152
- "\u0288": 132,
153
- "\u02a7": 133,
154
- "\u028a": 135,
155
- "\u028b": 136,
156
- "\u028c": 138,
157
- "\u0263": 139,
158
- "\u0264": 140,
159
- "\u03c7": 142,
160
- "\u028e": 143,
161
- "\u0292": 147,
162
- "\u0294": 148,
163
- "\u02c8": 156,
164
- "\u02cc": 157,
165
- "\u02d0": 158,
166
- "\u02b0": 162,
167
- "\u02b2": 164,
168
- "\u2193": 169,
169
- "\u2192": 171,
170
- "\u2197": 172,
171
- "\u2198": 173,
172
- "\u1d7b": 177
173
- }
174
- }
175
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/tokenizer_config.json DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "model_max_length": 512,
3
- "pad_token": "$",
4
- "tokenizer_class": "PreTrainedTokenizer",
5
- "unk_token": "$"
6
- }
 
 
 
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/af_bella.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:f69d836209b78eb8c66e75e3cda491e26ea838a3674257e9d4e5703cbaf55c8b
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/af_heart.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:d583ccff3cdca2f7fae535cb998ac07e9fcb90f09737b9a41fa2734ec44a8f0b
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/af_nicole.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:cd2191ab31b914ed7b318416b0e4440fdf392ddad9106a060819aa600a64f59a
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/am_fenrir.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c27989f741f7ee34d273a39d8a595cc0837d35f5ced9a29b7cc162614616df43
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/am_michael.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:1d1f21dd8da39c30705cd4c75d039d265e9bc4a2a93ed09bc9e1b1225eb95ba1
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/am_puck.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:fcf73c989033e9233e0b98713eca600c8c74dcc1614b37009d5450ff4a2274a0
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/bf_emma.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:669fe0647f9dd04fcab92f1439a40eeb4c8b4ab1f82e4996fe3d918ce4a63b73
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/Kokoro-82M-v1.0-ONNX/voices/bm_george.bin DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c4b235a4c1f2cd3b939fed08b899ce9385638b763f7b73a59616c4fc9bd6c9bc
3
- size 522240
 
 
 
 
_shared/voice/vendor/models/onnx-community/silero-vad/onnx/model.onnx DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:a4a068cd6cf1ea8355b84327595838ca748ec29a25bc91fc82e6c299ccdc5808
3
- size 2243022
 
 
 
 
_shared/voice/vendor/models/onnx-community/silero-vad/onnx/model_quantized.onnx DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:982c96dc518784fb9d19bc7f56cc8252473b020e4f2099f32049e4ad0b3b43e7
3
- size 639335
 
 
 
 
_shared/voice/vendor/transformers/ort-wasm-simd-threaded.jsep.wasm DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0f6fe5c40378504d1a25a77f766133464bb15705af23e01c994f185719fb080e
3
- size 21643825
 
 
 
 
_shared/voice/vendor/transformers/transformers.js DELETED
The diff for this file is too large to render. See raw diff
 
_shared/voice/vendor/transformers/transformers.mjs DELETED
The diff for this file is too large to render. See raw diff
 
blake3-gpu-parallel.html DELETED
@@ -1,145 +0,0 @@
1
- <!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
2
- <title>BLAKE3 — parallel, on your GPU</title>
3
- <style>
4
- :root{--bg:#0a0d13;--panel:#111825;--ink:#e8ebf1;--dim:#8b95a7;--ac:#7c5cff;--ok:#48c26c;--no:#f0616d;--line:#1e2836}
5
- *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.55 -apple-system,Segoe UI,Roboto,monospace;padding:24px;max-width:820px;margin:0 auto}
6
- h1{font-size:20px;margin:0 0 4px}.sub{color:var(--dim);font-size:13px;margin:0 0 18px}
7
- #status,#speed{font-family:ui-monospace,monospace;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--panel);margin-bottom:12px}
8
- #speed{font-size:16px}.big{font-size:17px;font-weight:600;margin:14px 0 6px}
9
- table{border-collapse:collapse;width:100%;font-family:ui-monospace,monospace;font-size:12.5px}
10
- th,td{text-align:left;padding:6px 10px;border-bottom:1px solid var(--line)}
11
- th{color:var(--dim);text-transform:uppercase;font-size:10.5px;letter-spacing:.08em}
12
- td.n{text-align:right;font-variant-numeric:tabular-nums}.ok{color:var(--ok)}.no{color:var(--no)}.hx{color:var(--dim)}
13
- </style></head><body>
14
- <h1>BLAKE3 — <span style="color:var(--ac)">parallel</span>, on your GPU</h1>
15
- <p class="sub">Phase 1: one GPU thread per 1024-byte chunk (parallel). Phase 2: stack tree-merge → root. Correctness vs the CPU oracle, plus throughput on a big block (the size of the 145 MB embed).</p>
16
- <div id="status">initializing…</div>
17
- <div id="speed"></div>
18
- <div id="result"></div>
19
- <table id="tbl"><thead><tr><th>bytes</th><th>match</th></tr></thead><tbody></tbody></table>
20
-
21
- <script type="module">
22
- // oracle (holo-blake3.mjs, inlined)
23
- const IV=[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19];
24
- const MSG=[2,6,3,10,7,0,4,13,1,11,12,5,9,14,15,8];const CS=1,CE=2,PA=4,RT=8,BL=64,CH=1024;
25
- const rr=(x,n)=>((x>>>n)|(x<<(32-n)))>>>0;
26
- function g(v,a,b,c,d,mx,my){v[a]=(v[a]+v[b]+mx)>>>0;v[d]=rr(v[d]^v[a],16);v[c]=(v[c]+v[d])>>>0;v[b]=rr(v[b]^v[c],12);v[a]=(v[a]+v[b]+my)>>>0;v[d]=rr(v[d]^v[a],8);v[c]=(v[c]+v[d])>>>0;v[b]=rr(v[b]^v[c],7);}
27
- function rnd(v,m){g(v,0,4,8,12,m[0],m[1]);g(v,1,5,9,13,m[2],m[3]);g(v,2,6,10,14,m[4],m[5]);g(v,3,7,11,15,m[6],m[7]);g(v,0,5,10,15,m[8],m[9]);g(v,1,6,11,12,m[10],m[11]);g(v,2,7,8,13,m[12],m[13]);g(v,3,4,9,14,m[14],m[15]);}
28
- function cmp(cv,m0,ct,bl,fl){const cl=ct>>>0,ch=Math.floor(ct/4294967296)>>>0;const v=[cv[0],cv[1],cv[2],cv[3],cv[4],cv[5],cv[6],cv[7],IV[0],IV[1],IV[2],IV[3],cl,ch,bl>>>0,fl>>>0];let m=m0.slice();for(let r=0;r<7;r++){rnd(v,m);if(r<6){const p=new Array(16);for(let i=0;i<16;i++)p[i]=m[MSG[i]];m=p;}}const o=new Array(16);for(let i=0;i<8;i++){o[i]=(v[i]^v[i+8])>>>0;o[i+8]=(v[i+8]^cv[i])>>>0;}return o;}
29
- function wd(b,o,l){const m=new Array(16).fill(0);for(let i=0;i<l;i++)m[i>>2]|=b[o+i]<<((i&3)*8);for(let i=0;i<16;i++)m[i]>>>=0;return m;}
30
- function ncv(o){return cmp(o.cv,o.m,o.counter,o.blockLen,o.flags).slice(0,8);}
31
- function nrb(o){const out=cmp(o.cv,o.m,0,o.blockLen,o.flags|RT);const b=new Uint8Array(32);for(let i=0;i<8;i++){const w=out[i];b[i*4]=w&255;b[i*4+1]=(w>>>8)&255;b[i*4+2]=(w>>>16)&255;b[i*4+3]=(w>>>24)&255;}return b;}
32
- function cn(b,s,l,ct){let cv=IV.slice();const nB=Math.max(1,Math.ceil(l/BL));let fl=CS;for(let i=0;i<nB-1;i++){cv=cmp(cv,wd(b,s+i*BL,BL),ct,BL,fl).slice(0,8);fl=0;}const lo=s+(nB-1)*BL,ll=l-(nB-1)*BL;return{cv,m:wd(b,lo,ll),counter:ct,blockLen:ll,flags:fl|CE};}
33
- function pn(l,r){return{cv:IV.slice(),m:l.concat(r),counter:0,blockLen:BL,flags:PA};}
34
- function st(b,s,l,ct){if(l<=CH)return cn(b,s,l,ct);let lf=CH;while(lf*2<l)lf*=2;const lc=ncv(st(b,s,lf,ct)),rc=ncv(st(b,s+lf,l-lf,ct+lf/CH));return pn(lc,rc);}
35
- function b3hex(b){const d=nrb(st(b,0,b.length,0));let s='';for(let i=0;i<32;i++)s+=d[i].toString(16).padStart(2,'0');return s;}
36
-
37
- // ── parallel WGSL: reuses the GPU-proven compress/chunkCV/chunkRoot/parentCV; adds two kernels ──
38
- const WGSL=`
39
- @group(0) @binding(0) var<storage, read> inp : array<u32>;
40
- @group(0) @binding(1) var<storage, read_write> cvs : array<u32>; // phase1 out / phase2 in: 8 u32 per chunk
41
- @group(0) @binding(2) var<storage, read_write> outp : array<u32>;
42
- @group(0) @binding(3) var<uniform> P : vec4<u32>; // x=len y=N
43
- const IV = array<u32,8>(0x6a09e667u,0xbb67ae85u,0x3c6ef372u,0xa54ff53au,0x510e527fu,0x9b05688cu,0x1f83d9abu,0x5be0cd19u);
44
- fn rotr(x:u32,n:u32)->u32 { return (x>>n)|(x<<(32u-n)); }
45
- fn compress(cv:array<u32,8>, m0:array<u32,16>, cl:u32, ch:u32, bl:u32, fl:u32)->array<u32,16>{
46
- var v:array<u32,16>;
47
- v[0]=cv[0];v[1]=cv[1];v[2]=cv[2];v[3]=cv[3];v[4]=cv[4];v[5]=cv[5];v[6]=cv[6];v[7]=cv[7];
48
- v[8]=IV[0];v[9]=IV[1];v[10]=IV[2];v[11]=IV[3];v[12]=cl;v[13]=ch;v[14]=bl;v[15]=fl;
49
- var m:array<u32,16>=m0;
50
- for(var r:u32=0u;r<7u;r=r+1u){
51
- v[0]=v[0]+v[4]+m[0];v[12]=rotr(v[12]^v[0],16u);v[8]=v[8]+v[12];v[4]=rotr(v[4]^v[8],12u);v[0]=v[0]+v[4]+m[1];v[12]=rotr(v[12]^v[0],8u);v[8]=v[8]+v[12];v[4]=rotr(v[4]^v[8],7u);
52
- v[1]=v[1]+v[5]+m[2];v[13]=rotr(v[13]^v[1],16u);v[9]=v[9]+v[13];v[5]=rotr(v[5]^v[9],12u);v[1]=v[1]+v[5]+m[3];v[13]=rotr(v[13]^v[1],8u);v[9]=v[9]+v[13];v[5]=rotr(v[5]^v[9],7u);
53
- v[2]=v[2]+v[6]+m[4];v[14]=rotr(v[14]^v[2],16u);v[10]=v[10]+v[14];v[6]=rotr(v[6]^v[10],12u);v[2]=v[2]+v[6]+m[5];v[14]=rotr(v[14]^v[2],8u);v[10]=v[10]+v[14];v[6]=rotr(v[6]^v[10],7u);
54
- v[3]=v[3]+v[7]+m[6];v[15]=rotr(v[15]^v[3],16u);v[11]=v[11]+v[15];v[7]=rotr(v[7]^v[11],12u);v[3]=v[3]+v[7]+m[7];v[15]=rotr(v[15]^v[3],8u);v[11]=v[11]+v[15];v[7]=rotr(v[7]^v[11],7u);
55
- v[0]=v[0]+v[5]+m[8];v[15]=rotr(v[15]^v[0],16u);v[10]=v[10]+v[15];v[5]=rotr(v[5]^v[10],12u);v[0]=v[0]+v[5]+m[9];v[15]=rotr(v[15]^v[0],8u);v[10]=v[10]+v[15];v[5]=rotr(v[5]^v[10],7u);
56
- v[1]=v[1]+v[6]+m[10];v[12]=rotr(v[12]^v[1],16u);v[11]=v[11]+v[12];v[6]=rotr(v[6]^v[11],12u);v[1]=v[1]+v[6]+m[11];v[12]=rotr(v[12]^v[1],8u);v[11]=v[11]+v[12];v[6]=rotr(v[6]^v[11],7u);
57
- v[2]=v[2]+v[7]+m[12];v[13]=rotr(v[13]^v[2],16u);v[8]=v[8]+v[13];v[7]=rotr(v[7]^v[8],12u);v[2]=v[2]+v[7]+m[13];v[13]=rotr(v[13]^v[2],8u);v[8]=v[8]+v[13];v[7]=rotr(v[7]^v[8],7u);
58
- v[3]=v[3]+v[4]+m[14];v[14]=rotr(v[14]^v[3],16u);v[9]=v[9]+v[14];v[4]=rotr(v[4]^v[9],12u);v[3]=v[3]+v[4]+m[15];v[14]=rotr(v[14]^v[3],8u);v[9]=v[9]+v[14];v[4]=rotr(v[4]^v[9],7u);
59
- if(r<6u){var perm=array<u32,16>(2u,6u,3u,10u,7u,0u,4u,13u,1u,11u,12u,5u,9u,14u,15u,8u);var p:array<u32,16>;for(var i:u32=0u;i<16u;i=i+1u){p[i]=m[perm[i]];}m=p;}
60
- }
61
- var o:array<u32,16>;for(var i:u32=0u;i<8u;i=i+1u){o[i]=v[i]^v[i+8u];o[i+8u]=v[i+8u]^cv[i];}return o;
62
- }
63
- fn loadBlock(bo:u32)->array<u32,16>{let base=bo>>2u;var m:array<u32,16>;for(var i:u32=0u;i<16u;i=i+1u){m[i]=inp[base+i];}return m;}
64
- fn chunkCV(s:u32,l:u32,ct:u32)->array<u32,8>{var cv:array<u32,8>=IV;let nB=max(1u,(l+63u)/64u);var fl:u32=1u;for(var i:u32=0u;i<nB-1u;i=i+1u){let o=compress(cv,loadBlock(s+i*64u),ct,0u,64u,fl);for(var j:u32=0u;j<8u;j=j+1u){cv[j]=o[j];}fl=0u;}let lo=s+(nB-1u)*64u;let ll=l-(nB-1u)*64u;let o2=compress(cv,loadBlock(lo),ct,0u,ll,fl|2u);var out:array<u32,8>;for(var j:u32=0u;j<8u;j=j+1u){out[j]=o2[j];}return out;}
65
- fn chunkRoot(s:u32,l:u32)->array<u32,8>{var cv:array<u32,8>=IV;let nB=max(1u,(l+63u)/64u);var fl:u32=1u;for(var i:u32=0u;i<nB-1u;i=i+1u){let o=compress(cv,loadBlock(s+i*64u),0u,0u,64u,fl);for(var j:u32=0u;j<8u;j=j+1u){cv[j]=o[j];}fl=0u;}let lo=s+(nB-1u)*64u;let ll=l-(nB-1u)*64u;let o=compress(cv,loadBlock(lo),0u,0u,ll,fl|2u|8u);var out:array<u32,8>;for(var j:u32=0u;j<8u;j=j+1u){out[j]=o[j];}return out;}
66
- fn parentCV(l:array<u32,8>,r:array<u32,8>,root:bool)->array<u32,8>{var m:array<u32,16>;for(var i:u32=0u;i<8u;i=i+1u){m[i]=l[i];m[i+8u]=r[i];}var fl:u32=4u;if(root){fl=12u;}let o=compress(IV,m,0u,0u,64u,fl);var out:array<u32,8>;for(var i:u32=0u;i<8u;i=i+1u){out[i]=o[i];}return out;}
67
- fn getCV(i:u32)->array<u32,8>{var c:array<u32,8>;for(var j:u32=0u;j<8u;j=j+1u){c[j]=cvs[i*8u+j];}return c;}
68
-
69
- // PHASE 1 — one invocation per chunk (parallel)
70
- @compute @workgroup_size(64)
71
- fn phase1(@builtin(global_invocation_id) gid:vec3<u32>){
72
- let i=gid.x; let N=P.y; let len=P.x;
73
- if(i>=N){return;}
74
- let off=i*1024u; let ln=min(1024u,len-off);
75
- var cv:array<u32,8>;
76
- if(N==1u){cv=chunkRoot(off,ln);}else{cv=chunkCV(off,ln,i);}
77
- for(var j:u32=0u;j<8u;j=j+1u){cvs[i*8u+j]=cv[j];}
78
- }
79
- // PHASE 2 — single invocation: stack tree-merge over the CVs → root
80
- @compute @workgroup_size(1)
81
- fn phase2(){
82
- let N=P.y;
83
- var root:array<u32,8>;
84
- if(N==1u){root=getCV(0u);}
85
- else{
86
- var stack:array<array<u32,8>,54>; var depth:u32=0u;
87
- for(var c:u32=0u;c<N-1u;c=c+1u){
88
- var cv=getCV(c); var t=c+1u;
89
- loop{ if((t&1u)!=0u){break;} depth=depth-1u; cv=parentCV(stack[depth],cv,false); t=t>>1u; }
90
- stack[depth]=cv; depth=depth+1u;
91
- }
92
- var node=getCV(N-1u);
93
- for(var i:u32=0u;i<depth;i=i+1u){ let li=depth-1u-i; root=parentCV(stack[li],node,i==depth-1u); node=root; }
94
- }
95
- for(var i:u32=0u;i<8u;i=i+1u){outp[i]=root[i];}
96
- }
97
- `;
98
- const $=s=>document.querySelector(s),st_=$("#status"),sp=$("#speed"),tb=$("#tbl tbody"),res=$("#result");
99
- const hexLE=w=>{let s='';for(let i=0;i<8;i++){const x=w[i]>>>0;s+=(x&255).toString(16).padStart(2,'0')+((x>>>8)&255).toString(16).padStart(2,'0')+((x>>>16)&255).toString(16).padStart(2,'0')+((x>>>24)&255).toString(16).padStart(2,'0');}return s;};
100
- (async()=>{
101
- if(!navigator.gpu){st_.textContent="✗ No WebGPU.";st_.classList.add("no");return;}
102
- const ad=await navigator.gpu.requestAdapter(),dev=await ad.requestDevice();
103
- const mod=dev.createShaderModule({code:WGSL});const ci=await mod.getCompilationInfo();const er=ci.messages.filter(m=>m.type==="error");
104
- if(er.length){st_.textContent="✗ WGSL: "+er[0].message+" (line "+er[0].lineNum+")";st_.classList.add("no");return;}
105
- // explicit shared layout so ONE bind group works for both phases (auto-layout would infer different layouts)
106
- const bgl=dev.createBindGroupLayout({entries:[
107
- {binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},
108
- {binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},
109
- {binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},
110
- {binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]});
111
- const pll=dev.createPipelineLayout({bindGroupLayouts:[bgl]});
112
- const p1=dev.createComputePipeline({layout:pll,compute:{module:mod,entryPoint:"phase1"}});
113
- const p2=dev.createComputePipeline({layout:pll,compute:{module:mod,entryPoint:"phase2"}});
114
- async function gpu(bytes){
115
- const len=bytes.length,N=len===0?1:Math.ceil(len/1024);
116
- const padU=Math.max(16,(Math.ceil(len/64)||1)*16);const u=new Uint32Array(padU);new Uint8Array(u.buffer).set(bytes);
117
- const inB=dev.createBuffer({size:u.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});dev.queue.writeBuffer(inB,0,u);
118
- const cvB=dev.createBuffer({size:Math.max(32,N*32),usage:GPUBufferUsage.STORAGE});
119
- const oB=dev.createBuffer({size:32,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});
120
- const pB=dev.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});dev.queue.writeBuffer(pB,0,new Uint32Array([len,N,0,0]));
121
- const sg=dev.createBuffer({size:32,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});
122
- const bg=dev.createBindGroup({layout:bgl,entries:[{binding:0,resource:{buffer:inB}},{binding:1,resource:{buffer:cvB}},{binding:2,resource:{buffer:oB}},{binding:3,resource:{buffer:pB}}]});
123
- const t0=performance.now();
124
- const e=dev.createCommandEncoder();
125
- let pass=e.beginComputePass();pass.setPipeline(p1);pass.setBindGroup(0,bg);pass.dispatchWorkgroups(Math.ceil(N/64));pass.end();
126
- pass=e.beginComputePass();pass.setPipeline(p2);pass.setBindGroup(0,bg);pass.dispatchWorkgroups(1);pass.end();
127
- e.copyBufferToBuffer(oB,0,sg,0,32);dev.queue.submit([e.finish()]);
128
- await sg.mapAsync(GPUMapMode.READ);const w=new Uint32Array(sg.getMappedRange().slice(0));sg.unmap();
129
- const ms=performance.now()-t0;
130
- inB.destroy();cvB.destroy();oB.destroy();pB.destroy();sg.destroy();
131
- return {hex:hexLE(w),ms};
132
- }
133
- // correctness
134
- st_.textContent="checking correctness…";let pass=0;const sizes=[0,1,64,1023,1024,1025,2048,4096,100000,1048576];
135
- for(const n of sizes){const b=new Uint8Array(n);for(let i=0;i<n;i++)b[i]=i&255;const {hex}=await gpu(b);const ok=hex===b3hex(b);if(ok)pass++;const tr=document.createElement("tr");tr.innerHTML=`<td class="n">${n.toLocaleString()}</td><td class="${ok?'ok':'no'}">${ok?'✓ match':'✗ MISMATCH'}</td>`;tb.appendChild(tr);}
136
- st_.textContent=`correctness: ${pass}/${sizes.length}`;st_.classList.add(pass===sizes.length?"ok":"no");
137
- // throughput — 138 MB (the embed block size)
138
- sp.textContent="timing 138 MB (embed-sized block)…";
139
- const BIG=138*1024*1024;const big=new Uint8Array(BIG);for(let i=0;i<BIG;i++)big[i]=i&255;
140
- let best=1e9;for(let k=0;k<3;k++){const {ms}=await gpu(big);best=Math.min(best,ms);}
141
- const gbps=(BIG/1073741824)/(best/1000);
142
- sp.innerHTML=`<b>138 MB verified on GPU in ${best.toFixed(0)} ms → ${gbps.toFixed(2)} GB/s</b>`;sp.classList.add(gbps>1?"ok":"");
143
- res.innerHTML=(pass===sizes.length)?`<div class="big ok">✓ Parallel BLAKE3 on your GPU — byte-exact, and ${gbps.toFixed(1)} GB/s on an embed-sized block.</div><div class="hx">Adapter: ${ad.info?ad.info.vendor+" "+ad.info.architecture:"?"}</div>`:`<div class="big no">✗ correctness failed — see table</div>`;
144
- })();
145
- </script></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
blake3-gpu-test.html DELETED
@@ -1,195 +0,0 @@
1
- <!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
2
- <title>BLAKE3 on your GPU — parity test</title>
3
- <style>
4
- :root{--bg:#0a0d13;--panel:#111825;--ink:#e8ebf1;--dim:#8b95a7;--ac:#7c5cff;--ok:#48c26c;--no:#f0616d;--line:#1e2836}
5
- *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.55 -apple-system,Segoe UI,Roboto,monospace;padding:24px;max-width:820px;margin:0 auto}
6
- h1{font-size:20px;margin:0 0 4px}.sub{color:var(--dim);font-size:13px;margin:0 0 18px}
7
- #status{font-family:ui-monospace,monospace;padding:10px 14px;border:1px solid var(--line);border-radius:10px;background:var(--panel);margin-bottom:16px}
8
- table{border-collapse:collapse;width:100%;font-family:ui-monospace,monospace;font-size:12.5px}
9
- th,td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--line)}
10
- th{color:var(--dim);text-transform:uppercase;font-size:10.5px;letter-spacing:.08em}
11
- td.n{text-align:right;font-variant-numeric:tabular-nums}
12
- .ok{color:var(--ok)}.no{color:var(--no)}
13
- .big{font-size:17px;font-weight:600;margin:16px 0 4px}
14
- .hx{color:var(--dim)}
15
- </style></head><body>
16
- <h1>BLAKE3 — <span style="color:var(--ac)">on your GPU</span> vs the CPU oracle</h1>
17
- <p class="sub">WGSL kernel hashes each input entirely on the GPU; compared byte-for-byte to <code>holo-blake3.mjs</code> and the official empty-input vector. Boundary sizes exercise block (64), chunk (1024), and tree merges.</p>
18
- <div id="status">initializing WebGPU…</div>
19
- <div id="result"></div>
20
- <table id="tbl"><thead><tr><th>input</th><th class="n">bytes</th><th>GPU digest (first 32 hex)</th><th>match</th></tr></thead><tbody></tbody></table>
21
-
22
- <script type="module">
23
- // ─────────────────── CPU ORACLE (holo-blake3.mjs, inlined verbatim) ───────────────────
24
- const IV=[0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19];
25
- const MSG=[2,6,3,10,7,0,4,13,1,11,12,5,9,14,15,8];
26
- const CHUNK_START=1,CHUNK_END=2,PARENT=4,ROOT=8,BLOCK=64,CHUNK=1024;
27
- const rotr=(x,n)=>((x>>>n)|(x<<(32-n)))>>>0;
28
- function g(v,a,b,c,d,mx,my){v[a]=(v[a]+v[b]+mx)>>>0;v[d]=rotr(v[d]^v[a],16);v[c]=(v[c]+v[d])>>>0;v[b]=rotr(v[b]^v[c],12);v[a]=(v[a]+v[b]+my)>>>0;v[d]=rotr(v[d]^v[a],8);v[c]=(v[c]+v[d])>>>0;v[b]=rotr(v[b]^v[c],7);}
29
- function roundFn(v,m){g(v,0,4,8,12,m[0],m[1]);g(v,1,5,9,13,m[2],m[3]);g(v,2,6,10,14,m[4],m[5]);g(v,3,7,11,15,m[6],m[7]);g(v,0,5,10,15,m[8],m[9]);g(v,1,6,11,12,m[10],m[11]);g(v,2,7,8,13,m[12],m[13]);g(v,3,4,9,14,m[14],m[15]);}
30
- function compress(cv,m0,counter,blockLen,flags){const cl=counter>>>0,ch=Math.floor(counter/4294967296)>>>0;const v=[cv[0],cv[1],cv[2],cv[3],cv[4],cv[5],cv[6],cv[7],IV[0],IV[1],IV[2],IV[3],cl,ch,blockLen>>>0,flags>>>0];let m=m0.slice();for(let r=0;r<7;r++){roundFn(v,m);if(r<6){const p=new Array(16);for(let i=0;i<16;i++)p[i]=m[MSG[i]];m=p;}}const out=new Array(16);for(let i=0;i<8;i++){out[i]=(v[i]^v[i+8])>>>0;out[i+8]=(v[i+8]^cv[i])>>>0;}return out;}
31
- function words(bytes,off,len){const m=new Array(16).fill(0);for(let i=0;i<len;i++)m[i>>2]|=bytes[off+i]<<((i&3)*8);for(let i=0;i<16;i++)m[i]>>>=0;return m;}
32
- function nodeCV(o){return compress(o.cv,o.m,o.counter,o.blockLen,o.flags).slice(0,8);}
33
- function nodeRoot(o){const out=compress(o.cv,o.m,0,o.blockLen,o.flags|ROOT);const b=new Uint8Array(32);for(let i=0;i<8;i++){const w=out[i];b[i*4]=w&255;b[i*4+1]=(w>>>8)&255;b[i*4+2]=(w>>>16)&255;b[i*4+3]=(w>>>24)&255;}return b;}
34
- function chunkNode(bytes,start,len,counter){let cv=IV.slice();const nB=Math.max(1,Math.ceil(len/BLOCK));let flags=CHUNK_START;for(let i=0;i<nB-1;i++){cv=compress(cv,words(bytes,start+i*BLOCK,BLOCK),counter,BLOCK,flags).slice(0,8);flags=0;}const lo=start+(nB-1)*BLOCK,ll=len-(nB-1)*BLOCK;return{cv,m:words(bytes,lo,ll),counter,blockLen:ll,flags:flags|CHUNK_END};}
35
- function parentNode(l,r){return{cv:IV.slice(),m:l.concat(r),counter:0,blockLen:BLOCK,flags:PARENT};}
36
- function subtree(bytes,start,len,counter){if(len<=CHUNK)return chunkNode(bytes,start,len,counter);let left=CHUNK;while(left*2<len)left*=2;const lcv=nodeCV(subtree(bytes,start,left,counter));const rcv=nodeCV(subtree(bytes,start+left,len-left,counter+left/CHUNK));return parentNode(lcv,rcv);}
37
- function blake3hex(bytes){const d=nodeRoot(subtree(bytes,0,bytes.length,0));let s="";for(let i=0;i<32;i++)s+=d[i].toString(16).padStart(2,"0");return s;}
38
-
39
- // ─────────────────── WGSL BLAKE3 — runs ENTIRELY on the GPU ───────────────────
40
- // Single-invocation port of the incremental/stack tree (no recursion). Input is zero-padded to a
41
- // multiple of 64 bytes as an array<u32> (LE) so each 64-byte block = 16 consecutive u32. blockLen in
42
- // the compression state carries the true length. Stack of subtree CVs collapses on even chunk counts,
43
- // exactly like createBlake3(); the final chunk merges down the stack with ROOT — byte-identical to blake3().
44
- const WGSL = `
45
- @group(0) @binding(0) var<storage, read> inp : array<u32>;
46
- @group(0) @binding(1) var<storage, read_write> outp : array<u32>;
47
- @group(0) @binding(2) var<uniform> P : vec4<u32>; // P.x = byte length
48
-
49
- const IV = array<u32,8>(0x6a09e667u,0xbb67ae85u,0x3c6ef372u,0xa54ff53au,0x510e527fu,0x9b05688cu,0x1f83d9abu,0x5be0cd19u);
50
-
51
- fn rotr(x:u32,n:u32)->u32 { return (x >> n) | (x << (32u - n)); }
52
-
53
- // compress → 16 words. cv[8], m[16], counter lo/hi, blockLen, flags.
54
- fn compress(cv:array<u32,8>, m0:array<u32,16>, cl:u32, ch:u32, blockLen:u32, flags:u32) -> array<u32,16> {
55
- var v:array<u32,16>;
56
- v[0]=cv[0]; v[1]=cv[1]; v[2]=cv[2]; v[3]=cv[3]; v[4]=cv[4]; v[5]=cv[5]; v[6]=cv[6]; v[7]=cv[7];
57
- v[8]=IV[0]; v[9]=IV[1]; v[10]=IV[2]; v[11]=IV[3]; v[12]=cl; v[13]=ch; v[14]=blockLen; v[15]=flags;
58
- var m:array<u32,16> = m0;
59
- for (var r:u32=0u; r<7u; r=r+1u) {
60
- // roundFn — 8 g() applications, indices are literals
61
- // g(a,b,c,d,mx,my): a=a+b+mx; d=rotr(d^a,16); c=c+d; b=rotr(b^c,12); a=a+b+my; d=rotr(d^a,8); c=c+d; b=rotr(b^c,7)
62
- // col 0
63
- v[0]=v[0]+v[4]+m[0]; v[12]=rotr(v[12]^v[0],16u); v[8]=v[8]+v[12]; v[4]=rotr(v[4]^v[8],12u); v[0]=v[0]+v[4]+m[1]; v[12]=rotr(v[12]^v[0],8u); v[8]=v[8]+v[12]; v[4]=rotr(v[4]^v[8],7u);
64
- v[1]=v[1]+v[5]+m[2]; v[13]=rotr(v[13]^v[1],16u); v[9]=v[9]+v[13]; v[5]=rotr(v[5]^v[9],12u); v[1]=v[1]+v[5]+m[3]; v[13]=rotr(v[13]^v[1],8u); v[9]=v[9]+v[13]; v[5]=rotr(v[5]^v[9],7u);
65
- v[2]=v[2]+v[6]+m[4]; v[14]=rotr(v[14]^v[2],16u); v[10]=v[10]+v[14]; v[6]=rotr(v[6]^v[10],12u); v[2]=v[2]+v[6]+m[5]; v[14]=rotr(v[14]^v[2],8u); v[10]=v[10]+v[14]; v[6]=rotr(v[6]^v[10],7u);
66
- v[3]=v[3]+v[7]+m[6]; v[15]=rotr(v[15]^v[3],16u); v[11]=v[11]+v[15]; v[7]=rotr(v[7]^v[11],12u); v[3]=v[3]+v[7]+m[7]; v[15]=rotr(v[15]^v[3],8u); v[11]=v[11]+v[15]; v[7]=rotr(v[7]^v[11],7u);
67
- // diag
68
- v[0]=v[0]+v[5]+m[8]; v[15]=rotr(v[15]^v[0],16u); v[10]=v[10]+v[15]; v[5]=rotr(v[5]^v[10],12u); v[0]=v[0]+v[5]+m[9]; v[15]=rotr(v[15]^v[0],8u); v[10]=v[10]+v[15]; v[5]=rotr(v[5]^v[10],7u);
69
- v[1]=v[1]+v[6]+m[10]; v[12]=rotr(v[12]^v[1],16u); v[11]=v[11]+v[12]; v[6]=rotr(v[6]^v[11],12u); v[1]=v[1]+v[6]+m[11]; v[12]=rotr(v[12]^v[1],8u); v[11]=v[11]+v[12]; v[6]=rotr(v[6]^v[11],7u);
70
- v[2]=v[2]+v[7]+m[12]; v[13]=rotr(v[13]^v[2],16u); v[8]=v[8]+v[13]; v[7]=rotr(v[7]^v[8],12u); v[2]=v[2]+v[7]+m[13]; v[13]=rotr(v[13]^v[2],8u); v[8]=v[8]+v[13]; v[7]=rotr(v[7]^v[8],7u);
71
- v[3]=v[3]+v[4]+m[14]; v[14]=rotr(v[14]^v[3],16u); v[9]=v[9]+v[14]; v[4]=rotr(v[4]^v[9],12u); v[3]=v[3]+v[4]+m[15]; v[14]=rotr(v[14]^v[3],8u); v[9]=v[9]+v[14]; v[4]=rotr(v[4]^v[9],7u);
72
- if (r < 6u) { var perm=array<u32,16>(2u,6u,3u,10u,7u,0u,4u,13u,1u,11u,12u,5u,9u,14u,15u,8u); var p:array<u32,16>; for (var i:u32=0u;i<16u;i=i+1u){ p[i]=m[perm[i]]; } m=p; }
73
- }
74
- var o:array<u32,16>;
75
- for (var i:u32=0u;i<8u;i=i+1u){ o[i]=v[i]^v[i+8u]; o[i+8u]=v[i+8u]^cv[i]; }
76
- return o;
77
- }
78
- fn loadBlock(byteOff:u32) -> array<u32,16> {
79
- let base = byteOff >> 2u; var m:array<u32,16>;
80
- for (var i:u32=0u;i<16u;i=i+1u){ m[i] = inp[base+i]; } // input is zero-padded → direct read
81
- return m;
82
- }
83
- // chunk [start,start+len) at index ctr → chaining value (8) ; final=false path
84
- fn chunkCV(start:u32, len:u32, ctr:u32) -> array<u32,8> {
85
- var cv:array<u32,8> = IV;
86
- let nB = max(1u, (len + 63u) / 64u);
87
- var flags:u32 = 1u; // CHUNK_START
88
- for (var i:u32=0u; i<nB-1u; i=i+1u) {
89
- let o = compress(cv, loadBlock(start + i*64u), ctr, 0u, 64u, flags);
90
- for (var j:u32=0u;j<8u;j=j+1u){ cv[j]=o[j]; }
91
- flags = 0u;
92
- }
93
- let lastOff = start + (nB-1u)*64u;
94
- let lastLen = len - (nB-1u)*64u;
95
- let o2 = compress(cv, loadBlock(lastOff), ctr, 0u, lastLen, flags | 2u); // CHUNK_END
96
- var out:array<u32,8>; for (var j:u32=0u;j<8u;j=j+1u){ out[j]=o2[j]; } return out;
97
- }
98
- // final chunk → 32-byte root (returns 8 words). merged with a running CV from the stack side is handled in main.
99
- // parent(left8,right8) → cv8 (or root8 if isRoot)
100
- fn parentCV(l:array<u32,8>, r:array<u32,8>, isRoot:bool) -> array<u32,8> {
101
- var m:array<u32,16>; for (var i:u32=0u;i<8u;i=i+1u){ m[i]=l[i]; m[i+8u]=r[i]; }
102
- var flags:u32 = 4u; if (isRoot) { flags = 4u | 8u; }
103
- let o = compress(IV, m, 0u, 0u, 64u, flags);
104
- var out:array<u32,8>; for (var i:u32=0u;i<8u;i=i+1u){ out[i]=o[i]; } return out;
105
- }
106
- // final chunk root (when there are no parents): compress final block with ROOT, counter 0
107
- fn chunkRoot(start:u32, len:u32, ctr:u32) -> array<u32,8> {
108
- var cv:array<u32,8> = IV;
109
- let nB = max(1u, (len + 63u) / 64u);
110
- var flags:u32 = 1u;
111
- for (var i:u32=0u; i<nB-1u; i=i+1u){ let o=compress(cv,loadBlock(start+i*64u),ctr,0u,64u,flags); for(var j:u32=0u;j<8u;j=j+1u){cv[j]=o[j];} flags=0u; }
112
- let lastOff=start+(nB-1u)*64u; let lastLen=len-(nB-1u)*64u;
113
- let o=compress(cv, loadBlock(lastOff), 0u,0u, lastLen, flags | 2u | 8u); // CHUNK_END|ROOT, counter 0
114
- var out:array<u32,8>; for(var j:u32=0u;j<8u;j=j+1u){out[j]=o[j];} return out;
115
- }
116
-
117
- @compute @workgroup_size(1)
118
- fn main() {
119
- let len = P.x;
120
- var stack: array<array<u32,8>, 54>;
121
- var depth:u32 = 0u;
122
- let totalChunks = select((len + 1023u) / 1024u, 1u, len == 0u);
123
- let flushed = totalChunks - 1u; // chunks 0..flushed-1 go to the stack; last is final
124
- // build the stack from the flushed chunks
125
- for (var c:u32=0u; c<flushed; c=c+1u) {
126
- var cv = chunkCV(c*1024u, 1024u, c);
127
- var t = c + 1u; // add(cv, totalChunks=c+1)
128
- loop { if ((t & 1u) != 0u) { break; } depth=depth-1u; cv = parentCV(stack[depth], cv, false); t = t >> 1u; }
129
- stack[depth] = cv; depth = depth + 1u;
130
- }
131
- let finalOff = flushed * 1024u;
132
- let finalLen = len - finalOff; // 0..1024
133
- var root: array<u32,8>;
134
- if (depth == 0u) {
135
- root = chunkRoot(finalOff, finalLen, flushed); // single chunk → its own root
136
- } else {
137
- // final chunk's CV, then merge down the stack; the LAST merge is ROOT
138
- var node = chunkCV(finalOff, finalLen, flushed);
139
- for (var i:u32=0u; i<depth; i=i+1u) {
140
- let li = depth - 1u - i;
141
- root = parentCV(stack[li], node, i == depth-1u); // top merge = ROOT
142
- node = root;
143
- }
144
- }
145
- for (var i:u32=0u;i<8u;i=i+1u){ outp[i] = root[i]; }
146
- }
147
- `;
148
-
149
- // ─────────────────── WebGPU harness ───────────────────
150
- const $=s=>document.querySelector(s), st=$("#status"), tb=$("#tbl tbody"), res=$("#result");
151
- function hexLE(words){let s="";for(let i=0;i<8;i++){const w=words[i]>>>0;s+=(w&255).toString(16).padStart(2,"0")+((w>>>8)&255).toString(16).padStart(2,"0")+((w>>>16)&255).toString(16).padStart(2,"0")+((w>>>24)&255).toString(16).padStart(2,"0");}return s;}
152
-
153
- (async()=>{
154
- if(!navigator.gpu){st.textContent="✗ No WebGPU in this browser. Open in Chrome/Edge (or enable WebGPU).";st.classList.add("no");return;}
155
- let adapter,device;
156
- try{adapter=await navigator.gpu.requestAdapter();device=await adapter.requestDevice();}
157
- catch(e){st.textContent="✗ WebGPU device error: "+e.message;return;}
158
- let module;
159
- try{ module=device.createShaderModule({code:WGSL}); const info=await module.getCompilationInfo(); const errs=info.messages.filter(m=>m.type==="error"); if(errs.length){st.textContent="✗ WGSL compile error: "+errs[0].message+" (line "+errs[0].lineNum+")";st.classList.add("no");return;} }
160
- catch(e){st.textContent="✗ shader error: "+e.message;return;}
161
- const pipeline=device.createComputePipeline({layout:"auto",compute:{module,entryPoint:"main"}});
162
-
163
- async function gpuHash(bytes){
164
- const len=bytes.length, padded=Math.max(16,(Math.ceil(len/64)||1)*16); // u32 count, ≥1 block
165
- const u=new Uint32Array(padded); const b=new Uint8Array(u.buffer); b.set(bytes);
166
- const inBuf=device.createBuffer({size:u.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}); device.queue.writeBuffer(inBuf,0,u);
167
- const outBuf=device.createBuffer({size:32,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});
168
- const parBuf=device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); device.queue.writeBuffer(parBuf,0,new Uint32Array([len,0,0,0]));
169
- const stg=device.createBuffer({size:32,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});
170
- const bg=device.createBindGroup({layout:pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:inBuf}},{binding:1,resource:{buffer:outBuf}},{binding:2,resource:{buffer:parBuf}}]});
171
- const enc=device.createCommandEncoder(); const p=enc.beginComputePass(); p.setPipeline(pipeline); p.setBindGroup(0,bg); p.dispatchWorkgroups(1); p.end();
172
- enc.copyBufferToBuffer(outBuf,0,stg,0,32); device.queue.submit([enc.finish()]);
173
- await stg.mapAsync(GPUMapMode.READ); const w=new Uint32Array(stg.getMappedRange().slice(0)); stg.unmap();
174
- inBuf.destroy();outBuf.destroy();parBuf.destroy();stg.destroy();
175
- return hexLE(w);
176
- }
177
-
178
- const sizes=[0,1,63,64,65,127,128,129,1023,1024,1025,2047,2048,2049,4096,10000,65536,100000];
179
- st.textContent="running "+sizes.length+" boundary cases on your GPU…";
180
- let pass=0;
181
- // official empty-input vector, an extra ground-truth anchor
182
- const OFFICIAL_EMPTY="af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262";
183
- for(const n of sizes){
184
- const bytes=new Uint8Array(n); for(let i=0;i<n;i++)bytes[i]=i&255;
185
- const cpu=blake3hex(bytes); const gpu=await gpuHash(bytes);
186
- const ok=gpu===cpu && (n!==0 || cpu===OFFICIAL_EMPTY); if(ok)pass++;
187
- const tr=document.createElement("tr");
188
- tr.innerHTML=`<td>${n===0?"empty":"pattern"}${n===0?" (official vector)":""}</td><td class="n">${n.toLocaleString()}</td><td class="hx">${gpu.slice(0,32)}…</td><td class="${ok?'ok':'no'}">${ok?'✓ match':'✗ MISMATCH'}</td>`;
189
- tb.appendChild(tr);
190
- if(!ok){res.innerHTML=`<div class="big no">✗ MISMATCH at ${n} bytes</div><div class="hx">gpu ${gpu}<br>cpu ${cpu}</div>`;}
191
- }
192
- st.textContent=`done · ${pass}/${sizes.length} cases`; st.classList.add(pass===sizes.length?"ok":"no");
193
- if(pass===sizes.length){res.innerHTML=`<div class="big ok">✓ BLAKE3 runs entirely on your GPU — byte-identical to the CPU oracle across every block, chunk, and tree boundary.</div><div class="hx" style="margin-top:6px">Adapter: ${adapter.info?adapter.info.vendor+" "+adapter.info.architecture:"(info withheld)"}</div>`;}
194
- })();
195
- </script></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/agents.js DELETED
@@ -1,74 +0,0 @@
1
- // core/agents.js — AGENTS as κ-objects (LibreChat agent semantics, substrate-native). An agent
2
- // bundles identity + instructions + model + parameters + armed tools + conversation starters;
3
- // selecting one shapes every turn (instructions ride the system block, its tool selection arms
4
- // the MCP loop). Field names follow the LibreChat agent schema so exports interoperate; each
5
- // version re-seals to a new κ (history is free, Law L3).
6
-
7
- import { normPreset } from "./schema.js";
8
-
9
- const LC = { lc: "https://librechat.ai/ns#" };
10
-
11
- export function normAgent(a = {}) {
12
- return {
13
- id: typeof a.id === "string" ? a.id : null,
14
- name: a.name || "New Agent",
15
- description: a.description || "",
16
- instructions: a.instructions || "",
17
- avatar: a.avatar || null, // { filepath, source } | emoji string | null
18
- provider: a.provider || "holo-q", // the local substrate engine
19
- model: a.model || null, // a MODELS[] name
20
- model_parameters: {
21
- temperature: +(a.model_parameters?.temperature ?? 0) || 0,
22
- max_output_tokens: +(a.model_parameters?.max_output_tokens ?? 900) || 900,
23
- },
24
- tools: Array.isArray(a.tools) ? a.tools : [], // armed tool names (the MCP loop selection)
25
- mcpServerNames: Array.isArray(a.mcpServerNames) ? a.mcpServerNames : [],
26
- conversation_starters: Array.isArray(a.conversation_starters) ? a.conversation_starters.filter(Boolean).slice(0, 4) : [],
27
- artifacts: a.artifacts || "default", // 'default' | 'custom' (custom: instructions own the format)
28
- recursion_limit: +(a.recursion_limit ?? 4) || 4, // max tool rounds
29
- category: a.category || "general",
30
- version: +(a.version ?? 1) || 1,
31
- };
32
- }
33
-
34
- export function makeAgents(chatStore) {
35
- const { store, getIndex, newId } = chatStore;
36
- const putIndex = async (idx) => { const b = new TextEncoder().encode(JSON.stringify(idx)); return store.backend.putRaw ? store.backend.putRaw("index:org.hologram.HoloQ", b) : store.backend.put("index:org.hologram.HoloQ", b); };
37
-
38
- async function save(a) {
39
- const norm = normAgent(a);
40
- if (!norm.id) norm.id = newId("agent");
41
- const prevPtr = ((await getIndex()).agents || []).find((x) => x.id === norm.id);
42
- if (prevPtr) norm.version = (prevPtr.version || 1) + 1;
43
- const obj = await store.makeObject({
44
- type: ["schema:SoftwareAgent", "prov:Entity"], context: [LC],
45
- "schema:identifier": norm.id, "schema:name": norm.name, "schema:description": norm.description,
46
- "lc:agent": norm,
47
- ...(prevPtr ? { links: [{ ...store.contentLink("prov:wasRevisionOf", prevPtr.kappa, "schema:SoftwareAgent"), "schema:name": "previousVersion" }] } : {}),
48
- });
49
- const idx = await getIndex();
50
- idx.agents = idx.agents || [];
51
- const ptr = { id: norm.id, kappa: obj.id, name: norm.name, avatar: norm.avatar, category: norm.category, version: norm.version };
52
- const i = idx.agents.findIndex((x) => x.id === norm.id);
53
- if (i >= 0) idx.agents[i] = ptr; else idx.agents.push(ptr);
54
- await putIndex(idx);
55
- return { ...norm, kappa: obj.id };
56
- }
57
-
58
- async function list() { return (await getIndex()).agents || []; }
59
-
60
- async function get(id) {
61
- const ptr = (await list()).find((x) => x.id === id); if (!ptr) return null;
62
- const obj = await store.getObj(ptr.kappa); if (!obj) return null;
63
- if (!(await store.verify(obj))) return null; // Law L5: a tampered agent is refused
64
- return { ...normAgent(obj["lc:agent"]), kappa: ptr.kappa };
65
- }
66
-
67
- async function remove(id) {
68
- const idx = await getIndex();
69
- idx.agents = (idx.agents || []).filter((x) => x.id !== id);
70
- await putIndex(idx);
71
- }
72
-
73
- return { save, list, get, remove, normAgent };
74
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/backend.js DELETED
@@ -1,23 +0,0 @@
1
- // core/backend.js — the durable byte backend for the κ-object store: IndexedDB via the OS
2
- // runtime's _shared/holo-store.js (Law L3: the store is the memory; RAM is a bounded cache).
3
- // Keys are κ hex strings (plus the one well-known boot-index pointer key). Same async shape
4
- // as the witness's Map backend, so the L5 contract exercises identical code in both runtimes.
5
-
6
- import { idbBackend } from "../_shared/holo-store.js";
7
-
8
- export function kappaBackend() {
9
- const idb = idbBackend({ db: "holo-q", store: "kappa" });
10
- return {
11
- get: async (hex) => (await idb.get(hex)) || undefined,
12
- put: (hex, bytes) => idb.set(hex, bytes),
13
- getRaw: async (k) => (await idb.get(k)) || undefined,
14
- putRaw: (k, bytes) => idb.set(k, bytes),
15
- has: (k) => idb.has(k),
16
- };
17
- }
18
-
19
- // Storage usage for the Settings → Data tab (W3C StorageManager).
20
- export async function storageEstimate() {
21
- try { const e = await navigator.storage.estimate(); return { usage: e.usage || 0, quota: e.quota || 0 }; }
22
- catch { return { usage: 0, quota: 0 }; }
23
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/code-tools.js DELETED
@@ -1,130 +0,0 @@
1
- // core/code-tools.js — NATIVE agentic-coding tools for Holo Q's Code mode. Self-contained over the
2
- // browser's OPFS (navigator.storage.getDirectory) — no external VFS, works in any browser, 100%
3
- // serverless. Each tool returns Holo Q's agent-tool shape { def, serverName:"code", call }, so the
4
- // Coder-7B brain drives real file work through the existing agentic loop + conscience gate + receipts.
5
- // The workspace is an OPFS "workspace" dir = the agent's writable home; every result is content-addressable.
6
- //
7
- // C2 semantic skin (extended to all κ-objects): build_app emits a schema:SoftwareApplication node and
8
- // verify_object returns the file's schema.org @type — so every object the agent makes is W3C-legible.
9
-
10
- import { appAsSoftware, fileAsDocument } from "./semantic.js";
11
-
12
- const te = new TextEncoder(), td = new TextDecoder();
13
- const sha256Hex = async (bytes) => [...new Uint8Array(await crypto.subtle.digest("SHA-256", bytes))].map((b) => b.toString(16).padStart(2, "0")).join("");
14
- const norm = (p) => ("/" + String(p || "").replace(/^\/+/, "").replace(/\/+/g, "/")).replace(/\/$/, "") || "/";
15
-
16
- async function root() { const d = await navigator.storage.getDirectory(); return d.getDirectoryHandle("workspace", { create: true }); }
17
- async function dirOf(parts, create = false) {
18
- let h = await root();
19
- for (const p of parts) if (p) h = await h.getDirectoryHandle(p, { create });
20
- return h;
21
- }
22
- function split(path) { const parts = norm(path).split("/").filter(Boolean); const name = parts.pop(); return { parts, name }; }
23
-
24
- async function readFile(path) {
25
- const { parts, name } = split(path);
26
- const dir = await dirOf(parts);
27
- const fh = await dir.getFileHandle(name);
28
- const f = await fh.getFile();
29
- return new Uint8Array(await f.arrayBuffer());
30
- }
31
- async function writeFile(path, content) {
32
- const { parts, name } = split(path);
33
- const dir = await dirOf(parts, true);
34
- const fh = await dir.getFileHandle(name, { create: true });
35
- const w = await fh.createWritable(); await w.write(te.encode(String(content ?? ""))); await w.close();
36
- }
37
- async function walk(dirHandle, prefix, out) {
38
- for await (const [n, h] of dirHandle.entries()) {
39
- const p = prefix + "/" + n;
40
- if (h.kind === "file") out.push(p);
41
- else await walk(h, p, out);
42
- }
43
- }
44
- async function listAll() { const out = []; await walk(await root(), "", out); return out.sort(); }
45
-
46
- function globToRe(glob) {
47
- let re = "^";
48
- for (let i = 0; i < glob.length; i++) { const c = glob[i];
49
- if (c === "*") { if (glob[i + 1] === "*") { re += ".*"; i++; if (glob[i + 1] === "/") i++; } else re += "[^/]*"; }
50
- else if (c === "?") re += "[^/]"; else if ("\\^$.|+()[]{}".includes(c)) re += "\\" + c; else re += c; }
51
- return new RegExp(re + "$");
52
- }
53
-
54
- export function codeTools() {
55
- return [
56
- {
57
- def: { name: "read_file", description: "Read a text file from the workspace. Returns its content.", inputSchema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
58
- serverName: "code", call: async ({ path }) => {
59
- try { const bytes = await readFile(path); return { text: td.decode(bytes), isError: false }; }
60
- catch (e) { return { text: "read error: " + (e.message || e), isError: true }; }
61
- },
62
- },
63
- {
64
- def: { name: "write_file", description: "Create or overwrite a file in the workspace with the given content.", inputSchema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] } },
65
- serverName: "code", call: async ({ path, content }) => {
66
- try { await writeFile(path, content); const k = await sha256Hex(te.encode(String(content ?? ""))); return { text: `wrote ${norm(path)} (${String(content ?? "").length} bytes) · did:holo:sha256:${k.slice(0, 16)}`, isError: false }; }
67
- catch (e) { return { text: "write error: " + (e.message || e), isError: true }; }
68
- },
69
- },
70
- {
71
- def: { name: "edit_file", description: "Replace the first exact occurrence of old_text with new_text in a file.", inputSchema: { type: "object", properties: { path: { type: "string" }, old_text: { type: "string" }, new_text: { type: "string" } }, required: ["path", "old_text", "new_text"] } },
72
- serverName: "code", call: async ({ path, old_text, new_text }) => {
73
- try { const cur = td.decode(await readFile(path)); if (!cur.includes(old_text)) return { text: "edit error: old_text not found", isError: true };
74
- const next = cur.replace(old_text, new_text); await writeFile(path, next); return { text: `edited ${norm(path)} (${cur.length}→${next.length} bytes)`, isError: false }; }
75
- catch (e) { return { text: "edit error: " + (e.message || e), isError: true }; }
76
- },
77
- },
78
- {
79
- def: { name: "list_files", description: "List all files in the workspace, optionally filtered by a glob (e.g. **/*.py).", inputSchema: { type: "object", properties: { glob: { type: "string" } }, required: [] } },
80
- serverName: "code", call: async ({ glob }) => {
81
- try { let files = await listAll(); if (glob) { const re = globToRe(glob); files = files.filter((f) => re.test(f)); }
82
- return { text: files.length ? files.join("\n") : "(workspace empty)", isError: false }; }
83
- catch (e) { return { text: "list error: " + (e.message || e), isError: true }; }
84
- },
85
- },
86
- {
87
- def: { name: "grep", description: "Search file contents for a regular expression. Returns matching path:line: text.", inputSchema: { type: "object", properties: { pattern: { type: "string" }, glob: { type: "string" } }, required: ["pattern"] } },
88
- serverName: "code", call: async ({ pattern, glob }) => {
89
- try { const re = new RegExp(pattern); let files = await listAll(); if (glob) { const g = globToRe(glob); files = files.filter((f) => g.test(f)); }
90
- const hits = [];
91
- for (const f of files) { let text; try { text = td.decode(await readFile(f)); } catch { continue; }
92
- text.split("\n").forEach((ln, i) => { if (re.test(ln) && hits.length < 100) hits.push(`${f}:${i + 1}: ${ln.trim().slice(0, 160)}`); }); }
93
- return { text: hits.length ? hits.join("\n") : "(no matches)", isError: false }; }
94
- catch (e) { return { text: "grep error: " + (e.message || e), isError: true }; }
95
- },
96
- },
97
- // ── κ-NATIVE: build a RENDERABLE app object, sealed (the neural-computer flagship: an agent
98
- // produces a real app, content-addressed, that renders + re-derives — serverless, verifiable) ──
99
- {
100
- def: { name: "build_app", description: "Build a complete self-contained HTML app (one file, inline CSS/JS) and seal it as a content-addressed object. Returns its did:holo κ; the app renders live in the preview pane. Use for 'build me an app/page/tool' requests.", inputSchema: { type: "object", properties: { name: { type: "string" }, html: { type: "string" } }, required: ["name", "html"] } },
101
- serverName: "code", call: async ({ name, html }) => {
102
- try {
103
- const path = (name.endsWith(".html") ? name : name + ".html");
104
- await writeFile(path, html);
105
- const bytes = te.encode(String(html));
106
- const kappa = "did:holo:sha256:" + await sha256Hex(bytes);
107
- // semantic skin: the app object carries a W3C @type (schema:SoftwareApplication + prov:Entity),
108
- // written as a sidecar .jsonld so the object is self-describing to any agent / RDF tool.
109
- const ld = appAsSoftware({ name: path, kappa, bytes: bytes.length });
110
- await writeFile(path.replace(/\.html$/i, "") + ".app.jsonld", JSON.stringify(ld, null, 1));
111
- return { text: `built app "${path}" (${html.length} bytes), sealed ${kappa.slice(0, 30)}… · typed ${ld["@type"].join("+")} — renders in the preview, re-derivable (Law L5).`, isError: false, render: { kind: "app", path: norm(path), kappa, html: String(html), ld } };
112
- } catch (e) { return { text: "build_app error: " + (e.message || e), isError: true }; }
113
- },
114
- },
115
- {
116
- def: { name: "verify_object", description: "Re-derive a workspace file's content address and confirm it matches (Law L5 — verify every byte). Returns whether the bytes are authentic.", inputSchema: { type: "object", properties: { path: { type: "string" }, kappa: { type: "string" } }, required: ["path"] } },
117
- serverName: "code", call: async ({ path, kappa }) => {
118
- try {
119
- const bytes = await readFile(path);
120
- const got = "did:holo:sha256:" + await sha256Hex(bytes);
121
- const ok = !kappa || got === kappa || got.startsWith(kappa) || kappa.startsWith(got.slice(0, kappa.length));
122
- // verify = re-derive κ (Law L5) AND emit the W3C @type — apps are SoftwareApplication, all else DigitalDocument.
123
- const ld = /\.html$/i.test(path) ? appAsSoftware({ name: norm(path), kappa: got, bytes: bytes.length })
124
- : fileAsDocument({ path: norm(path), kappa: got, bytes: bytes.length });
125
- return { text: `${norm(path)} re-derives to ${got.slice(0, 34)}…${kappa ? (ok ? " ✓ matches (authentic)" : " ✗ MISMATCH") : ""} · @type ${ld["@type"].join("+")}`, isError: false, render: { kind: "linked-data", ld } };
126
- } catch (e) { return { text: "verify error: " + (e.message || e), isError: true }; }
127
- },
128
- },
129
- ];
130
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/keymap.js DELETED
@@ -1,29 +0,0 @@
1
- // core/keymap.js — the keyboard map as a data table (LibreChat's native set): Alt+N new chat,
2
- // Alt+S toggle sidebar, Alt+W focus the input, Ctrl/⌘+Enter send, Esc stop generation,
3
- // Ctrl/⌘+K model menu. `/` and `@` composer menus live in ui/composer.js (they are caret-local).
4
-
5
- export const BINDINGS = [
6
- { combo: "Alt+N", action: "newChat", label: "New chat" },
7
- { combo: "Alt+S", action: "toggleNav", label: "Toggle sidebar" },
8
- { combo: "Alt+W", action: "focusInput", label: "Focus message box" },
9
- { combo: "Ctrl+Enter", action: "send", label: "Send message" },
10
- { combo: "Escape", action: "stop", label: "Stop generating" },
11
- { combo: "Ctrl+K", action: "modelMenu", label: "Choose model" },
12
- ];
13
-
14
- export function installKeymap(handlers) {
15
- const onKey = (e) => {
16
- const ctrl = e.ctrlKey || e.metaKey;
17
- const fire = (name) => { const fn = handlers[name]; if (fn) { e.preventDefault(); fn(e); } };
18
- if (e.altKey && !ctrl && !e.shiftKey) {
19
- if (e.code === "KeyN") return fire("newChat");
20
- if (e.code === "KeyS") return fire("toggleNav");
21
- if (e.code === "KeyW") return fire("focusInput");
22
- }
23
- if (ctrl && e.key === "Enter") return fire("send");
24
- if (ctrl && !e.shiftKey && e.code === "KeyK") return fire("modelMenu");
25
- if (e.key === "Escape") { const fn = handlers.stop; if (fn) fn(e); } // don't preventDefault — Esc also closes menus
26
- };
27
- document.addEventListener("keydown", onKey);
28
- return () => document.removeEventListener("keydown", onKey);
29
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/mcp.js DELETED
@@ -1,144 +0,0 @@
1
- // core/mcp.js — a lean, browser-native Model Context Protocol CLIENT. Speaks the open MCP
2
- // spec (JSON-RPC 2.0) over the Streamable HTTP transport (single endpoint, POST per message,
3
- // optional SSE response bodies, Mcp-Session-Id header) with a fallback for plain HTTP+SSE
4
- // servers. No SDK, no build step — the protocol is small and this is all of it that a chat
5
- // client needs: initialize → tools/list → tools/call.
6
- //
7
- // Substrate twist: every connected server and every tool call is content-addressable — the
8
- // caller can seal a PROV-O receipt around call inputs/outputs (see core/tools.js), so tool
9
- // use gets the same verifiability as inference (Law L5).
10
-
11
- const PROTOCOL_VERSION = "2025-03-26";
12
- const CLIENT_INFO = { name: "holo-q", version: "2.0.0" };
13
-
14
- let _seq = 0;
15
- const nextId = () => ++_seq;
16
-
17
- // Parse an SSE stream body and resolve with the JSON-RPC response matching `id`.
18
- async function readSse(res, id) {
19
- const reader = res.body.getReader(); const dec = new TextDecoder();
20
- let buf = "", result = null;
21
- for (;;) {
22
- const { done, value } = await reader.read(); if (done) break;
23
- buf += dec.decode(value, { stream: true });
24
- let i;
25
- while ((i = buf.indexOf("\n\n")) >= 0) {
26
- const frame = buf.slice(0, i); buf = buf.slice(i + 2);
27
- const data = frame.split("\n").filter((l) => l.startsWith("data:")).map((l) => l.slice(5).trim()).join("");
28
- if (!data) continue;
29
- try { const msg = JSON.parse(data); if (msg.id === id) { result = msg; reader.cancel().catch(() => {}); return result; } } catch {}
30
- }
31
- }
32
- return result;
33
- }
34
-
35
- export function makeMcpClient({ url, headers = {}, name = "", timeoutMs = 30000 } = {}) {
36
- let sessionId = null, initialized = null, serverInfo = null, toolCache = null;
37
-
38
- async function rpc(method, params, { notification = false } = {}) {
39
- const body = notification
40
- ? { jsonrpc: "2.0", method, ...(params ? { params } : {}) }
41
- : { jsonrpc: "2.0", id: nextId(), method, ...(params ? { params } : {}) };
42
- const ctrl = new AbortController();
43
- const t = setTimeout(() => ctrl.abort(), timeoutMs);
44
- try {
45
- const res = await fetch(url, {
46
- method: "POST", signal: ctrl.signal,
47
- headers: { "content-type": "application/json", accept: "application/json, text/event-stream", ...(sessionId ? { "mcp-session-id": sessionId } : {}), ...headers },
48
- body: JSON.stringify(body),
49
- });
50
- const sid = res.headers.get("mcp-session-id"); if (sid) sessionId = sid;
51
- if (notification) return null;
52
- if (res.status === 202) return null;
53
- if (!res.ok) throw new Error(`MCP ${res.status} ${res.statusText}`);
54
- const ctype = res.headers.get("content-type") || "";
55
- const msg = ctype.includes("text/event-stream") ? await readSse(res, body.id) : await res.json();
56
- if (!msg) throw new Error("MCP: no response for request " + body.id);
57
- if (msg.error) throw new Error(`MCP ${method}: ${msg.error.message || JSON.stringify(msg.error)}`);
58
- return msg.result;
59
- } finally { clearTimeout(t); }
60
- }
61
-
62
- async function initialize() {
63
- if (initialized) return initialized;
64
- initialized = (async () => {
65
- const r = await rpc("initialize", { protocolVersion: PROTOCOL_VERSION, capabilities: {}, clientInfo: CLIENT_INFO });
66
- serverInfo = r && r.serverInfo || { name: name || url };
67
- await rpc("notifications/initialized", undefined, { notification: true }).catch(() => {});
68
- return r;
69
- })();
70
- return initialized;
71
- }
72
-
73
- // tools/list (cached; paginated per spec)
74
- async function listTools(force = false) {
75
- if (toolCache && !force) return toolCache;
76
- await initialize();
77
- const out = []; let cursor;
78
- do {
79
- const r = await rpc("tools/list", cursor ? { cursor } : {});
80
- out.push(...(r.tools || [])); cursor = r.nextCursor;
81
- } while (cursor);
82
- toolCache = out;
83
- return out;
84
- }
85
-
86
- // tools/call → { content: [{type:"text",text}|{type:"image",...}], isError }
87
- async function callTool(toolName, args) {
88
- await initialize();
89
- const r = await rpc("tools/call", { name: toolName, arguments: args || {} });
90
- return r;
91
- }
92
-
93
- return {
94
- url, name: () => (serverInfo && serverInfo.name) || name || url,
95
- initialize, listTools, callTool,
96
- get serverInfo() { return serverInfo; },
97
- };
98
- }
99
-
100
- // Flatten a tools/call result's content into plain text for the model's <tool_response>.
101
- export function contentToText(result) {
102
- if (!result) return "";
103
- if (result.isError) return "ERROR: " + (result.content || []).map((c) => c.text || "").join("\n");
104
- return (result.content || []).map((c) => c.type === "text" ? c.text : c.type === "image" ? "[image]" : c.type === "resource" ? JSON.stringify(c.resource).slice(0, 2000) : "").join("\n");
105
- }
106
-
107
- // ── DISCOVERY — the MCP universe, three rings out from the substrate ─────────────────────
108
- // 1. the SUBSTRATE's own roster (/.well-known/mcp.json — same-origin, verifiable)
109
- // 2. user-added servers (κ-pinned config in the boot index)
110
- // 3. the OFFICIAL public MCP registry (registry.modelcontextprotocol.io — the open index
111
- // of the ecosystem; remote/streamable-http entries are directly connectable from a tab)
112
- export async function discoverSubstrate() {
113
- try {
114
- const r = await fetch("/.well-known/mcp.json"); if (!r.ok) return [];
115
- const j = await r.json();
116
- const servers = j.servers || j.mcpServers || (Array.isArray(j) ? j : [j]);
117
- return (Array.isArray(servers) ? servers : Object.entries(servers).map(([k, v]) => ({ name: k, ...v })))
118
- .map((s) => ({ source: "substrate", name: s.name || "hologram", url: s.url || s.endpoint || null, description: s.description || "", tools: s.tools || null, raw: s }))
119
- .filter((s) => s.url || s.tools);
120
- } catch { return []; }
121
- }
122
-
123
- export async function searchRegistry(query, { limit = 20 } = {}) {
124
- // The official registry's public REST API (v0). Remote servers carry `remotes[]` with
125
- // streamable-http/sse URLs — those are connectable straight from the browser.
126
- const base = "https://registry.modelcontextprotocol.io/v0/servers";
127
- const u = base + "?limit=" + limit + (query ? "&search=" + encodeURIComponent(query) : "");
128
- const r = await fetch(u, { headers: { accept: "application/json" } });
129
- if (!r.ok) throw new Error("registry " + r.status);
130
- const j = await r.json();
131
- return (j.servers || []).map((s) => {
132
- const remote = (s.remotes || []).find((x) => /streamable|http/.test(x.type || "")) || (s.remotes || [])[0] || null;
133
- return { source: "registry", name: s.name, description: s.description || "", version: s.version,
134
- url: remote ? remote.url : null, transport: remote ? remote.type : (s.packages?.length ? "package (host-run)" : "unknown"), raw: s };
135
- });
136
- }
137
-
138
- export async function discoverAgents() {
139
- // The substrate's agent doors: NANDA AgentFacts + A2A AgentCards + Skills — one entry point.
140
- try {
141
- const r = await fetch("/.well-known/agents.json"); if (!r.ok) return null;
142
- return await r.json();
143
- } catch { return null; }
144
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/mcphub.js DELETED
@@ -1,107 +0,0 @@
1
- // core/mcphub.js — the MCP connection HUB: manages servers (substrate roster · user-added ·
2
- // registry finds), their lifecycles and tool lists, and exposes the flat enabled-tool set the
3
- // generation loop consumes. Server configs persist in the boot index (substrate-local).
4
- //
5
- // Discovery rings: (1) the substrate's own /.well-known/mcp.json (the OS's 30 verified tools),
6
- // (2) servers the user added by URL, (3) the official public MCP registry. One hub, the
7
- // whole universe reachable from a tab.
8
-
9
- import { makeMcpClient, contentToText, discoverSubstrate, searchRegistry, discoverAgents } from "./mcp.js";
10
-
11
- export function makeMcpHub({ chatStore, bus }) {
12
- const servers = new Map(); // id → { id, name, url, headers, enabled, client, tools, status, error }
13
- let loaded = false;
14
-
15
- const INDEX_KEY = "index:org.hologram.HoloQ";
16
- async function persist() {
17
- const idx = await chatStore.getIndex();
18
- idx.mcpServers = [...servers.values()].map((s) => ({ id: s.id, name: s.name, url: s.url, headers: s.headers || {}, enabled: !!s.enabled, source: s.source || "user" }));
19
- const b = new TextEncoder().encode(JSON.stringify(idx));
20
- await (chatStore.store.backend.putRaw ? chatStore.store.backend.putRaw(INDEX_KEY, b) : chatStore.store.backend.put(INDEX_KEY, b));
21
- }
22
-
23
- async function restore() {
24
- if (loaded) return; loaded = true;
25
- const idx = await chatStore.getIndex();
26
- for (const s of idx.mcpServers || []) if (!servers.has(s.id)) servers.set(s.id, { ...s, client: null, tools: [], status: "saved" }); // never clobber a live entry
27
- bus.emit("mcp-changed");
28
- }
29
-
30
- const norm = (url) => { try { return new URL(url, location.origin).href; } catch { return url; } };
31
- const idOf = (url) => "mcp-" + norm(url).replace(/[^\w]+/g, "-").slice(0, 60);
32
-
33
- async function add({ name, url, headers = {}, source = "user", enabled = true }) {
34
- const u = norm(url); const id = idOf(u);
35
- if (!servers.has(id)) servers.set(id, { id, name: name || u, url: u, headers, source, enabled, client: null, tools: [], status: "saved" });
36
- const s = servers.get(id);
37
- s.enabled = enabled; // adding is an explicit intent — (re)enable even if a saved entry existed
38
- await connect(s.id).catch(() => {});
39
- await persist();
40
- bus.emit("mcp-changed");
41
- return s;
42
- }
43
-
44
- async function connect(id) {
45
- const s = servers.get(id); if (!s) return null;
46
- s.status = "connecting"; s.error = null; bus.emit("mcp-changed");
47
- try {
48
- s.client = makeMcpClient({ url: s.url, headers: s.headers, name: s.name });
49
- await s.client.initialize();
50
- s.tools = await s.client.listTools();
51
- s.name = s.client.name() || s.name;
52
- s.status = "connected";
53
- } catch (e) {
54
- s.client = null; s.tools = []; s.status = "error"; s.error = String(e && e.message || e);
55
- }
56
- bus.emit("mcp-changed");
57
- return s;
58
- }
59
-
60
- async function remove(id) { servers.delete(id); await persist(); bus.emit("mcp-changed"); }
61
- async function setEnabled(id, on) { const s = servers.get(id); if (s) { s.enabled = !!on; if (on && !s.client) await connect(id); await persist(); bus.emit("mcp-changed"); } }
62
-
63
- // The flat ARMED tool set the loop consumes: [{ def, serverName, call(args)→{text,isError} }].
64
- // Per-server `toolFilter` (a name allowlist, set from the UI) selects which tools arm; without
65
- // one, the first DEFAULT_ARM tools arm. A hard ceiling keeps the system block inside the model's
66
- // context (a local model can't juggle 30 schemas — pick, like LibreChat's per-server selection).
67
- const DEFAULT_ARM = 4, MAX_ARM = 8;
68
- // the substrate's own roster is curated to its core verbs by default
69
- const SUBSTRATE_DEFAULT = ["search_web", "resolve_object", "answer", "verify_object"];
70
- function enabledTools() {
71
- const out = [];
72
- for (const s of servers.values()) {
73
- if (!s.enabled || s.status !== "connected") continue;
74
- const names = s.toolFilter && s.toolFilter.length ? s.toolFilter
75
- : (s.source === "substrate" ? SUBSTRATE_DEFAULT.filter((n) => s.tools.some((t) => t.name === n)) : s.tools.slice(0, DEFAULT_ARM).map((t) => t.name));
76
- for (const t of s.tools) {
77
- if (!names.includes(t.name)) continue;
78
- out.push({
79
- def: { name: t.name, description: t.description, inputSchema: t.inputSchema },
80
- serverName: s.name, serverId: s.id,
81
- call: async (args) => { const r = await s.client.callTool(t.name, args); return { text: contentToText(r), isError: !!(r && r.isError) }; },
82
- });
83
- }
84
- }
85
- // de-dup by tool name (first server wins) — small models address tools by bare name
86
- const seen = new Set();
87
- return out.filter((t) => (seen.has(t.def.name) ? false : (seen.add(t.def.name), true))).slice(0, MAX_ARM);
88
- }
89
- async function setToolFilter(id, names) { const s = servers.get(id); if (s) { s.toolFilter = names && names.length ? names : null; bus.emit("mcp-changed"); } }
90
-
91
- // Substrate ring: read the OS roster; candidate endpoints = declared, same-origin /mcp, the
92
- // conventional localhost MCP port. First reachable wins.
93
- async function discoverSubstrateServers() {
94
- const entries = await discoverSubstrate();
95
- const candidates = new Set();
96
- for (const e of entries) if (e.url) candidates.add(norm(e.url));
97
- candidates.add(norm("/mcp"));
98
- candidates.add("http://127.0.0.1:8787/mcp");
99
- return { entries, candidates: [...candidates] };
100
- }
101
-
102
- return {
103
- restore, add, connect, remove, setEnabled, setToolFilter, enabledTools, persist,
104
- list: () => [...servers.values()],
105
- discoverSubstrateServers, searchRegistry, discoverAgents,
106
- };
107
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/memory.js DELETED
@@ -1,69 +0,0 @@
1
- // core/memory.js — persistent USER MEMORY (LibreChat memory semantics, substrate-native).
2
- // Memories are key/value facts (key validated /^[a-z_]+$/, value a complete sentence) stored as
3
- // κ-objects with pointers in the boot index. They inject into the system block as the
4
- // "# Existing memory:" section, and the model maintains them itself through two LOCAL tools
5
- // (set_memory / delete_memory) armed alongside MCP tools in the agentic loop — no server,
6
- // every write content-addressed and verifiable.
7
-
8
- const LC = { lc: "https://librechat.ai/ns#" };
9
- export const KEY_RE = /^[a-z_]+$/;
10
-
11
- export function makeMemory(chatStore, { tokenLimit = 2000 } = {}) {
12
- const { store, getIndex, newId } = chatStore;
13
- const putIndex = async (idx) => { const b = new TextEncoder().encode(JSON.stringify(idx)); return store.backend.putRaw ? store.backend.putRaw("index:org.hologram.HoloQ", b) : store.backend.put("index:org.hologram.HoloQ", b); };
14
- const tokensOf = (s) => Math.ceil((s || "").length / 4); // a fair, dependency-free estimate
15
-
16
- async function list() { return (await getIndex()).memories || []; }
17
-
18
- async function set(key, value) {
19
- key = String(key || "").toLowerCase().trim();
20
- if (!KEY_RE.test(key)) return { ok: false, error: "invalid key — use lowercase letters and underscores" };
21
- const idx = await getIndex();
22
- idx.memories = idx.memories || [];
23
- const used = idx.memories.filter((m) => m.key !== key).reduce((n, m) => n + (m.tokenCount || 0), 0);
24
- const tc = tokensOf(value);
25
- if (used + tc > tokenLimit) return { ok: false, error: `memory full: ${used}+${tc} > ${tokenLimit} tokens` };
26
- const obj = await store.makeObject({
27
- type: ["schema:Statement", "prov:Entity"], context: [LC],
28
- "lc:key": key, "lc:value": String(value || ""), "lc:tokenCount": tc,
29
- "schema:dateModified": new Date().toISOString(),
30
- });
31
- const i = idx.memories.findIndex((m) => m.key === key);
32
- const ptr = { key, kappa: obj.id, value: String(value || ""), tokenCount: tc, updated_at: new Date().toISOString() };
33
- if (i >= 0) idx.memories[i] = ptr; else idx.memories.push(ptr);
34
- await putIndex(idx);
35
- return { ok: true, key, kappa: obj.id };
36
- }
37
-
38
- async function remove(key) {
39
- const idx = await getIndex();
40
- idx.memories = (idx.memories || []).filter((m) => m.key !== key);
41
- await putIndex(idx);
42
- return { ok: true };
43
- }
44
-
45
- // The system-block injection ("# Existing memory:" — the LibreChat convention).
46
- async function injection() {
47
- const mems = await list();
48
- if (!mems.length) return "";
49
- const used = mems.reduce((n, m) => n + (m.tokenCount || 0), 0);
50
- return `# Memory Status:\nCurrent memory usage: ${used} tokens\nToken limit: ${tokenLimit} tokens\nRemaining capacity: ${Math.max(0, tokenLimit - used)} tokens\n\n# Existing memory:\n` +
51
- mems.map((m) => `- ${m.key}: ${m.value}`).join("\n");
52
- }
53
-
54
- // The two LOCAL tools the agentic loop arms (same shape as MCP hub tools).
55
- function localTools() {
56
- return [
57
- {
58
- def: { name: "set_memory", description: "Remember a fact about the user across conversations. Only when the user explicitly asks (\"remember that…\"). key: lowercase_with_underscores; value: one complete sentence.", inputSchema: { type: "object", properties: { key: { type: "string" }, value: { type: "string" } }, required: ["key", "value"] } },
59
- serverName: "memory", call: async (a) => { const r = await set(a.key, a.value); return { text: JSON.stringify(r), isError: !r.ok }; },
60
- },
61
- {
62
- def: { name: "delete_memory", description: "Forget a remembered fact, by key. Only when the user explicitly asks.", inputSchema: { type: "object", properties: { key: { type: "string" } }, required: ["key"] } },
63
- serverName: "memory", call: async (a) => { const r = await remove(a.key); return { text: JSON.stringify(r), isError: false }; },
64
- },
65
- ];
66
- }
67
-
68
- return { list, set, remove, injection, localTools, tokenLimit };
69
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/presets.js DELETED
@@ -1,54 +0,0 @@
1
- // core/presets.js — preset CRUD (the saved parameter bundles a conversation spreads, LibreChat's
2
- // conversationPreset semantics). Each preset is a κ-object in the store; the boot index keeps
3
- // pointer rows { presetId, kappa, title } so listing is O(1) without a scan.
4
-
5
- import { normPreset } from "./schema.js";
6
-
7
- const LC = { lc: "https://librechat.ai/ns#" };
8
-
9
- export function makePresets(chatStore) {
10
- const { store, getIndex, newId } = chatStore;
11
- const putIndex = async (idx) => { const b = new TextEncoder().encode(JSON.stringify(idx)); return store.backend.putRaw ? store.backend.putRaw("index:org.hologram.HoloQ", b) : store.backend.put("index:org.hologram.HoloQ", b); };
12
-
13
- async function save(p) {
14
- const norm = normPreset(p);
15
- if (!norm.presetId) norm.presetId = newId("preset");
16
- const obj = await store.makeObject({ type: ["schema:PropertyValue", "prov:Entity"], context: [LC], "schema:identifier": norm.presetId, "schema:name": norm.title, "lc:preset": norm });
17
- const idx = await getIndex();
18
- idx.presets = idx.presets || [];
19
- const i = idx.presets.findIndex((x) => x.presetId === norm.presetId);
20
- const ptr = { presetId: norm.presetId, kappa: obj.id, title: norm.title, defaultPreset: !!p.defaultPreset };
21
- if (i >= 0) idx.presets[i] = ptr; else idx.presets.push(ptr);
22
- if (p.defaultPreset) idx.presets.forEach((x) => { if (x.presetId !== norm.presetId) x.defaultPreset = false; });
23
- await putIndex(idx);
24
- return { ...norm, kappa: obj.id };
25
- }
26
-
27
- async function list() { return (await getIndex()).presets || []; }
28
-
29
- async function get(presetId) {
30
- const ptr = (await list()).find((x) => x.presetId === presetId); if (!ptr) return null;
31
- const obj = await store.getObj(ptr.kappa); if (!obj) return null;
32
- if (!(await store.verify(obj))) return null; // Law L5: a tampered preset is refused
33
- return { ...normPreset(obj["lc:preset"]), kappa: ptr.kappa };
34
- }
35
-
36
- async function getDefault() {
37
- const ptrs = await list(); const d = ptrs.find((x) => x.defaultPreset) || null;
38
- return d ? get(d.presetId) : null;
39
- }
40
-
41
- async function remove(presetId) {
42
- const idx = await getIndex();
43
- idx.presets = (idx.presets || []).filter((x) => x.presetId !== presetId);
44
- await putIndex(idx); // the κ-object stays content-addressed in the store (dedup'd, unreferenced)
45
- }
46
-
47
- return { save, list, get, getDefault, remove };
48
- }
49
-
50
- // The factory default — mirrors the engine's real capabilities (greedy decode is the
51
- // deterministic, verifiable path; temperature stays 0 unless a model declares one).
52
- export const DEFAULT_PRESET = () => normPreset({
53
- title: "Default", temperature: 0, maxOutputTokens: 900, promptPrefix: "",
54
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/promptsLib.js DELETED
@@ -1,109 +0,0 @@
1
- // core/promptsLib.js — the PROMPTS LIBRARY as κ-objects (LibreChat prompt-group semantics).
2
- // A group carries name · category · oneliner · command (the /slash trigger) and points at its
3
- // PRODUCTION version; every version is its own immutable κ-object (text or chat type). The
4
- // {{variable}} syntax matches LibreChat: {{name}}, {{name:opt1|opt2}} dropdowns, and the
5
- // special variables {{current_date}} {{current_datetime}} {{iso_datetime}} {{current_user}}.
6
-
7
- const LC = { lc: "https://librechat.ai/ns#" };
8
- export const COMMAND_RE = /^[a-z0-9-]{1,56}$/;
9
- export const VAR_RE = /{{([^{}]+?)}}/g;
10
- const SPECIAL = ["current_date", "current_datetime", "iso_datetime", "current_user"];
11
-
12
- export function detectVariables(text) {
13
- const out = []; const seen = new Set(); let m;
14
- VAR_RE.lastIndex = 0;
15
- while ((m = VAR_RE.exec(text || ""))) {
16
- const raw = m[1].trim();
17
- const name = raw.split(":")[0].trim();
18
- if (SPECIAL.includes(name.toLowerCase()) || seen.has(name)) continue;
19
- seen.add(name);
20
- const opts = raw.includes(":") ? raw.slice(raw.indexOf(":") + 1).split("|").map((s) => s.trim()).filter(Boolean) : null;
21
- out.push({ name, raw, options: opts });
22
- }
23
- return out;
24
- }
25
-
26
- export function replaceSpecialVars(text, { userName = "operator" } = {}) {
27
- const d = new Date();
28
- const pad = (n) => String(n).padStart(2, "0");
29
- const day = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][d.getDay()];
30
- const date = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
31
- const time = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
32
- const off = -d.getTimezoneOffset(); const tz = (off >= 0 ? "+" : "-") + pad(Math.floor(Math.abs(off) / 60)) + ":" + pad(Math.abs(off) % 60);
33
- const sub = (t, name, v) => t.replace(new RegExp(`{{\\s*${name}\\s*}}`, "gi"), v);
34
- let out = text || "";
35
- out = sub(out, "current_date", `${date} (${day})`);
36
- out = sub(out, "current_datetime", `${date} ${time} ${tz} (${day})`);
37
- out = sub(out, "iso_datetime", d.toISOString());
38
- out = sub(out, "current_user", userName);
39
- return out;
40
- }
41
-
42
- export function fillVariables(text, values) {
43
- let out = text || "";
44
- for (const [raw, v] of Object.entries(values || {})) {
45
- const esc = raw.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
46
- out = out.replace(new RegExp(`{{\\s*${esc}\\s*}}`, "g"), v);
47
- }
48
- return out;
49
- }
50
-
51
- export function makePromptsLib(chatStore) {
52
- const { store, getIndex, newId } = chatStore;
53
- const putIndex = async (idx) => { const b = new TextEncoder().encode(JSON.stringify(idx)); return store.backend.putRaw ? store.backend.putRaw("index:org.hologram.HoloQ", b) : store.backend.put("index:org.hologram.HoloQ", b); };
54
-
55
- // Save a version into a group (creates the group when groupId is null); production by default.
56
- async function save({ groupId, name, category = "", oneliner = "", command = "", prompt, type = "text", production = true }) {
57
- command = (command || "").toLowerCase();
58
- if (command && !COMMAND_RE.test(command)) throw new Error("command must be a-z 0-9 dash, ≤56 chars");
59
- const versionObj = await store.makeObject({
60
- type: ["schema:CreativeWork", "prov:Entity"], context: [LC],
61
- "lc:prompt": prompt || "", "lc:type": type === "chat" ? "chat" : "text",
62
- "schema:dateCreated": new Date().toISOString(),
63
- });
64
- const idx = await getIndex();
65
- idx.promptGroups = idx.promptGroups || [];
66
- let g = groupId ? idx.promptGroups.find((x) => x.groupId === groupId) : null;
67
- if (!g) {
68
- g = { groupId: newId("pgroup"), name: name || "New Prompt", category, oneliner, command, versions: [], productionKappa: null, numberOfGenerations: 0 };
69
- idx.promptGroups.push(g);
70
- }
71
- if (name) g.name = name;
72
- if (category !== undefined) g.category = category;
73
- if (oneliner !== undefined) g.oneliner = oneliner;
74
- if (command !== undefined) g.command = command;
75
- g.versions.push({ kappa: versionObj.id, createdAt: new Date().toISOString() });
76
- if (production || !g.productionKappa) g.productionKappa = versionObj.id;
77
- await putIndex(idx);
78
- return { ...g };
79
- }
80
-
81
- async function list() { return (await getIndex()).promptGroups || []; }
82
-
83
- async function production(groupId) {
84
- const g = (await list()).find((x) => x.groupId === groupId); if (!g || !g.productionKappa) return null;
85
- const obj = await store.getObj(g.productionKappa); if (!obj) return null;
86
- if (!(await store.verify(obj))) return null; // Law L5
87
- return { group: g, prompt: obj["lc:prompt"], type: obj["lc:type"], kappa: g.productionKappa };
88
- }
89
-
90
- async function setProduction(groupId, kappa) {
91
- const idx = await getIndex();
92
- const g = (idx.promptGroups || []).find((x) => x.groupId === groupId);
93
- if (g && g.versions.some((v) => v.kappa === kappa)) { g.productionKappa = kappa; await putIndex(idx); }
94
- }
95
-
96
- async function recordUse(groupId) {
97
- const idx = await getIndex();
98
- const g = (idx.promptGroups || []).find((x) => x.groupId === groupId);
99
- if (g) { g.numberOfGenerations = (g.numberOfGenerations || 0) + 1; await putIndex(idx); }
100
- }
101
-
102
- async function remove(groupId) {
103
- const idx = await getIndex();
104
- idx.promptGroups = (idx.promptGroups || []).filter((x) => x.groupId !== groupId);
105
- await putIndex(idx);
106
- }
107
-
108
- return { save, list, production, setProduction, recordUse, remove };
109
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/q-brain-fast.mjs DELETED
@@ -1,153 +0,0 @@
1
- // core/q-brain-fast.mjs — Q's FAST on-device brain, drop-in for createHoloModelBrain.
2
- //
3
- // Same provider shape (load · generate → text-delta async-iterator · chat · info · setSkill), so
4
- // holo-q-contact.mjs's makeQResponder / makeQGroupResponder bind it with ZERO changes: Q rides the exact
5
- // stream→finalize pipeline, it just sources its bytes from THIS engine (core/loader + core/engine — the
6
- // native-ternary κ-object path with the fixed incremental-detok decode) instead of the qwen holo-brain.
7
- //
8
- // Why this exists: the messenger's default brain (qwen2.5-0.5b via holo-brain-engine) is heavy and its
9
- // app-path decode was O(n²). This one loads a native-ternary BitNet κ-object (0.69 GB, verified per-block),
10
- // decodes at ~70 tok/s warm, and streams byte-identical incremental text. It is 100% on-device at decode
11
- // time — only a ONE-TIME tokenizer-header Range fetch touches the source host at load (the weights are the
12
- // local, L5-verified b/<κ>.gz blocks). Bundle the header to make load fully egress-free (follow-up).
13
- //
14
- // URL discipline (the one gotcha): core/loader's MODELS use a PAGE-relative kappaUrl ("./models/<name>"),
15
- // which is wrong from any page other than /apps/q/. loadKappaObject resolves the manifest, blocks AND the
16
- // bundled tokenizer relative to its baseUrl, so we override kappaUrl to an ABSOLUTE mount ("/apps/q/models/
17
- // <name>") — that makes the whole load self-contained from the messenger (or anywhere).
18
-
19
- import { ready, loadModel, MODELS } from "./loader.js";
20
- import { createEngine } from "./engine.js";
21
- import { selfFacts, selfPersona, selfIntro } from "./q-self.mjs"; // Q's live, grounded self-knowledge (M0)
22
-
23
- // The default fast brain = BitNet-2B (native ternary, llama3 template, coherent — Falcon-E degenerates).
24
- // Override via opts.family / opts.modelName. kappaBase is the absolute mount core/loader's models live under.
25
- const DEFAULTS = { family: "BitNet", kappaBase: "/apps/q/models", maxTokens: 512 };
26
-
27
- function pickModel(cfg) {
28
- const want = String(cfg.modelName || cfg.family || "BitNet").toLowerCase();
29
- const m = MODELS.find((x) => (x.fam || "").toLowerCase() === want || (x.name || "").toLowerCase().includes(want)) || MODELS.find((x) => (x.fam || "").toLowerCase() === "bitnet");
30
- if (!m) throw new Error("q-brain-fast: no model matches " + want);
31
- // An ABSOLUTE host URL (the κ-object now lives on HF, not on this machine) is already page-independent —
32
- // use it verbatim. Only a page-relative "./models/<name>" needs absolute-mounting so it resolves from ANY page.
33
- if (/^https?:\/\//.test(m.kappaUrl || "")) return { ...m };
34
- const rel = String(m.kappaUrl || "").replace(/^\.?\//, "").replace(/^models\//, ""); // "./models/bitnet-2b" → "bitnet-2b"
35
- return { ...m, kappaUrl: String(cfg.kappaBase).replace(/\/+$/, "") + "/" + rel };
36
- }
37
-
38
- // Render an [{role,content}] history (system + turns, as makeQResponder builds it) to the model's chat
39
- // template — the multi-turn generalization of core/engine's single-turn frameTurn. Covers the templates
40
- // the engine knows; unknown families fall back to a persona-led last-user Q/A frame.
41
- function frameHistory(M, history) {
42
- const list = Array.isArray(history) ? history : [];
43
- // merge ALL system turns into one system block (persona + any injected context, e.g. M1 grounded retrieval) —
44
- // taking only the first would silently DROP injected context and the model would fall back to a generic refusal.
45
- const persona = list.filter((x) => x && x.role === "system" && x.content).map((x) => x.content).join("\n\n");
46
- const turns = list.filter((x) => x && x.role !== "system" && (x.content || "").length);
47
-
48
- if (M.llama3) {
49
- let s = persona ? `<|start_header_id|>system<|end_header_id|>\n\n${persona}<|eot_id|>` : "";
50
- for (const t of turns) s += `<|start_header_id|>${t.role === "assistant" ? "assistant" : "user"}<|end_header_id|>\n\n${t.content}<|eot_id|>`;
51
- return s + `<|start_header_id|>assistant<|end_header_id|>\n\n`;
52
- }
53
- if (M.qwen) {
54
- const noThink = M.qwen3 ? "<think>\n\n</think>\n\n" : "";
55
- let s = persona ? `<|im_start|>system\n${persona}<|im_end|>\n` : "";
56
- for (const t of turns) s += `<|im_start|>${t.role === "assistant" ? "assistant" : "user"}\n${t.content}<|im_end|>\n`;
57
- return s + `<|im_start|>assistant\n` + noThink;
58
- }
59
- if (M.olmo) {
60
- let s = persona ? `<|system|>\n${persona}\n` : "";
61
- for (const t of turns) s += t.role === "assistant" ? `<|assistant|>\n${t.content}\n` : `<|user|>\n${t.content}\n`;
62
- return s + `<|assistant|>\n`;
63
- }
64
- // word-frame / plain: only the last user turn carries (base models have no multi-turn template)
65
- const lastUser = [...turns].reverse().find((t) => t.role !== "assistant");
66
- const q = (lastUser && lastUser.content) || "";
67
- if (M.userWord) return (persona ? persona + "\n" : "") + "User: " + q + "\nFalcon:";
68
- return (persona ? persona + "\n" : "") + "Question: " + q + "\nAnswer:";
69
- }
70
-
71
- export function createFastQBrain(opts = {}) {
72
- const cfg = Object.assign({}, DEFAULTS, opts);
73
- const M = pickModel(cfg);
74
- let engine = null, loadingP = null;
75
- let info = { ready: false, model: M.name, device: null, resident: false };
76
-
77
- // encode a history to the running token ids (framed + optional bos), ready for engine.generate
78
- function idsFor(history) {
79
- let ids = engine.tokenize(frameHistory(M, history));
80
- if (M.bos && engine.bosId != null) ids = [engine.bosId, ...ids];
81
- return ids;
82
- }
83
-
84
- async function load(onProgress) {
85
- if (engine) return info;
86
- if (loadingP) return loadingP;
87
- loadingP = (async () => {
88
- if (!(typeof navigator !== "undefined" && navigator.gpu)) throw new Error("no WebGPU on this device");
89
- await ready(); // wasm tokenizer init (shared instance)
90
- const loaded = await loadModel(M, {
91
- onStatus: () => {},
92
- onProgress: (d, t, w) => { try { onProgress && onProgress({ done: d, total: t, phase: w, model: M.name }); } catch (e) {} },
93
- });
94
- if (!loaded || !loaded.gpu) throw new Error("q-brain-fast: model load failed (" + M.name + ")");
95
- engine = await createEngine(M, loaded);
96
- // MEASURED from the real engine, not asserted: device/resident reflect an engine that actually uploaded
97
- // weights to the GPU (dims + gpuBytes are live signals) — so info() can never claim residency it lacks.
98
- info = { ready: true, model: M.name, device: (engine && engine.dims ? "webgpu" : null), resident: !!(engine && (engine.gpuBytes || engine.dims)) };
99
- return info;
100
- })().catch((e) => { loadingP = null; throw e; });
101
- return loadingP;
102
- }
103
- async function ensure(onProgress) { if (!engine) await load(onProgress); return engine; }
104
-
105
- // generate(history, { signal, onProgress }) → async-iterator of TEXT DELTAS (exactly what makeQResponder
106
- // accumulates + paints via onDelta). engine.generate reports CUMULATIVE text per step; we diff to deltas
107
- // and pump them through a small queue so this stays a clean generator (and honors the abort signal).
108
- async function* generate(history, o = {}) {
109
- await ensure(o.onProgress);
110
- if (!engine) return;
111
- const signal = o.signal || null;
112
- const ids = idsFor(history);
113
- const cap = o.maxTokens || cfg.maxTokens || M.cap || 256;
114
-
115
- const queue = []; let done = false, wake = null, prev = "";
116
- const kick = () => { if (wake) { const w = wake; wake = null; w(); } };
117
- const run = engine.generate(ids, {
118
- maxNew: cap, signal,
119
- onToken: ({ text }) => { const d = (text || "").slice(prev.length); if (d) { prev = text; queue.push(d); kick(); } },
120
- }).then(() => { done = true; kick(); }).catch(() => { done = true; kick(); });
121
-
122
- while (true) {
123
- if (queue.length) { yield queue.shift(); continue; }
124
- if (done) break;
125
- if (signal && signal.aborted) break;
126
- await new Promise((r) => (wake = r));
127
- }
128
- try { await run; } catch (e) {}
129
- }
130
-
131
- // chat(history, opts) → full string (used by window.HoloQ.generate + light background features)
132
- async function chat(history, o = {}) {
133
- await ensure(o.onProgress);
134
- if (!engine) return "";
135
- const res = await engine.generate(idsFor(history), { maxNew: o.maxTokens || cfg.maxTokens || M.cap || 256, signal: o.signal || null });
136
- return ((res && res.text) || "").trim();
137
- }
138
-
139
- // native-ternary κ-object → no LoRA adapters; skill routing is a no-op (the base is the specialist).
140
- const setSkill = async () => ({ adapter: false, unsupported: true });
141
- const setAdapter = async () => ({ adapter: false, unsupported: true });
142
-
143
- // Q's LIVE self-knowledge (M0), derived from THIS instance's real model + engine κ — the grounded truth
144
- // every surface leads with so Q is honestly self-aware and never confabulates a cloud identity. Available
145
- // even before load (identity is in M); the κ fills in once the engine is resident.
146
- const facts = () => selfFacts({ model: M, engine });
147
- const persona = () => selfPersona({ model: M, engine });
148
- const intro = () => selfIntro({ model: M, engine });
149
-
150
- return { id: "q-brain-fast-" + (M.fam || M.name), load, generate, chat, setSkill, setAdapter, info: () => info, facts, persona, intro };
151
- }
152
-
153
- export default createFastQBrain;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/schema.js DELETED
@@ -1,85 +0,0 @@
1
- // core/schema.js — lean, dependency-free validators ("zod-lite") for the LibreChat-faithful
2
- // Conversation / Message / Preset shapes. Field names mirror LibreChat's data model (packages/
3
- // data-schemas) so an exported conversation interoperates; values are validated/normalised, not
4
- // hashed (the κ-object store is what makes them content-addressed). No build step, no dep.
5
-
6
- const isStr = (v) => typeof v === "string";
7
- const isBool = (v) => typeof v === "boolean";
8
- const isNum = (v) => typeof v === "number" && !Number.isNaN(v);
9
- const arr = (v) => (Array.isArray(v) ? v : []);
10
- const clampNum = (v, lo, hi, d) => (isNum(v) ? Math.min(hi, Math.max(lo, v)) : d);
11
-
12
- // A chat message (one node in the parentMessageId tree).
13
- export function normMessage(m = {}) {
14
- return {
15
- messageId: isStr(m.messageId) ? m.messageId : null,
16
- conversationId: isStr(m.conversationId) ? m.conversationId : null,
17
- parentMessageId: isStr(m.parentMessageId) ? m.parentMessageId : null, // tree edge
18
- sender: isStr(m.sender) ? m.sender : (m.isCreatedByUser ? "User" : "Assistant"),
19
- isCreatedByUser: isBool(m.isCreatedByUser) ? m.isCreatedByUser : false,
20
- model: isStr(m.model) ? m.model : null,
21
- text: isStr(m.text) ? m.text : "",
22
- content: arr(m.content), // structured parts (text/tool/image/reasoning)
23
- tokenCount: isNum(m.tokenCount) ? m.tokenCount : null,
24
- error: m.error || null,
25
- unfinished: !!m.unfinished,
26
- feedback: m.feedback && isStr(m.feedback.rating || "") ? { rating: m.feedback.rating, tag: m.feedback.tag || null, text: m.feedback.text || "" } : (m.feedback || null),
27
- files: arr(m.files),
28
- createdAt: isStr(m.createdAt) ? m.createdAt : null,
29
- receiptKappa: isStr(m.receiptKappa) ? m.receiptKappa : null, // links the PROV-O inference receipt
30
- };
31
- }
32
-
33
- // A conversation (spreads the active preset, like LibreChat's conversationPreset).
34
- export function normConversation(c = {}) {
35
- return {
36
- conversationId: isStr(c.conversationId) ? c.conversationId : null,
37
- title: isStr(c.title) ? c.title : "New Chat",
38
- tags: arr(c.tags),
39
- files: arr(c.files),
40
- folder: isStr(c.folder) ? c.folder : null,
41
- archived: !!c.archived,
42
- favorite: !!c.favorite,
43
- isTemporary: !!c.isTemporary,
44
- preset: c.preset ? normPreset(c.preset) : null,
45
- createdAt: isStr(c.createdAt) ? c.createdAt : null,
46
- updatedAt: isStr(c.updatedAt) ? c.updatedAt : null,
47
- };
48
- }
49
-
50
- // A preset / parameter bundle. Bounds mirror common LLM ranges; model is the local κ-object id.
51
- export function normPreset(p = {}) {
52
- return {
53
- presetId: isStr(p.presetId) ? p.presetId : null,
54
- title: isStr(p.title) ? p.title : "Preset",
55
- model: isStr(p.model) ? p.model : null,
56
- temperature: clampNum(p.temperature, 0, 2, 0),
57
- top_p: clampNum(p.top_p, 0, 1, 1),
58
- top_k: clampNum(p.top_k, 0, 200, 40),
59
- maxOutputTokens: clampNum(p.maxOutputTokens, 1, 8192, 1024),
60
- promptPrefix: isStr(p.promptPrefix) ? p.promptPrefix : "",
61
- presence_penalty: clampNum(p.presence_penalty, -2, 2, 0),
62
- frequency_penalty: clampNum(p.frequency_penalty, -2, 2, 0),
63
- stop: arr(p.stop),
64
- iconURL: isStr(p.iconURL) ? p.iconURL : null,
65
- isArchived: !!p.isArchived,
66
- };
67
- }
68
-
69
- // Walk a flat message list into the LibreChat parentMessageId tree → {roots, byId, childrenOf}.
70
- export function buildTree(messages) {
71
- const byId = new Map(); const childrenOf = new Map(); const roots = [];
72
- for (const m of messages) { byId.set(m.messageId, m); childrenOf.set(m.messageId, []); }
73
- for (const m of messages) {
74
- if (m.parentMessageId && childrenOf.has(m.parentMessageId)) childrenOf.get(m.parentMessageId).push(m.messageId);
75
- else roots.push(m.messageId);
76
- }
77
- return { roots, byId, childrenOf };
78
- }
79
-
80
- // The active thread = follow the chosen child at each branch from a root to a leaf.
81
- export function threadOf(tree, { choose = (siblings) => siblings[siblings.length - 1] } = {}) {
82
- const out = []; let cur = tree.roots.length ? choose(tree.roots) : null;
83
- while (cur) { out.push(tree.byId.get(cur)); const kids = tree.childrenOf.get(cur) || []; cur = kids.length ? choose(kids) : null; }
84
- return out;
85
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/semantic-witness.mjs DELETED
@@ -1,33 +0,0 @@
1
- // core/semantic-witness.mjs — the W3C SEMANTIC-TYPING gate (C2, extended to all κ-objects).
2
- // Proves EVERY substrate object kind yields a node that is simultaneously: content-addressed (Law L1,
3
- // @id = did:holo), schema.org-typed (WHAT it is), and PROV-O-bearing (HOW it came to be) — i.e. legible
4
- // to any W3C JSON-LD/RDF tool. Pure + node-runnable: `node core/semantic-witness.mjs`. Exit 1 on any fail.
5
-
6
- import { linkedDataFor, skillAsHowTo, fileAsDocument, appAsSoftware, modelAsSource, asLinkedData, verifySemantic, HOLO_CONTEXT } from "./semantic.js";
7
-
8
- const K = (h) => "did:holo:sha256:" + h.padEnd(64, "0").slice(0, 64);
9
- const cases = [
10
- { kind: "skill", node: skillAsHowTo({ name: "Format JSON", description: "When asked to pretty-print JSON", instructions: "1. Parse the text\n2. Re-serialize with 2-space indent", kappa: K("a1"), prov: [{ v: 1, kappa: K("a0") }, { v: 2, kappa: K("a1") }] }), want: "schema:HowTo" },
11
- { kind: "file", node: fileAsDocument({ path: "/src/main.py", kappa: K("b1"), bytes: 412 }), want: "schema:DigitalDocument" },
12
- { kind: "app", node: appAsSoftware({ name: "counter.html", kappa: K("c1"), bytes: 980 }), want: "schema:SoftwareApplication" },
13
- { kind: "model", node: modelAsSource({ name: "BitNet-2B-4T", family: "BitNet", params: "0.69 GB", format: "t2 1.58-bit κ", kappa: K("19e16e6d") }), want: "schema:SoftwareSourceCode" },
14
- { kind: "conversation", node: linkedDataFor("conversation", { kappa: K("d1"), props: { "schema:name": "chat #1" } }), want: "schema:Conversation" },
15
- { kind: "receipt", node: asLinkedData({ kind: "receipt", kappa: K("e1"), props: { "schema:name": "tool-call receipt" } }), want: "schema:CreativeWork" },
16
- ];
17
-
18
- let pass = 0;
19
- console.log("W3C semantic-typing gate — every κ-object is schema.org-typed + PROV-O + content-addressed\n");
20
- for (const c of cases) {
21
- const v = verifySemantic(c.node);
22
- const types = [].concat(c.node["@type"]);
23
- const hasWant = types.includes(c.want);
24
- const ctxOk = c.node["@context"] === HOLO_CONTEXT || !!c.node["@context"];
25
- // JSON round-trip must be lossless (it's just data)
26
- let rt = false; try { rt = JSON.stringify(JSON.parse(JSON.stringify(c.node))) === JSON.stringify(c.node); } catch {}
27
- const ok = v.ok && hasWant && ctxOk && rt;
28
- if (ok) pass++;
29
- console.log(`${ok ? "✓" : "✗"} ${c.kind.padEnd(13)} @id=${String(c.node["@id"]).slice(0, 24)}… @type=[${types.join(", ")}] schema:${v.hasSchema?"y":"n"} prov:${v.hasProv?"y":"n"} id:${v.hasId?"y":"n"} ctx:${ctxOk?"y":"n"} rt:${rt?"y":"n"}`);
30
- }
31
- const all = pass === cases.length;
32
- console.log(`\n${all ? "PASS" : "FAIL"} — ${pass}/${cases.length} κ-object kinds carry a valid W3C @type`);
33
- process.exit(all ? 0 : 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/skills.js DELETED
@@ -1,92 +0,0 @@
1
- // core/skills.js — SELF-EVOLVING AGENT SKILLS, 100% agentskills.io-compatible, enhanced by the UOR
2
- // substrate. A skill is a folder with SKILL.md (name + description frontmatter + instructions) —
3
- // the open Anthropic/agentskills.io format, portable to any skills-compatible agent. The Hermes
4
- // idea (the agent autonomously CREATES and IMPROVES skills from experience) is realized as the
5
- // agent's own tools. The substrate enhancement: every skill version is content-addressed (κ) and
6
- // chained — a tamper-proof PROVENANCE of how the skill evolved (Holo Prov). Skills live in OPFS
7
- // "/skills/<name>/SKILL.md"; the chain log in "/skills/<name>/.prov" (one κ per version).
8
- //
9
- // Progressive disclosure (the spec): DISCOVERY (names+descriptions injected at session start) →
10
- // ACTIVATION (read_skill loads full SKILL.md) → EXECUTION (the agent follows it, using file tools).
11
-
12
- import { skillAsHowTo, verifySemantic } from "./semantic.js";
13
-
14
- const te = new TextEncoder(), td = new TextDecoder();
15
- const sha = async (s) => "did:holo:sha256:" + [...new Uint8Array(await crypto.subtle.digest("SHA-256", te.encode(s)))].map((b) => b.toString(16).padStart(2, "0")).join("");
16
- const slug = (s) => String(s || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48) || "skill";
17
-
18
- async function skillsRoot() { const d = await navigator.storage.getDirectory(); const a = await d.getDirectoryHandle("skills", { create: true }); return a; }
19
- async function skillDir(name, create = false) { return (await skillsRoot()).getDirectoryHandle(slug(name), { create }); }
20
- async function readText(dir, file) { const fh = await dir.getFileHandle(file); return td.decode(await (await fh.getFile()).arrayBuffer()); }
21
- async function writeText(dir, file, text) { const fh = await dir.getFileHandle(file, { create: true }); const w = await fh.createWritable(); await w.write(te.encode(text)); await w.close(); }
22
-
23
- // SKILL.md = YAML-ish frontmatter (name, description) + markdown instructions (verbatim spec form).
24
- function buildSkillMd({ name, description, instructions }) {
25
- return `---\nname: ${name}\ndescription: ${description}\n---\n\n${instructions || ""}\n`;
26
- }
27
- function parseSkillMd(text) {
28
- const m = text.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/);
29
- const meta = {}; if (m) for (const line of m[1].split("\n")) { const i = line.indexOf(":"); if (i > 0) meta[line.slice(0, i).trim()] = line.slice(i + 1).trim(); }
30
- return { name: meta.name || "", description: meta.description || "", instructions: m ? m[2].trim() : text.trim() };
31
- }
32
-
33
- export async function listSkills() {
34
- const out = [];
35
- try { const root = await skillsRoot();
36
- for await (const [n, h] of root.entries()) { if (h.kind !== "directory") continue;
37
- try { const sk = parseSkillMd(await readText(h, "SKILL.md")); out.push({ slug: n, name: sk.name || n, description: sk.description }); } catch {} } }
38
- catch {}
39
- return out.sort((a, b) => a.name.localeCompare(b.name));
40
- }
41
-
42
- export async function readSkill(name) { const dir = await skillDir(name); return parseSkillMd(await readText(dir, "SKILL.md")); }
43
-
44
- // save = create OR improve (self-evolution). Appends a κ to the provenance chain — every version
45
- // sealed + chained to its parent, so the skill's evolution is verifiable (Holo Prov shape).
46
- export async function saveSkill({ name, description, instructions }) {
47
- const dir = await skillDir(name, true);
48
- const md = buildSkillMd({ name, description, instructions });
49
- const kappa = await sha(md);
50
- let prov = []; try { prov = JSON.parse(await readText(dir, ".prov")); } catch {}
51
- const parent = prov.length ? prov[prov.length - 1].kappa : null;
52
- prov.push({ v: prov.length + 1, kappa, parent, descKappa: await sha(description || "") });
53
- await writeText(dir, "SKILL.md", md);
54
- await writeText(dir, ".prov", JSON.stringify(prov, null, 1));
55
- // semantic skin (C2): emit the W3C linked-data view — schema:HowTo + PROV-O revision chain.
56
- const ld = skillAsHowTo({ name, description, instructions, kappa, prov });
57
- await writeText(dir, "skill.jsonld", JSON.stringify(ld, null, 1));
58
- return { slug: slug(name), kappa, version: prov.length, parent, semantic: verifySemantic(ld).ok };
59
- }
60
-
61
- // the W3C linked-data view of a skill (schema:HowTo + PROV-O), for export / validation / agents.
62
- export async function skillLinkedData(name) { try { return JSON.parse(await readText(await skillDir(name), "skill.jsonld")); } catch { return null; } }
63
-
64
- export async function skillProvenance(name) { try { return JSON.parse(await readText(await skillDir(name), ".prov")); } catch { return []; } }
65
-
66
- // DISCOVERY block (progressive disclosure stage 1): names + descriptions only — small footprint.
67
- export async function skillsDiscoveryPrompt() {
68
- const sk = await listSkills();
69
- if (!sk.length) return "";
70
- return "You have these learned SKILLS available (each a verifiable, content-addressed capability you built from experience). " +
71
- "When a task matches a skill's description, call read_skill to load its full instructions, then follow them. " +
72
- "When you complete a non-trivial task worth reusing, call save_skill to capture it (or improve an existing one):\n" +
73
- sk.map((s) => `- ${s.name}: ${s.description}`).join("\n");
74
- }
75
-
76
- // the agent's skill tools (Hermes self-evolution: the agent creates/improves/uses skills itself)
77
- export function skillTools() {
78
- return [
79
- {
80
- def: { name: "list_skills", description: "List the learned skills available (name + description).", inputSchema: { type: "object", properties: {}, required: [] } },
81
- serverName: "skills", call: async () => { const s = await listSkills(); return { text: s.length ? s.map((x) => `${x.name}: ${x.description}`).join("\n") : "(no skills yet)", isError: false }; },
82
- },
83
- {
84
- def: { name: "read_skill", description: "Load a skill's full instructions by name, to follow them for the current task.", inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] } },
85
- serverName: "skills", call: async ({ name }) => { try { const s = await readSkill(name); return { text: `# ${s.name}\n${s.description}\n\n${s.instructions}`, isError: false }; } catch (e) { return { text: "no such skill: " + name, isError: true }; } },
86
- },
87
- {
88
- def: { name: "save_skill", description: "Capture a reusable skill from what you just did (or improve an existing one). name: short; description: one line of WHEN to use it; instructions: the step-by-step procedure. Each save is sealed + chained (verifiable provenance).", inputSchema: { type: "object", properties: { name: { type: "string" }, description: { type: "string" }, instructions: { type: "string" } }, required: ["name", "description", "instructions"] } },
89
- serverName: "skills", call: async ({ name, description, instructions }) => { try { const r = await saveSkill({ name, description, instructions }); return { text: `skill "${name}" saved (v${r.version}, ${r.kappa.slice(0, 28)}…${r.parent ? `, evolved from ${r.parent.slice(0, 20)}…` : ", first version"})`, isError: false }; } catch (e) { return { text: "save error: " + (e.message || e), isError: true }; } },
90
- },
91
- ];
92
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/state.js DELETED
@@ -1,39 +0,0 @@
1
- // core/state.js — a tiny event bus + the app's shared mutable state. No framework: modules
2
- // subscribe to named events and re-render their own DOM islands. Deliberately minimal — the
3
- // durable truth lives in the κ-object store (Law L3); this is only the session's working set.
4
-
5
- export function makeBus() {
6
- const subs = new Map();
7
- return {
8
- on(ev, fn) { if (!subs.has(ev)) subs.set(ev, new Set()); subs.get(ev).add(fn); return () => subs.get(ev)?.delete(fn); },
9
- emit(ev, data) { for (const fn of subs.get(ev) || []) { try { fn(data); } catch (e) { console.error(`[bus:${ev}]`, e); } } },
10
- };
11
- }
12
-
13
- export function makeState() {
14
- return {
15
- // model / engine
16
- engine: null, // core/engine.js instance (null until a model loads)
17
- modelIndex: 0, // index into loader.MODELS
18
- loading: false,
19
- gateOk: false, // conscience constitution self-verify
20
-
21
- // conversation working set
22
- convId: null, // active conversation id
23
- convKappa: null, // its latest sealed κ
24
- title: "New Chat",
25
- messages: [], // [{ obj (sealed κ-object), id, kappa, ...norm fields, tokenIds }]
26
- chosenChild: new Map(), // parent messageId → chosen child messageId (sibling switch)
27
- streaming: false,
28
- abort: null, // AbortController while generating
29
-
30
- // ui
31
- navOpen: window.innerWidth > 900,
32
- panelOpen: false, // the chat is the product — the panel opens on demand
33
- panelTab: "params",
34
- settingsOpen: false,
35
-
36
- // preset (the active parameter bundle — LibreChat conversationPreset semantics)
37
- preset: null,
38
- };
39
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/store.js DELETED
@@ -1,185 +0,0 @@
1
- // core/store.js — the κ-object CONVERSATION STORE. Conversations are NOT database rows; each
2
- // Message and each Conversation is a self-verifying UOR object (a canonical JSON-LD document whose
3
- // identity is did:holo:sha256 of its own content), and the LibreChat parentMessageId tree is
4
- // expressed as content-addressed LINKS so a child's κ commits to its parent's κ — a Merkle-DAG
5
- // (Law L3 dedup, Law L5 verify-on-resolve). The object envelope mirrors _shared/holo-object.mjs
6
- // byte-for-byte (same UOR_CONTEXT, same address() = H(canonical without id), same link digests),
7
- // but is implemented here over Web Crypto (core/kappa.js) so it runs in the browser AND in the
8
- // pure-Node witness. Bytes are persisted through a pluggable BACKEND: holo-kstore (IndexedDB) in
9
- // the app, a Map in the witness. No server; everything is content-addressed and re-derivable.
10
-
11
- import { jcs, sha256hex, didHolo } from "./kappa.js";
12
-
13
- const _enc = new TextEncoder();
14
- const _dec = new TextDecoder();
15
-
16
- // The base envelope @context — identical to _shared/holo-object.mjs.
17
- export const UOR_CONTEXT = [
18
- "https://www.w3.org/ns/did/v1",
19
- "https://w3id.org/security/data-integrity/v2",
20
- { schema: "https://schema.org/", prov: "http://www.w3.org/ns/prov#", dcterms: "http://purl.org/dc/terms/",
21
- rel: "schema:additionalType", links: { "@id": "schema:hasPart", "@container": "@set" } },
22
- ];
23
-
24
- const hexOf = (did) => String(did).split(":").pop();
25
- const _b64 = (u8) => { let s = ""; for (let i = 0; i < u8.length; i++) s += String.fromCharCode(u8[i]); return btoa(s); };
26
- const _b64url = (u8) => _b64(u8).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
27
- async function sha256raw(u8) { return new Uint8Array(await crypto.subtle.digest("SHA-256", u8)); }
28
- async function sriOf(u8) { return "sha256-" + _b64(await sha256raw(u8)); }
29
- async function mbOf(u8) { const d = await sha256raw(u8); const mh = new Uint8Array(d.length + 2); mh[0] = 0x12; mh[1] = 0x20; mh.set(d, 2); return "u" + _b64url(mh); }
30
-
31
- // address(obj): self-verifying identity = did:holo:sha256:H(canonical content with id/alsoKnownAs removed).
32
- const stripId = (obj) => { const { id, alsoKnownAs, ...content } = obj; return content; };
33
- const addressOf = (obj) => didHolo(stripId(obj));
34
- const canonStored = (sealed) => _enc.encode(jcs(sealed)); // the EXACT bytes a link's digest commits to (sealed, WITH id — mirrors holo-object put())
35
-
36
- // contentLink(rel, kappa): a LEAF edge to raw content already addressed by its κ (no bytes needed) —
37
- // identical to holo-object.contentLink. Verified at resolve by re-hashing the raw bytes to the address.
38
- export function contentLink(rel, kappa, type = "schema:MediaObject") {
39
- const hex = String(kappa).split(":").pop();
40
- const digest = Uint8Array.from(hex.match(/.{2}/g).map((h) => parseInt(h, 16)));
41
- const mh = new Uint8Array(digest.length + 2); mh[0] = 0x12; mh[1] = 0x20; mh.set(digest, 2);
42
- return { id: `did:holo:sha256:${hex}`, rel, "@type": type, leaf: true, digestSRI: "sha256-" + _b64(digest), digestMultibase: "u" + _b64url(mh) };
43
- }
44
-
45
- // makeStore(backend) — backend = { get(hex)→Promise<Uint8Array|undefined>, put(hex,bytes)→Promise,
46
- // putRaw?(key,bytes)/getRaw?(key) for the boot-index pointer record }.
47
- export function makeStore(backend) {
48
- const mem = new Map(); // hex → Uint8Array (session cache; sync verifyDeep operates over it)
49
-
50
- async function putObj(obj) {
51
- const sealed = { ...obj, id: await addressOf(obj) };
52
- const bytes = canonStored(sealed);
53
- const hex = hexOf(sealed.id);
54
- mem.set(hex, bytes);
55
- await backend.put(hex, bytes);
56
- return sealed;
57
- }
58
- async function getBytes(did) { const hex = hexOf(did); let b = mem.get(hex); if (b) return b; b = await backend.get(hex); if (b) mem.set(hex, b); return b; }
59
- async function getObj(did) { const b = await getBytes(did); return b ? JSON.parse(_dec.decode(b)) : null; }
60
-
61
- // a typed Merkle edge to a sealed UOR child (the digest commits to the child's stored bytes).
62
- async function uorLink(rel, child) {
63
- const bytes = mem.get(hexOf(child.id)) || await backend.get(hexOf(child.id));
64
- return { id: child.id, rel, "@type": child["@type"], digestSRI: await sriOf(bytes), digestMultibase: await mbOf(bytes) };
65
- }
66
-
67
- // build + seal + store a UOR object. `links` already built (children stored first → Merkle).
68
- async function makeObject({ type, context = [], links = [], ...props }) {
69
- const obj = { "@context": [...UOR_CONTEXT, ...context], "@type": type, ...props, ...(links.length ? { links } : {}) };
70
- return putObj(obj);
71
- }
72
-
73
- const verify = async (obj) => obj.id === await addressOf(obj);
74
-
75
- // verifyDeep — re-derive + verify the WHOLE DAG (Law L5 at every level). Pre-loads links into mem.
76
- async function verifyDeep(obj, depth = 0) {
77
- if (!(await verify(obj))) return { ok: false, at: obj.id, why: "id does not re-derive", depth };
78
- let maxDepth = depth;
79
- for (const link of obj.links || []) {
80
- const bytes = await getBytes(link.id);
81
- if (!bytes) return { ok: false, at: link.id, why: "unresolved link", depth };
82
- if ((await sriOf(bytes)) !== link.digestSRI) return { ok: false, at: link.id, why: "link digest mismatch", depth };
83
- if (link.leaf) { if ((await sha256hex(bytes)) !== hexOf(link.id)) return { ok: false, at: link.id, why: "content hash mismatch", depth }; maxDepth = Math.max(maxDepth, depth + 1); continue; }
84
- const child = JSON.parse(_dec.decode(bytes));
85
- if (child.id !== link.id) return { ok: false, at: link.id, why: "id/link mismatch", depth };
86
- const r = await verifyDeep(child, depth + 1); if (!r.ok) return r; maxDepth = Math.max(maxDepth, r.depth);
87
- }
88
- return { ok: true, depth: maxDepth };
89
- }
90
-
91
- // tamper helper (for the witness): overwrite a stored object's bytes with a flipped field.
92
- async function _corrupt(did, mutate) { const o = await getObj(did); mutate(o); const bytes = canonStored(o); mem.set(hexOf(did), bytes); await backend.put(hexOf(did), bytes); }
93
-
94
- return { makeObject, putObj, getObj, getBytes, uorLink, contentLink, verify, verifyDeep, mem, backend, _corrupt };
95
- }
96
-
97
- // ── high-level chat API over a κ-object store ───────────────────────────────────────────────
98
- // LibreChat-faithful field names. parentMessageId → an "lc:parentMessage" content-addressed link.
99
- const LC = { lc: "https://librechat.ai/ns#" };
100
- const rid = (p) => p + "-" + Math.random().toString(36).slice(2, 12); // id is a human handle; substrate identity is the κ
101
-
102
- export function makeChatStore(backend, { now = () => new Date().toISOString() } = {}) {
103
- const S = makeStore(backend);
104
- const INDEX_KEY = "index:org.hologram.HoloQ";
105
- const getIndex = async () => { try { const b = await (backend.getRaw ? backend.getRaw(INDEX_KEY) : backend.get(INDEX_KEY)); return b ? JSON.parse(_dec.decode(b)) : { conversations: [], presets: [] }; } catch { return { conversations: [], presets: [] }; } };
106
- const putIndex = async (idx) => { const b = _enc.encode(JSON.stringify(idx)); return backend.putRaw ? backend.putRaw(INDEX_KEY, b) : backend.put(INDEX_KEY, b); };
107
-
108
- // Persist a PROV-O inference receipt as raw content addressed by its own κ (rec.id = H(jcs(body))),
109
- // so a message's contentLink("lc:receipt", rec.id) leaf-verifies (sha256(stored bytes) === κ).
110
- async function saveReceipt(rec) {
111
- const bytes = _enc.encode(jcs(rec.body));
112
- const hex = String(rec.id).split(":").pop();
113
- S.mem.set(hex, bytes); await backend.put(hex, bytes);
114
- return rec.id;
115
- }
116
-
117
- // Save one message as a κ-object. `parent` (a sealed message object) is a Merkle uorLink — the
118
- // branch tree, so the child's κ commits to the parent's κ. receiptKappa is a leaf content-link.
119
- // tokenIds (the turn's exact token sequence) makes context reconstruction and Law-L5
120
- // re-derivation possible after a cold reload.
121
- async function saveMessage({ messageId, conversationId, sender, isCreatedByUser, model, text, content, tokenCount, tokenIds, error, unfinished, feedback, fromMemo, toolTrace, createdAt, parent, receiptKappa, toolReceiptKappas = [], files = [] }) {
122
- const links = [];
123
- if (parent) links.push({ ...(await S.uorLink("lc:parentMessage", parent)), "schema:name": "parentMessageId" });
124
- if (receiptKappa) links.push({ ...S.contentLink("lc:receipt", receiptKappa, "prov:Activity"), "schema:name": "receipt" });
125
- for (const k of toolReceiptKappas) links.push({ ...S.contentLink("lc:toolReceipt", k, "prov:Activity"), "schema:name": "toolReceipt" });
126
- for (const f of files) links.push({ ...S.contentLink("schema:associatedMedia", f.kappa, "schema:MediaObject"), "schema:name": f.name });
127
- return S.makeObject({
128
- type: ["schema:Message", "prov:Entity"], context: [LC],
129
- "schema:identifier": messageId || rid("msg"), "lc:conversationId": conversationId,
130
- "lc:parentMessageId": (parent && parent["schema:identifier"]) || null, // the human handle of the parent (for export/tree rebuild)
131
- "lc:sender": sender, "lc:isCreatedByUser": !!isCreatedByUser, "lc:model": model || null,
132
- "schema:text": text || "", "lc:content": content || null, "lc:tokenCount": tokenCount ?? null,
133
- "lc:tokenIds": tokenIds || null, "lc:fromMemo": !!fromMemo,
134
- "lc:toolTrace": toolTrace || null,
135
- "lc:error": error || null, "lc:unfinished": !!unfinished, "lc:feedback": feedback || null,
136
- "schema:dateCreated": createdAt || now(),
137
- links,
138
- });
139
- }
140
-
141
- // Save the conversation κ-object → links to the head (active leaf) + branch tips. Re-sealed each turn.
142
- async function saveConversation({ conversationId, title, tags, files, preset, createdAt, headMessage, branchTips = [] }) {
143
- const links = [];
144
- if (headMessage) links.push({ ...(await S.uorLink("lc:head", headMessage)), "schema:name": "head" });
145
- for (const t of branchTips) links.push({ ...(await S.uorLink("lc:branchTip", t)), "schema:name": "tip" });
146
- const conv = await S.makeObject({
147
- type: ["schema:Conversation", "prov:Collection"], context: [LC],
148
- "schema:identifier": conversationId, "schema:name": title || "New Chat",
149
- "lc:tags": tags || [], "lc:files": files || [], "lc:preset": preset || null,
150
- "schema:dateCreated": createdAt || now(), "schema:dateModified": now(),
151
- links,
152
- });
153
- // update the boot index (pointer-only; the conversation itself is verifiable)
154
- const idx = await getIndex();
155
- const ptr = { conversationId, kappa: conv.id, title: conv["schema:name"], updatedAt: conv["schema:dateModified"], archived: false, favorite: false, folder: null };
156
- const i = idx.conversations.findIndex((c) => c.conversationId === conversationId);
157
- if (i >= 0) idx.conversations[i] = { ...idx.conversations[i], ...ptr }; else idx.conversations.unshift(ptr);
158
- await putIndex(idx);
159
- return conv;
160
- }
161
-
162
- async function listConversations() { return (await getIndex()).conversations; }
163
- async function updatePointer(conversationId, patch) { const idx = await getIndex(); const i = idx.conversations.findIndex((c) => c.conversationId === conversationId); if (i >= 0) { idx.conversations[i] = { ...idx.conversations[i], ...patch }; await putIndex(idx); } }
164
- async function loadConversation(conversationId) {
165
- const idx = await getIndex(); const ptr = idx.conversations.find((c) => c.conversationId === conversationId); if (!ptr) return null;
166
- const conv = await S.getObj(ptr.kappa); if (!conv) return null;
167
- const v = await S.verifyDeep(conv);
168
- return { conv, kappa: ptr.kappa, ok: v.ok, integrity: v };
169
- }
170
- const verifyConversation = async (kappa) => { const conv = await S.getObj(kappa); return conv ? S.verifyDeep(conv) : { ok: false, why: "not found" }; };
171
-
172
- return { store: S, saveReceipt, saveMessage, saveConversation, listConversations, loadConversation, verifyConversation, updatePointer, getIndex, newId: rid };
173
- }
174
-
175
- // A simple Map backend (the witness uses this; the app wraps holo-kstore instead).
176
- export function mapBackend() {
177
- const m = new Map();
178
- return {
179
- get: async (hex) => m.get(hex),
180
- put: async (hex, bytes) => { m.set(hex, bytes); },
181
- getRaw: async (k) => m.get(k),
182
- putRaw: async (k, bytes) => { m.set(k, bytes); },
183
- _map: m,
184
- };
185
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/tools.js DELETED
@@ -1,112 +0,0 @@
1
- // core/tools.js — the agentic TOOL-CALLING loop over the local engine + MCP. Qwen2.5's
2
- // native function-calling convention: the system turn declares tools as JSON schemas inside
3
- // a <tools>…</tools> block; the model emits <tool_call>{"name":…,"arguments":…}</tool_call>;
4
- // each result returns as a user-role <tool_response>…</tool_response> turn and generation
5
- // continues — until a turn arrives with no tool call (the final answer) or maxRounds hits.
6
- //
7
- // Substrate-native: EVERY tool call is sealed as its own PROV-O activity (tool ⊕ args ⊕
8
- // result, each by κ) and the per-call receipts ride the answer's receipt — a verifiable
9
- // work-trail for agentic answers, the chat-layer analogue of Holo Orchestrate (ADR-045).
10
-
11
- import { didHolo, kappaText, jcs } from "./kappa.js";
12
-
13
- // The system turn that arms the model with tools (Qwen2.5 function-calling convention).
14
- export function toolSystemPrompt(tools, extra = "") {
15
- const decls = tools.map((t) => JSON.stringify({ type: "function", function: { name: t.name, description: t.description || "", parameters: t.inputSchema || { type: "object", properties: {} } } })).join("\n");
16
- return (
17
- (extra ? extra + "\n\n" : "") +
18
- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\n" +
19
- "You are provided with function signatures within <tools></tools> XML tags:\n<tools>\n" + decls + "\n</tools>\n\n" +
20
- "For each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n" +
21
- '<tool_call>\n{"name": <function-name>, "arguments": <args-json-object>}\n</tool_call>'
22
- );
23
- }
24
-
25
- // Parse <tool_call> blocks out of a model turn. Tolerant: bare JSON with name+arguments
26
- // also counts (small models sometimes drop the tags).
27
- export function parseToolCalls(text) {
28
- const calls = [];
29
- const re = /<tool_call>\s*([\s\S]*?)\s*<\/tool_call>/g;
30
- let m;
31
- while ((m = re.exec(text))) { try { const j = JSON.parse(m[1]); if (j && j.name) calls.push({ name: j.name, arguments: j.arguments || {} }); } catch {} }
32
- // ```json fenced code blocks with {name, arguments} (Qwen2.5-Coder often emits this form)
33
- if (!calls.length) {
34
- const cb = /```(?:json|tool_call)?\s*(\{[\s\S]*?\})\s*```/g;
35
- while ((m = cb.exec(text))) { try { const j = JSON.parse(m[1]); if (j && j.name && ("arguments" in j)) calls.push({ name: j.name, arguments: j.arguments || {} }); } catch {} }
36
- }
37
- if (!calls.length) {
38
- const t = text.trim();
39
- if (t.startsWith("{") && t.includes('"name"')) { try { const j = JSON.parse(t); if (j.name && ("arguments" in j)) calls.push({ name: j.name, arguments: j.arguments || {} }); } catch {} }
40
- }
41
- return calls;
42
- }
43
-
44
- export const stripToolCalls = (text) => text
45
- .replace(/<tool_call>[\s\S]*?<\/tool_call>/g, "")
46
- .replace(/```(?:json|tool_call)?\s*\{[\s\S]*?"name"[\s\S]*?\}\s*```/g, "") // strip fenced tool calls too
47
- .trim();
48
-
49
- // Seal one tool call as a PROV-O activity (its own did:holo — tamper → refuse).
50
- export async function sealToolReceipt({ server, tool, args, resultText, ok }) {
51
- const body = {
52
- "@context": ["http://www.w3.org/ns/prov#", { holo: "https://hologram.os/ns/q#" }],
53
- "@type": "prov:Activity", "holo:kind": "tool-call",
54
- "prov:used": { "holo:server": server, "holo:tool": tool, "holo:args": await didHolo(JSON.parse(jcs(args || {}))), "holo:argsJson": jcs(args || {}) },
55
- "prov:generated": { "holo:result": await kappaText(resultText), "holo:ok": !!ok },
56
- };
57
- return { id: await didHolo(body), body };
58
- }
59
-
60
- // Frame the agentic first turn: system(tools) + user prompt (ChatML, by hand so the system
61
- // block rides this turn). Exposed so the caller can persist the EXACT ids that run (the
62
- // ctx-concat invariant of the message tree).
63
- export function frameAgenticTurn({ tools, promptText, hasHistory, extraSystem = "" }) {
64
- const sys = toolSystemPrompt(tools.map((t) => t.def), extraSystem);
65
- return (hasHistory ? "<|im_end|>\n" : "") +
66
- `<|im_start|>system\n${sys}<|im_end|>\n<|im_start|>user\n${promptText}<|im_end|>\n<|im_start|>assistant\n`;
67
- }
68
-
69
- // The loop. `callbacks.onToolCall({name,args})` / `onToolResult({name,text,receipt})` let the
70
- // UI stream the work-trail live. Returns { text, rounds, toolReceipts, trace, ids }.
71
- export async function runToolLoop({ engine, tools, promptText, ctxIds, firstFramed, signal, onToken, onToolCall, onToolResult, maxRounds = 4 }) {
72
- const toolReceipts = []; const trace = [];
73
- let framed = firstFramed || frameAgenticTurn({ tools, promptText, hasHistory: ctxIds.length > 0 });
74
- let ids = ctxIds.slice();
75
- let finalText = "", rounds = 0;
76
-
77
- for (; rounds < maxRounds; rounds++) {
78
- const turnIds = engine.tokenize(framed);
79
- ids = ids.concat(turnIds);
80
- // tight per-round budget: a tool_call is ~50 tokens, a final answer ~300 — snappy rounds,
81
- // the same total work, far lower latency than letting one round run the whole cap.
82
- // generous budget: tool calls that carry CODE (write_file, build_app) need room — a truncated
83
- // call is invalid JSON and silently fails. 1536 fits a small app; plain rounds end early on EOS.
84
- const res = await engine.generate(ids, { signal, onToken, maxNew: 1536 });
85
- ids = res.ids;
86
- const calls = parseToolCalls(res.text);
87
- if (!calls.length || (signal && signal.aborted)) { finalText = stripToolCalls(res.text); break; }
88
-
89
- // execute every call this round through MCP, seal a receipt each
90
- const responses = [];
91
- for (const c of calls) {
92
- if (signal && signal.aborted) break;
93
- const t = tools.find((x) => x.def.name === c.name);
94
- onToolCall && onToolCall({ name: c.name, args: c.arguments, server: t ? t.serverName : "?" });
95
- let text, ok = true, render = null;
96
- try {
97
- if (!t) throw new Error("unknown tool: " + c.name);
98
- const r = await t.call(c.arguments);
99
- text = r.text; ok = !r.isError; render = r.render || null; // build_app → live preview payload
100
- } catch (e) { text = "ERROR: " + (e && e.message || e); ok = false; }
101
- const receipt = await sealToolReceipt({ server: t ? t.serverName : "?", tool: c.name, args: c.arguments, resultText: text, ok });
102
- toolReceipts.push(receipt);
103
- trace.push({ name: c.name, args: c.arguments, text: text.slice(0, 4000), ok, receiptId: receipt.id, server: t ? t.serverName : "?" });
104
- onToolResult && onToolResult({ name: c.name, text, ok, receipt, render });
105
- responses.push(`<tool_response>\n${text.slice(0, 2400)}\n</tool_response>`); // bounded — tool output must fit the local context window
106
- }
107
- // feed results back (user role per the Qwen convention) and continue
108
- framed = `<|im_end|>\n<|im_start|>user\n${responses.join("\n")}<|im_end|>\n<|im_start|>assistant\n`;
109
- finalText = stripToolCalls(res.text); // best-so-far, replaced if a later round answers
110
- }
111
- return { text: finalText, rounds: rounds + 1, toolReceipts, trace, ids };
112
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
gemv-bench.html DELETED
@@ -1,183 +0,0 @@
1
- <!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
2
- <title>Ternary GEMV kernel lab — your GPU</title>
3
- <style>
4
- :root{--bg:#0a0d13;--panel:#111825;--ink:#e8ebf1;--dim:#8b95a7;--ac:#7c5cff;--ok:#48c26c;--no:#f0616d;--warn:#e0a94a;--line:#1e2836}
5
- *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.6 -apple-system,Segoe UI,Roboto,monospace;padding:24px;max-width:820px;margin:0 auto}
6
- h1{font-size:20px;margin:0 0 4px}.sub{color:var(--dim);font-size:13px;margin:0 0 18px}
7
- .card{font-family:ui-monospace,monospace;padding:14px 16px;border:1px solid var(--line);border-radius:10px;background:var(--panel);margin-bottom:12px;word-break:break-word}
8
- .big{font-size:22px;font-weight:700}.k{color:var(--dim)}
9
- .ok{color:var(--ok)}.no{color:var(--no)}.warn{color:var(--warn)}
10
- table{width:100%;border-collapse:collapse;font-family:ui-monospace,monospace;font-size:13px}
11
- td,th{padding:6px 8px;border-bottom:1px solid var(--line);text-align:left}th{color:var(--dim);font-weight:600}
12
- td.n{text-align:right;font-variant-numeric:tabular-nums}
13
- .verdict{font-size:16px;font-weight:600;margin-top:14px}
14
- </style></head><body>
15
- <h1>Ternary GEMV <span style="color:var(--ac)">kernel lab</span> — your GPU</h1>
16
- <p class="sub">Runs the batch-1 BitNet decode kernel (weights read once/token) in several variants against a ~0.69&nbsp;GB ternary matrix on your real GPU, and reports the decode rate each reaches vs the 152&nbsp;GB/s roofline (220&nbsp;tok/s).</p>
17
- <div id="status" class="card">starting…</div>
18
- <div id="out"></div>
19
-
20
- <script type="module">
21
- const $=s=>document.querySelector(s), st=$("#status"), out=$("#out");
22
- const MODEL_GB = 0.69, ROOF_TOK = 220, CUR_TOK = 54;
23
- const say=(t,cls)=>{ st.textContent=t; st.className="card"+(cls?" "+cls:""); };
24
- window.addEventListener("unhandledrejection",e=>say("✗ unhandled: "+(e.reason&&(e.reason.message||e.reason)),"no"));
25
-
26
- // ---- kernel body templates (KX=1 decode). Same reduction structure; vary the inner math. ----
27
- // V0: scalar u32 load, per-code f32 convert + (-1) bias (the current engine kernel)
28
- const DOT_V0 = `
29
- fn dot16(word:u32, v:u32) -> f32 {
30
- var s4=vec4<f32>(0.0);
31
- s4=s4+x[v] *(vec4<f32>(f32(word&3u),f32((word>>2u)&3u),f32((word>>4u)&3u),f32((word>>6u)&3u))-vec4<f32>(1.0));
32
- s4=s4+x[v+1u]*(vec4<f32>(f32((word>>8u)&3u),f32((word>>10u)&3u),f32((word>>12u)&3u),f32((word>>14u)&3u))-vec4<f32>(1.0));
33
- s4=s4+x[v+2u]*(vec4<f32>(f32((word>>16u)&3u),f32((word>>18u)&3u),f32((word>>20u)&3u),f32((word>>22u)&3u))-vec4<f32>(1.0));
34
- s4=s4+x[v+3u]*(vec4<f32>(f32((word>>24u)&3u),f32((word>>26u)&3u),f32((word>>28u)&3u),f32((word>>30u)&3u))-vec4<f32>(1.0));
35
- return s4.x+s4.y+s4.z+s4.w;
36
- }`;
37
- const BODY_V0 = `let word=qw[rowW+w]; acc=acc+dot16(word, w<<2u);`;
38
- const LOOP_V0 = { arrQw:"array<u32>", stride:"64u", nwExpr:"nw", asum:false };
39
-
40
- // V1: wide vec4<u32> load (64 codes / 16 bytes per load), same math as V0
41
- const BODY_V1 = `let qv=qw[rowW+w]; let v=(w<<2u)<<2u;
42
- acc=acc+dot16(qv.x,v)+dot16(qv.y,v+4u)+dot16(qv.z,v+8u)+dot16(qv.w,v+12u);`;
43
- const LOOP_V1 = { arrQw:"array<vec4<u32>>", stride:"64u", nwExpr:"(nw>>2u)", asum:false };
44
-
45
- // V2: wide load + BIAS FOLD — drop the 16 per-code (-1); subtract sum(activations) once per row
46
- const DOT_V2 = `
47
- fn dot16(word:u32, v:u32) -> f32 {
48
- var s4=vec4<f32>(0.0);
49
- s4=s4+x[v] *vec4<f32>(f32(word&3u),f32((word>>2u)&3u),f32((word>>4u)&3u),f32((word>>6u)&3u));
50
- s4=s4+x[v+1u]*vec4<f32>(f32((word>>8u)&3u),f32((word>>10u)&3u),f32((word>>12u)&3u),f32((word>>14u)&3u));
51
- s4=s4+x[v+2u]*vec4<f32>(f32((word>>16u)&3u),f32((word>>18u)&3u),f32((word>>20u)&3u),f32((word>>22u)&3u));
52
- s4=s4+x[v+3u]*vec4<f32>(f32((word>>24u)&3u),f32((word>>26u)&3u),f32((word>>28u)&3u),f32((word>>30u)&3u));
53
- return s4.x+s4.y+s4.z+s4.w;
54
- }`;
55
- const BODY_V2 = `let qv=qw[rowW+w]; let v=(w<<2u)<<2u;
56
- acc=acc+dot16(qv.x,v)+dot16(qv.y,v+4u)+dot16(qv.z,v+8u)+dot16(qv.w,v+12u);`;
57
- const LOOP_V2 = { arrQw:"array<vec4<u32>>", stride:"64u", nwExpr:"(nw>>2u)", asum:true };
58
-
59
- function kernelWGSL(dot, body, L){
60
- return `
61
- @group(0) @binding(0) var<storage,read> x: array<vec4<f32>>;
62
- @group(0) @binding(1) var<storage,read> qw: ${L.arrQw};
63
- @group(0) @binding(2) var<storage,read_write> o: array<f32>;
64
- @group(0) @binding(3) var<uniform> P: vec4<u32>; // x=K, y=N, z=0, w=asumBits
65
- var<workgroup> red: array<f32, 256>;
66
- ${dot}
67
- @compute @workgroup_size(256)
68
- fn main(@builtin(workgroup_id) wg:vec3<u32>, @builtin(local_invocation_id) lid:vec3<u32>){
69
- let K=P.x; let nw=K>>4u; let rr=lid.x/64u; let t=lid.x%64u;
70
- let n0=(wg.y*65535u+wg.x)*4u+rr; let n=min(n0, P.y-1u);
71
- let rowW=n*${L.nwExpr}; var acc=0.0;
72
- var w=t;
73
- loop{ if(w>=${L.nwExpr}){break;}
74
- ${body}
75
- w=w+${L.stride}; }
76
- ${L.asum? "acc = acc - bitcast<f32>(P.w);" : ""}
77
- red[lid.x]=acc; workgroupBarrier();
78
- var s=32u; loop{ if(s==0u){break;} if(t<s){ red[rr*64u+t]=red[rr*64u+t]+red[rr*64u+t+s]; } workgroupBarrier(); s=s/2u; }
79
- if(t==0u && n0<P.y){ o[n0]=red[rr*64u]; }
80
- }`;
81
- }
82
-
83
- // pseudo-random 2-bit codes fill (non-zero, non-compressible)
84
- const FILL = `
85
- @group(0) @binding(0) var<storage,read_write> d: array<u32>;
86
- @group(0) @binding(1) var<uniform> P: vec4<u32>; // x=#u32, y=stride
87
- @compute @workgroup_size(256)
88
- fn main(@builtin(global_invocation_id) gid:vec3<u32>){
89
- let n=P.x; var i=gid.x;
90
- loop{ if(i>=n){break;} d[i]=(i*2654435761u+1u)^((i<<7u)*40503u); i=i+P.y; }
91
- }`;
92
-
93
- const VARIANTS=[
94
- {id:"V0", name:"V0 baseline (scalar load, per-code −1)", dot:DOT_V0, body:BODY_V0, L:LOOP_V0},
95
- {id:"V1", name:"V1 wide vec4 load", dot:DOT_V0, body:BODY_V1, L:LOOP_V1},
96
- {id:"V2", name:"V2 wide load + bias-fold", dot:DOT_V2, body:BODY_V2, L:LOOP_V2},
97
- ];
98
-
99
- (async()=>{
100
- try{
101
- if(!navigator.gpu){ say("✗ No WebGPU. Open in Chrome/Edge.","no"); return; }
102
- say("requesting adapter…");
103
- let ad=await navigator.gpu.requestAdapter({powerPreference:"high-performance"}); if(!ad) ad=await navigator.gpu.requestAdapter();
104
- if(!ad){ say("✗ no GPU adapter.","no"); return; }
105
- const L=ad.limits, info=ad.info||{};
106
- const dev=await ad.requestDevice({requiredLimits:{
107
- maxStorageBufferBindingSize:L.maxStorageBufferBindingSize, maxBufferSize:L.maxBufferSize,
108
- maxComputeWorkgroupsPerDimension:L.maxComputeWorkgroupsPerDimension }});
109
- dev.lost.then(i=>say("✗ device lost: "+(i&&i.message||i.reason||""),"no"));
110
-
111
- const K=4096, nw=K/16; // 256 words/row
112
- // weight bytes: as close to 0.69 GB as the device allows
113
- const wantBytes=Math.min(L.maxStorageBufferBindingSize, L.maxBufferSize, Math.round(MODEL_GB*1e9));
114
- const N=Math.floor((wantBytes/4)/nw); // whole rows
115
- const qU32=N*nw, wBytes=qU32*4;
116
- say("allocating "+(wBytes/1048576).toFixed(0)+" MB ternary weights ("+N.toLocaleString()+" rows × "+K+")…");
117
-
118
- const qw=dev.createBuffer({size:wBytes, usage:GPUBufferUsage.STORAGE});
119
- const xbuf=dev.createBuffer({size:K*4, usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});
120
- const obuf=dev.createBuffer({size:N*4, usage:GPUBufferUsage.STORAGE});
121
- const P=dev.createBuffer({size:16, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});
122
-
123
- // activations: random f32, and their sum (for V2 bias fold)
124
- const xa=new Float32Array(K); let asum=0; for(let i=0;i<K;i++){ xa[i]=(Math.sin(i*12.9898)*43758.5453)%1; asum+=xa[i]; }
125
- dev.queue.writeBuffer(xbuf,0,xa);
126
- const asumBits=new Uint32Array(new Float32Array([asum]).buffer)[0];
127
- dev.queue.writeBuffer(P,0,new Uint32Array([K, N, 0, asumBits]));
128
-
129
- // fill weights (non-zero) so reads hit real VRAM
130
- say("filling weights…");
131
- { const fmod=dev.createShaderModule({code:FILL});
132
- const fpipe=dev.createComputePipeline({layout:"auto",compute:{module:fmod,entryPoint:"main"}});
133
- const fp=dev.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});
134
- const wgF=Math.min(L.maxComputeWorkgroupsPerDimension,65535);
135
- dev.queue.writeBuffer(fp,0,new Uint32Array([qU32, wgF*256, 0, 0]));
136
- const fbg=dev.createBindGroup({layout:fpipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:qw}},{binding:1,resource:{buffer:fp}}]});
137
- const e=dev.createCommandEncoder(); const p=e.beginComputePass(); p.setPipeline(fpipe); p.setBindGroup(0,fbg); p.dispatchWorkgroups(wgF); p.end();
138
- dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); }
139
-
140
- // dispatch dims: workgroup = 4 rows
141
- const groups=Math.ceil(N/4), wgx=Math.min(groups,65535), wgy=Math.ceil(groups/65535);
142
- const PASSES=8, ITERS=5;
143
-
144
- const rows=[];
145
- for(const V of VARIANTS){
146
- say("compiling "+V.id+"…");
147
- dev.pushErrorScope("validation");
148
- const mod=dev.createShaderModule({code:kernelWGSL(V.dot,V.body,V.L)});
149
- const ci=await mod.getCompilationInfo(); const er=ci.messages.filter(m=>m.type==="error");
150
- if(er.length){ await dev.popErrorScope(); rows.push({V, err:er[0].message}); continue; }
151
- const pipe=dev.createComputePipeline({layout:"auto",compute:{module:mod,entryPoint:"main"}});
152
- const bg=dev.createBindGroup({layout:pipe.getBindGroupLayout(0),entries:[
153
- {binding:0,resource:{buffer:xbuf}},{binding:1,resource:{buffer:qw}},{binding:2,resource:{buffer:obuf}},{binding:3,resource:{buffer:P}}]});
154
- const scopeErr=await dev.popErrorScope();
155
- if(scopeErr){ rows.push({V, err:scopeErr.message}); continue; }
156
- async function run(passes){
157
- const e=dev.createCommandEncoder();
158
- for(let k=0;k<passes;k++){ const p=e.beginComputePass(); p.setPipeline(pipe); p.setBindGroup(0,bg); p.dispatchWorkgroups(wgx,wgy); p.end(); }
159
- const t0=performance.now(); dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); return performance.now()-t0;
160
- }
161
- say("timing "+V.id+"…");
162
- await run(2); // warm
163
- let best=1e9; for(let k=0;k<ITERS;k++){ best=Math.min(best, await run(PASSES)); }
164
- const msPer=best/PASSES, gbps=(wBytes/1073741824)/(msPer/1000), tok=gbps/MODEL_GB, pct=100*tok/ROOF_TOK;
165
- rows.push({V, msPer, gbps, tok, pct});
166
- }
167
-
168
- say("done · adapter: "+((info.vendor||"?")+" "+(info.architecture||"")+" "+(info.device||"")).trim(),"ok");
169
- const best=rows.filter(r=>r.tok).sort((a,b)=>b.tok-a.tok)[0];
170
- out.innerHTML=`
171
- <div class="card"><span class="k">Test matrix</span><br><span class="big">${N.toLocaleString()} × ${K}</span> &nbsp;·&nbsp; ${(wBytes/1073741824).toFixed(2)} GB ternary weights · roofline ${ROOF_TOK} tok/s</div>
172
- <div class="card"><table>
173
- <tr><th>variant</th><th class="n">ms/token</th><th class="n">GB/s</th><th class="n">tok/s</th><th class="n">% roofline</th></tr>
174
- ${rows.map(r=>r.err
175
- ? `<tr><td>${r.V.name}</td><td colspan=4 class="no">compile/validate failed: ${r.err.slice(0,60)}</td></tr>`
176
- : `<tr><td>${r.V.name}</td><td class="n">${r.msPer.toFixed(2)}</td><td class="n">${r.gbps.toFixed(0)}</td><td class="n ${r===best?'ok':''}"><b>${r.tok.toFixed(0)}</b></td><td class="n ${r.pct<30?'no':r.pct<70?'warn':'ok'}">${r.pct.toFixed(0)}%</td></tr>`).join("")}
177
- <tr><td class="k">current shipped kernel (measured)</td><td class="n k">18.4</td><td class="n k">38</td><td class="n k">${CUR_TOK}</td><td class="n k">${(100*CUR_TOK/ROOF_TOK).toFixed(0)}%</td></tr>
178
- </table></div>
179
- ${best? `<div class="verdict ok">✓ Best: <b>${best.V.name}</b> → ${best.tok.toFixed(0)} tok/s (${best.pct.toFixed(0)}% of roofline, ${(best.tok/CUR_TOK).toFixed(1)}× the shipped kernel). ${best.pct>=70? "Bandwidth-bound — ship it." : "Still ALU-bound; next lever = integer dot / fewer converts."}</div>`
180
- : `<div class="verdict no">All variants failed to run.</div>`}`;
181
- }catch(e){ say("✗ "+(e&&(e.message||e)), "no"); }
182
- })();
183
- </script></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
gpu-blake3.mjs DELETED
@@ -1,107 +0,0 @@
1
- // gpu-blake3.mjs — BLAKE3 verification that runs ENTIRELY on the GPU (WGSL). The parallel two-phase kernel
2
- // (phase1: one GPU thread per 1024-byte chunk; phase2: stack tree-merge → root) — PROVEN byte-exact vs the CPU
3
- // oracle (holo-blake3.mjs) and measured at 2.74 GB/s on AMD RDNA-3 (138 MB in 49 ms). Used by holo-load2bit's
4
- // getBlock to re-derive each streamed weight block's κ on the GPU (Law L5) — no CPU hash on the hot path.
5
- // Lazy: the device + pipelines are created once on first use; gpuBlake3Hex throws if WebGPU is absent so the
6
- // caller can fall back to the CPU verifier.
7
- import { getDevice } from "./holo-gpu-device.mjs"; // the ONE shared device (max limits) — never a second one
8
-
9
- const WGSL = `
10
- @group(0) @binding(0) var<storage, read> inp : array<u32>;
11
- @group(0) @binding(1) var<storage, read_write> cvs : array<u32>;
12
- @group(0) @binding(2) var<storage, read_write> outp : array<u32>;
13
- @group(0) @binding(3) var<uniform> P : vec4<u32>;
14
- const IV = array<u32,8>(0x6a09e667u,0xbb67ae85u,0x3c6ef372u,0xa54ff53au,0x510e527fu,0x9b05688cu,0x1f83d9abu,0x5be0cd19u);
15
- fn rotr(x:u32,n:u32)->u32 { return (x>>n)|(x<<(32u-n)); }
16
- fn compress(cv:array<u32,8>, m0:array<u32,16>, cl:u32, ch:u32, bl:u32, fl:u32)->array<u32,16>{
17
- var v:array<u32,16>;
18
- v[0]=cv[0];v[1]=cv[1];v[2]=cv[2];v[3]=cv[3];v[4]=cv[4];v[5]=cv[5];v[6]=cv[6];v[7]=cv[7];
19
- v[8]=IV[0];v[9]=IV[1];v[10]=IV[2];v[11]=IV[3];v[12]=cl;v[13]=ch;v[14]=bl;v[15]=fl;
20
- var m:array<u32,16>=m0;
21
- for(var r:u32=0u;r<7u;r=r+1u){
22
- v[0]=v[0]+v[4]+m[0];v[12]=rotr(v[12]^v[0],16u);v[8]=v[8]+v[12];v[4]=rotr(v[4]^v[8],12u);v[0]=v[0]+v[4]+m[1];v[12]=rotr(v[12]^v[0],8u);v[8]=v[8]+v[12];v[4]=rotr(v[4]^v[8],7u);
23
- v[1]=v[1]+v[5]+m[2];v[13]=rotr(v[13]^v[1],16u);v[9]=v[9]+v[13];v[5]=rotr(v[5]^v[9],12u);v[1]=v[1]+v[5]+m[3];v[13]=rotr(v[13]^v[1],8u);v[9]=v[9]+v[13];v[5]=rotr(v[5]^v[9],7u);
24
- v[2]=v[2]+v[6]+m[4];v[14]=rotr(v[14]^v[2],16u);v[10]=v[10]+v[14];v[6]=rotr(v[6]^v[10],12u);v[2]=v[2]+v[6]+m[5];v[14]=rotr(v[14]^v[2],8u);v[10]=v[10]+v[14];v[6]=rotr(v[6]^v[10],7u);
25
- v[3]=v[3]+v[7]+m[6];v[15]=rotr(v[15]^v[3],16u);v[11]=v[11]+v[15];v[7]=rotr(v[7]^v[11],12u);v[3]=v[3]+v[7]+m[7];v[15]=rotr(v[15]^v[3],8u);v[11]=v[11]+v[15];v[7]=rotr(v[7]^v[11],7u);
26
- v[0]=v[0]+v[5]+m[8];v[15]=rotr(v[15]^v[0],16u);v[10]=v[10]+v[15];v[5]=rotr(v[5]^v[10],12u);v[0]=v[0]+v[5]+m[9];v[15]=rotr(v[15]^v[0],8u);v[10]=v[10]+v[15];v[5]=rotr(v[5]^v[10],7u);
27
- v[1]=v[1]+v[6]+m[10];v[12]=rotr(v[12]^v[1],16u);v[11]=v[11]+v[12];v[6]=rotr(v[6]^v[11],12u);v[1]=v[1]+v[6]+m[11];v[12]=rotr(v[12]^v[1],8u);v[11]=v[11]+v[12];v[6]=rotr(v[6]^v[11],7u);
28
- v[2]=v[2]+v[7]+m[12];v[13]=rotr(v[13]^v[2],16u);v[8]=v[8]+v[13];v[7]=rotr(v[7]^v[8],12u);v[2]=v[2]+v[7]+m[13];v[13]=rotr(v[13]^v[2],8u);v[8]=v[8]+v[13];v[7]=rotr(v[7]^v[8],7u);
29
- v[3]=v[3]+v[4]+m[14];v[14]=rotr(v[14]^v[3],16u);v[9]=v[9]+v[14];v[4]=rotr(v[4]^v[9],12u);v[3]=v[3]+v[4]+m[15];v[14]=rotr(v[14]^v[3],8u);v[9]=v[9]+v[14];v[4]=rotr(v[4]^v[9],7u);
30
- if(r<6u){var perm=array<u32,16>(2u,6u,3u,10u,7u,0u,4u,13u,1u,11u,12u,5u,9u,14u,15u,8u);var p:array<u32,16>;for(var i:u32=0u;i<16u;i=i+1u){p[i]=m[perm[i]];}m=p;}
31
- }
32
- var o:array<u32,16>;for(var i:u32=0u;i<8u;i=i+1u){o[i]=v[i]^v[i+8u];o[i+8u]=v[i+8u]^cv[i];}return o;
33
- }
34
- fn loadBlock(bo:u32)->array<u32,16>{let base=bo>>2u;var m:array<u32,16>;for(var i:u32=0u;i<16u;i=i+1u){m[i]=inp[base+i];}return m;}
35
- fn chunkCV(s:u32,l:u32,ct:u32)->array<u32,8>{var cv:array<u32,8>=IV;let nB=max(1u,(l+63u)/64u);var fl:u32=1u;for(var i:u32=0u;i<nB-1u;i=i+1u){let o=compress(cv,loadBlock(s+i*64u),ct,0u,64u,fl);for(var j:u32=0u;j<8u;j=j+1u){cv[j]=o[j];}fl=0u;}let lo=s+(nB-1u)*64u;let ll=l-(nB-1u)*64u;let o2=compress(cv,loadBlock(lo),ct,0u,ll,fl|2u);var out:array<u32,8>;for(var j:u32=0u;j<8u;j=j+1u){out[j]=o2[j];}return out;}
36
- fn chunkRoot(s:u32,l:u32)->array<u32,8>{var cv:array<u32,8>=IV;let nB=max(1u,(l+63u)/64u);var fl:u32=1u;for(var i:u32=0u;i<nB-1u;i=i+1u){let o=compress(cv,loadBlock(s+i*64u),0u,0u,64u,fl);for(var j:u32=0u;j<8u;j=j+1u){cv[j]=o[j];}fl=0u;}let lo=s+(nB-1u)*64u;let ll=l-(nB-1u)*64u;let o=compress(cv,loadBlock(lo),0u,0u,ll,fl|2u|8u);var out:array<u32,8>;for(var j:u32=0u;j<8u;j=j+1u){out[j]=o[j];}return out;}
37
- fn parentCV(l:array<u32,8>,r:array<u32,8>,root:bool)->array<u32,8>{var m:array<u32,16>;for(var i:u32=0u;i<8u;i=i+1u){m[i]=l[i];m[i+8u]=r[i];}var fl:u32=4u;if(root){fl=12u;}let o=compress(IV,m,0u,0u,64u,fl);var out:array<u32,8>;for(var i:u32=0u;i<8u;i=i+1u){out[i]=o[i];}return out;}
38
- fn getCV(i:u32)->array<u32,8>{var c:array<u32,8>;for(var j:u32=0u;j<8u;j=j+1u){c[j]=cvs[i*8u+j];}return c;}
39
- @compute @workgroup_size(64)
40
- fn phase1(@builtin(global_invocation_id) gid:vec3<u32>){
41
- let i=gid.x; let N=P.y; let len=P.x; if(i>=N){return;}
42
- let off=i*1024u; let ln=min(1024u,len-off);
43
- var cv:array<u32,8>; if(N==1u){cv=chunkRoot(off,ln);}else{cv=chunkCV(off,ln,i);}
44
- for(var j:u32=0u;j<8u;j=j+1u){cvs[i*8u+j]=cv[j];}
45
- }
46
- @compute @workgroup_size(1)
47
- fn phase2(){
48
- let N=P.y; var root:array<u32,8>;
49
- if(N==1u){root=getCV(0u);}
50
- else{
51
- var stack:array<array<u32,8>,54>; var depth:u32=0u;
52
- for(var c:u32=0u;c<N-1u;c=c+1u){var cv=getCV(c);var t=c+1u;loop{if((t&1u)!=0u){break;}depth=depth-1u;cv=parentCV(stack[depth],cv,false);t=t>>1u;}stack[depth]=cv;depth=depth+1u;}
53
- var node=getCV(N-1u);for(var i:u32=0u;i<depth;i=i+1u){let li=depth-1u-i;root=parentCV(stack[li],node,i==depth-1u);node=root;}
54
- }
55
- for(var i:u32=0u;i<8u;i=i+1u){outp[i]=root[i];}
56
- }
57
- `;
58
-
59
- let _dev = null, _p1 = null, _p2 = null, _bgl = null, _initP = null;
60
- async function ensure() {
61
- if (_dev) return true;
62
- if (_initP) return _initP;
63
- _initP = (async () => {
64
- _dev = (await getDevice()).dev; // SHARE the engine's device (max limits) — no second device
65
- const mod = _dev.createShaderModule({ code: WGSL });
66
- const ci = await mod.getCompilationInfo();
67
- const er = ci.messages.filter((m) => m.type === "error");
68
- if (er.length) throw new Error("gpu-blake3 WGSL: " + er[0].message);
69
- _bgl = _dev.createBindGroupLayout({ entries: [
70
- { binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: "read-only-storage" } },
71
- { binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: "storage" } },
72
- { binding: 2, visibility: GPUShaderStage.COMPUTE, buffer: { type: "storage" } },
73
- { binding: 3, visibility: GPUShaderStage.COMPUTE, buffer: { type: "uniform" } }] });
74
- const pll = _dev.createPipelineLayout({ bindGroupLayouts: [_bgl] });
75
- _p1 = _dev.createComputePipeline({ layout: pll, compute: { module: mod, entryPoint: "phase1" } });
76
- _p2 = _dev.createComputePipeline({ layout: pll, compute: { module: mod, entryPoint: "phase2" } });
77
- return true;
78
- })().catch((e) => { _initP = null; throw e; });
79
- return _initP;
80
- }
81
-
82
- // gpuBlake3Hex(bytes) → 64-hex BLAKE3 of `bytes`, computed entirely on the GPU. Throws if WebGPU is unavailable.
83
- export async function gpuBlake3Hex(bytes) {
84
- await ensure();
85
- const dev = _dev;
86
- const len = bytes.length, N = len === 0 ? 1 : Math.ceil(len / 1024);
87
- const padU = Math.max(16, (Math.ceil(len / 64) || 1) * 16);
88
- const u = new Uint32Array(padU); new Uint8Array(u.buffer).set(bytes);
89
- const inB = dev.createBuffer({ size: u.byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST }); dev.queue.writeBuffer(inB, 0, u);
90
- const cvB = dev.createBuffer({ size: Math.max(32, N * 32), usage: GPUBufferUsage.STORAGE });
91
- const oB = dev.createBuffer({ size: 32, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });
92
- const pB = dev.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }); dev.queue.writeBuffer(pB, 0, new Uint32Array([len, N, 0, 0]));
93
- const sg = dev.createBuffer({ size: 32, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ });
94
- const bg = dev.createBindGroup({ layout: _bgl, entries: [{ binding: 0, resource: { buffer: inB } }, { binding: 1, resource: { buffer: cvB } }, { binding: 2, resource: { buffer: oB } }, { binding: 3, resource: { buffer: pB } }] });
95
- const e = dev.createCommandEncoder();
96
- let pass = e.beginComputePass(); pass.setPipeline(_p1); pass.setBindGroup(0, bg); pass.dispatchWorkgroups(Math.ceil(N / 64)); pass.end();
97
- pass = e.beginComputePass(); pass.setPipeline(_p2); pass.setBindGroup(0, bg); pass.dispatchWorkgroups(1); pass.end();
98
- e.copyBufferToBuffer(oB, 0, sg, 0, 32); dev.queue.submit([e.finish()]);
99
- await sg.mapAsync(GPUMapMode.READ);
100
- const w = new Uint32Array(sg.getMappedRange().slice(0)); sg.unmap();
101
- inB.destroy(); cvB.destroy(); oB.destroy(); pB.destroy(); sg.destroy();
102
- let s = "";
103
- for (let i = 0; i < 8; i++) { const x = w[i] >>> 0; s += (x & 255).toString(16).padStart(2, "0") + ((x >>> 8) & 255).toString(16).padStart(2, "0") + ((x >>> 16) & 255).toString(16).padStart(2, "0") + ((x >>> 24) & 255).toString(16).padStart(2, "0"); }
104
- return s;
105
- }
106
- export function gpuBlake3Available() { return typeof navigator !== "undefined" && !!navigator.gpu; }
107
- export default { gpuBlake3Hex, gpuBlake3Available };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
holo-blake3.mjs DELETED
@@ -1,128 +0,0 @@
1
- // holo-blake3.mjs — BLAKE3 (the hologram substrate's σ-axis, ADR-052), pure JS, lean +
2
- // browser-native. This is the convergence seam made real: the substrate addresses content as
3
- // `blake3:<hex>` = standard BLAKE3 of the canonical bytes (proven: its own differential test
4
- // asserts the blake3 axis == the reference `blake3` crate). Reproducing standard BLAKE3 here —
5
- // witnessed byte-identical against the substrate's own `kappa()` wasm across chunk boundaries —
6
- // makes OS2 κ byte-identical to upstream WITHOUT a 6.5 MB wasm or restating substrate internals
7
- // (BLAKE3 is the public standard the substrate itself consumes). Implements the official spec:
8
- // 1024-byte chunks, 64-byte blocks, 7-round compression, binary tree of chaining values.
9
-
10
- const IV = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
11
- const MSG = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
12
- const CHUNK_START = 1, CHUNK_END = 2, PARENT = 4, ROOT = 8, BLOCK = 64, CHUNK = 1024;
13
- const rotr = (x, n) => ((x >>> n) | (x << (32 - n))) >>> 0;
14
-
15
- function g(v, a, b, c, d, mx, my) {
16
- v[a] = (v[a] + v[b] + mx) >>> 0; v[d] = rotr(v[d] ^ v[a], 16);
17
- v[c] = (v[c] + v[d]) >>> 0; v[b] = rotr(v[b] ^ v[c], 12);
18
- v[a] = (v[a] + v[b] + my) >>> 0; v[d] = rotr(v[d] ^ v[a], 8);
19
- v[c] = (v[c] + v[d]) >>> 0; v[b] = rotr(v[b] ^ v[c], 7);
20
- }
21
- function roundFn(v, m) {
22
- g(v, 0, 4, 8, 12, m[0], m[1]); g(v, 1, 5, 9, 13, m[2], m[3]);
23
- g(v, 2, 6, 10, 14, m[4], m[5]); g(v, 3, 7, 11, 15, m[6], m[7]);
24
- g(v, 0, 5, 10, 15, m[8], m[9]); g(v, 1, 6, 11, 12, m[10], m[11]);
25
- g(v, 2, 7, 8, 13, m[12], m[13]); g(v, 3, 4, 9, 14, m[14], m[15]);
26
- }
27
- // compress(cv[8], m[16], counter, blockLen, flags) → out[16]
28
- function compress(cv, m0, counter, blockLen, flags) {
29
- const cl = counter >>> 0, ch = Math.floor(counter / 4294967296) >>> 0;
30
- const v = [cv[0], cv[1], cv[2], cv[3], cv[4], cv[5], cv[6], cv[7],
31
- IV[0], IV[1], IV[2], IV[3], cl, ch, blockLen >>> 0, flags >>> 0];
32
- let m = m0.slice();
33
- for (let r = 0; r < 7; r++) { roundFn(v, m); if (r < 6) { const p = new Array(16); for (let i = 0; i < 16; i++) p[i] = m[MSG[i]]; m = p; } }
34
- const out = new Array(16);
35
- for (let i = 0; i < 8; i++) { out[i] = (v[i] ^ v[i + 8]) >>> 0; out[i + 8] = (v[i + 8] ^ cv[i]) >>> 0; }
36
- return out;
37
- }
38
- // read a 64-byte block (zero-padded) into 16 LE u32 words
39
- function words(bytes, off, len) {
40
- const m = new Array(16).fill(0);
41
- for (let i = 0; i < len; i++) m[i >> 2] |= bytes[off + i] << ((i & 3) * 8);
42
- for (let i = 0; i < 16; i++) m[i] >>>= 0;
43
- return m;
44
- }
45
-
46
- // An "output" node: its chaining value, or (with ROOT) its 32-byte hash.
47
- function nodeChainingValue(o) { return compress(o.cv, o.m, o.counter, o.blockLen, o.flags).slice(0, 8); }
48
- function nodeRootBytes(o) {
49
- const out = compress(o.cv, o.m, 0, o.blockLen, o.flags | ROOT); // output block counter 0 → first 32 bytes
50
- const b = new Uint8Array(32);
51
- for (let i = 0; i < 8; i++) { const w = out[i]; b[i * 4] = w & 255; b[i * 4 + 1] = (w >>> 8) & 255; b[i * 4 + 2] = (w >>> 16) & 255; b[i * 4 + 3] = (w >>> 24) & 255; }
52
- return b;
53
- }
54
-
55
- // One chunk (≤1024 bytes) → its output node (its last block carries CHUNK_END).
56
- function chunkNode(bytes, start, len, counter) {
57
- let cv = IV.slice();
58
- const nBlocks = Math.max(1, Math.ceil(len / BLOCK));
59
- let flags = CHUNK_START;
60
- for (let i = 0; i < nBlocks - 1; i++) { cv = compress(cv, words(bytes, start + i * BLOCK, BLOCK), counter, BLOCK, flags).slice(0, 8); flags = 0; }
61
- const lastOff = start + (nBlocks - 1) * BLOCK;
62
- const lastLen = len - (nBlocks - 1) * BLOCK; // 0..64 (0 only when len==0)
63
- return { cv, m: words(bytes, lastOff, lastLen), counter, blockLen: lastLen, flags: flags | CHUNK_END };
64
- }
65
- function parentNode(leftCV, rightCV) {
66
- const m = leftCV.concat(rightCV);
67
- return { cv: IV.slice(), m, counter: 0, blockLen: BLOCK, flags: PARENT };
68
- }
69
- // Hash a subtree [start, start+len) starting at chunk index `counter` → an output node.
70
- function subtree(bytes, start, len, counter) {
71
- if (len <= CHUNK) return chunkNode(bytes, start, len, counter);
72
- let left = CHUNK; while (left * 2 < len) left *= 2; // largest power-of-two chunk span < len
73
- const leftCV = nodeChainingValue(subtree(bytes, start, left, counter));
74
- const rightCV = nodeChainingValue(subtree(bytes, start + left, len - left, counter + left / CHUNK));
75
- return parentNode(leftCV, rightCV);
76
- }
77
-
78
- export function blake3(bytes) {
79
- const b = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
80
- return nodeRootBytes(subtree(b, 0, b.length, 0));
81
- }
82
- export function blake3hex(bytes) {
83
- const d = blake3(bytes); let s = "";
84
- for (let i = 0; i < 32; i++) s += d[i].toString(16).padStart(2, "0");
85
- return s;
86
- }
87
- // the hologram σ-axis κ-label: "blake3:" + 64 hex (the 71-byte ContentLabel).
88
- export function kappaBlake3(bytes) { return "blake3:" + blake3hex(bytes); }
89
-
90
- // ── tree internals (the σ-axis Merkle structure) ─────────────────────────────────────
91
- // Exposed so holo-bao.mjs can build verified-streaming (Bao) proofs against the SAME ONE
92
- // implementation (Law L2 — no second hash). These are the standard BLAKE3 tree pieces:
93
- // a chunk → output node, two CVs → parent node, a node → its chaining value or ROOT bytes.
94
- export const CHUNK_BYTES = CHUNK;
95
- export { chunkNode, parentNode, nodeChainingValue, nodeRootBytes, subtree };
96
-
97
- // ── incremental hasher (stream-mint without a tail pass) ─────────────────────────────
98
- // BLAKE3's streaming Hasher: feed chunks via update(), get the SAME digest as one-shot blake3() at
99
- // digest()/hex(). Buffers at most ONE 1024-byte chunk; each completed chunk's CV folds into a stack via the
100
- // standard add-chunk-cv merge (collapse while the chunk count is even), and digest() merges the final chunk
101
- // down the stack with the ROOT flag — the canonical left-balanced tree, byte-identical to blake3() across
102
- // chunk boundaries. Lets the streaming seam mint a κ AS bytes arrive instead of re-hashing the whole buffer.
103
- export function createBlake3() {
104
- const stack = []; // CVs of completed left subtrees (bottom = leftmost)
105
- let counter = 0; // index of the current chunk
106
- const buf = new Uint8Array(CHUNK);
107
- let bufLen = 0;
108
- const add = (cv, totalChunks) => { let t = totalChunks, c = cv; while ((t & 1) === 0) { c = nodeChainingValue(parentNode(stack.pop(), c)); t >>= 1; } stack.push(c); };
109
- const api = {
110
- update(bytes) {
111
- const b = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
112
- let off = 0; const n = b.length;
113
- while (off < n) {
114
- if (bufLen === CHUNK) { const cv = nodeChainingValue(chunkNode(buf, 0, CHUNK, counter)); counter++; add(cv, counter); bufLen = 0; }
115
- const take = Math.min(CHUNK - bufLen, n - off);
116
- buf.set(b.subarray(off, off + take), bufLen); bufLen += take; off += take;
117
- }
118
- return api;
119
- },
120
- digest() {
121
- let node = chunkNode(buf, 0, bufLen, counter);
122
- for (let i = stack.length - 1; i >= 0; i--) node = parentNode(stack[i], nodeChainingValue(node));
123
- return nodeRootBytes(node);
124
- },
125
- hex() { const d = api.digest(); let s = ""; for (let i = 0; i < 32; i++) s += d[i].toString(16).padStart(2, "0"); return s; },
126
- };
127
- return api;
128
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
holo-gpu-device.mjs DELETED
@@ -1,27 +0,0 @@
1
- // holo-gpu-device.mjs — ONE WebGPU device for the whole app (the engine, BLAKE3 verify, Bao streaming).
2
- // Memoized: exactly one requestDevice() per page. Created with the ADAPTER'S MAX limits so a 145 MB block
3
- // binds as a storage buffer (the default cap is 128 MB — a separate default-limits device silently produced a
4
- // wrong hash on the embed → κ mismatch → the two-device clash). timestamp-query is requested when available.
5
- // Sharing ONE device is what lets fetch→verify→decode coexist without contending.
6
- let _p = null;
7
- export function getDevice() {
8
- if (_p) return _p;
9
- _p = (async () => {
10
- if (typeof navigator === "undefined" || !navigator.gpu) throw new Error("no WebGPU");
11
- const adapter = await navigator.gpu.requestAdapter();
12
- const L = adapter.limits;
13
- const canTs = adapter.features.has("timestamp-query");
14
- const dev = await adapter.requestDevice({
15
- requiredFeatures: canTs ? ["timestamp-query"] : [],
16
- requiredLimits: {
17
- maxStorageBufferBindingSize: L.maxStorageBufferBindingSize,
18
- maxBufferSize: L.maxBufferSize,
19
- maxComputeWorkgroupsPerDimension: L.maxComputeWorkgroupsPerDimension,
20
- },
21
- });
22
- try { if (typeof globalThis !== "undefined") globalThis.__gpuDeviceCount = (globalThis.__gpuDeviceCount || 0) + 1; } catch (e) {}
23
- return { dev, adapter, canTs };
24
- })().catch((e) => { _p = null; throw e; });
25
- return _p;
26
- }
27
- export default { getDevice };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
kernel-profile.html DELETED
@@ -1,147 +0,0 @@
1
- <!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
2
- <title>Ternary GEMV limiter profile — your GPU</title>
3
- <style>
4
- :root{--bg:#0a0d13;--panel:#111825;--ink:#e8ebf1;--dim:#8b95a7;--ac:#7c5cff;--ok:#48c26c;--no:#f0616d;--warn:#e0a94a;--line:#1e2836}
5
- *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.6 -apple-system,Segoe UI,Roboto,monospace;padding:24px;max-width:860px;margin:0 auto}
6
- h1{font-size:20px;margin:0 0 4px}.sub{color:var(--dim);font-size:13px;margin:0 0 18px}
7
- .card{font-family:ui-monospace,monospace;padding:14px 16px;border:1px solid var(--line);border-radius:10px;background:var(--panel);margin-bottom:12px;word-break:break-word}
8
- table{width:100%;border-collapse:collapse;font-family:ui-monospace,monospace;font-size:13px}
9
- td,th{padding:6px 8px;border-bottom:1px solid var(--line);text-align:left}th{color:var(--dim);font-weight:600}
10
- td.n{text-align:right;font-variant-numeric:tabular-nums}
11
- .verdict{font-size:16px;font-weight:600;margin-top:14px}.bar{display:inline-block;height:9px;background:var(--ac);border-radius:2px;vertical-align:middle}
12
- </style></head><body>
13
- <h1>Ternary GEMV <span style="color:var(--ac)">limiter profile</span> — your GPU</h1>
14
- <p class="sub">Same GEMV access pattern, one knob at a time. <b>read-only</b> = the reads with zero math (memory ceiling at this pattern). <b>dot ×1</b> = the real kernel. <b>×2/×4</b> = same reads, more ALU. If read-only ≫ dot, the ALU is the wall (int8 is the lever); if read-only ≈ dot, the memory access pattern is the wall (int8 won't help).</p>
15
- <div id="status" class="card">starting…</div>
16
- <div id="out"></div>
17
-
18
- <script type="module">
19
- const $=s=>document.querySelector(s), st=$("#status"), out=$("#out");
20
- const MODEL_GB=0.69;
21
- const say=(t,cls)=>{ st.textContent=t; st.className="card"+(cls?" "+cls:""); };
22
- window.addEventListener("unhandledrejection",e=>say("✗ unhandled: "+(e.reason&&(e.reason.message||e.reason)),"no"));
23
-
24
- const DOT16=`
25
- fn dot16(word:u32, v:u32) -> f32 {
26
- var s4=vec4<f32>(0.0);
27
- s4=s4+x[v] *(vec4<f32>(f32(word&3u),f32((word>>2u)&3u),f32((word>>4u)&3u),f32((word>>6u)&3u))-vec4<f32>(1.0));
28
- s4=s4+x[v+1u]*(vec4<f32>(f32((word>>8u)&3u),f32((word>>10u)&3u),f32((word>>12u)&3u),f32((word>>14u)&3u))-vec4<f32>(1.0));
29
- s4=s4+x[v+2u]*(vec4<f32>(f32((word>>16u)&3u),f32((word>>18u)&3u),f32((word>>20u)&3u),f32((word>>22u)&3u))-vec4<f32>(1.0));
30
- s4=s4+x[v+3u]*(vec4<f32>(f32((word>>24u)&3u),f32((word>>26u)&3u),f32((word>>28u)&3u),f32((word>>30u)&3u))-vec4<f32>(1.0));
31
- return s4.x+s4.y+s4.z+s4.w;
32
- }`;
33
- // mode: 'read' (xor raw, no unpack) | 'dot' (R× dot16, same reads). T threads/row, ROWS rows/wg (T*ROWS=256).
34
- const kern=(mode,R,T,ROWS)=>`
35
- @group(0) @binding(0) var<storage,read> x: array<vec4<f32>>;
36
- @group(0) @binding(1) var<storage,read> qw: array<u32>;
37
- @group(0) @binding(2) var<storage,read_write> o: array<f32>;
38
- @group(0) @binding(3) var<uniform> P: vec4<u32>; // K, N
39
- var<workgroup> red: array<f32, 256>;
40
- ${mode==='dot'?DOT16:''}
41
- @compute @workgroup_size(256)
42
- fn main(@builtin(workgroup_id) wg:vec3<u32>, @builtin(local_invocation_id) lid:vec3<u32>){
43
- let K=P.x; let nw=K>>4u;
44
- let rr=lid.x/${T}u; let t=lid.x%${T}u;
45
- let n0=(wg.y*65535u+wg.x)*${ROWS}u+rr; let n=min(n0, P.y-1u);
46
- let rowW=n*nw;
47
- ${mode==='read'?'var accu=0u;':'var acc=0.0;'}
48
- var w=t;
49
- loop{ if(w>=nw){break;}
50
- let word=qw[rowW+w]; let v=w<<2u;
51
- ${mode==='read'?'accu=accu^word;':Array.from({length:R},(_,r)=>`acc=acc+dot16(word^${r}u, v);`).join(' ')}
52
- w=w+${T}u; }
53
- ${mode==='read'?'var acc=f32(accu&1u); if(accu==0xffffffffu){ acc=acc+x[0].x; }':''}
54
- red[lid.x]=acc; workgroupBarrier();
55
- var s=${T>>1}u; loop{ if(s==0u){break;} if(t<s){ red[rr*${T}u+t]=red[rr*${T}u+t]+red[rr*${T}u+t+s]; } workgroupBarrier(); s=s/2u; }
56
- if(t==0u && n0<P.y){ o[n0]=red[rr*${T}u]; }
57
- }`;
58
-
59
- const FILL=`
60
- @group(0) @binding(0) var<storage,read_write> d: array<u32>;
61
- @group(0) @binding(1) var<uniform> P: vec4<u32>;
62
- @compute @workgroup_size(256)
63
- fn main(@builtin(global_invocation_id) gid:vec3<u32>){ let n=P.x; var i=gid.x; loop{ if(i>=n){break;} d[i]=(i*2654435761u+1u)^((i<<7u)*40503u); i=i+P.y; } }`;
64
-
65
- const VARIANTS=[
66
- {id:"read", name:"read-only (no ALU) — memory ceiling", mode:"read", R:0, T:64, ROWS:4, grp:"alu"},
67
- {id:"dot1", name:"dot ×1 (the real kernel)", mode:"dot", R:1, T:64, ROWS:4, grp:"alu"},
68
- {id:"dot2", name:"dot ×2 (2× ALU, same reads)", mode:"dot", R:2, T:64, ROWS:4, grp:"alu"},
69
- {id:"dot4", name:"dot ×4 (4× ALU, same reads)", mode:"dot", R:4, T:64, ROWS:4, grp:"alu"},
70
- {id:"dot8", name:"dot ×8 (KX=8 batched-verify proxy)", mode:"dot", R:8, T:64, ROWS:4, grp:"alu"},
71
- {id:"occ32", name:"dot ×1 · 32 thr/row · 8 rows/wg", mode:"dot", R:1, T:32, ROWS:8, grp:"occ"},
72
- {id:"occ128",name:"dot ×1 · 128 thr/row · 2 rows/wg", mode:"dot", R:1, T:128,ROWS:2, grp:"occ"},
73
- ];
74
-
75
- (async()=>{
76
- try{
77
- if(!navigator.gpu){ say("✗ No WebGPU. Open in Chrome/Edge.","no"); return; }
78
- say("requesting adapter…");
79
- let ad=await navigator.gpu.requestAdapter({powerPreference:"high-performance"}); if(!ad) ad=await navigator.gpu.requestAdapter();
80
- if(!ad){ say("✗ no GPU adapter.","no"); return; }
81
- const L=ad.limits, info=ad.info||{};
82
- const dev=await ad.requestDevice({requiredLimits:{maxStorageBufferBindingSize:L.maxStorageBufferBindingSize, maxBufferSize:L.maxBufferSize, maxComputeWorkgroupsPerDimension:L.maxComputeWorkgroupsPerDimension}});
83
- dev.lost.then(i=>say("✗ device lost: "+(i&&i.message||i.reason||""),"no"));
84
-
85
- const K=4096, nw=K/16;
86
- const wantBytes=Math.min(L.maxStorageBufferBindingSize, L.maxBufferSize, Math.round(MODEL_GB*1e9));
87
- const N=Math.floor((wantBytes/4)/nw), qU32=N*nw, wBytes=qU32*4;
88
- say("allocating "+(wBytes/1048576).toFixed(0)+" MB…");
89
- const qw=dev.createBuffer({size:wBytes, usage:GPUBufferUsage.STORAGE});
90
- const xbuf=dev.createBuffer({size:K*4, usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});
91
- const obuf=dev.createBuffer({size:N*4, usage:GPUBufferUsage.STORAGE});
92
- const P=dev.createBuffer({size:16, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});
93
- const xa=new Float32Array(K); for(let i=0;i<K;i++) xa[i]=(Math.sin(i*12.9898)*43758.5453)%1;
94
- dev.queue.writeBuffer(xbuf,0,xa); dev.queue.writeBuffer(P,0,new Uint32Array([K,N,0,0]));
95
-
96
- say("filling weights…");
97
- { const fmod=dev.createShaderModule({code:FILL}); const fpipe=dev.createComputePipeline({layout:"auto",compute:{module:fmod,entryPoint:"main"}});
98
- const fp=dev.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); const wgF=Math.min(L.maxComputeWorkgroupsPerDimension,65535);
99
- dev.queue.writeBuffer(fp,0,new Uint32Array([qU32, wgF*256, 0, 0]));
100
- const fbg=dev.createBindGroup({layout:fpipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:qw}},{binding:1,resource:{buffer:fp}}]});
101
- const e=dev.createCommandEncoder(); const p=e.beginComputePass(); p.setPipeline(fpipe); p.setBindGroup(0,fbg); p.dispatchWorkgroups(wgF); p.end();
102
- dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); }
103
-
104
- const PASSES=10, ITERS=5;
105
- const rows=[];
106
- for(const V of VARIANTS){
107
- say("compiling "+V.id+"…");
108
- dev.pushErrorScope("validation");
109
- const mod=dev.createShaderModule({code:kern(V.mode,V.R,V.T,V.ROWS)});
110
- const ci=await mod.getCompilationInfo(); const er=ci.messages.filter(m=>m.type==="error");
111
- if(er.length){ await dev.popErrorScope(); rows.push({V,err:er[0].message}); continue; }
112
- const pipe=dev.createComputePipeline({layout:"auto",compute:{module:mod,entryPoint:"main"}});
113
- const bg=dev.createBindGroup({layout:pipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:xbuf}},{binding:1,resource:{buffer:qw}},{binding:2,resource:{buffer:obuf}},{binding:3,resource:{buffer:P}}]});
114
- const se=await dev.popErrorScope(); if(se){ rows.push({V,err:se.message}); continue; }
115
- const groups=Math.ceil(N/V.ROWS), wgx=Math.min(groups,65535), wgy=Math.ceil(groups/65535);
116
- async function run(passes){ const e=dev.createCommandEncoder(); for(let k=0;k<passes;k++){ const p=e.beginComputePass(); p.setPipeline(pipe); p.setBindGroup(0,bg); p.dispatchWorkgroups(wgx,wgy); p.end(); } const t0=performance.now(); dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); return performance.now()-t0; }
117
- say("timing "+V.id+"…");
118
- await run(2); let best=1e9; for(let k=0;k<ITERS;k++){ best=Math.min(best, await run(PASSES)); }
119
- const gbps=(wBytes/1073741824)/((best/PASSES)/1000);
120
- rows.push({V, gbps, tok:gbps/MODEL_GB});
121
- }
122
-
123
- say("done · adapter: "+((info.vendor||"?")+" "+(info.architecture||"")+" "+(info.device||"")).trim(),"ok");
124
- const g=id=>rows.find(r=>r.V.id===id&&r.gbps); const rd=g("read"), d1=g("dot1"), d4=g("dot4"), d8=g("dot8"), o32=g("occ32"), o128=g("occ128");
125
- const maxG=Math.max(...rows.filter(r=>r.gbps).map(r=>r.gbps));
126
- const readVsDot = (rd&&d1)? rd.gbps/d1.gbps : 0; // >~1.5 ⇒ reads themselves fly, ALU is the wall
127
- const aluSlope = (d1&&d4)? d1.gbps/d4.gbps : 0; // >~1.5 ⇒ time scales with ALU ⇒ ALU-throughput bound
128
- const occGain = d1? Math.max(o32?o32.gbps/d1.gbps:0, o128?o128.gbps/d1.gbps:0) : 0;
129
- const batchFree = (d1&&d8)? d8.gbps/d1.gbps : 0; // ~1 ⇒ 8-wide batched verify costs ~same as 1 ⇒ spec-decode is ~free
130
- const readCeil = rd? rd.gbps : 0;
131
- let verdict, cls;
132
- const specNote = d8 ? ` Batched verify (dot ×8, the KX=8 spec proxy) runs at ${d8.gbps.toFixed(0)} GB/s = ${batchFree.toFixed(2)}× the single kernel — so verifying 8 tokens costs ≈ 1 token. Spec-decode IS ~free here; its earlier 1.0× was per-window JS/fence OVERHEAD, not GPU cost. Killing that overhead unlocks the ~4× the 93%-acceptance implies.` : "";
133
- if(aluSlope>=1.6 && readVsDot>=1.6){ verdict = `ALU-BOUND. reads fly (${readCeil.toFixed(0)} GB/s) but dot ×1 only ${d1.gbps.toFixed(0)}, and ×1→×4 scales ${aluSlope.toFixed(1)}×. Fewer instructions per weight (int8 dot4I8Packed) is the lever.` + specNote; cls="warn"; }
134
- else{ verdict = `MEMORY-LATENCY-BOUND — NOT ALU-bound. Quadrupling the ALU (×1→×4) costs only ${aluSlope.toFixed(1)}× → the f32 unpack is hidden; int8 will NOT help. read-only tops ${readCeil.toFixed(0)} GB/s at this pattern vs 152 pure-stream, and dot ×1 sits at ${d1?d1.gbps.toFixed(0):"?"} (${readCeil?(100*d1.gbps/readCeil).toFixed(0):"?"}% of even the read ceiling). Lever = more memory-level parallelism (register-block several output rows per thread so more loads are in flight before the barrier), NOT int8/occupancy.` + specNote; cls=(occGain>=1.15?"warn":"no"); }
135
-
136
- out.innerHTML=`
137
- <div class="card"><span class="k" style="color:var(--dim)">Test matrix</span> &nbsp; ${N.toLocaleString()} × ${K} · ${(wBytes/1073741824).toFixed(2)} GB · pure-stream roofline 152 GB/s (220 tok/s)</div>
138
- <div class="card"><table>
139
- <tr><th>variant</th><th class="n">GB/s</th><th class="n">tok/s-equiv</th><th></th></tr>
140
- ${rows.map(r=>r.err
141
- ? `<tr><td>${r.V.name}</td><td colspan=3 class="no">failed: ${r.err.slice(0,54)}</td></tr>`
142
- : `<tr><td>${r.V.name}</td><td class="n">${r.gbps.toFixed(0)}</td><td class="n">${r.tok.toFixed(0)}</td><td><span class="bar" style="width:${Math.round(140*r.gbps/maxG)}px"></span></td></tr>`).join("")}
143
- </table></div>
144
- <div class="verdict ${cls}">${verdict}</div>`;
145
- }catch(e){ say("✗ "+(e&&(e.message||e)), "no"); }
146
- })();
147
- </script></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
q-chat.html DELETED
@@ -1,120 +0,0 @@
1
- <!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
2
- <title>Q · local chat</title>
3
- <style>
4
- :root{--bg:#0b0e14;--panel:#141922;--ink:#e6e9ef;--dim:#8a94a6;--q:#7c5cff;--u:#1f6feb;--line:#1e2531}
5
- *{box-sizing:border-box}html,body{height:100%}
6
- body{margin:0;font:15px/1.55 -apple-system,Segoe UI,Roboto,monospace;background:var(--bg);color:var(--ink);display:flex;flex-direction:column}
7
- header{padding:10px 16px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;flex:0 0 auto}
8
- header b{font-weight:600}header .s{color:var(--dim);font-size:12px}
9
- #log{flex:1;overflow:auto;padding:16px;display:flex;flex-direction:column;gap:12px}
10
- .msg{max-width:82%;padding:9px 13px;border-radius:12px;white-space:pre-wrap;word-wrap:break-word}
11
- .u{align-self:flex-end;background:var(--u)}.a{align-self:flex-start;background:var(--panel);border:1px solid #232b3a}
12
- .a.think{color:var(--dim);font-style:italic}
13
- footer{padding:12px 16px;border-top:1px solid var(--line);display:flex;gap:8px;flex:0 0 auto}
14
- #in{flex:1;background:var(--panel);border:1px solid #232b3a;color:var(--ink);border-radius:10px;padding:10px 12px;font:inherit;resize:none;max-height:140px}
15
- button{background:var(--q);color:#fff;border:0;border-radius:10px;padding:0 18px;font:inherit;cursor:pointer}button:disabled{opacity:.4;cursor:default}
16
- .stat{color:var(--dim);font-size:11px;margin-top:3px}
17
- </style></head><body>
18
- <header><b>Q</b> <span class=s id=st>booting…</span></header>
19
- <div id=log></div>
20
- <footer><textarea id=in rows=1 placeholder="Message Q…" disabled></textarea><button id=send disabled>Send</button></footer>
21
- <script type=module>
22
- import { ready, loadModel, MODELS, defaultModelIndex } from "./core/loader.js";
23
- import { createEngine } from "./core/engine.js";
24
- import { selfPersona } from "./core/q-self.mjs"; // ONE grounded self-knowledge, shared with the messenger + voice
25
- const $ = (s) => document.querySelector(s);
26
- const log = $("#log"), input = $("#in"), send = $("#send"), st = $("#st");
27
- const bubble = (cls, text = "") => { const d = document.createElement("div"); d.className = "msg " + cls; d.textContent = text; log.appendChild(d); log.scrollTop = log.scrollHeight; return d; };
28
- const params = new URLSearchParams(location.search);
29
- const pick = params.get("m");
30
- let m = pick ? (MODELS.find((x) => new RegExp(pick, "i").test(x.name)) || MODELS[0]) : MODELS[defaultModelIndex()];
31
- // STREAM FROM ANYWHERE: ?hf=<org/repo> (a HuggingFace κ-object) or ?kappa=<absolute-url> loads the weights from
32
- // that host's CDN instead of the local mount. The κ-object is content-addressed + pinned, so the host is an
33
- // UNTRUSTED CDN — every block is re-derived (Law L5); a bad byte is rejected. Blocks cache locally after first
34
- // load (0-network on return). Uses BitNet's engine flags (the HOLOGRAMTECH model is BitNet-2B).
35
- {
36
- const hf = params.get("hf"), kappa = params.get("kappa");
37
- if (hf || kappa) {
38
- const base = (kappa || `https://huggingface.co/${hf}/resolve/main`).replace(/\/+$/, "");
39
- const bit = MODELS.find((x) => (x.fam || "").toLowerCase() === "bitnet") || m;
40
- m = { ...bit, kappaUrl: base, name: bit.name + " · via " + (hf || new URL(base).host) };
41
- }
42
- }
43
-
44
- // GROUND the model as on-device Q (a base/instruct model has NO self-knowledge — without this it confabulates
45
- // a generic "I run on OpenAI/AWS cloud servers" identity, which is false). Injected as the SYSTEM turn.
46
- // the system block for the model's own chat template (matches core/engine frameTurn's per-family markers).
47
- // PERSONA is Q's LIVE grounded self-knowledge (q-self), computed at call time so it names the real resident
48
- // model + κ — without it a base model confabulates a cloud/OpenAI/AWS identity.
49
- function frameSystem() {
50
- const PERSONA = selfPersona({ model: m, engine });
51
- if (m.llama3) return `<|start_header_id|>system<|end_header_id|>\n\n${PERSONA}<|eot_id|>`;
52
- if (m.qwen) return `<|im_start|>system\n${PERSONA}<|im_end|>\n`;
53
- if (m.olmo) return `<|system|>\n${PERSONA}\n`;
54
- return PERSONA + "\n\n"; // word/plain frame: prepend as leading context
55
- }
56
-
57
- let engine = null, convIds = [], busy = false, armed = false, pending = null;
58
- // type immediately — don't wait for the model. The first message is queued and auto-sent the instant Q is ready.
59
- input.disabled = send.disabled = false; input.placeholder = "Message Q… (model loading — will send the moment it's ready)"; input.focus();
60
-
61
- async function generate(text, skipUser) {
62
- busy = true; input.disabled = send.disabled = true;
63
- if (!skipUser) bubble("u", text);
64
- const a = bubble("a think", "…"); let first = true;
65
- const stat = document.createElement("div"); stat.className = "stat";
66
- const t0 = performance.now();
67
- try {
68
- let framed = engine.frameTurn(text, convIds.length > 0);
69
- if (convIds.length === 0) framed = frameSystem() + framed; // first turn → lead with the on-device Q persona
70
- let turnIds = engine.tokenize(framed);
71
- if (m.bos && engine.bosId != null && convIds.length === 0) turnIds = [engine.bosId, ...turnIds];
72
- const res = await engine.generate(convIds.concat(turnIds), { maxNew: m.cap || 256, onToken: ({ text: t, stats }) => {
73
- if (first && t) { a.classList.remove("think"); a.textContent = ""; first = false; }
74
- a.textContent = t; log.scrollTop = log.scrollHeight;
75
- if (stats) stat.textContent = `${stats.tokps ? stats.tokps.toFixed(0) + " tok/s" : ""}${stats.ttft ? " · TTFT " + Math.round(stats.ttft) + "ms" : ""}`;
76
- } });
77
- if (first) { a.classList.remove("think"); a.textContent = res.text || "(no output)"; }
78
- convIds = res.ids; a.after(stat);
79
- } catch (e) { a.classList.remove("think"); a.textContent = "⚠ " + e.message; }
80
- busy = false; input.disabled = send.disabled = false; input.focus();
81
- }
82
- // Q reaches out first — a real, model-GENERATED opening (not a canned line), so it feels alive.
83
- // This also warms the GPU pipelines. It is standalone (not added to convIds) so the real chat starts fresh.
84
- async function proactiveGreeting() {
85
- busy = true; input.disabled = send.disabled = true;
86
- const a = bubble("a think", "…"); let first = true;
87
- const stat = document.createElement("div"); stat.className = "stat";
88
- const FALLBACK = "Hey — I'm Q, running entirely on your device, no server, my weights verified by re-derivation. What can I help you with?";
89
- try {
90
- const P = "This is the very first thing you say to the person who just opened you. You are Q — a private AI running entirely on their device with no server, your weights verified by re-derivation. Greet them warmly in one or two sentences and invite them to ask you anything.";
91
- let ids = engine.tokenize(engine.frameTurn(P, false));
92
- if (m.bos && engine.bosId != null) ids = [engine.bosId, ...ids];
93
- await engine.generate(ids, { maxNew: 64, onToken: ({ text: t, stats }) => { if (first && t) { a.classList.remove("think"); a.textContent = ""; first = false; } a.textContent = t; log.scrollTop = log.scrollHeight; if (stats && stats.tokps) stat.textContent = `${stats.tokps.toFixed(0)} tok/s`; } });
94
- if (first || a.textContent.trim().length < 4) { a.classList.remove("think"); a.textContent = FALLBACK; } else a.after(stat);
95
- } catch (e) { a.classList.remove("think"); a.textContent = FALLBACK; }
96
- busy = false; input.disabled = send.disabled = false; input.focus();
97
- }
98
- function onSend() {
99
- const text = input.value.trim(); if (!text || busy) return;
100
- input.value = ""; input.style.height = "auto";
101
- if (!armed) { pending = text; bubble("u", text); const w = bubble("a think", "…starting the model, one moment…"); w.dataset.pending = "1"; return; }
102
- generate(text);
103
- }
104
- send.onclick = onSend;
105
- input.onkeydown = (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); onSend(); } };
106
- input.oninput = () => { input.style.height = "auto"; input.style.height = Math.min(140, input.scrollHeight) + "px"; };
107
-
108
- try {
109
- if (!navigator.gpu) throw new Error("This browser has no WebGPU. Use Chrome/Edge.");
110
- st.textContent = `loading ${m.name} (${m.size})…`;
111
- const loaded = await loadModel(m, { onStatus: (s) => { if (s) st.textContent = `${m.name}: ${s}`; }, onProgress: (d, t, w) => { st.textContent = `${m.name}: ${w} ${t ? Math.round(100 * d / t) : 0}%`; } });
112
- if (!loaded || !loaded.gpu) throw new Error("model load failed");
113
- engine = await createEngine(m, loaded);
114
- armed = true;
115
- st.textContent = `${m.name} · ${m.size} · resident on your GPU · ready`;
116
- input.placeholder = "Message Q…";
117
- if (pending) { const w = [...log.querySelectorAll(".a")].reverse().find((x) => x.dataset.pending); if (w) w.remove(); const p = pending; pending = null; generate(p, true); } // you jumped in first → answer that
118
- else await proactiveGreeting(); // otherwise Q reaches out the moment it's ready (also warms the GPU)
119
- } catch (e) { st.textContent = "⚠ " + e.message; bubble("a", "Could not start: " + e.message); }
120
- </script></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
rb-bench.html DELETED
@@ -1,130 +0,0 @@
1
- <!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
2
- <title>Register-blocked GEMV — your GPU</title>
3
- <style>
4
- :root{--bg:#0a0d13;--panel:#111825;--ink:#e8ebf1;--dim:#8b95a7;--ac:#7c5cff;--ok:#48c26c;--no:#f0616d;--warn:#e0a94a;--line:#1e2836}
5
- *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.6 -apple-system,Segoe UI,Roboto,monospace;padding:24px;max-width:860px;margin:0 auto}
6
- h1{font-size:20px;margin:0 0 4px}.sub{color:var(--dim);font-size:13px;margin:0 0 18px}
7
- .card{font-family:ui-monospace,monospace;padding:14px 16px;border:1px solid var(--line);border-radius:10px;background:var(--panel);margin-bottom:12px;word-break:break-word}
8
- table{width:100%;border-collapse:collapse;font-family:ui-monospace,monospace;font-size:13px}
9
- td,th{padding:6px 8px;border-bottom:1px solid var(--line);text-align:left}th{color:var(--dim);font-weight:600}
10
- td.n{text-align:right;font-variant-numeric:tabular-nums}
11
- .verdict{font-size:16px;font-weight:600;margin-top:14px}.bar{display:inline-block;height:9px;background:var(--ac);border-radius:2px;vertical-align:middle}
12
- </style></head><body>
13
- <h1>Register-blocked <span style="color:var(--ac)">ternary GEMV</span> — your GPU</h1>
14
- <p class="sub">The kernel is memory-latency-bound (45 of 152 GB/s). Each 64-thread group here computes <b>B output rows</b>, so each thread issues B independent weight loads per step (more loads in flight to hide latency) while sharing the activation reads. B=1 is today's kernel. Higher B should climb toward the 152 GB/s roofline — until register pressure drops occupancy.</p>
15
- <div id="status" class="card">starting…</div>
16
- <div id="out"></div>
17
-
18
- <script type="module">
19
- const $=s=>document.querySelector(s), st=$("#status"), out=$("#out");
20
- const MODEL_GB=0.69, ROOF=152, ROOF_TOK=220;
21
- const say=(t,cls)=>{ st.textContent=t; st.className="card"+(cls?" "+cls:""); };
22
- window.addEventListener("unhandledrejection",e=>say("✗ unhandled: "+(e.reason&&(e.reason.message||e.reason)),"no"));
23
-
24
- const DOT16=`
25
- fn dot16(word:u32, v:u32) -> f32 {
26
- var s4=vec4<f32>(0.0);
27
- s4=s4+x[v] *(vec4<f32>(f32(word&3u),f32((word>>2u)&3u),f32((word>>4u)&3u),f32((word>>6u)&3u))-vec4<f32>(1.0));
28
- s4=s4+x[v+1u]*(vec4<f32>(f32((word>>8u)&3u),f32((word>>10u)&3u),f32((word>>12u)&3u),f32((word>>14u)&3u))-vec4<f32>(1.0));
29
- s4=s4+x[v+2u]*(vec4<f32>(f32((word>>16u)&3u),f32((word>>18u)&3u),f32((word>>20u)&3u),f32((word>>22u)&3u))-vec4<f32>(1.0));
30
- s4=s4+x[v+3u]*(vec4<f32>(f32((word>>24u)&3u),f32((word>>26u)&3u),f32((word>>28u)&3u),f32((word>>30u)&3u))-vec4<f32>(1.0));
31
- return s4.x+s4.y+s4.z+s4.w;
32
- }`;
33
- // B output rows per 64-thread group, 4 groups per workgroup (256 threads). Each thread does B independent
34
- // weight loads/iteration (memory-level parallelism), reusing the shared activation reads.
35
- const kern=(B)=>`
36
- @group(0) @binding(0) var<storage,read> x: array<vec4<f32>>;
37
- @group(0) @binding(1) var<storage,read> qw: array<u32>;
38
- @group(0) @binding(2) var<storage,read_write> o: array<f32>;
39
- @group(0) @binding(3) var<uniform> P: vec4<u32>; // K, N
40
- var<workgroup> red: array<f32, 256>;
41
- ${DOT16}
42
- @compute @workgroup_size(256)
43
- fn main(@builtin(workgroup_id) wg:vec3<u32>, @builtin(local_invocation_id) lid:vec3<u32>){
44
- let K=P.x; let nw=K>>4u; let grp=lid.x/64u; let t=lid.x%64u;
45
- let base=((wg.y*65535u+wg.x)*4u + grp)*${B}u;
46
- var acc: array<f32, ${B}>;
47
- ${Array.from({length:B},(_,b)=>`acc[${b}]=0.0;`).join(" ")}
48
- var w=t;
49
- loop{ if(w>=nw){break;} let v=w<<2u;
50
- ${Array.from({length:B},(_,b)=>`let word${b}=qw[min(base+${b}u,P.y-1u)*nw + w];`).join("\n ")}
51
- ${Array.from({length:B},(_,b)=>`acc[${b}]=acc[${b}]+dot16(word${b}, v);`).join("\n ")}
52
- w=w+64u; }
53
- ${Array.from({length:B},(_,b)=>`
54
- red[lid.x]=acc[${b}]; workgroupBarrier();
55
- { var s=32u; loop{ if(s==0u){break;} if(t<s){ red[grp*64u+t]=red[grp*64u+t]+red[grp*64u+t+s]; } workgroupBarrier(); s=s/2u; } }
56
- if(t==0u){ let n=base+${b}u; if(n<P.y){ o[n]=red[grp*64u]; } }
57
- workgroupBarrier();`).join("")}
58
- }`;
59
-
60
- const FILL=`
61
- @group(0) @binding(0) var<storage,read_write> d: array<u32>;
62
- @group(0) @binding(1) var<uniform> P: vec4<u32>;
63
- @compute @workgroup_size(256)
64
- fn main(@builtin(global_invocation_id) gid:vec3<u32>){ let n=P.x; var i=gid.x; loop{ if(i>=n){break;} d[i]=(i*2654435761u+1u)^((i<<7u)*40503u); i=i+P.y; } }`;
65
-
66
- const BS=[1,2,4,8,16];
67
-
68
- (async()=>{
69
- try{
70
- if(!navigator.gpu){ say("✗ No WebGPU. Open in Chrome/Edge.","no"); return; }
71
- say("requesting adapter…");
72
- let ad=await navigator.gpu.requestAdapter({powerPreference:"high-performance"}); if(!ad) ad=await navigator.gpu.requestAdapter();
73
- if(!ad){ say("✗ no GPU adapter.","no"); return; }
74
- const L=ad.limits, info=ad.info||{};
75
- const dev=await ad.requestDevice({requiredLimits:{maxStorageBufferBindingSize:L.maxStorageBufferBindingSize, maxBufferSize:L.maxBufferSize, maxComputeWorkgroupsPerDimension:L.maxComputeWorkgroupsPerDimension}});
76
- dev.lost.then(i=>say("✗ device lost: "+(i&&i.message||i.reason||""),"no"));
77
-
78
- const K=4096, nw=K/16;
79
- const wantBytes=Math.min(L.maxStorageBufferBindingSize, L.maxBufferSize, Math.round(MODEL_GB*1e9));
80
- const N=Math.floor((wantBytes/4)/nw), qU32=N*nw, wBytes=qU32*4;
81
- say("allocating "+(wBytes/1048576).toFixed(0)+" MB…");
82
- const qw=dev.createBuffer({size:wBytes, usage:GPUBufferUsage.STORAGE});
83
- const xbuf=dev.createBuffer({size:K*4, usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});
84
- const obuf=dev.createBuffer({size:N*4, usage:GPUBufferUsage.STORAGE});
85
- const P=dev.createBuffer({size:16, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});
86
- const xa=new Float32Array(K); for(let i=0;i<K;i++) xa[i]=(Math.sin(i*12.9898)*43758.5453)%1;
87
- dev.queue.writeBuffer(xbuf,0,xa); dev.queue.writeBuffer(P,0,new Uint32Array([K,N,0,0]));
88
-
89
- say("filling weights…");
90
- { const fmod=dev.createShaderModule({code:FILL}); const fpipe=dev.createComputePipeline({layout:"auto",compute:{module:fmod,entryPoint:"main"}});
91
- const fp=dev.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}); const wgF=Math.min(L.maxComputeWorkgroupsPerDimension,65535);
92
- dev.queue.writeBuffer(fp,0,new Uint32Array([qU32, wgF*256, 0, 0]));
93
- const fbg=dev.createBindGroup({layout:fpipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:qw}},{binding:1,resource:{buffer:fp}}]});
94
- const e=dev.createCommandEncoder(); const p=e.beginComputePass(); p.setPipeline(fpipe); p.setBindGroup(0,fbg); p.dispatchWorkgroups(wgF); p.end();
95
- dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); }
96
-
97
- const PASSES=10, ITERS=5, rows=[];
98
- for(const B of BS){
99
- say("compiling B="+B+"…");
100
- dev.pushErrorScope("validation");
101
- const mod=dev.createShaderModule({code:kern(B)});
102
- const ci=await mod.getCompilationInfo(); const er=ci.messages.filter(m=>m.type==="error");
103
- if(er.length){ await dev.popErrorScope(); rows.push({B,err:er[0].message}); continue; }
104
- const pipe=dev.createComputePipeline({layout:"auto",compute:{module:mod,entryPoint:"main"}});
105
- const bg=dev.createBindGroup({layout:pipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:xbuf}},{binding:1,resource:{buffer:qw}},{binding:2,resource:{buffer:obuf}},{binding:3,resource:{buffer:P}}]});
106
- const se=await dev.popErrorScope(); if(se){ rows.push({B,err:se.message}); continue; }
107
- const groups=Math.ceil(N/(4*B)), wgx=Math.min(groups,65535), wgy=Math.ceil(groups/65535);
108
- async function run(passes){ const e=dev.createCommandEncoder(); for(let k=0;k<passes;k++){ const p=e.beginComputePass(); p.setPipeline(pipe); p.setBindGroup(0,bg); p.dispatchWorkgroups(wgx,wgy); p.end(); } const t0=performance.now(); dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); return performance.now()-t0; }
109
- say("timing B="+B+"…");
110
- await run(2); let best=1e9; for(let k=0;k<ITERS;k++){ best=Math.min(best, await run(PASSES)); }
111
- const gbps=(wBytes/1073741824)/((best/PASSES)/1000);
112
- rows.push({B, gbps, tok:gbps/MODEL_GB, pct:100*gbps/ROOF});
113
- }
114
-
115
- say("done · adapter: "+((info.vendor||"?")+" "+(info.architecture||"")+" "+(info.device||"")).trim(),"ok");
116
- const ok=rows.filter(r=>r.gbps); const best=ok.slice().sort((a,b)=>b.gbps-a.gbps)[0]; const b1=ok.find(r=>r.B===1);
117
- const maxG=Math.max(...ok.map(r=>r.gbps));
118
- const gain=(best&&b1)? best.gbps/b1.gbps : 0;
119
- out.innerHTML=`
120
- <div class="card"><span style="color:var(--dim)">Test matrix</span> &nbsp; ${N.toLocaleString()} × ${K} · ${(wBytes/1073741824).toFixed(2)} GB · roofline ${ROOF} GB/s (${ROOF_TOK} tok/s)</div>
121
- <div class="card"><table>
122
- <tr><th>rows/group (B)</th><th class="n">GB/s</th><th class="n">tok/s-equiv</th><th class="n">% roofline</th><th></th></tr>
123
- ${rows.map(r=>r.err
124
- ? `<tr><td>B=${r.B}</td><td colspan=4 class="no">failed: ${r.err.slice(0,50)}</td></tr>`
125
- : `<tr><td>B=${r.B}${r.B===1?" (today)":""}</td><td class="n">${r.gbps.toFixed(0)}</td><td class="n ${r===best?'ok':''}"><b>${r.tok.toFixed(0)}</b></td><td class="n ${r.pct<40?'no':r.pct<70?'warn':'ok'}">${r.pct.toFixed(0)}%</td><td><span class="bar" style="width:${Math.round(150*r.gbps/maxG)}px"></span></td></tr>`).join("")}
126
- </table></div>
127
- ${best? `<div class="verdict ${best.pct>=70?'ok':best.pct>=45?'warn':'no'}">Best: <b>B=${best.B}</b> → ${best.gbps.toFixed(0)} GB/s (${best.tok.toFixed(0)} tok/s, ${best.pct.toFixed(0)}% of roofline, <b>${gain.toFixed(2)}×</b> today's kernel). ${best.pct>=70?"Memory-latency hidden — port B="+best.B+" into mmT2/mmT2KK.":best.pct>=45?"Real gain; register pressure likely caps it here — port B="+best.B+".":"Little movement — the pattern needs a deeper restructure (shared-mem staging / wider loads)."}</div>` : `<div class="verdict no">All variants failed.</div>`}`;
128
- }catch(e){ say("✗ "+(e&&(e.message||e)), "no"); }
129
- })();
130
- </script></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
roofline.html DELETED
@@ -1,126 +0,0 @@
1
- <!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
2
- <title>Decode roofline — your GPU</title>
3
- <style>
4
- :root{--bg:#0a0d13;--panel:#111825;--ink:#e8ebf1;--dim:#8b95a7;--ac:#7c5cff;--ok:#48c26c;--no:#f0616d;--warn:#e0a94a;--line:#1e2836}
5
- *{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.6 -apple-system,Segoe UI,Roboto,monospace;padding:24px;max-width:760px;margin:0 auto}
6
- h1{font-size:20px;margin:0 0 4px}.sub{color:var(--dim);font-size:13px;margin:0 0 18px}
7
- .card{font-family:ui-monospace,monospace;padding:14px 16px;border:1px solid var(--line);border-radius:10px;background:var(--panel);margin-bottom:12px;word-break:break-word}
8
- .big{font-size:22px;font-weight:700}.k{color:var(--dim)}.v{font-weight:600}
9
- .ok{color:var(--ok)}.no{color:var(--no)}.warn{color:var(--warn)}
10
- table{width:100%;border-collapse:collapse;font-family:ui-monospace,monospace;font-size:13px}
11
- td{padding:5px 8px;border-bottom:1px solid var(--line)}td.n{text-align:right;font-variant-numeric:tabular-nums}
12
- .verdict{font-size:17px;font-weight:600;margin-top:14px}
13
- </style></head><body>
14
- <h1>BitNet decode <span style="color:var(--ac)">roofline</span> on your GPU</h1>
15
- <p class="sub">Measures your GPU's achievable VRAM read bandwidth, then computes the batch-1 decode ceiling for BitNet-2B (0.69&nbsp;GB read per token) and how far the current kernel is from it.</p>
16
- <div id="status" class="card">starting…</div>
17
- <div id="out"></div>
18
-
19
- <script type="module">
20
- const $=s=>document.querySelector(s), st=$("#status"), out=$("#out");
21
- const MODEL_GB = 0.69, CUR_MS = 18.4;
22
- const say = (t,cls) => { st.textContent = t; st.className = "card" + (cls?" "+cls:""); };
23
- window.addEventListener("unhandledrejection", e => say("✗ unhandled: " + (e.reason && (e.reason.message||e.reason)), "no"));
24
-
25
- // FILL: write a non-zero, non-compressible pattern so the read pass hits real VRAM
26
- // (an uninitialised STORAGE buffer is zero/DCC-compressed → the memory controller
27
- // never fetches it → measured bandwidth is fictional). Must run before timing.
28
- const FILL = `
29
- @group(0) @binding(0) var<storage, read_write> d : array<vec4<u32>>;
30
- @group(0) @binding(1) var<uniform> P : vec4<u32>; // x=#vec4 elems, y=total threads
31
- @compute @workgroup_size(256)
32
- fn main(@builtin(global_invocation_id) gid:vec3<u32>){
33
- let n=P.x; let stride=P.y; var i=gid.x;
34
- loop { if(i>=n){break;}
35
- d[i]=vec4<u32>(i*2654435761u+1u, i*40503u+7u, i^0x9e3779b9u, i*2246822519u+3u);
36
- i=i+stride; }
37
- }`;
38
- const WGSL = `
39
- @group(0) @binding(0) var<storage, read> data : array<vec4<u32>>;
40
- @group(0) @binding(1) var<storage, read_write> sink : array<u32>;
41
- @group(0) @binding(2) var<uniform> P : vec4<u32>; // x=#vec4 elems, y=total threads, z=repeat
42
- @compute @workgroup_size(256)
43
- fn main(@builtin(global_invocation_id) gid:vec3<u32>){
44
- let n=P.x; let stride=P.y; let R=P.z; var acc=vec4<u32>(0u);
45
- for(var rep=0u; rep<R; rep=rep+1u){ var i=gid.x; loop { if(i>=n){break;} acc=acc ^ data[i]; i=i+stride; } }
46
- sink[gid.x]=acc.x ^ acc.y ^ acc.z ^ acc.w;
47
- }`;
48
-
49
- (async()=>{
50
- try{
51
- if(!navigator.gpu){ say("✗ No WebGPU. Open in Chrome/Edge or a recent browser.","no"); return; }
52
- say("requesting adapter…");
53
- let ad = await navigator.gpu.requestAdapter({powerPreference:"high-performance"});
54
- if(!ad) ad = await navigator.gpu.requestAdapter();
55
- if(!ad){ say("✗ no GPU adapter available.","no"); return; }
56
- const L=ad.limits;
57
- say("requesting device…");
58
- const dev=await ad.requestDevice({requiredLimits:{
59
- maxStorageBufferBindingSize:L.maxStorageBufferBindingSize, maxBufferSize:L.maxBufferSize,
60
- maxComputeWorkgroupsPerDimension:L.maxComputeWorkgroupsPerDimension }});
61
- dev.lost.then(i => say("✗ device lost: "+(i&&i.message||i.reason||""),"no"));
62
- dev.pushErrorScope("validation");
63
- const info=ad.info||{};
64
- // Buffer must exceed the GPU's last-level cache (RDNA-3 Infinity Cache is up to 96 MB)
65
- // so re-reads actually miss to VRAM. Aim as large as the device allows, floor 512 MB.
66
- const wantBytes=Math.min(L.maxStorageBufferBindingSize, L.maxBufferSize, 1024*1024*1024);
67
- const bytes=Math.floor(Math.max(512*1024*1024, wantBytes)/16)*16;
68
- const nVec=bytes/16;
69
- say("allocating "+(bytes/1048576).toFixed(0)+" MB…");
70
- const buf=dev.createBuffer({size:bytes, usage:GPUBufferUsage.STORAGE});
71
- const wg=Math.min(L.maxComputeWorkgroupsPerDimension,65535), TOTAL=wg*256, R=1;
72
- const sink=dev.createBuffer({size:TOTAL*4, usage:GPUBufferUsage.STORAGE});
73
- const P=dev.createBuffer({size:16, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});
74
- dev.queue.writeBuffer(P,0,new Uint32Array([nVec, TOTAL, R, 0]));
75
- // fill pipeline (non-zero pattern) — its own bind group, same buffer
76
- const fmod=dev.createShaderModule({code:FILL});
77
- const fci=await fmod.getCompilationInfo(); const fer=fci.messages.filter(m=>m.type==="error");
78
- if(fer.length){ say("✗ FILL WGSL: "+fer[0].message,"no"); return; }
79
- const fpipe=dev.createComputePipeline({layout:"auto",compute:{module:fmod,entryPoint:"main"}});
80
- const fbg=dev.createBindGroup({layout:fpipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:buf}},{binding:1,resource:{buffer:P}}]});
81
- const mod=dev.createShaderModule({code:WGSL});
82
- const ci=await mod.getCompilationInfo(); const er=ci.messages.filter(m=>m.type==="error");
83
- if(er.length){ say("✗ WGSL: "+er[0].message,"no"); return; }
84
- const pipe=dev.createComputePipeline({layout:"auto",compute:{module:mod,entryPoint:"main"}});
85
- const bg=dev.createBindGroup({layout:pipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:buf}},{binding:1,resource:{buffer:sink}},{binding:2,resource:{buffer:P}}]});
86
- const rb=dev.createBuffer({size:4, usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});
87
- const scopeErr = await dev.popErrorScope();
88
- if(scopeErr){ say("✗ GPU validation: "+scopeErr.message,"no"); return; }
89
- // write the non-zero pattern into VRAM before we time reads
90
- say("filling "+(bytes/1048576).toFixed(0)+" MB with non-zero pattern…");
91
- { const e=dev.createCommandEncoder(); const p=e.beginComputePass(); p.setPipeline(fpipe); p.setBindGroup(0,fbg); p.dispatchWorkgroups(wg); p.end(); dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); }
92
- // Batch many read passes into ONE command buffer, submit once, sync with
93
- // onSubmittedWorkDone. Moving tens of GB makes GPU time >> fixed submit/map
94
- // latency, so wall-clock reflects real VRAM bandwidth (not the ~0.1 ms overhead floor).
95
- const PASSES=64; // 64 × buffer ≈ 32–64 GB of reads
96
- async function timeReads(passes){
97
- const e=dev.createCommandEncoder();
98
- for(let k=0;k<passes;k++){ const p=e.beginComputePass(); p.setPipeline(pipe); p.setBindGroup(0,bg); p.dispatchWorkgroups(wg); p.end(); }
99
- const t0=performance.now();
100
- dev.queue.submit([e.finish()]);
101
- await dev.queue.onSubmittedWorkDone();
102
- return performance.now()-t0;
103
- }
104
- say("timing "+(bytes/1048576*PASSES/1024).toFixed(1)+" GB of reads…");
105
- await timeReads(4); // warm up (compile, clocks up)
106
- let best=1e9; for(let k=0;k<5;k++){ best=Math.min(best, await timeReads(PASSES)); }
107
- const gbps = (bytes*PASSES/1073741824)/(best/1000);
108
- const roofTok=gbps/MODEL_GB, curTok=1000/CUR_MS, curGBps=MODEL_GB/(CUR_MS/1000);
109
- const pct=100*curGBps/gbps, gap=gbps/curGBps, reachable=roofTok>=1000, specNeeded=Math.max(1,1000/roofTok);
110
- say("done · adapter: "+((info.vendor||"?")+" "+(info.architecture||"")+" "+(info.device||"")).trim(),"ok");
111
- out.innerHTML=`
112
- <div class="card"><span class="k">Achievable VRAM read bandwidth</span><br><span class="big">${gbps.toFixed(0)} GB/s</span></div>
113
- <div class="card"><table>
114
- <tr><td>Weights read / token (BitNet-2B t2)</td><td class="n">${MODEL_GB} GB</td></tr>
115
- <tr><td><b>Bandwidth roofline (batch-1 ceiling)</b></td><td class="n"><b>${roofTok.toFixed(0)} tok/s</b></td></tr>
116
- <tr><td>Current kernel</td><td class="n">${curTok.toFixed(0)} tok/s · ${curGBps.toFixed(0)} GB/s</td></tr>
117
- <tr><td>Current kernel reaches</td><td class="n ${pct<20?'no':pct<60?'warn':'ok'}">${pct.toFixed(1)}% of roofline</td></tr>
118
- <tr><td>Kernel headroom to roofline</td><td class="n">${gap.toFixed(1)}×</td></tr>
119
- </table></div>
120
- <div class="verdict ${reachable?'ok':'warn'}">${reachable
121
- ? '✓ >1000 tok/s is within your GPU roofline ('+roofTok.toFixed(0)+') — a bandwidth-optimal ternary kernel ('+gap.toFixed(1)+'× headroom) gets there; spec-decode is margin.'
122
- : '⚠ Your GPU batch-1 roofline is '+roofTok.toFixed(0)+' tok/s. A perfect kernel reaches ~'+roofTok.toFixed(0)+'; >1000 needs speculative decode accepting ≥'+specNeeded.toFixed(1)+' tokens/pass, or a card with more bandwidth.'}
123
- </div>`;
124
- }catch(e){ say("✗ "+(e && (e.message||e)), "no"); }
125
- })();
126
- </script></body></html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
style.css DELETED
@@ -1,28 +0,0 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
- }
5
-
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
- }
10
-
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
- }
17
-
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
- }
25
-
26
- .card p:last-child {
27
- margin-bottom: 0;
28
- }