murmur-rag 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +2 -1
  2. package/dist/cdn/{embed-we24qtes.js → embed-pnm9593k.js} +1 -1
  3. package/dist/cdn/index-hv290nbv.js +9 -0
  4. package/dist/cdn/{murmur-5vkc01ns.js → murmur-bnm335nb.js} +1 -1
  5. package/dist/cdn/murmur.js +5 -5
  6. package/dist/cdn/retriever-m8peqj5t.js +1 -0
  7. package/dist/cli.js +8 -5
  8. package/dist/lib/chunks/{index-z8pn9sdj.js → index-10g918kt.js} +16 -3
  9. package/dist/lib/chunks/{index-v9expxwm.js → index-4at214g0.js} +22 -7
  10. package/dist/lib/chunks/{index-fs6gmhz9.js → index-ynjdey8j.js} +1 -1
  11. package/dist/lib/chunks/{murmur-wq1d15n7.js → murmur-c1c79eh8.js} +2 -2
  12. package/dist/lib/chunks/{retriever-1rw4z2n6.js → retriever-h8nz6jsc.js} +1 -1
  13. package/dist/lib/embed.js +2 -2
  14. package/dist/lib/index.js +2 -2
  15. package/dist/lib/indexer/index.js +8 -5
  16. package/dist/lib/rag/index.js +1 -1
  17. package/dist/lib/widget/index.js +2 -2
  18. package/dist/types/core/murmur.d.ts +2 -2
  19. package/dist/types/embed.d.ts +1 -1
  20. package/dist/types/index.d.ts +2 -2
  21. package/dist/types/indexer/extract.d.ts +1 -1
  22. package/dist/types/indexer/files.d.ts +1 -1
  23. package/dist/types/indexer/index.d.ts +4 -4
  24. package/dist/types/rag/chunk.d.ts +1 -1
  25. package/dist/types/rag/ground.d.ts +1 -1
  26. package/dist/types/rag/index.d.ts +4 -4
  27. package/dist/types/rag/retriever.d.ts +1 -1
  28. package/dist/types/widget/element.d.ts +4 -3
  29. package/dist/types/widget/index.d.ts +6 -6
  30. package/dist/types/widget/session.d.ts +5 -5
  31. package/package.json +5 -2
  32. package/dist/cdn/index-zrmby2xc.js +0 -9
  33. package/dist/cdn/retriever-k9mmdcz5.js +0 -1
package/README.md CHANGED
@@ -90,7 +90,8 @@ No server, no analytics. The question and the matching passages go to the AI pro
90
90
  bun install
91
91
  bun run dev # build, then serve on http://localhost:4317/murmur/
92
92
  bun run test # unit tests
93
- bun run test:e2e # Playwright, against a fake OpenAI-compatible endpoint
93
+ bun run test:e2e # Playwright against a fake OpenAI-compatible endpoint, axe WCAG 2.2 AA scans
94
+ bun run test:package # packs, installs and checks the CLI, Node imports and types
94
95
  bun run typecheck && bun run lint
95
96
  ```
96
97
 
@@ -1,2 +1,2 @@
1
- import{Ye}from"./embed-2xm309sb.js";class L{constructor(t,e){let s=t._tree,n=Array.from(s.keys());this.set=t,this._type=e,this._path=n.length>0?[{node:s,keys:n}]:[]}next(){let t=this.dive();return this.backtrack(),t}dive(){if(this._path.length===0)return{done:!0,value:void 0};let{node:t,keys:e}=y(this._path);if(y(e)==="")return{done:!1,value:this.result()};let s=t.get(y(e));return this._path.push({node:s,keys:Array.from(s.keys())}),this.dive()}backtrack(){if(this._path.length===0)return;let t=y(this._path).keys;if(t.pop(),t.length>0)return;this._path.pop(),this.backtrack()}key(){return this.set._prefix+this._path.map(({keys:t})=>y(t)).filter((t)=>t!=="").join("")}value(){return y(this._path).node.get("")}result(){switch(this._type){case"VALUES":return this.value();case"KEYS":return this.key();default:return[this.key(),this.value()]}}[Symbol.iterator](){return this}}var y=(t)=>t[t.length-1],G=(t,e,s)=>{let n=new Map;if(e===void 0)return n;let i=e.length+1,r=i+s,c=new Uint8Array(r*i).fill(s+1);for(let o=0;o<i;++o)c[o]=o;for(let o=1;o<r;++o)c[o*i]=o;return Q(t,e,s,n,c,1,i,""),n},Q=(t,e,s,n,i,r,c,o)=>{let d=r*c;t:for(let u of t.keys())if(u===""){let h=i[d-1];if(h<=s)n.set(o,[t.get(u),h])}else{let h=r;for(let a=0;a<u.length;++a,++h){let f=u[a],m=c*h,g=m-c,l=i[m],_=Math.max(0,h-s-1),F=Math.min(c-1,h+s);for(let p=_;p<F;++p){let E=f!==e[p],S=i[g+p]+ +E,x=i[g+p+1]+1,I=i[m+p]+1,j=i[m+p+1]=Math.min(S,x,I);if(j<l)l=j}if(l>s)continue t}Q(t.get(u),e,s,n,i,h,c,o+u)}};class w{constructor(t=new Map,e=""){this._size=void 0,this._tree=t,this._prefix=e}atPrefix(t){if(!t.startsWith(this._prefix))throw Error("Mismatched prefix");let[e,s]=k(this._tree,t.slice(this._prefix.length));if(e===void 0){let[n,i]=R(s);for(let r of n.keys())if(r!==""&&r.startsWith(i)){let c=new Map;return c.set(r.slice(i.length),n.get(r)),new w(c,t)}}return new w(e,t)}clear(){this._size=void 0,this._tree.clear()}delete(t){return this._size=void 0,Z(this._tree,t)}entries(){return new L(this,"ENTRIES")}forEach(t){for(let[e,s]of this)t(e,s,this)}fuzzyGet(t,e){return G(this._tree,t,e)}get(t){let e=A(this._tree,t);return e!==void 0?e.get(""):void 0}has(t){let e=A(this._tree,t);return e!==void 0&&e.has("")}keys(){return new L(this,"KEYS")}set(t,e){if(typeof t!=="string")throw Error("key must be a string");return this._size=void 0,M(this._tree,t).set("",e),this}get size(){if(this._size)return this._size;this._size=0;let t=this.entries();while(!t.next().done)this._size+=1;return this._size}update(t,e){if(typeof t!=="string")throw Error("key must be a string");this._size=void 0;let s=M(this._tree,t);return s.set("",e(s.get(""))),this}fetch(t,e){if(typeof t!=="string")throw Error("key must be a string");this._size=void 0;let s=M(this._tree,t),n=s.get("");if(n===void 0)s.set("",n=e());return n}values(){return new L(this,"VALUES")}[Symbol.iterator](){return this.entries()}static from(t){let e=new w;for(let[s,n]of t)e.set(s,n);return e}static fromObject(t){return w.from(Object.entries(t))}}var k=(t,e,s=[])=>{if(e.length===0||t==null)return[t,s];for(let n of t.keys())if(n!==""&&e.startsWith(n))return s.push([t,n]),k(t.get(n),e.slice(n.length),s);return s.push([t,e]),k(void 0,"",s)},A=(t,e)=>{if(e.length===0||t==null)return t;for(let s of t.keys())if(s!==""&&e.startsWith(s))return A(t.get(s),e.slice(s.length))},M=(t,e)=>{let s=e.length;t:for(let n=0;t&&n<s;){for(let r of t.keys())if(r!==""&&e[n]===r[0]){let c=Math.min(s-n,r.length),o=1;while(o<c&&e[n+o]===r[o])++o;let d=t.get(r);if(o===r.length)t=d;else{let u=new Map;u.set(r.slice(o),d),t.set(e.slice(n,n+o),u),t.delete(r),t=u}n+=o;continue t}let i=new Map;return t.set(e.slice(n),i),i}return t},Z=(t,e)=>{let[s,n]=k(t,e);if(s===void 0)return;if(s.delete(""),s.size===0)B(n);else if(s.size===1){let[i,r]=s.entries().next().value;K(n,i,r)}},B=(t)=>{if(t.length===0)return;let[e,s]=R(t);if(e.delete(s),e.size===0)B(t.slice(0,-1));else if(e.size===1){let[n,i]=e.entries().next().value;if(n!=="")K(t.slice(0,-1),n,i)}},K=(t,e,s)=>{if(t.length===0)return;let[n,i]=R(t);n.set(i+e,s),n.delete(i)},R=(t)=>t[t.length-1],N="or",q="and",H="and_not";class z{constructor(t){if((t===null||t===void 0?void 0:t.fields)==null)throw Error('MiniSearch: option "fields" must be provided');let e=t.autoVacuum==null||t.autoVacuum===!0?C:t.autoVacuum;this._options={...V,...t,autoVacuum:e,searchOptions:{...P,...t.searchOptions||{}},autoSuggestOptions:{...nt,...t.autoSuggestOptions||{}}},this._index=new w,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldIds={},this._fieldLength=new Map,this._avgFieldLength=[],this._nextId=0,this._storedFields=new Map,this._dirtCount=0,this._currentVacuum=null,this._enqueuedVacuum=null,this._enqueuedVacuumConditions=D,this.addFields(this._options.fields)}add(t){let{extractField:e,stringifyField:s,tokenize:n,processTerm:i,fields:r,idField:c}=this._options,o=e(t,c);if(o==null)throw Error(`MiniSearch: document does not have ID field "${c}"`);if(this._idToShortId.has(o))throw Error(`MiniSearch: duplicate ID ${o}`);let d=this.addDocumentId(o);this.saveStoredFields(d,t);for(let u of r){let h=e(t,u);if(h==null)continue;let a=n(s(h,u),u),f=this._fieldIds[u],m=new Set(a).size;this.addFieldLength(d,f,this._documentCount-1,m);for(let g of a){let l=i(g,u);if(Array.isArray(l))for(let _ of l)this.addTerm(f,d,_);else if(l)this.addTerm(f,d,l)}}}addAll(t){for(let e of t)this.add(e)}addAllAsync(t,e={}){let{chunkSize:s=10}=e,n={chunk:[],promise:Promise.resolve()},{chunk:i,promise:r}=t.reduce(({chunk:c,promise:o},d,u)=>{if(c.push(d),(u+1)%s===0)return{chunk:[],promise:o.then(()=>new Promise((h)=>setTimeout(h,0))).then(()=>this.addAll(c))};else return{chunk:c,promise:o}},n);return r.then(()=>this.addAll(i))}remove(t){let{tokenize:e,processTerm:s,extractField:n,stringifyField:i,fields:r,idField:c}=this._options,o=n(t,c);if(o==null)throw Error(`MiniSearch: document does not have ID field "${c}"`);let d=this._idToShortId.get(o);if(d==null)throw Error(`MiniSearch: cannot remove document with ID ${o}: it is not in the index`);for(let u of r){let h=n(t,u);if(h==null)continue;let a=e(i(h,u),u),f=this._fieldIds[u],m=new Set(a).size;this.removeFieldLength(d,f,this._documentCount,m);for(let g of a){let l=s(g,u);if(Array.isArray(l))for(let _ of l)this.removeTerm(f,d,_);else if(l)this.removeTerm(f,d,l)}}this._storedFields.delete(d),this._documentIds.delete(d),this._idToShortId.delete(o),this._fieldLength.delete(d),this._documentCount-=1}removeAll(t){if(t)for(let e of t)this.remove(e);else if(arguments.length>0)throw Error("Expected documents to be present. Omit the argument to remove all documents.");else this._index=new w,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}discard(t){let e=this._idToShortId.get(t);if(e==null)throw Error(`MiniSearch: cannot discard document with ID ${t}: it is not in the index`);this._idToShortId.delete(t),this._documentIds.delete(e),this._storedFields.delete(e),(this._fieldLength.get(e)||[]).forEach((s,n)=>{this.removeFieldLength(e,n,this._documentCount,s)}),this._fieldLength.delete(e),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()}maybeAutoVacuum(){if(this._options.autoVacuum===!1)return;let{minDirtFactor:t,minDirtCount:e,batchSize:s,batchWait:n}=this._options.autoVacuum;this.conditionalVacuum({batchSize:s,batchWait:n},{minDirtCount:e,minDirtFactor:t})}discardAll(t){let e=this._options.autoVacuum;try{this._options.autoVacuum=!1;for(let s of t)this.discard(s)}finally{this._options.autoVacuum=e}this.maybeAutoVacuum()}replace(t){let{idField:e,extractField:s}=this._options,n=s(t,e);this.discard(n),this.add(t)}vacuum(t={}){return this.conditionalVacuum(t)}conditionalVacuum(t,e){if(this._currentVacuum){if(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&e,this._enqueuedVacuum!=null)return this._enqueuedVacuum;return this._enqueuedVacuum=this._currentVacuum.then(()=>{let s=this._enqueuedVacuumConditions;return this._enqueuedVacuumConditions=D,this.performVacuuming(t,s)}),this._enqueuedVacuum}if(this.vacuumConditionsMet(e)===!1)return Promise.resolve();return this._currentVacuum=this.performVacuuming(t),this._currentVacuum}async performVacuuming(t,e){let s=this._dirtCount;if(this.vacuumConditionsMet(e)){let n=t.batchSize||T.batchSize,i=t.batchWait||T.batchWait,r=1;for(let[c,o]of this._index){for(let[d,u]of o)for(let[h]of u){if(this._documentIds.has(h))continue;if(u.size<=1)o.delete(d);else u.delete(h)}if(this._index.get(c).size===0)this._index.delete(c);if(r%n===0)await new Promise((d)=>setTimeout(d,i));r+=1}this._dirtCount-=s}await null,this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null}vacuumConditionsMet(t){if(t==null)return!0;let{minDirtCount:e,minDirtFactor:s}=t;return e=e||C.minDirtCount,s=s||C.minDirtFactor,this.dirtCount>=e&&this.dirtFactor>=s}get isVacuuming(){return this._currentVacuum!=null}get dirtCount(){return this._dirtCount}get dirtFactor(){return this._dirtCount/(1+this._documentCount+this._dirtCount)}has(t){return this._idToShortId.has(t)}getStoredFields(t){let e=this._idToShortId.get(t);if(e==null)return;return this._storedFields.get(e)}search(t,e={}){let{searchOptions:s}=this._options,n={...s,...e},i=this.executeQuery(t,e),r=[];for(let[c,{score:o,terms:d,match:u}]of i){let h=d.length||1,a={id:this._documentIds.get(c),score:o*h,terms:Object.keys(u),queryTerms:d,match:u};if(Object.assign(a,this._storedFields.get(c)),n.filter==null||n.filter(a))r.push(a)}if(t===z.wildcard&&n.boostDocument==null)return r;return r.sort(J),r}autoSuggest(t,e={}){e={...this._options.autoSuggestOptions,...e};let s=new Map;for(let{score:i,terms:r}of this.search(t,e)){let c=r.join(" "),o=s.get(c);if(o!=null)o.score+=i,o.count+=1;else s.set(c,{score:i,terms:r,count:1})}let n=[];for(let[i,{score:r,terms:c,count:o}]of s)n.push({suggestion:i,terms:c,score:r/o});return n.sort(J),n}get documentCount(){return this._documentCount}get termCount(){return this._index.size}static loadJSON(t,e){if(e==null)throw Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(t),e)}static async loadJSONAsync(t,e){if(e==null)throw Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJSAsync(JSON.parse(t),e)}static getDefault(t){if(V.hasOwnProperty(t))return O(V,t);else throw Error(`MiniSearch: unknown option "${t}"`)}static loadJS(t,e){let{index:s,documentIds:n,fieldLength:i,storedFields:r,serializationVersion:c}=t,o=this.instantiateMiniSearch(t,e);o._documentIds=b(n),o._fieldLength=b(i),o._storedFields=b(r);for(let[d,u]of o._documentIds)o._idToShortId.set(u,d);for(let[d,u]of s){let h=new Map;for(let a of Object.keys(u)){let f=u[a];if(c===1)f=f.ds;h.set(parseInt(a,10),b(f))}o._index.set(d,h)}return o}static async loadJSAsync(t,e){let{index:s,documentIds:n,fieldLength:i,storedFields:r,serializationVersion:c}=t,o=this.instantiateMiniSearch(t,e);o._documentIds=await v(n),o._fieldLength=await v(i),o._storedFields=await v(r);for(let[u,h]of o._documentIds)o._idToShortId.set(h,u);let d=0;for(let[u,h]of s){let a=new Map;for(let f of Object.keys(h)){let m=h[f];if(c===1)m=m.ds;a.set(parseInt(f,10),await v(m))}if(++d%1000===0)await Y(0);o._index.set(u,a)}return o}static instantiateMiniSearch(t,e){let{documentCount:s,nextId:n,fieldIds:i,averageFieldLength:r,dirtCount:c,serializationVersion:o}=t;if(o!==1&&o!==2)throw Error("MiniSearch: cannot deserialize an index created with an incompatible version");let d=new z(e);return d._documentCount=s,d._nextId=n,d._idToShortId=new Map,d._fieldIds=i,d._avgFieldLength=r,d._dirtCount=c||0,d._index=new w,d}executeQuery(t,e={}){if(t===z.wildcard)return this.executeWildcardQuery(e);if(typeof t!=="string"){let a={...e,...t,queries:void 0},f=t.queries.map((m)=>this.executeQuery(m,a));return this.combineResults(f,a.combineWith)}let{tokenize:s,processTerm:n,searchOptions:i}=this._options,r={tokenize:s,processTerm:n,...i,...e},{tokenize:c,processTerm:o}=r,h=c(t).flatMap((a)=>o(a)).filter((a)=>!!a).map(st(r)).map((a)=>this.executeQuerySpec(a,r));return this.combineResults(h,r.combineWith)}executeQuerySpec(t,e){let s={...this._options.searchOptions,...e},n=(s.fields||this._options.fields).reduce((g,l)=>({...g,[l]:O(s.boost,l)||1}),{}),{boostDocument:i,weights:r,maxFuzzy:c,bm25:o}=s,{fuzzy:d,prefix:u}={...P.weights,...r},h=this._index.get(t.term),a=this.termResults(t.term,t.term,1,t.termBoost,h,n,i,o),f,m;if(t.prefix)f=this._index.atPrefix(t.term);if(t.fuzzy){let g=t.fuzzy===!0?0.2:t.fuzzy,l=g<1?Math.min(c,Math.round(t.term.length*g)):g;if(l)m=this._index.fuzzyGet(t.term,l)}if(f)for(let[g,l]of f){let _=g.length-t.term.length;if(!_)continue;m===null||m===void 0||m.delete(g);let F=u*g.length/(g.length+0.3*_);this.termResults(t.term,g,F,t.termBoost,l,n,i,o,a)}if(m)for(let g of m.keys()){let[l,_]=m.get(g);if(!_)continue;let F=d*g.length/(g.length+_);this.termResults(t.term,g,F,t.termBoost,l,n,i,o,a)}return a}executeWildcardQuery(t){let e=new Map,s={...this._options.searchOptions,...t};for(let[n,i]of this._documentIds){let r=s.boostDocument?s.boostDocument(i,"",this._storedFields.get(n)):1;e.set(n,{score:r,terms:[],match:{}})}return e}combineResults(t,e=N){if(t.length===0)return new Map;let s=e.toLowerCase(),n=X[s];if(!n)throw Error(`Invalid combination operator: ${e}`);return t.reduce(n)||new Map}toJSON(){let t=[];for(let[e,s]of this._index){let n={};for(let[i,r]of s)n[i]=Object.fromEntries(r);t.push([e,n])}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:t,serializationVersion:2}}termResults(t,e,s,n,i,r,c,o,d=new Map){if(i==null)return d;for(let u of Object.keys(r)){let h=r[u],a=this._fieldIds[u],f=i.get(a);if(f==null)continue;let m=f.size,g=this._avgFieldLength[a];for(let l of f.keys()){if(!this._documentIds.has(l)){this.removeTerm(a,l,e),m-=1;continue}let _=c?c(this._documentIds.get(l),e,this._storedFields.get(l)):1;if(!_)continue;let F=f.get(l),p=this._fieldLength.get(l)[a],E=et(F,m,this._documentCount,p,g,o),S=s*n*h*_*E,x=d.get(l);if(x){x.score+=S,it(x.terms,t);let I=O(x.match,e);if(I)I.push(u);else x.match[e]=[u]}else d.set(l,{score:S,terms:[t],match:{[e]:[u]}})}}return d}addTerm(t,e,s){let n=this._index.fetch(s,U),i=n.get(t);if(i==null)i=new Map,i.set(e,1),n.set(t,i);else{let r=i.get(e);i.set(e,(r||0)+1)}}removeTerm(t,e,s){if(!this._index.has(s)){this.warnDocumentChanged(e,t,s);return}let n=this._index.fetch(s,U),i=n.get(t);if(i==null||i.get(e)==null)this.warnDocumentChanged(e,t,s);else if(i.get(e)<=1)if(i.size<=1)n.delete(t);else i.delete(e);else i.set(e,i.get(e)-1);if(this._index.get(s).size===0)this._index.delete(s)}warnDocumentChanged(t,e,s){for(let n of Object.keys(this._fieldIds))if(this._fieldIds[n]===e){this._options.logger("warn",`MiniSearch: document with ID ${this._documentIds.get(t)} has changed before removal: term "${s}" was not present in field "${n}". Removing a document after it has changed can corrupt the index!`,"version_conflict");return}}addDocumentId(t){let e=this._nextId;return this._idToShortId.set(t,e),this._documentIds.set(e,t),this._documentCount+=1,this._nextId+=1,e}addFields(t){for(let e=0;e<t.length;e++)this._fieldIds[t[e]]=e}addFieldLength(t,e,s,n){let i=this._fieldLength.get(t);if(i==null)this._fieldLength.set(t,i=[]);i[e]=n;let c=(this._avgFieldLength[e]||0)*s+n;this._avgFieldLength[e]=c/(s+1)}removeFieldLength(t,e,s,n){if(s===1){this._avgFieldLength[e]=0;return}let i=this._avgFieldLength[e]*s-n;this._avgFieldLength[e]=i/(s-1)}saveStoredFields(t,e){let{storeFields:s,extractField:n}=this._options;if(s==null||s.length===0)return;let i=this._storedFields.get(t);if(i==null)this._storedFields.set(t,i={});for(let r of s){let c=n(e,r);if(c!==void 0)i[r]=c}}}z.wildcard=Symbol("*");var O=(t,e)=>Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0,X={[N]:(t,e)=>{for(let s of e.keys()){let n=t.get(s);if(n==null)t.set(s,e.get(s));else{let{score:i,terms:r,match:c}=e.get(s);n.score=n.score+i,n.match=Object.assign(n.match,c),W(n.terms,r)}}return t},[q]:(t,e)=>{let s=new Map;for(let n of e.keys()){let i=t.get(n);if(i==null)continue;let{score:r,terms:c,match:o}=e.get(n);W(i.terms,c),s.set(n,{score:i.score+r,terms:i.terms,match:Object.assign(i.match,o)})}return s},[H]:(t,e)=>{for(let s of e.keys())t.delete(s);return t}},tt={k:1.2,b:0.7,d:0.5},et=(t,e,s,n,i,r)=>{let{k:c,b:o,d}=r;return Math.log(1+(s-e+0.5)/(e+0.5))*(d+t*(c+1)/(t+c*(1-o+o*n/i)))},st=(t)=>(e,s,n)=>{let i=typeof t.fuzzy==="function"?t.fuzzy(e,s,n):t.fuzzy||!1,r=typeof t.prefix==="function"?t.prefix(e,s,n):t.prefix===!0,c=typeof t.boostTerm==="function"?t.boostTerm(e,s,n):1;return{term:e,fuzzy:i,prefix:r,termBoost:c}},V={idField:"id",extractField:(t,e)=>t[e],stringifyField:(t,e)=>t.toString(),tokenize:(t)=>t.split(ot),processTerm:(t)=>t.toLowerCase(),fields:void 0,searchOptions:void 0,storeFields:[],logger:(t,e)=>{if(typeof(console===null||console===void 0?void 0:console[t])==="function")console[t](e)},autoVacuum:!0},P={combineWith:N,prefix:!1,fuzzy:!1,maxFuzzy:6,boost:{},weights:{fuzzy:0.45,prefix:0.375},bm25:tt},nt={combineWith:q,prefix:(t,e,s)=>e===s.length-1},T={batchSize:1000,batchWait:10},D={minDirtFactor:0.1,minDirtCount:20},C={...T,...D},it=(t,e)=>{if(!t.includes(e))t.push(e)},W=(t,e)=>{for(let s of e)if(!t.includes(s))t.push(s)},J=({score:t},{score:e})=>e-t,U=()=>new Map,b=(t)=>{let e=new Map;for(let s of Object.keys(t))e.set(parseInt(s,10),t[s]);return e},v=async(t)=>{let e=new Map,s=0;for(let n of Object.keys(t))if(e.set(parseInt(n,10),t[n]),++s%1000===0)await Y(0);return e},Y=(t)=>new Promise((e)=>setTimeout(e,t)),ot=/[\n\r\p{Z}\p{P}]+/u;var rt=(t)=>t.normalize("NFD").replace(/\p{M}/gu,"").toLowerCase();function ct(t){return t.chunks.map((e)=>{let s=t.docs[e.doc];return{...e,url:s?.url??"",title:s?.title??""}})}function It(t){let e=ct(t),s=new z({fields:["title","heading","text"],processTerm:(n)=>rt(n),searchOptions:{prefix:!0,fuzzy:0.15,boost:{title:2,heading:1.5}}});return s.addAll(e.map((n,i)=>({id:i,title:n.title,heading:n.heading,text:n.text}))),{async search(n,{limit:i=6,budgetTokens:r=3000}={}){let c=[],o=0;for(let d of s.search(n,{combineWith:"OR"})){let u=e[Number(d.id)];if(!u)continue;let h=Ye(u.text)+24;if(o+h>r)continue;if(o+=h,c.push(u),c.length>=i)break}return c}}}
1
+ import{Ye}from"./embed-2xm309sb.js";class L{constructor(t,e){let s=t._tree,n=Array.from(s.keys());this.set=t,this._type=e,this._path=n.length>0?[{node:s,keys:n}]:[]}next(){let t=this.dive();return this.backtrack(),t}dive(){if(this._path.length===0)return{done:!0,value:void 0};let{node:t,keys:e}=z(this._path);if(z(e)==="")return{done:!1,value:this.result()};let s=t.get(z(e));return this._path.push({node:s,keys:Array.from(s.keys())}),this.dive()}backtrack(){if(this._path.length===0)return;let t=z(this._path).keys;if(t.pop(),t.length>0)return;this._path.pop(),this.backtrack()}key(){return this.set._prefix+this._path.map(({keys:t})=>z(t)).filter((t)=>t!=="").join("")}value(){return z(this._path).node.get("")}result(){switch(this._type){case"VALUES":return this.value();case"KEYS":return this.key();default:return[this.key(),this.value()]}}[Symbol.iterator](){return this}}var z=(t)=>t[t.length-1],G=(t,e,s)=>{let n=new Map;if(e===void 0)return n;let i=e.length+1,r=i+s,c=new Uint8Array(r*i).fill(s+1);for(let o=0;o<i;++o)c[o]=o;for(let o=1;o<r;++o)c[o*i]=o;return U(t,e,s,n,c,1,i,""),n},U=(t,e,s,n,i,r,c,o)=>{let u=r*c;t:for(let d of t.keys())if(d===""){let a=i[u-1];if(a<=s)n.set(o,[t.get(d),a])}else{let a=r;for(let h=0;h<d.length;++h,++a){let f=d[h],m=c*a,g=m-c,l=i[m],_=Math.max(0,a-s-1),F=Math.min(c-1,a+s);for(let p=_;p<F;++p){let k=f!==e[p],S=i[g+p]+ +k,y=i[g+p+1]+1,I=i[m+p]+1,j=i[m+p+1]=Math.min(S,y,I);if(j<l)l=j}if(l>s)continue t}U(t.get(d),e,s,n,i,a,c,o+d)}};class w{constructor(t=new Map,e=""){this._size=void 0,this._tree=t,this._prefix=e}atPrefix(t){if(!t.startsWith(this._prefix))throw Error("Mismatched prefix");let[e,s]=E(this._tree,t.slice(this._prefix.length));if(e===void 0){let[n,i]=R(s);for(let r of n.keys())if(r!==""&&r.startsWith(i)){let c=new Map;return c.set(r.slice(i.length),n.get(r)),new w(c,t)}}return new w(e,t)}clear(){this._size=void 0,this._tree.clear()}delete(t){return this._size=void 0,Z(this._tree,t)}entries(){return new L(this,"ENTRIES")}forEach(t){for(let[e,s]of this)t(e,s,this)}fuzzyGet(t,e){return G(this._tree,t,e)}get(t){let e=A(this._tree,t);return e!==void 0?e.get(""):void 0}has(t){let e=A(this._tree,t);return e!==void 0&&e.has("")}keys(){return new L(this,"KEYS")}set(t,e){if(typeof t!=="string")throw Error("key must be a string");return this._size=void 0,M(this._tree,t).set("",e),this}get size(){if(this._size)return this._size;this._size=0;let t=this.entries();while(!t.next().done)this._size+=1;return this._size}update(t,e){if(typeof t!=="string")throw Error("key must be a string");this._size=void 0;let s=M(this._tree,t);return s.set("",e(s.get(""))),this}fetch(t,e){if(typeof t!=="string")throw Error("key must be a string");this._size=void 0;let s=M(this._tree,t),n=s.get("");if(n===void 0)s.set("",n=e());return n}values(){return new L(this,"VALUES")}[Symbol.iterator](){return this.entries()}static from(t){let e=new w;for(let[s,n]of t)e.set(s,n);return e}static fromObject(t){return w.from(Object.entries(t))}}var E=(t,e,s=[])=>{if(e.length===0||t==null)return[t,s];for(let n of t.keys())if(n!==""&&e.startsWith(n))return s.push([t,n]),E(t.get(n),e.slice(n.length),s);return s.push([t,e]),E(void 0,"",s)},A=(t,e)=>{if(e.length===0||t==null)return t;for(let s of t.keys())if(s!==""&&e.startsWith(s))return A(t.get(s),e.slice(s.length))},M=(t,e)=>{let s=e.length;t:for(let n=0;t&&n<s;){for(let r of t.keys())if(r!==""&&e[n]===r[0]){let c=Math.min(s-n,r.length),o=1;while(o<c&&e[n+o]===r[o])++o;let u=t.get(r);if(o===r.length)t=u;else{let d=new Map;d.set(r.slice(o),u),t.set(e.slice(n,n+o),d),t.delete(r),t=d}n+=o;continue t}let i=new Map;return t.set(e.slice(n),i),i}return t},Z=(t,e)=>{let[s,n]=E(t,e);if(s===void 0)return;if(s.delete(""),s.size===0)Q(n);else if(s.size===1){let[i,r]=s.entries().next().value;B(n,i,r)}},Q=(t)=>{if(t.length===0)return;let[e,s]=R(t);if(e.delete(s),e.size===0)Q(t.slice(0,-1));else if(e.size===1){let[n,i]=e.entries().next().value;if(n!=="")B(t.slice(0,-1),n,i)}},B=(t,e,s)=>{if(t.length===0)return;let[n,i]=R(t);n.set(i+e,s),n.delete(i)},R=(t)=>t[t.length-1],N="or",K="and",H="and_not";class x{constructor(t){if((t===null||t===void 0?void 0:t.fields)==null)throw Error('MiniSearch: option "fields" must be provided');let e=t.autoVacuum==null||t.autoVacuum===!0?C:t.autoVacuum;this._options={...V,...t,autoVacuum:e,searchOptions:{...P,...t.searchOptions||{}},autoSuggestOptions:{...nt,...t.autoSuggestOptions||{}}},this._index=new w,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldIds={},this._fieldLength=new Map,this._avgFieldLength=[],this._nextId=0,this._storedFields=new Map,this._dirtCount=0,this._currentVacuum=null,this._enqueuedVacuum=null,this._enqueuedVacuumConditions=D,this.addFields(this._options.fields)}add(t){let{extractField:e,stringifyField:s,tokenize:n,processTerm:i,fields:r,idField:c}=this._options,o=e(t,c);if(o==null)throw Error(`MiniSearch: document does not have ID field "${c}"`);if(this._idToShortId.has(o))throw Error(`MiniSearch: duplicate ID ${o}`);let u=this.addDocumentId(o);this.saveStoredFields(u,t);for(let d of r){let a=e(t,d);if(a==null)continue;let h=n(s(a,d),d),f=this._fieldIds[d],m=new Set(h).size;this.addFieldLength(u,f,this._documentCount-1,m);for(let g of h){let l=i(g,d);if(Array.isArray(l))for(let _ of l)this.addTerm(f,u,_);else if(l)this.addTerm(f,u,l)}}}addAll(t){for(let e of t)this.add(e)}addAllAsync(t,e={}){let{chunkSize:s=10}=e,n={chunk:[],promise:Promise.resolve()},{chunk:i,promise:r}=t.reduce(({chunk:c,promise:o},u,d)=>{if(c.push(u),(d+1)%s===0)return{chunk:[],promise:o.then(()=>new Promise((a)=>setTimeout(a,0))).then(()=>this.addAll(c))};else return{chunk:c,promise:o}},n);return r.then(()=>this.addAll(i))}remove(t){let{tokenize:e,processTerm:s,extractField:n,stringifyField:i,fields:r,idField:c}=this._options,o=n(t,c);if(o==null)throw Error(`MiniSearch: document does not have ID field "${c}"`);let u=this._idToShortId.get(o);if(u==null)throw Error(`MiniSearch: cannot remove document with ID ${o}: it is not in the index`);for(let d of r){let a=n(t,d);if(a==null)continue;let h=e(i(a,d),d),f=this._fieldIds[d],m=new Set(h).size;this.removeFieldLength(u,f,this._documentCount,m);for(let g of h){let l=s(g,d);if(Array.isArray(l))for(let _ of l)this.removeTerm(f,u,_);else if(l)this.removeTerm(f,u,l)}}this._storedFields.delete(u),this._documentIds.delete(u),this._idToShortId.delete(o),this._fieldLength.delete(u),this._documentCount-=1}removeAll(t){if(t)for(let e of t)this.remove(e);else if(arguments.length>0)throw Error("Expected documents to be present. Omit the argument to remove all documents.");else this._index=new w,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}discard(t){let e=this._idToShortId.get(t);if(e==null)throw Error(`MiniSearch: cannot discard document with ID ${t}: it is not in the index`);this._idToShortId.delete(t),this._documentIds.delete(e),this._storedFields.delete(e),(this._fieldLength.get(e)||[]).forEach((s,n)=>{this.removeFieldLength(e,n,this._documentCount,s)}),this._fieldLength.delete(e),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()}maybeAutoVacuum(){if(this._options.autoVacuum===!1)return;let{minDirtFactor:t,minDirtCount:e,batchSize:s,batchWait:n}=this._options.autoVacuum;this.conditionalVacuum({batchSize:s,batchWait:n},{minDirtCount:e,minDirtFactor:t})}discardAll(t){let e=this._options.autoVacuum;try{this._options.autoVacuum=!1;for(let s of t)this.discard(s)}finally{this._options.autoVacuum=e}this.maybeAutoVacuum()}replace(t){let{idField:e,extractField:s}=this._options,n=s(t,e);this.discard(n),this.add(t)}vacuum(t={}){return this.conditionalVacuum(t)}conditionalVacuum(t,e){if(this._currentVacuum){if(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&e,this._enqueuedVacuum!=null)return this._enqueuedVacuum;return this._enqueuedVacuum=this._currentVacuum.then(()=>{let s=this._enqueuedVacuumConditions;return this._enqueuedVacuumConditions=D,this.performVacuuming(t,s)}),this._enqueuedVacuum}if(this.vacuumConditionsMet(e)===!1)return Promise.resolve();return this._currentVacuum=this.performVacuuming(t),this._currentVacuum}async performVacuuming(t,e){let s=this._dirtCount;if(this.vacuumConditionsMet(e)){let n=t.batchSize||T.batchSize,i=t.batchWait||T.batchWait,r=1;for(let[c,o]of this._index){for(let[u,d]of o)for(let[a]of d){if(this._documentIds.has(a))continue;if(d.size<=1)o.delete(u);else d.delete(a)}if(this._index.get(c).size===0)this._index.delete(c);if(r%n===0)await new Promise((u)=>setTimeout(u,i));r+=1}this._dirtCount-=s}await null,this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null}vacuumConditionsMet(t){if(t==null)return!0;let{minDirtCount:e,minDirtFactor:s}=t;return e=e||C.minDirtCount,s=s||C.minDirtFactor,this.dirtCount>=e&&this.dirtFactor>=s}get isVacuuming(){return this._currentVacuum!=null}get dirtCount(){return this._dirtCount}get dirtFactor(){return this._dirtCount/(1+this._documentCount+this._dirtCount)}has(t){return this._idToShortId.has(t)}getStoredFields(t){let e=this._idToShortId.get(t);if(e==null)return;return this._storedFields.get(e)}search(t,e={}){let{searchOptions:s}=this._options,n={...s,...e},i=this.executeQuery(t,e),r=[];for(let[c,{score:o,terms:u,match:d}]of i){let a=u.length||1,h={id:this._documentIds.get(c),score:o*a,terms:Object.keys(d),queryTerms:u,match:d};if(Object.assign(h,this._storedFields.get(c)),n.filter==null||n.filter(h))r.push(h)}if(t===x.wildcard&&n.boostDocument==null)return r;return r.sort(J),r}autoSuggest(t,e={}){e={...this._options.autoSuggestOptions,...e};let s=new Map;for(let{score:i,terms:r}of this.search(t,e)){let c=r.join(" "),o=s.get(c);if(o!=null)o.score+=i,o.count+=1;else s.set(c,{score:i,terms:r,count:1})}let n=[];for(let[i,{score:r,terms:c,count:o}]of s)n.push({suggestion:i,terms:c,score:r/o});return n.sort(J),n}get documentCount(){return this._documentCount}get termCount(){return this._index.size}static loadJSON(t,e){if(e==null)throw Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(t),e)}static async loadJSONAsync(t,e){if(e==null)throw Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJSAsync(JSON.parse(t),e)}static getDefault(t){if(V.hasOwnProperty(t))return O(V,t);else throw Error(`MiniSearch: unknown option "${t}"`)}static loadJS(t,e){let{index:s,documentIds:n,fieldLength:i,storedFields:r,serializationVersion:c}=t,o=this.instantiateMiniSearch(t,e);o._documentIds=b(n),o._fieldLength=b(i),o._storedFields=b(r);for(let[u,d]of o._documentIds)o._idToShortId.set(d,u);for(let[u,d]of s){let a=new Map;for(let h of Object.keys(d)){let f=d[h];if(c===1)f=f.ds;a.set(parseInt(h,10),b(f))}o._index.set(u,a)}return o}static async loadJSAsync(t,e){let{index:s,documentIds:n,fieldLength:i,storedFields:r,serializationVersion:c}=t,o=this.instantiateMiniSearch(t,e);o._documentIds=await v(n),o._fieldLength=await v(i),o._storedFields=await v(r);for(let[d,a]of o._documentIds)o._idToShortId.set(a,d);let u=0;for(let[d,a]of s){let h=new Map;for(let f of Object.keys(a)){let m=a[f];if(c===1)m=m.ds;h.set(parseInt(f,10),await v(m))}if(++u%1000===0)await Y(0);o._index.set(d,h)}return o}static instantiateMiniSearch(t,e){let{documentCount:s,nextId:n,fieldIds:i,averageFieldLength:r,dirtCount:c,serializationVersion:o}=t;if(o!==1&&o!==2)throw Error("MiniSearch: cannot deserialize an index created with an incompatible version");let u=new x(e);return u._documentCount=s,u._nextId=n,u._idToShortId=new Map,u._fieldIds=i,u._avgFieldLength=r,u._dirtCount=c||0,u._index=new w,u}executeQuery(t,e={}){if(t===x.wildcard)return this.executeWildcardQuery(e);if(typeof t!=="string"){let h={...e,...t,queries:void 0},f=t.queries.map((m)=>this.executeQuery(m,h));return this.combineResults(f,h.combineWith)}let{tokenize:s,processTerm:n,searchOptions:i}=this._options,r={tokenize:s,processTerm:n,...i,...e},{tokenize:c,processTerm:o}=r,a=c(t).flatMap((h)=>o(h)).filter((h)=>!!h).map(st(r)).map((h)=>this.executeQuerySpec(h,r));return this.combineResults(a,r.combineWith)}executeQuerySpec(t,e){let s={...this._options.searchOptions,...e},n=(s.fields||this._options.fields).reduce((g,l)=>({...g,[l]:O(s.boost,l)||1}),{}),{boostDocument:i,weights:r,maxFuzzy:c,bm25:o}=s,{fuzzy:u,prefix:d}={...P.weights,...r},a=this._index.get(t.term),h=this.termResults(t.term,t.term,1,t.termBoost,a,n,i,o),f,m;if(t.prefix)f=this._index.atPrefix(t.term);if(t.fuzzy){let g=t.fuzzy===!0?0.2:t.fuzzy,l=g<1?Math.min(c,Math.round(t.term.length*g)):g;if(l)m=this._index.fuzzyGet(t.term,l)}if(f)for(let[g,l]of f){let _=g.length-t.term.length;if(!_)continue;m===null||m===void 0||m.delete(g);let F=d*g.length/(g.length+0.3*_);this.termResults(t.term,g,F,t.termBoost,l,n,i,o,h)}if(m)for(let g of m.keys()){let[l,_]=m.get(g);if(!_)continue;let F=u*g.length/(g.length+_);this.termResults(t.term,g,F,t.termBoost,l,n,i,o,h)}return h}executeWildcardQuery(t){let e=new Map,s={...this._options.searchOptions,...t};for(let[n,i]of this._documentIds){let r=s.boostDocument?s.boostDocument(i,"",this._storedFields.get(n)):1;e.set(n,{score:r,terms:[],match:{}})}return e}combineResults(t,e=N){if(t.length===0)return new Map;let s=e.toLowerCase(),n=X[s];if(!n)throw Error(`Invalid combination operator: ${e}`);return t.reduce(n)||new Map}toJSON(){let t=[];for(let[e,s]of this._index){let n={};for(let[i,r]of s)n[i]=Object.fromEntries(r);t.push([e,n])}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:t,serializationVersion:2}}termResults(t,e,s,n,i,r,c,o,u=new Map){if(i==null)return u;for(let d of Object.keys(r)){let a=r[d],h=this._fieldIds[d],f=i.get(h);if(f==null)continue;let m=f.size,g=this._avgFieldLength[h];for(let l of f.keys()){if(!this._documentIds.has(l)){this.removeTerm(h,l,e),m-=1;continue}let _=c?c(this._documentIds.get(l),e,this._storedFields.get(l)):1;if(!_)continue;let F=f.get(l),p=this._fieldLength.get(l)[h],k=et(F,m,this._documentCount,p,g,o),S=s*n*a*_*k,y=u.get(l);if(y){y.score+=S,it(y.terms,t);let I=O(y.match,e);if(I)I.push(d);else y.match[e]=[d]}else u.set(l,{score:S,terms:[t],match:{[e]:[d]}})}}return u}addTerm(t,e,s){let n=this._index.fetch(s,q),i=n.get(t);if(i==null)i=new Map,i.set(e,1),n.set(t,i);else{let r=i.get(e);i.set(e,(r||0)+1)}}removeTerm(t,e,s){if(!this._index.has(s)){this.warnDocumentChanged(e,t,s);return}let n=this._index.fetch(s,q),i=n.get(t);if(i==null||i.get(e)==null)this.warnDocumentChanged(e,t,s);else if(i.get(e)<=1)if(i.size<=1)n.delete(t);else i.delete(e);else i.set(e,i.get(e)-1);if(this._index.get(s).size===0)this._index.delete(s)}warnDocumentChanged(t,e,s){for(let n of Object.keys(this._fieldIds))if(this._fieldIds[n]===e){this._options.logger("warn",`MiniSearch: document with ID ${this._documentIds.get(t)} has changed before removal: term "${s}" was not present in field "${n}". Removing a document after it has changed can corrupt the index!`,"version_conflict");return}}addDocumentId(t){let e=this._nextId;return this._idToShortId.set(t,e),this._documentIds.set(e,t),this._documentCount+=1,this._nextId+=1,e}addFields(t){for(let e=0;e<t.length;e++)this._fieldIds[t[e]]=e}addFieldLength(t,e,s,n){let i=this._fieldLength.get(t);if(i==null)this._fieldLength.set(t,i=[]);i[e]=n;let c=(this._avgFieldLength[e]||0)*s+n;this._avgFieldLength[e]=c/(s+1)}removeFieldLength(t,e,s,n){if(s===1){this._avgFieldLength[e]=0;return}let i=this._avgFieldLength[e]*s-n;this._avgFieldLength[e]=i/(s-1)}saveStoredFields(t,e){let{storeFields:s,extractField:n}=this._options;if(s==null||s.length===0)return;let i=this._storedFields.get(t);if(i==null)this._storedFields.set(t,i={});for(let r of s){let c=n(e,r);if(c!==void 0)i[r]=c}}}x.wildcard=Symbol("*");var O=(t,e)=>Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0,X={[N]:(t,e)=>{for(let s of e.keys()){let n=t.get(s);if(n==null)t.set(s,e.get(s));else{let{score:i,terms:r,match:c}=e.get(s);n.score=n.score+i,n.match=Object.assign(n.match,c),W(n.terms,r)}}return t},[K]:(t,e)=>{let s=new Map;for(let n of e.keys()){let i=t.get(n);if(i==null)continue;let{score:r,terms:c,match:o}=e.get(n);W(i.terms,c),s.set(n,{score:i.score+r,terms:i.terms,match:Object.assign(i.match,o)})}return s},[H]:(t,e)=>{for(let s of e.keys())t.delete(s);return t}},tt={k:1.2,b:0.7,d:0.5},et=(t,e,s,n,i,r)=>{let{k:c,b:o,d:u}=r;return Math.log(1+(s-e+0.5)/(e+0.5))*(u+t*(c+1)/(t+c*(1-o+o*n/i)))},st=(t)=>(e,s,n)=>{let i=typeof t.fuzzy==="function"?t.fuzzy(e,s,n):t.fuzzy||!1,r=typeof t.prefix==="function"?t.prefix(e,s,n):t.prefix===!0,c=typeof t.boostTerm==="function"?t.boostTerm(e,s,n):1;return{term:e,fuzzy:i,prefix:r,termBoost:c}},V={idField:"id",extractField:(t,e)=>t[e],stringifyField:(t,e)=>t.toString(),tokenize:(t)=>t.split(ot),processTerm:(t)=>t.toLowerCase(),fields:void 0,searchOptions:void 0,storeFields:[],logger:(t,e)=>{if(typeof(console===null||console===void 0?void 0:console[t])==="function")console[t](e)},autoVacuum:!0},P={combineWith:N,prefix:!1,fuzzy:!1,maxFuzzy:6,boost:{},weights:{fuzzy:0.45,prefix:0.375},bm25:tt},nt={combineWith:K,prefix:(t,e,s)=>e===s.length-1},T={batchSize:1000,batchWait:10},D={minDirtFactor:0.1,minDirtCount:20},C={...T,...D},it=(t,e)=>{if(!t.includes(e))t.push(e)},W=(t,e)=>{for(let s of e)if(!t.includes(s))t.push(s)},J=({score:t},{score:e})=>e-t,q=()=>new Map,b=(t)=>{let e=new Map;for(let s of Object.keys(t))e.set(parseInt(s,10),t[s]);return e},v=async(t)=>{let e=new Map,s=0;for(let n of Object.keys(t))if(e.set(parseInt(n,10),t[n]),++s%1000===0)await Y(0);return e},Y=(t)=>new Promise((e)=>setTimeout(e,t)),ot=/[\n\r\p{Z}\p{P}]+/u;var rt=new Set(("a an and are as at be but by can do does for from how i if in is it its me my of on or so that the their them then there these this to was what when where which who why will with you your au aux avec ce ces comment dans de des du elle en est et il je la le les leur ma mais me mes "+"mon ne nous on ou où par pas pour qu que quel quelle quels qui sa se ses son sont sur ta te tu "+"un une vos votre vous y").split(" ")),ct=0.05,ut=(t)=>t.normalize("NFD").replace(/\p{M}/gu,"").toLowerCase();function dt(t){return t.chunks.map((e)=>{let s=t.docs[e.doc];return{...e,url:s?.url??"",title:s?.title??""}})}function It(t){let e=dt(t),s=new x({fields:["title","heading","text"],processTerm:(n)=>{let i=ut(n);return i.length<2||rt.has(i)?null:i},searchOptions:{prefix:(n)=>n.length>3,fuzzy:(n)=>n.length>4?0.15:0,boost:{title:2,heading:1.5}}});return s.addAll(e.map((n,i)=>({id:i,title:n.title,heading:n.heading,text:n.text}))),{async search(n,{limit:i=6,budgetTokens:r=3000}={}){let c=[],o=0,u=s.search(n,{combineWith:"OR"}),d=(u[0]?.score??0)*ct;for(let a of u){if(a.score<d)break;let h=e[Number(a.id)];if(!h)continue;let f=Ye(h.text)+24;if(o+f>r)continue;if(o+=f,c.push(h),c.length>=i)break}return c}}}
2
2
  export{It};
@@ -0,0 +1,9 @@
1
+ import{xt,pt,St}from"./embed-q6y6vgv1.js";var E="script,style,noscript,template,svg,canvas,iframe,nav,header,footer,aside,form,button,dialog,[hidden],[aria-hidden='true'],[data-murmur-ignore],murmur-chat",O="main,article,[role='main'],body",y=/^(P|LI|DT|DD|PRE|BLOCKQUOTE|TABLE|TR|FIGCAPTION|DIV|SECTION|ARTICLE|UL|OL|DL|MAIN|H[1-6])$/;function g(i,{root:l=O,exclude:o=E}={}){let r=l.split(",").map((t)=>i.querySelector(t.trim())).find((t)=>!!t),p=r?.querySelector("h1")?.textContent?.replace(/\s+/g," ").trim()||i.querySelector("title")?.textContent?.trim()||"";if(!r)return{title:p,sections:[]};let u=[],e={heading:"",anchor:"",text:""},d=new Map,f=(t)=>{if(t.nodeType===3){e.text+=(t.textContent??"").replace(/\s+/g," ");return}if(t.nodeType!==1)return;let n=t;if(n.matches(o))return;let s=n.tagName.toUpperCase();if(/^H[1-3]$/.test(s)){u.push(e);let c=(n.textContent??"").replace(/\s+/g," ").trim(),m=n.id||n.closest("[id]")?.id||"";if(!m){let a=pt(c),x=d.get(a)??0;d.set(a,x+1),m=x?`${a}-${x}`:a}e={heading:c,anchor:m,text:""};return}if(s==="BR")e.text+=`
2
+ `;let h=y.test(s);if(h)e.text+=`
3
+
4
+ `;if(s==="LI")e.text+="- ";for(let c of Array.from(n.childNodes))f(c);if(h)e.text+=`
5
+
6
+ `};for(let t of Array.from(r.childNodes))f(t);return u.push(e),{title:p,sections:u.map((t)=>({...t,text:t.text.replace(/[ \t]+\n/g,`
7
+ `).replace(/\n{3,}/g,`
8
+
9
+ `).trim()})).filter((t)=>t.text)}}function T(i,l=i.location?.href??"",o={}){let r=g(i,o);return St([{url:l,title:r.title,sections:r.sections}],o.maxChunk??xt)}export{T as indexDocument};
@@ -1,4 +1,4 @@
1
- import{Ct}from"./embed-n7jskdxd.js";import{It}from"./embed-we24qtes.js";import{Ye,qt,Nt,Lt}from"./embed-2xm309sb.js";function M(e,n){let t=[...n].reverse().find((s)=>s.role==="user");return Ye(e)<12&&t?`${t.content} ${e}`:e}function w(e){let n=e.retriever??(e.index?It(e.index):null)??(()=>{throw Error("murmur: pass `index` or `retriever`.")})();return{retriever:n,async ask(t,{history:s=[],signal:u}={}){let i={};if(e.limit!==void 0)i.limit=e.limit;if(e.budgetTokens!==void 0)i.budgetTokens=e.budgetTokens;let o=await n.search(M(t,s),i),d=[e.instructions?.trim(),Nt(e.language),o.length?`Sources:
1
+ import{Ct}from"./embed-n7jskdxd.js";import{It}from"./embed-pnm9593k.js";import{Ye,qt,Nt,Lt}from"./embed-2xm309sb.js";function M(e,n){let t=[...n].reverse().find((s)=>s.role==="user");return Ye(e)<12&&t?`${t.content} ${e}`:e}function w(e){let n=e.retriever??(e.index?It(e.index):null)??(()=>{throw Error("murmur: pass `index` or `retriever`.")})();return{retriever:n,async ask(t,{history:s=[],signal:u}={}){let i={};if(e.limit!==void 0)i.limit=e.limit;if(e.budgetTokens!==void 0)i.budgetTokens=e.budgetTokens;let o=await n.search(M(t,s),i),d=[e.instructions?.trim(),Nt(e.language),o.length?`Sources:
2
2
 
3
3
  ${qt(o)}`:"Sources: none matched this question. Say you could not find it on this site."].filter(Boolean).join(`
4
4
 
@@ -1,8 +1,8 @@
1
- import{G,gn,kt}from"./embed-2xm309sb.js";gn(import.meta.url,["dehtcj0y","11c9cspb","e0j28zmb","zrmby2xc","5vkc01ns","k9mmdcz5","e5entetm","2xm309sb","hn0r8fmg","q6y6vgv1","n7jskdxd","we24qtes","t87kf8t0","dhy4fp4c","w7nkjk5e","qha5xyx4","16bekg8b","za7hc1fv","kk9hgxdc","sgjh2kg2","59r4jck6"],[["./murmur.js",7],["./index-11c9cspb.js",8],["./chunk-e0j28zmb.js",9],["./index-zrmby2xc.js",9],["./murmur-5vkc01ns.js",10,11,7],["./retriever-k9mmdcz5.js",11],["./index-e5entetm.js",8],["./embed-2xm309sb.js"],["./embed-hn0r8fmg.js",7],["./embed-q6y6vgv1.js"],["./embed-n7jskdxd.js",7,19],["./embed-we24qtes.js",7],["./browser-t87kf8t0.js"],["./openai-dhy4fp4c.js",8,7,19],["./anthropic-w7nkjk5e.js",8,20,19],["./google-qha5xyx4.js",8,20,19],["./mistral-16bekg8b.js",8,19],["./openai-compatible-za7hc1fv.js",8,19],["./index-kk9hgxdc.js",10],["./embed-sgjh2kg2.js"],["./embed-59r4jck6.js",19]],0);
2
- var D={open:"Ask a question",close:"Close",title:"Ask this site",greeting:"Hi! Ask me anything about this site. I answer from its pages and link to them.",placeholder:"Your question…",send:"Send",stop:"Stop",settings:"AI settings",back:"Back to chat",sources:"Sources",notFound:"Nothing on this site matched. Try other words?",thinking:"Looking through the site…",newChat:"New conversation",poweredBy:"Answers from this site's pages, by murmur",errorAuth:"The key was refused. Check it in the AI settings.",errorNetwork:"No answer from the AI provider: key refused or network down.",errorRate:"The AI provider is busy or rate-limited. Try again in a moment.",errorOther:"The answer failed:",retry:"Try again",setupTitle:"Connect an AI model",setupIntro:"This site lets you use your own AI key. It stays in your browser, encrypted, and is only sent to the provider you pick.",provider:"Provider",model:"Model",apiKey:"API key",apiKeyHint:"Sent only to the provider, never to this site.",remember:"Remember on this device",local:"Local server (Ollama, LM Studio)",localHint:"The server must allow this site's origin (CORS).",endpoint:"Server URL",test:"Test",testing:"Testing…",testOk:"Connected.",testFail:"Connection failed:",save:"Save and chat",forget:"Forget my key",loadingCatalog:"Loading models…",catalogError:"Could not load the model list.",searchModels:"Search models",recommended:"Recommended",otherProviders:"Other providers"},J={open:"Poser une question",close:"Fermer",title:"Demandez au site",greeting:"Bonjour ! Posez-moi une question sur ce site. Je réponds à partir de ses pages, avec les liens.",placeholder:"Votre question…",send:"Envoyer",stop:"Arrêter",settings:"Réglages IA",back:"Retour au chat",sources:"Sources",notFound:"Rien sur ce site ne correspond. Essayez d'autres mots ?",thinking:"Je cherche dans le site…",newChat:"Nouvelle conversation",poweredBy:"Réponses tirées des pages de ce site, par murmur",errorAuth:"La clé a été refusée. Vérifiez-la dans les réglages IA.",errorNetwork:"Pas de réponse du fournisseur d'IA : clé refusée ou réseau coupé.",errorRate:"Le fournisseur d'IA est saturé ou limite les appels. Réessayez dans un instant.",errorOther:"La réponse a échoué :",retry:"Réessayer",setupTitle:"Connecter un modèle d'IA",setupIntro:"Ce site vous laisse utiliser votre propre clé d'IA. Elle reste dans votre navigateur, chiffrée, et n'est envoyée qu'au fournisseur choisi.",provider:"Fournisseur",model:"Modèle",apiKey:"Clé API",apiKeyHint:"Envoyée uniquement au fournisseur, jamais à ce site.",remember:"Mémoriser sur cet appareil",local:"Serveur local (Ollama, LM Studio)",localHint:"Le serveur doit autoriser l'origine de ce site (CORS).",endpoint:"URL du serveur",test:"Tester",testing:"Test…",testOk:"Connecté.",testFail:"Échec de la connexion :",save:"Enregistrer et discuter",forget:"Oublier ma clé",loadingCatalog:"Chargement des modèles…",catalogError:"Impossible de charger la liste des modèles.",searchModels:"Chercher un modèle",recommended:"Recommandés",otherProviders:"Autres fournisseurs"},F={en:D,fr:J};function V(...e){for(let i of e){let n=i?.toLowerCase().split(/[-_]/)[0];if(n&&n in F)return n}return"en"}function P(e,i={}){return{...F[e]??D,...i}}var Z={chat:'<path d="M4 6.5A2.5 2.5 0 0 1 6.5 4h11A2.5 2.5 0 0 1 20 6.5v7a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.4c-.5.4-1.3 0-1.3-.6V6.5Z"/><path d="M8.5 9h7M8.5 12h4.5"/>',close:'<path d="M6 6l12 12M18 6 6 18"/>',send:'<path d="M12 19V5M6 11l6-6 6 6"/>',stop:'<rect x="7" y="7" width="10" height="10" rx="1.5"/>',settings:'<path d="M4 7h9M17 7h3M4 17h3M11 17h9"/><circle cx="15" cy="7" r="2"/><circle cx="9" cy="17" r="2"/>',reset:'<path d="M5 12a7 7 0 1 0 2.1-5"/><path d="M5 4.5V8h3.5"/>',back:'<path d="M14.5 6 8.5 12l6 6"/>',check:'<path d="m5.5 12.5 4 4 9-9"/>',key:'<circle cx="8" cy="15" r="3.5"/><path d="m10.5 12.5 8-8M16 7l2 2M14 9l1.5 1.5"/>'};function R(e,i){let n=e.createElement("template");return n.innerHTML=`<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${Z[i]??""}</svg>`,n.content.firstElementChild}var Q=/^(https?:\/\/|\/|#|\.\/|mailto:)/i;function k(e,i,n,t){let s=/(`[^`]+`)|(\*\*[^*]+\*\*)|(\*[^*\s][^*]*\*|_[^_\s][^_]*_)|(\[[^\]]+\]\([^)\s]+\))|(\[\d{1,2}\])/g,a=0;for(let c of i.matchAll(s)){let p=c.index??0;if(p>a)t.appendChild(e.createTextNode(i.slice(a,p)));a=p+c[0].length;let o=c[0];if(c[1]){let l=e.createElement("code");l.textContent=o.slice(1,-1),t.appendChild(l)}else if(c[2]){let l=e.createElement("strong");k(e,o.slice(2,-2),n,l),t.appendChild(l)}else if(c[3]){let l=e.createElement("em");k(e,o.slice(1,-1),n,l),t.appendChild(l)}else if(c[4]){let l=o.indexOf("]("),d=o.slice(1,l),u=o.slice(l+2,-1);if(Q.test(u)){let h=e.createElement("a");if(h.href=u,h.textContent=d,/^https?:/i.test(u))h.target="_blank",h.rel="noopener noreferrer";t.appendChild(h)}else t.appendChild(e.createTextNode(d))}else{let l=n(Number(o.slice(1,-1)));t.appendChild(l??e.createTextNode(o))}}if(a<i.length)t.appendChild(e.createTextNode(i.slice(a)))}function j(e,i,n){let t=e.ownerDocument,s=t.createDocumentFragment(),a=i.replace(/\r\n?/g,`
1
+ import{G,gn,kt}from"./embed-2xm309sb.js";gn(import.meta.url,["5fjz22kb","11c9cspb","e0j28zmb","hv290nbv","bnm335nb","m8peqj5t","e5entetm","2xm309sb","hn0r8fmg","q6y6vgv1","n7jskdxd","pnm9593k","t87kf8t0","dhy4fp4c","w7nkjk5e","qha5xyx4","16bekg8b","za7hc1fv","kk9hgxdc","sgjh2kg2","59r4jck6"],[["./murmur.js",7],["./index-11c9cspb.js",8],["./chunk-e0j28zmb.js",9],["./index-hv290nbv.js",9],["./murmur-bnm335nb.js",10,11,7],["./retriever-m8peqj5t.js",11],["./index-e5entetm.js",8],["./embed-2xm309sb.js"],["./embed-hn0r8fmg.js",7],["./embed-q6y6vgv1.js"],["./embed-n7jskdxd.js",7,19],["./embed-pnm9593k.js",7],["./browser-t87kf8t0.js"],["./openai-dhy4fp4c.js",8,7,19],["./anthropic-w7nkjk5e.js",8,20,19],["./google-qha5xyx4.js",8,20,19],["./mistral-16bekg8b.js",8,19],["./openai-compatible-za7hc1fv.js",8,19],["./index-kk9hgxdc.js",10],["./embed-sgjh2kg2.js"],["./embed-59r4jck6.js",19]],0);
2
+ var F={open:"Ask a question",close:"Close",title:"Ask this site",greeting:"Hi! Ask me anything about this site. I answer from its pages and link to them.",placeholder:"Your question…",send:"Send",stop:"Stop",settings:"AI settings",back:"Back to chat",sources:"Sources",notFound:"Nothing on this site matched. Try other words?",thinking:"Looking through the site…",newChat:"New conversation",poweredBy:"Answers from this site's pages, by murmur",errorAuth:"The key was refused. Check it in the AI settings.",errorNetwork:"No answer from the AI provider: key refused or network down.",errorRate:"The AI provider is busy or rate-limited. Try again in a moment.",errorOther:"The answer failed:",retry:"Try again",setupTitle:"Connect an AI model",setupIntro:"This site lets you use your own AI key. It stays in your browser, encrypted, and is only sent to the provider you pick.",provider:"Provider",model:"Model",apiKey:"API key",apiKeyHint:"Sent only to the provider, never to this site.",remember:"Remember on this device",local:"Local server (Ollama, LM Studio)",localHint:"The server must allow this site's origin (CORS).",endpoint:"Server URL",test:"Test",testing:"Testing…",testOk:"Connected.",testFail:"Connection failed:",save:"Save and chat",forget:"Forget my key",loadingCatalog:"Loading models…",catalogError:"Could not load the model list.",searchModels:"Search models",recommended:"Recommended",otherProviders:"Other providers"},Z={open:"Poser une question",close:"Fermer",title:"Demandez au site",greeting:"Bonjour ! Posez-moi une question sur ce site. Je réponds à partir de ses pages, avec les liens.",placeholder:"Votre question…",send:"Envoyer",stop:"Arrêter",settings:"Réglages IA",back:"Retour au chat",sources:"Sources",notFound:"Rien sur ce site ne correspond. Essayez d'autres mots ?",thinking:"Je cherche dans le site…",newChat:"Nouvelle conversation",poweredBy:"Réponses tirées des pages de ce site, par murmur",errorAuth:"La clé a été refusée. Vérifiez-la dans les réglages IA.",errorNetwork:"Pas de réponse du fournisseur d'IA : clé refusée ou réseau coupé.",errorRate:"Le fournisseur d'IA est saturé ou limite les appels. Réessayez dans un instant.",errorOther:"La réponse a échoué :",retry:"Réessayer",setupTitle:"Connecter un modèle d'IA",setupIntro:"Ce site vous laisse utiliser votre propre clé d'IA. Elle reste dans votre navigateur, chiffrée, et n'est envoyée qu'au fournisseur choisi.",provider:"Fournisseur",model:"Modèle",apiKey:"Clé API",apiKeyHint:"Envoyée uniquement au fournisseur, jamais à ce site.",remember:"Mémoriser sur cet appareil",local:"Serveur local (Ollama, LM Studio)",localHint:"Le serveur doit autoriser l'origine de ce site (CORS).",endpoint:"URL du serveur",test:"Tester",testing:"Test…",testOk:"Connecté.",testFail:"Échec de la connexion :",save:"Enregistrer et discuter",forget:"Oublier ma clé",loadingCatalog:"Chargement des modèles…",catalogError:"Impossible de charger la liste des modèles.",searchModels:"Chercher un modèle",recommended:"Recommandés",otherProviders:"Autres fournisseurs"},V={en:F,fr:Z};function j(...e){for(let n of e){let i=n?.toLowerCase().split(/[-_]/)[0];if(i&&i in V)return i}return"en"}function P(e,n={}){return{...V[e]??F,...n}}var Q={chat:'<path d="M4 6.5A2.5 2.5 0 0 1 6.5 4h11A2.5 2.5 0 0 1 20 6.5v7a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.4c-.5.4-1.3 0-1.3-.6V6.5Z"/><path d="M8.5 9h7M8.5 12h4.5"/>',close:'<path d="M6 6l12 12M18 6 6 18"/>',send:'<path d="M12 19V5M6 11l6-6 6 6"/>',stop:'<rect x="7" y="7" width="10" height="10" rx="1.5"/>',settings:'<path d="M4 7h9M17 7h3M4 17h3M11 17h9"/><circle cx="15" cy="7" r="2"/><circle cx="9" cy="17" r="2"/>',reset:'<path d="M5 12a7 7 0 1 0 2.1-5"/><path d="M5 4.5V8h3.5"/>',back:'<path d="M14.5 6 8.5 12l6 6"/>',check:'<path d="m5.5 12.5 4 4 9-9"/>',key:'<circle cx="8" cy="15" r="3.5"/><path d="m10.5 12.5 8-8M16 7l2 2M14 9l1.5 1.5"/>'};function R(e,n){let i=e.createElement("template");return i.innerHTML=`<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${Q[n]??""}</svg>`,i.content.firstElementChild}var X=/^(https?:\/\/|\/|#|\.\/|mailto:)/i;function k(e,n,i,t){let s=/(`[^`]+`)|(\*\*[^*]+\*\*)|(\*[^*\s][^*]*\*|_[^_\s][^_]*_)|(\[[^\]]+\]\([^)\s]+\))|(\[\d{1,2}\])/g,a=0;for(let c of n.matchAll(s)){let p=c.index??0;if(p>a)t.appendChild(e.createTextNode(n.slice(a,p)));a=p+c[0].length;let o=c[0];if(c[1]){let l=e.createElement("code");l.textContent=o.slice(1,-1),t.appendChild(l)}else if(c[2]){let l=e.createElement("strong");k(e,o.slice(2,-2),i,l),t.appendChild(l)}else if(c[3]){let l=e.createElement("em");k(e,o.slice(1,-1),i,l),t.appendChild(l)}else if(c[4]){let l=o.indexOf("]("),d=o.slice(1,l),u=o.slice(l+2,-1);if(X.test(u)){let h=e.createElement("a");if(h.href=u,h.textContent=d,/^https?:/i.test(u))h.target="_blank",h.rel="noopener noreferrer";t.appendChild(h)}else t.appendChild(e.createTextNode(d))}else{let l=i(Number(o.slice(1,-1)));t.appendChild(l??e.createTextNode(o))}}if(a<n.length)t.appendChild(e.createTextNode(n.slice(a)))}function U(e,n,i){let t=e.ownerDocument,s=t.createDocumentFragment(),a=n.replace(/\r\n?/g,`
3
3
  `).split(`
4
- `),c=[],p=null,o=()=>{if(!c.length)return;let d=t.createElement("p");k(t,c.join(" "),n,d),s.appendChild(d),c=[]},l=()=>{p=null};for(let d=0;d<a.length;d++){let u=a[d]??"";if(/^\s*```/.exec(u)){o(),l();let m=[];for(d++;d<a.length&&!/^\s*```/.test(a[d]??"");d++)m.push(a[d]??"");let x=t.createElement("pre"),M=t.createElement("code");M.textContent=m.join(`
5
- `),x.appendChild(M),s.appendChild(x);continue}let b=/^\s*(?:([-*+])|(\d+)[.)])\s+(.*)$/.exec(u);if(b){o();let m=b[1]?"ul":"ol";if(!p||p.tagName.toLowerCase()!==m)p=t.createElement(m),s.appendChild(p);let x=t.createElement("li");k(t,b[3]??"",n,x),p.appendChild(x);continue}let f=/^\s*#{1,6}\s+(.*)$/.exec(u);if(f){o(),l();let m=t.createElement("p"),x=t.createElement("strong");k(t,f[1]??"",n,x),m.appendChild(x),s.appendChild(m);continue}if(!u.trim()){o(),l();continue}if(p&&/^\s{2,}\S/.test(u)){let m=p.lastElementChild;if(m){m.appendChild(t.createTextNode(" ")),k(t,u.trim(),n,m);continue}}l(),c.push(u.trim())}o(),e.replaceChildren(s)}class O{options;turns=[];engine=null;storePromise=null;historyKey;constructor(e){this.options=e;this.historyKey=`${e.storageKey??"murmur"}-chat:${location.pathname.split("/")[1]??""}`;try{let i=sessionStorage.getItem(this.historyKey);if(i)this.turns=JSON.parse(i)}catch{this.turns=[]}}get mode(){if(this.options.model)return"custom";return this.options.llm?.endpoint?"proxy":"visitor"}persist(){try{sessionStorage.setItem(this.historyKey,JSON.stringify(this.turns.slice(-30)))}catch{}}clear(){this.turns=[],this.persist()}store(){return this.storePromise??=(G("11c9cspb"),import("./index-11c9cspb.js")).then((e)=>{let i={};if(this.options.catalogUrl)i.catalogUrl=this.options.catalogUrl;if(this.options.storageKey)i.storageKey=this.options.storageKey;return e.visitorStore(this.options.llm??{},i)}),this.storePromise}async settings(){if(this.mode==="custom")return null;let e=await (G("11c9cspb"),import("./index-11c9cspb.js"));return e.resolveSettings(this.options.llm??{},this.mode==="visitor"?await this.store():null)}async needsSetup(){return this.mode==="visitor"&&!await this.settings()}async loadIndex(){let{index:e}=this.options;if(e&&typeof e!=="string")return e;let{isMurmurIndex:i}=await (G("e0j28zmb"),import("./chunk-e0j28zmb.js"));if(e){let t=await fetch(new URL(e,location.href));if(!t.ok)throw Error(`murmur: index ${t.status}`);let s=await t.json();if(!i(s))throw Error("murmur: not a murmur index");return s}let{indexDocument:n}=await (G("zrmby2xc"),import("./index-zrmby2xc.js"));return n(document,location.pathname+location.search)}createEngine(){return(async()=>{let[{createMurmur:e},i]=await Promise.all([(G("5vkc01ns"),import("./murmur-5vkc01ns.js")),this.options.retriever??(G("k9mmdcz5"),import("./retriever-k9mmdcz5.js")).then(async(s)=>s.bm25Retriever(await this.loadIndex()))]),n=this.options.model??(async()=>{let s=await this.settings();if(!s)throw new C;let{loadModel:a}=await (G("11c9cspb"),import("./index-11c9cspb.js"));return a(s)}),t={retriever:i,model:n};if(this.options.instructions)t.instructions=this.options.instructions;if(this.options.lang)t.language=this.options.lang;return e(t)})()}async ask(e,i,n){let t=this.turns.filter((a)=>!a.error).map(({role:a,content:c})=>({role:a,content:c}));this.turns.push({role:"user",content:e});let s={role:"assistant",content:""};this.turns.push(s);try{this.engine??=this.createEngine();let c=await(await this.engine.catch((p)=>{throw this.engine=null,p})).ask(e,{history:t,signal:n});s.passages=c.passages.map(({url:p,anchor:o,title:l,heading:d})=>({url:p,anchor:o,title:l,heading:d}));for await(let p of c.textStream)s.content+=p,i(s.content,s);s.cited=(await c.done).cited}catch(a){if(n.aborted)s.cited=[];else if(a instanceof C)throw this.turns.splice(-2,2),a;else s.error=await this.describe(a)}finally{this.persist()}return s}async describe(e){try{let{describeError:i}=await (G("11c9cspb"),import("./index-11c9cspb.js")),n=this.mode==="custom"?null:await this.settings(),t=i(e,n?.apiKey);return`${t.code}|${t.message}`}catch{return`unknown|${e instanceof Error?e.message:String(e)}`}}}class C extends Error{constructor(){super("murmur: no model set up")}}var U=`
4
+ `),c=[],p=null,o=()=>{if(!c.length)return;let d=t.createElement("p");k(t,c.join(" "),i,d),s.appendChild(d),c=[]},l=()=>{p=null};for(let d=0;d<a.length;d++){let u=a[d]??"";if(/^\s*```/.exec(u)){o(),l();let m=[];for(d++;d<a.length&&!/^\s*```/.test(a[d]??"");d++)m.push(a[d]??"");let x=t.createElement("pre");x.tabIndex=0;let M=t.createElement("code");M.textContent=m.join(`
5
+ `),x.appendChild(M),s.appendChild(x);continue}let b=/^\s*(?:([-*+])|(\d+)[.)])\s+(.*)$/.exec(u);if(b){o();let m=b[1]?"ul":"ol";if(!p||p.tagName.toLowerCase()!==m)p=t.createElement(m),s.appendChild(p);let x=t.createElement("li");k(t,b[3]??"",i,x),p.appendChild(x);continue}let f=/^\s*#{1,6}\s+(.*)$/.exec(u);if(f){o(),l();let m=t.createElement("p"),x=t.createElement("strong");k(t,f[1]??"",i,x),m.appendChild(x),s.appendChild(m);continue}if(!u.trim()){o(),l();continue}if(p&&/^\s{2,}\S/.test(u)){let m=p.lastElementChild;if(m){m.appendChild(t.createTextNode(" ")),k(t,u.trim(),i,m);continue}}l(),c.push(u.trim())}o(),e.replaceChildren(s)}class O{options;turns=[];engine=null;storePromise=null;historyKey;constructor(e){this.options=e;this.historyKey=`${e.storageKey??"murmur"}-chat:${location.pathname.split("/")[1]??""}`;try{let n=sessionStorage.getItem(this.historyKey);if(n)this.turns=JSON.parse(n)}catch{this.turns=[]}}get mode(){if(this.options.model)return"custom";return this.options.llm?.endpoint?"proxy":"visitor"}persist(){try{sessionStorage.setItem(this.historyKey,JSON.stringify(this.turns.slice(-30)))}catch{}}clear(){this.turns=[],this.persist()}store(){return this.storePromise??=(G("11c9cspb"),import("./index-11c9cspb.js")).then((e)=>{let n={};if(this.options.catalogUrl)n.catalogUrl=this.options.catalogUrl;if(this.options.storageKey)n.storageKey=this.options.storageKey;return e.visitorStore(this.options.llm??{},n)}),this.storePromise}async settings(){if(this.mode==="custom")return null;let e=await (G("11c9cspb"),import("./index-11c9cspb.js"));return e.resolveSettings(this.options.llm??{},this.mode==="visitor"?await this.store():null)}async needsSetup(){return this.mode==="visitor"&&!await this.settings()}async loadIndex(){let{index:e}=this.options;if(e&&typeof e!=="string")return e;let{isMurmurIndex:n}=await (G("e0j28zmb"),import("./chunk-e0j28zmb.js"));if(e){let t=await fetch(new URL(e,location.href));if(!t.ok)throw Error(`murmur: index ${t.status}`);let s=await t.json();if(!n(s))throw Error("murmur: not a murmur index");return s}let{indexDocument:i}=await (G("hv290nbv"),import("./index-hv290nbv.js"));return i(document,location.pathname+location.search)}createEngine(){return(async()=>{let[{createMurmur:e},n]=await Promise.all([(G("bnm335nb"),import("./murmur-bnm335nb.js")),this.options.retriever??(G("m8peqj5t"),import("./retriever-m8peqj5t.js")).then(async(s)=>s.bm25Retriever(await this.loadIndex()))]),i=this.options.model??(async()=>{let s=await this.settings();if(!s)throw new L;let{loadModel:a}=await (G("11c9cspb"),import("./index-11c9cspb.js"));return a(s)}),t={retriever:n,model:i};if(this.options.instructions)t.instructions=this.options.instructions;if(this.options.lang)t.language=this.options.lang;return e(t)})()}async ask(e,n,i){let t=this.turns.filter((a)=>!a.error).map(({role:a,content:c})=>({role:a,content:c}));this.turns.push({role:"user",content:e});let s={role:"assistant",content:""};this.turns.push(s),this.persist();try{this.engine??=this.createEngine();let c=await(await this.engine.catch((p)=>{throw this.engine=null,p})).ask(e,{history:t,signal:i});s.passages=c.passages.map(({url:p,anchor:o,title:l,heading:d})=>({url:p,anchor:o,title:l,heading:d}));for await(let p of c.textStream)s.content+=p,n(s.content,s);s.cited=(await c.done).cited}catch(a){if(i.aborted)s.cited=[];else if(a instanceof L)throw this.turns.splice(-2,2),a;else s.error=await this.describe(a)}finally{this.persist()}return s}async describe(e){try{let{describeError:n}=await (G("11c9cspb"),import("./index-11c9cspb.js")),i=this.mode==="custom"?null:await this.settings(),t=n(e,i?.apiKey);return`${t.code}|${t.message}`}catch{return`unknown|${e instanceof Error?e.message:String(e)}`}}}class L extends Error{constructor(){super("murmur: no model set up")}}var W=`
6
6
  :host {
7
7
  --accent: var(--murmur-accent, #211c17);
8
8
  --accent-ink: var(--murmur-accent-ink, #f6efe0);
@@ -201,4 +201,4 @@ footer a:hover { text-decoration: underline; }
201
201
  @media (prefers-reduced-motion: reduce) {
202
202
  *, .panel { animation: none !important; transition: none !important; }
203
203
  }
204
- `;var X={auth:"errorAuth","auth-or-network":"errorNetwork","rate-limit":"errorRate",overloaded:"errorRate"};class K extends HTMLElement{options={};session=null;t=P("en");root;launcher;panel;log;chatView;setupView;input;sendBtn;settingsBtn;controller=null;built=!1;unsubscribe=null;constructor(){super();this.root=this.attachShadow({mode:"open"})}configure(e){if(this.options={...this.options,...e},this.isConnected)this.build();return this}get isOpen(){return this.hasAttribute("inline")||this.launcher?.getAttribute("aria-expanded")==="true"}connectedCallback(){this.build()}disconnectedCallback(){this.controller?.abort(),this.unsubscribe?.()}async open(){if(!this.built)this.build();this.launcher.setAttribute("aria-expanded","true"),this.panel.hidden=!1,this.session?.persist(),sessionStorage.setItem(this.openKey,"1"),this.input.focus()}close(){if(this.hasAttribute("inline"))return;this.launcher.setAttribute("aria-expanded","false"),this.panel.hidden=!0,sessionStorage.removeItem(this.openKey),this.launcher.focus()}async ask(e){if(!this.isOpen)await this.open();this.input.value=e,await this.submit()}get openKey(){return`${this.options.storageKey??"murmur"}-open`}build(){let e=this.options,i=V(e.lang,document.documentElement.lang,navigator.language),n={...e.messages};if(this.t=P(i,n),e.position)this.setAttribute("position",e.position);if(e.theme&&e.theme!=="auto")this.setAttribute("theme",e.theme);if(e.accent)this.style.setProperty("--murmur-accent",e.accent);this.controller?.abort(),this.unsubscribe?.();let t=this.ownerDocument,s=t.createElement("style");s.textContent=U,this.launcher=r(t,"button",{class:"launcher",type:"button","aria-expanded":"false"}),this.launcher.setAttribute("aria-controls","murmur-panel"),this.launcher.append(r(t,"span",{class:"lamp","aria-hidden":"true"}),v(t,"span",this.t.open)),this.launcher.addEventListener("click",()=>void this.open()),this.panel=r(t,"section",{class:"panel",id:"murmur-panel",role:"dialog"}),this.panel.setAttribute("aria-label",this.t.title),this.panel.hidden=!this.hasAttribute("inline"),this.panel.addEventListener("keydown",(h)=>{if(h.key==="Escape")this.close()});let a=r(t,"header"),c=v(t,"h2",this.t.title),p=N(t,"reset",this.t.newChat);p.addEventListener("click",()=>{this.controller?.abort(),this.session?.clear(),this.renderChat(),this.input.focus()}),this.settingsBtn=N(t,"settings",this.t.settings),this.settingsBtn.hidden=!!e.model||!!e.llm?.endpoint,this.settingsBtn.addEventListener("click",()=>void this.showSetup());let o=N(t,"close",this.t.close);o.hidden=this.hasAttribute("inline"),o.addEventListener("click",()=>this.close()),a.append(c,p,this.settingsBtn,o),this.chatView=r(t,"div",{class:"chat"}),this.chatView.style.cssText="display:flex;flex-direction:column;flex:1;min-height:0",this.log=r(t,"div",{class:"log",role:"log","aria-live":"polite","aria-relevant":"additions"});let l=r(t,"form",{class:"composer"});this.input=r(t,"textarea",{rows:"1",placeholder:this.t.placeholder}),this.input.setAttribute("aria-label",this.t.placeholder),this.input.addEventListener("input",()=>this.autosize()),this.input.addEventListener("keydown",(h)=>{if(h.key==="Enter"&&!h.shiftKey&&!h.isComposing)h.preventDefault(),this.submit()}),this.sendBtn=r(t,"button",{class:"send",type:"submit"}),this.setSendMode("send"),l.addEventListener("submit",(h)=>{if(h.preventDefault(),this.controller)this.controller.abort();else this.submit()}),l.append(this.input,this.sendBtn);let d=r(t,"footer"),u=r(t,"a",{href:"https://maxgfr.github.io/murmur/",target:"_blank",rel:"noopener"});if(u.textContent=this.t.poweredBy,d.append(u),this.chatView.append(this.log,l,d),this.setupView=r(t,"div",{class:"setup"}),this.setupView.hidden=!0,this.panel.append(a,this.chatView,this.setupView),this.root.replaceChildren(s,this.launcher,this.panel),this.hasAttribute("inline"))this.launcher.hidden=!0;if(this.built=!0,this.session=new O({...e,lang:i}),this.renderChat(),e.open||!this.hasAttribute("inline")&&sessionStorage.getItem(this.openKey))this.open()}autosize(){this.input.style.height="auto",this.input.style.height=`${Math.min(this.input.scrollHeight,140)}px`}setSendMode(e){this.sendBtn.replaceChildren(R(this.ownerDocument,e)),this.sendBtn.setAttribute("aria-label",e==="send"?this.t.send:this.t.stop)}emit(e){this.dispatchEvent(new CustomEvent("murmur:state",{detail:e,bubbles:!0,composed:!0}))}renderChat(){let e=this.ownerDocument,i=this.session?.turns??[],n=[],t=r(e,"div",{class:"msg bot greeting"});t.append(v(e,"p",this.t.greeting)),n.push(t);for(let s of i)n.push(this.turnNode(s));this.log.replaceChildren(...n),this.log.scrollTop=this.log.scrollHeight}turnNode(e){let i=this.ownerDocument;if(e.role==="user"){let t=r(i,"div",{class:"msg user"});return t.textContent=e.content,t}let n=r(i,"div",{class:"msg bot"});return this.fillAnswer(n,e,!0),n}fillAnswer(e,i,n){let t=this.ownerDocument;if(i.error){let[o="unknown",...l]=i.error.split("|"),d=X[o],u=r(t,"div",{class:"error",role:"alert"});u.append(v(t,"p",d?this.t[d]:`${this.t.errorOther} ${l.join("|")}`));let h=r(t,"div",{class:"row"}),b=r(t,"button",{class:"text-btn",type:"button"});if(b.textContent=this.t.retry,b.addEventListener("click",()=>{let f=this.session?.turns??[],m=f.at(-2)?.content??"";if(f.splice(-2,2),this.renderChat(),m)this.ask(m)}),h.append(b),o==="auth"||o==="auth-or-network"){if(!this.settingsBtn.hidden){let f=r(t,"button",{class:"text-btn",type:"button"});f.textContent=this.t.settings,f.addEventListener("click",()=>void this.showSetup()),h.append(f)}}u.append(h),e.replaceChildren(u);return}let s=i.passages??[],a=r(t,"div");j(a,i.content,(o)=>{let l=s[o-1];if(!l)return null;let d=r(t,"a",{class:"cite",href:kt(l)});return d.textContent=String(o),d.setAttribute("aria-label",`${this.t.sources} ${o}: ${l.title}`),d});let c=[a];if(n&&!i.content.trim()&&!s.length){let o=r(t,"p",{class:"status"});o.append(r(t,"span",{class:"lamp off","aria-hidden":"true"}),t.createTextNode(this.t.notFound)),c.push(o)}let p=i.cited??[];if(n&&p.length){c.push(v(t,"p",this.t.sources,"sources-label"));let o=r(t,"ol",{class:"sources"});for(let l of p){let d=s[l-1];if(!d)continue;let u=r(t,"li"),h=r(t,"a",{href:kt(d)}),b=v(t,"span",String(l),"cite");b.setAttribute("aria-hidden","true");let f=r(t,"span",{class:"where"});if(f.append(t.createTextNode(d.title||d.url)),d.heading&&d.heading!==d.title)f.append(v(t,"span",` › ${d.heading}`));h.append(b,f),u.append(h),o.append(u)}c.push(o)}e.replaceChildren(...c)}async submit(){let e=this.input.value.trim();if(!e||this.controller||!this.session)return;if(await this.session.needsSetup()){await this.showSetup(e);return}let i=this.ownerDocument;this.input.value="",this.autosize(),this.log.append(this.turnNode({role:"user",content:e}));let n=r(i,"div",{class:"msg bot"}),t=r(i,"p",{class:"status"});t.append(r(i,"span",{class:"lamp busy","aria-hidden":"true"}),i.createTextNode(this.t.thinking)),n.append(t),this.log.append(n),this.log.scrollTop=this.log.scrollHeight,this.log.setAttribute("aria-busy","true");let s=new AbortController;this.controller=s,this.setSendMode("stop"),this.emit({state:"searching"});let a=!1;try{let c=await this.session.ask(e,(p,o)=>{if(!a)a=!0,this.emit({state:"streaming",passages:o.passages??[]});let l=this.log.scrollHeight-this.log.scrollTop-this.log.clientHeight<40;if(this.fillAnswer(n,o,!1),l)this.log.scrollTop=this.log.scrollHeight},s.signal);this.fillAnswer(n,c,!0),this.emit(c.error?{state:"error"}:{state:"done",passages:c.passages??[],cited:c.cited??[]})}catch(c){if(n.remove(),this.log.lastElementChild?.remove(),this.emit({state:"idle"}),c instanceof C)await this.showSetup(e);else throw c}finally{this.controller=null,this.setSendMode("send"),this.log.setAttribute("aria-busy","false"),this.log.scrollTop=this.log.scrollHeight}}async showSetup(e){if(!this.session)return;let i=this.ownerDocument,n=await this.session.store();await n.load(),n.open(),this.chatView.hidden=!0,this.setupView.hidden=!1;let t=this.t,s=r(i,"button",{class:"link-btn",type:"button"});s.textContent=t.back,s.addEventListener("click",()=>this.hideSetup());let a=v(i,"h3",t.setupTitle);a.style.cssText="margin:0;font-size:17px;font-weight:650";let c=v(i,"p",t.setupIntro,"intro"),p=W(i,t.local),o=L(i,t.provider,r(i,"select")),l=o.control,d=L(i,t.model,r(i,"select")),u=d.control,h=L(i,t.endpoint,r(i,"input",{type:"url",inputmode:"url"}),t.localHint),b=h.control,f=L(i,t.model,r(i,"input",{type:"text",autocomplete:"off"})),m=f.control,x=r(i,"div",{class:"presets"});for(let g of["ollama","lmstudio"]){let y=r(i,"button",{class:"text-btn",type:"button"});y.textContent=g==="ollama"?"Ollama":"LM Studio",y.addEventListener("click",async()=>{let{ENDPOINT_PRESETS:w}=await (G("e5entetm"),import("./index-e5entetm.js"));n.applyPreset(w[g])}),x.append(y)}let M=L(i,t.apiKey,r(i,"input",{type:"password",autocomplete:"off",spellcheck:"false"}),t.apiKeyHint),S=M.control,T=W(i,t.remember),E=r(i,"button",{class:"text-btn",type:"button"});E.textContent=t.test;let H=r(i,"p",{class:"result",role:"status"});H.style.margin="0";let A=r(i,"button",{class:"primary",type:"button"});A.textContent=t.save;let I=r(i,"button",{class:"link-btn",type:"button"});I.textContent=t.forget,p.input.addEventListener("change",()=>n.toggleCustom(p.input.checked)),l.addEventListener("change",()=>n.selectProvider(l.value)),u.addEventListener("change",()=>n.selectModel(u.value)),b.addEventListener("input",()=>n.setEndpoint(b.value)),m.addEventListener("input",()=>n.setCustomModel(m.value)),S.addEventListener("input",()=>n.setApiKey(S.value)),T.input.addEventListener("change",()=>n.setRememberKey(T.input.checked)),E.addEventListener("click",()=>void n.test()),A.addEventListener("click",async()=>{if(!(await n.save()).ok)return;if(this.hideSetup(),e)this.input.value=e,this.submit()}),I.addEventListener("click",()=>void n.clear());let z=r(i,"div",{class:"row"});z.append(E,H),this.setupView.replaceChildren(s,a,c,p.label,o.label,d.label,x,h.label,f.label,M.label,T.label,z,A,I);let Y=(g)=>{let y=g.draft.custom;if(p.input.checked=y,o.label.hidden=y,d.label.hidden=y,x.hidden=!y,h.label.hidden=!y,f.label.hidden=!y,g.catalogStatus==="ready")ee(i,l,g,t),te(i,u,g);else l.replaceChildren(B(i,"",g.catalogStatus==="error"?t.catalogError:t.loadingCatalog)),u.replaceChildren();if(b!==this.root.activeElement)b.value=g.draft.customEndpoint;if(m!==this.root.activeElement)m.value=g.draft.customModel;if(S!==this.root.activeElement)S.value=g.apiKey;T.input.checked=g.draft.rememberKey,E.disabled=!g.canTest||g.testing,E.textContent=g.testing?t.testing:t.test,A.disabled=!g.canSave;let w=g.testResult;H.className=w?w.ok?"result ok":"result fail":"result",H.textContent=!w?"":w.ok?t.testOk:`${t.testFail} ${w.reason}${w.message?` (${w.message})`:""}`};this.unsubscribe?.(),this.unsubscribe=n.subscribe(Y),(n.getState().draft.custom?b:l).focus()}hideSetup(){this.unsubscribe?.(),this.unsubscribe=null,this.setupView.hidden=!0,this.chatView.hidden=!1,this.input.focus()}}function ee(e,i,n,t){let s=[[t.recommended,n.providers.recommended],[t.otherProviders,n.providers.others]],a=`${n.draft.providerId}|${n.providers.recommended.length+n.providers.others.length}`;if(i.dataset.sig===a)return;i.dataset.sig=a,i.replaceChildren(...s.filter(([,c])=>c.length).map(([c,p])=>{let o=e.createElement("optgroup");return o.label=c,o.append(...p.map((l)=>B(e,l.id,l.name))),o})),i.value=n.draft.providerId}function te(e,i,n){let t=`${n.draft.providerId}|${n.draft.model}|${n.models.length}`;if(i.dataset.sig===t)return;i.dataset.sig=t;let s=n.recommendedModel?.id;i.replaceChildren(...n.models.map((a)=>B(e,a.id,a.id===s?`${a.name} ★`:a.name))),i.value=n.draft.model}function r(e,i,n={}){let t=e.createElement(i);for(let[s,a]of Object.entries(n))t.setAttribute(s,a);return t}function v(e,i,n,t){let s=e.createElement(i);if(s.textContent=n,t)s.className=t;return s}function B(e,i,n){let t=e.createElement("option");return t.value=i,t.textContent=n,t}function N(e,i,n){let t=r(e,"button",{class:"icon-btn",type:"button",title:n});return t.setAttribute("aria-label",n),t.append(R(e,i)),t}function L(e,i,n,t){let s=r(e,"label",{class:"field"});if(s.append(v(e,"span",i),n),t)s.append(v(e,"small",t));return{label:s,control:n}}function W(e,i){let n=r(e,"label",{class:"check"}),t=r(e,"input",{type:"checkbox"});return n.append(t,e.createTextNode(i)),{label:n,input:t}}function ne(e="murmur-chat"){if(!customElements.get(e))customElements.define(e,class extends K{});return customElements.get(e)}function _(e={}){ne();let{target:i,inline:n,...t}=e,s=document.createElement("murmur-chat");if(n)s.setAttribute("inline","");return s.configure(t),(i??document.body).append(s),s}function ie(e,i){let n={};if(e.index)n.index=new URL(e.index,i).href;let t={};if(e.provider)t.provider=e.provider;if(e.model)t.model=e.model;if(e.endpoint)t.endpoint=e.endpoint;if(Object.keys(t).length)n.llm=t;if(e.instructions)n.instructions=e.instructions;if(e.lang)n.lang=e.lang;let s={};if(e.title)s.title=e.title;if(e.greeting)s.greeting=e.greeting;if(e.placeholder)s.placeholder=e.placeholder;if(e.button)s.open=e.button;if(Object.keys(s).length)n.messages=s;if(e.position==="bottom-left"||e.position==="bottom-right")n.position=e.position;if(e.theme==="light"||e.theme==="dark"||e.theme==="auto")n.theme=e.theme;if(e.accent)n.accent=e.accent;if(e.catalog)n.catalogUrl=new URL(e.catalog,i).href;if(e.storageKey)n.storageKey=e.storageKey;if(e.open==="true")n.open=!0;return n}function q(){let e=import.meta.url,i=[...document.querySelectorAll("script[src]")].find((t)=>t.src===e&&!t.dataset.murmurReady);if(i)i.dataset.murmurReady="true";let n=ie(i?.dataset??{},location.href);n.catalogUrl??=new URL("./models.json",e).href,_(n)}if(typeof document<"u"&&!document.querySelector("murmur-chat:not([inline])"))if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",q,{once:!0});else q();export{ie as optionsFromDataset};
204
+ `;var ee={auth:"errorAuth","auth-or-network":"errorNetwork","rate-limit":"errorRate",overloaded:"errorRate"},te=typeof HTMLElement>"u"?class{}:HTMLElement;class K extends te{options={};session=null;t=P("en");root;launcher;panel;log;chatView;setupView;input;sendBtn;settingsBtn;controller=null;built=!1;unsubscribe=null;constructor(){super();this.root=this.attachShadow({mode:"open"})}configure(e){if(this.options={...this.options,...e},this.isConnected)this.build();return this}get isOpen(){return this.hasAttribute("inline")||this.launcher?.getAttribute("aria-expanded")==="true"}connectedCallback(){this.build()}disconnectedCallback(){this.controller?.abort(),this.unsubscribe?.()}async open(){if(!this.built)this.build();this.launcher.setAttribute("aria-expanded","true"),this.panel.hidden=!1,this.session?.persist(),N("set",this.openKey),this.input.focus()}close(){if(this.hasAttribute("inline"))return;this.launcher.setAttribute("aria-expanded","false"),this.panel.hidden=!0,N("remove",this.openKey),this.launcher.focus()}async ask(e){if(!this.isOpen)await this.open();this.input.value=e,await this.submit()}get openKey(){return`${this.options.storageKey??"murmur"}-open`}build(){let e=this.options,n=j(e.lang,document.documentElement.lang,navigator.language),i={...e.messages};if(this.t=P(n,i),e.position)this.setAttribute("position",e.position);if(e.theme&&e.theme!=="auto")this.setAttribute("theme",e.theme);if(e.accent)this.style.setProperty("--murmur-accent",e.accent);this.controller?.abort(),this.unsubscribe?.();let t=this.ownerDocument,s=t.createElement("style");s.textContent=W,this.launcher=r(t,"button",{class:"launcher",type:"button","aria-expanded":"false"}),this.launcher.setAttribute("aria-controls","murmur-panel"),this.launcher.append(r(t,"span",{class:"lamp","aria-hidden":"true"}),v(t,"span",this.t.open)),this.launcher.addEventListener("click",()=>void this.open()),this.panel=r(t,"section",{class:"panel",id:"murmur-panel",role:"dialog"}),this.panel.setAttribute("aria-label",this.t.title),this.panel.hidden=!this.hasAttribute("inline"),this.panel.addEventListener("keydown",(h)=>{if(h.key==="Escape")this.close()});let a=r(t,"header"),c=v(t,"h2",this.t.title),p=B(t,"reset",this.t.newChat);p.addEventListener("click",()=>{this.controller?.abort(),this.session?.clear(),this.renderChat(),this.input.focus()}),this.settingsBtn=B(t,"settings",this.t.settings),this.settingsBtn.hidden=!!e.model||!!e.llm?.endpoint,this.settingsBtn.addEventListener("click",()=>void this.showSetup());let o=B(t,"close",this.t.close);o.hidden=this.hasAttribute("inline"),o.addEventListener("click",()=>this.close()),a.append(c,p,this.settingsBtn,o),this.chatView=r(t,"div",{class:"chat"}),this.chatView.style.cssText="display:flex;flex-direction:column;flex:1;min-height:0",this.log=r(t,"div",{class:"log",role:"log","aria-live":"polite","aria-relevant":"additions"});let l=r(t,"form",{class:"composer"});this.input=r(t,"textarea",{rows:"1",placeholder:this.t.placeholder}),this.input.setAttribute("aria-label",this.t.placeholder),this.input.addEventListener("input",()=>this.autosize()),this.input.addEventListener("keydown",(h)=>{if(h.key==="Enter"&&!h.shiftKey&&!h.isComposing)h.preventDefault(),this.submit()}),this.sendBtn=r(t,"button",{class:"send",type:"submit"}),this.setSendMode("send"),l.addEventListener("submit",(h)=>{if(h.preventDefault(),this.controller)this.controller.abort();else this.submit()}),l.append(this.input,this.sendBtn);let d=r(t,"footer"),u=r(t,"a",{href:"https://maxgfr.github.io/murmur/",target:"_blank",rel:"noopener"});if(u.textContent=this.t.poweredBy,d.append(u),this.chatView.append(this.log,l,d),this.setupView=r(t,"div",{class:"setup"}),this.setupView.hidden=!0,this.panel.append(a,this.chatView,this.setupView),this.root.replaceChildren(s,this.launcher,this.panel),this.hasAttribute("inline"))this.launcher.hidden=!0;if(this.built=!0,this.session=new O({...e,lang:n}),this.renderChat(),e.open||!this.hasAttribute("inline")&&N("get",this.openKey))this.open()}autosize(){this.input.style.height="auto",this.input.style.height=`${Math.min(this.input.scrollHeight,140)}px`}setSendMode(e){this.sendBtn.replaceChildren(R(this.ownerDocument,e)),this.sendBtn.setAttribute("aria-label",e==="send"?this.t.send:this.t.stop)}emit(e){this.dispatchEvent(new CustomEvent("murmur:state",{detail:e,bubbles:!0,composed:!0}))}renderChat(){let e=this.ownerDocument,n=this.session?.turns??[],i=[],t=r(e,"div",{class:"msg bot greeting"});t.append(v(e,"p",this.t.greeting)),i.push(t);for(let s of n)i.push(this.turnNode(s));this.log.replaceChildren(...i),this.log.scrollTop=this.log.scrollHeight}turnNode(e){let n=this.ownerDocument;if(e.role==="user"){let t=r(n,"div",{class:"msg user"});return t.textContent=e.content,t}let i=r(n,"div",{class:"msg bot"});return this.fillAnswer(i,e,!0),i}fillAnswer(e,n,i){let t=this.ownerDocument;if(n.error){let[o="unknown",...l]=n.error.split("|"),d=ee[o],u=r(t,"div",{class:"error",role:"alert"});u.append(v(t,"p",d?this.t[d]:`${this.t.errorOther} ${l.join("|")}`));let h=r(t,"div",{class:"row"}),b=r(t,"button",{class:"text-btn",type:"button"});if(b.textContent=this.t.retry,b.addEventListener("click",()=>{let f=this.session?.turns??[],m=f.at(-2)?.content??"";if(f.splice(-2,2),this.renderChat(),m)this.ask(m)}),h.append(b),o==="auth"||o==="auth-or-network"){if(!this.settingsBtn.hidden){let f=r(t,"button",{class:"text-btn",type:"button"});f.textContent=this.t.settings,f.addEventListener("click",()=>void this.showSetup()),h.append(f)}}u.append(h),e.replaceChildren(u);return}let s=n.passages??[],a=r(t,"div");U(a,n.content,(o)=>{let l=s[o-1];if(!l)return null;let d=r(t,"a",{class:"cite",href:kt(l)});return d.textContent=String(o),d.setAttribute("aria-label",`${this.t.sources} ${o}: ${l.title}`),d});let c=[a];if(i&&!n.content.trim()&&!s.length){let o=r(t,"p",{class:"status"});o.append(r(t,"span",{class:"lamp off","aria-hidden":"true"}),t.createTextNode(this.t.notFound)),c.push(o)}let p=n.cited??[];if(i&&p.length){c.push(v(t,"p",this.t.sources,"sources-label"));let o=r(t,"ol",{class:"sources"});for(let l of p){let d=s[l-1];if(!d)continue;let u=r(t,"li"),h=r(t,"a",{href:kt(d)}),b=v(t,"span",String(l),"cite");b.setAttribute("aria-hidden","true");let f=r(t,"span",{class:"where"});if(f.append(t.createTextNode(d.title||d.url)),d.heading&&d.heading!==d.title)f.append(v(t,"span",` › ${d.heading}`));h.append(b,f),u.append(h),o.append(u)}c.push(o)}e.replaceChildren(...c)}async submit(){let e=this.input.value.trim();if(!e||this.controller||!this.session)return;if(await this.session.needsSetup()){await this.showSetup(e);return}let n=this.ownerDocument;this.input.value="",this.autosize(),this.log.append(this.turnNode({role:"user",content:e}));let i=r(n,"div",{class:"msg bot"}),t=r(n,"p",{class:"status"});t.append(r(n,"span",{class:"lamp busy","aria-hidden":"true"}),n.createTextNode(this.t.thinking)),i.append(t),this.log.append(i),this.log.scrollTop=this.log.scrollHeight,this.log.setAttribute("aria-busy","true");let s=new AbortController;this.controller=s,this.setSendMode("stop"),this.emit({state:"searching"});let a=!1;try{let c=await this.session.ask(e,(p,o)=>{if(!a)a=!0,this.emit({state:"streaming",passages:o.passages??[]});let l=this.log.scrollHeight-this.log.scrollTop-this.log.clientHeight<40;if(this.fillAnswer(i,o,!1),l)this.log.scrollTop=this.log.scrollHeight},s.signal);this.fillAnswer(i,c,!0),this.emit(c.error?{state:"error"}:{state:"done",passages:c.passages??[],cited:c.cited??[]})}catch(c){if(i.remove(),this.log.lastElementChild?.remove(),this.emit({state:"idle"}),c instanceof L)await this.showSetup(e);else throw c}finally{this.controller=null,this.setSendMode("send"),this.log.setAttribute("aria-busy","false"),this.log.scrollTop=this.log.scrollHeight}}async showSetup(e){if(!this.session)return;let n=this.ownerDocument,i=await this.session.store();await i.load(),i.open(),this.chatView.hidden=!0,this.setupView.hidden=!1;let t=this.t,s=r(n,"button",{class:"link-btn",type:"button"});s.textContent=t.back,s.addEventListener("click",()=>this.hideSetup());let a=v(n,"h3",t.setupTitle);a.style.cssText="margin:0;font-size:17px;font-weight:650";let c=v(n,"p",t.setupIntro,"intro"),p=_(n,t.local),o=C(n,t.provider,r(n,"select")),l=o.control,d=C(n,t.model,r(n,"select")),u=d.control,h=C(n,t.endpoint,r(n,"input",{type:"url",inputmode:"url"}),t.localHint),b=h.control,f=C(n,t.model,r(n,"input",{type:"text",autocomplete:"off"})),m=f.control,x=r(n,"div",{class:"presets"});for(let g of["ollama","lmstudio"]){let y=r(n,"button",{class:"text-btn",type:"button"});y.textContent=g==="ollama"?"Ollama":"LM Studio",y.addEventListener("click",async()=>{let{ENDPOINT_PRESETS:w}=await (G("e5entetm"),import("./index-e5entetm.js"));i.applyPreset(w[g])}),x.append(y)}let M=C(n,t.apiKey,r(n,"input",{type:"password",autocomplete:"off",spellcheck:"false"}),t.apiKeyHint),S=M.control,T=_(n,t.remember),E=r(n,"button",{class:"text-btn",type:"button"});E.textContent=t.test;let H=r(n,"p",{class:"result",role:"status"});H.style.margin="0";let A=r(n,"button",{class:"primary",type:"button"});A.textContent=t.save;let I=r(n,"button",{class:"link-btn",type:"button"});I.textContent=t.forget,p.input.addEventListener("change",()=>i.toggleCustom(p.input.checked)),l.addEventListener("change",()=>i.selectProvider(l.value)),u.addEventListener("change",()=>i.selectModel(u.value)),b.addEventListener("input",()=>i.setEndpoint(b.value)),m.addEventListener("input",()=>i.setCustomModel(m.value)),S.addEventListener("input",()=>i.setApiKey(S.value)),T.input.addEventListener("change",()=>i.setRememberKey(T.input.checked)),E.addEventListener("click",()=>void i.test()),A.addEventListener("click",async()=>{if(!(await i.save()).ok)return;if(this.hideSetup(),e)this.input.value=e,this.submit()}),I.addEventListener("click",()=>void i.clear());let D=r(n,"div",{class:"row"});D.append(E,H),this.setupView.replaceChildren(s,a,c,p.label,o.label,d.label,x,h.label,f.label,M.label,T.label,D,A,I);let J=(g)=>{let y=g.draft.custom;if(p.input.checked=y,o.label.hidden=y,d.label.hidden=y,x.hidden=!y,h.label.hidden=!y,f.label.hidden=!y,g.catalogStatus==="ready")ne(n,l,g,t),ie(n,u,g);else l.replaceChildren(z(n,"",g.catalogStatus==="error"?t.catalogError:t.loadingCatalog)),u.replaceChildren();if(b!==this.root.activeElement)b.value=g.draft.customEndpoint;if(m!==this.root.activeElement)m.value=g.draft.customModel;if(S!==this.root.activeElement)S.value=g.apiKey;T.input.checked=g.draft.rememberKey,E.disabled=!g.canTest||g.testing,E.textContent=g.testing?t.testing:t.test,A.disabled=!g.canSave;let w=g.testResult;H.className=w?w.ok?"result ok":"result fail":"result",H.textContent=!w?"":w.ok?t.testOk:`${t.testFail} ${w.reason}${w.message?` (${w.message})`:""}`};this.unsubscribe?.(),this.unsubscribe=i.subscribe(J),(i.getState().draft.custom?b:l).focus()}hideSetup(){this.unsubscribe?.(),this.unsubscribe=null,this.setupView.hidden=!0,this.chatView.hidden=!1,this.input.focus()}}function ne(e,n,i,t){let s=[[t.recommended,i.providers.recommended],[t.otherProviders,i.providers.others]],a=`${i.draft.providerId}|${i.providers.recommended.length+i.providers.others.length}`;if(n.dataset.sig===a)return;n.dataset.sig=a,n.replaceChildren(...s.filter(([,c])=>c.length).map(([c,p])=>{let o=e.createElement("optgroup");return o.label=c,o.append(...p.map((l)=>z(e,l.id,l.name))),o})),n.value=i.draft.providerId}function ie(e,n,i){let t=`${i.draft.providerId}|${i.draft.model}|${i.models.length}`;if(n.dataset.sig===t)return;n.dataset.sig=t;let s=i.recommendedModel?.id;n.replaceChildren(...i.models.map((a)=>z(e,a.id,a.id===s?`${a.name} ★`:a.name))),n.value=i.draft.model}function N(e,n){try{if(e==="set")sessionStorage.setItem(n,"1");else if(e==="remove")sessionStorage.removeItem(n);else return sessionStorage.getItem(n)!==null}catch{}return!1}function r(e,n,i={}){let t=e.createElement(n);for(let[s,a]of Object.entries(i))t.setAttribute(s,a);return t}function v(e,n,i,t){let s=e.createElement(n);if(s.textContent=i,t)s.className=t;return s}function z(e,n,i){let t=e.createElement("option");return t.value=n,t.textContent=i,t}function B(e,n,i){let t=r(e,"button",{class:"icon-btn",type:"button",title:i});return t.setAttribute("aria-label",i),t.append(R(e,n)),t}function C(e,n,i,t){let s=r(e,"label",{class:"field"});if(s.append(v(e,"span",n),i),t)s.append(v(e,"small",t));return{label:s,control:i}}function _(e,n){let i=r(e,"label",{class:"check"}),t=r(e,"input",{type:"checkbox"});return i.append(t,e.createTextNode(n)),{label:i,input:t}}function se(e="murmur-chat"){if(!customElements.get(e))customElements.define(e,class extends K{});return customElements.get(e)}function q(e={}){se();let{target:n,inline:i,...t}=e,s=document.createElement("murmur-chat");if(i)s.setAttribute("inline","");return s.configure(t),(n??document.body).append(s),s}function re(e,n){let i={};if(e.index)i.index=new URL(e.index,n).href;let t={};if(e.provider)t.provider=e.provider;if(e.model)t.model=e.model;if(e.endpoint)t.endpoint=e.endpoint;if(Object.keys(t).length)i.llm=t;if(e.instructions)i.instructions=e.instructions;if(e.lang)i.lang=e.lang;let s={};if(e.title)s.title=e.title;if(e.greeting)s.greeting=e.greeting;if(e.placeholder)s.placeholder=e.placeholder;if(e.button)s.open=e.button;if(Object.keys(s).length)i.messages=s;if(e.position==="bottom-left"||e.position==="bottom-right")i.position=e.position;if(e.theme==="light"||e.theme==="dark"||e.theme==="auto")i.theme=e.theme;if(e.accent)i.accent=e.accent;if(e.catalog)i.catalogUrl=new URL(e.catalog,n).href;if(e.storageKey)i.storageKey=e.storageKey;if(e.open==="true")i.open=!0;return i}function Y(){let e=import.meta.url,n=[...document.querySelectorAll("script[src]")].find((t)=>t.src===e&&!t.dataset.murmurReady);if(n)n.dataset.murmurReady="true";let i=re(n?.dataset??{},location.href);i.catalogUrl??=new URL("./models.json",e).href,q(i)}if(typeof document<"u"&&!document.querySelector("murmur-chat:not([inline])"))if(document.readyState==="loading")document.addEventListener("DOMContentLoaded",Y,{once:!0});else Y();export{re as optionsFromDataset};
@@ -0,0 +1 @@
1
+ import{It}from"./embed-pnm9593k.js";export{It as bm25Retriever};
package/dist/cli.js CHANGED
@@ -99,7 +99,7 @@ function extractSections(doc, { root = DEFAULT_ROOT, exclude = DEFAULT_EXCLUDE }
99
99
  return { title, sections: [] };
100
100
  const sections = [];
101
101
  let cur = { heading: "", anchor: "", text: "" };
102
- const used = new Set;
102
+ const slugs = new Map;
103
103
  const walk = (node) => {
104
104
  if (node.nodeType === 3) {
105
105
  cur.text += (node.textContent ?? "").replace(/\s+/g, " ");
@@ -114,10 +114,13 @@ function extractSections(doc, { root = DEFAULT_ROOT, exclude = DEFAULT_EXCLUDE }
114
114
  if (/^H[1-3]$/.test(tag)) {
115
115
  sections.push(cur);
116
116
  const heading = (el.textContent ?? "").replace(/\s+/g, " ").trim();
117
- let anchor = el.id || el.closest("[id]")?.id || slugify(heading);
118
- while (used.has(anchor))
119
- anchor += "-";
120
- used.add(anchor);
117
+ let anchor = el.id || el.closest("[id]")?.id || "";
118
+ if (!anchor) {
119
+ const base = slugify(heading);
120
+ const n = slugs.get(base) ?? 0;
121
+ slugs.set(base, n + 1);
122
+ anchor = n ? `${base}-${n}` : base;
123
+ }
121
124
  cur = { heading, anchor, text: "" };
122
125
  return;
123
126
  }
@@ -4,6 +4,8 @@ import {
4
4
 
5
5
  // src/rag/retriever.ts
6
6
  import MiniSearch from "minisearch";
7
+ var STOPWORDS = new Set(("a an and are as at be but by can do does for from how i if in is it its me my of on or so that the " + "their them then there these this to was what when where which who why will with you your " + "au aux avec ce ces comment dans de des du elle en est et il je la le les leur ma mais me mes " + "mon ne nous on ou où par pas pour qu que quel quelle quels qui sa se ses son sont sur ta te tu " + "un une vos votre vous y").split(" "));
8
+ var MIN_RELATIVE_SCORE = 0.05;
7
9
  var fold = (s) => s.normalize("NFD").replace(/\p{M}/gu, "").toLowerCase();
8
10
  function passagesOf2(index) {
9
11
  return index.chunks.map((c) => {
@@ -15,15 +17,26 @@ function bm25Retriever2(index) {
15
17
  const passages = passagesOf2(index);
16
18
  const engine = new MiniSearch({
17
19
  fields: ["title", "heading", "text"],
18
- processTerm: (t) => fold(t),
19
- searchOptions: { prefix: true, fuzzy: 0.15, boost: { title: 2, heading: 1.5 } }
20
+ processTerm: (t) => {
21
+ const term = fold(t);
22
+ return term.length < 2 || STOPWORDS.has(term) ? null : term;
23
+ },
24
+ searchOptions: {
25
+ prefix: (term) => term.length > 3,
26
+ fuzzy: (term) => term.length > 4 ? 0.15 : 0,
27
+ boost: { title: 2, heading: 1.5 }
28
+ }
20
29
  });
21
30
  engine.addAll(passages.map((p, id) => ({ id, title: p.title, heading: p.heading, text: p.text })));
22
31
  return {
23
32
  async search(query, { limit = 6, budgetTokens = 3000 } = {}) {
24
33
  const out = [];
25
34
  let used = 0;
26
- for (const hit of engine.search(query, { combineWith: "OR" })) {
35
+ const hits = engine.search(query, { combineWith: "OR" });
36
+ const floor = (hits[0]?.score ?? 0) * MIN_RELATIVE_SCORE;
37
+ for (const hit of hits) {
38
+ if (hit.score < floor)
39
+ break;
27
40
  const p = passages[Number(hit.id)];
28
41
  if (!p)
29
42
  continue;
@@ -223,6 +223,7 @@ function renderMarkdown2(target, markdown, cite) {
223
223
  for (i++;i < lines.length && !/^\s*```/.test(lines[i] ?? ""); i++)
224
224
  body.push(lines[i] ?? "");
225
225
  const pre = doc.createElement("pre");
226
+ pre.tabIndex = 0;
226
227
  const code = doc.createElement("code");
227
228
  code.textContent = body.join(`
228
229
  `);
@@ -340,14 +341,14 @@ class ChatSession {
340
341
  throw new Error("murmur: not a murmur index");
341
342
  return data;
342
343
  }
343
- const { indexDocument } = await (__preload("hp2p9tp9"), import("../indexer/index.js"));
344
+ const { indexDocument } = await (__preload("gp7czjd1"), import("../indexer/index.js"));
344
345
  return indexDocument(document, location.pathname + location.search);
345
346
  }
346
347
  createEngine() {
347
348
  return (async () => {
348
349
  const [{ createMurmur }, retriever] = await Promise.all([
349
- (__preload("wq1d15n7"), import("./murmur-wq1d15n7.js")),
350
- this.options.retriever ?? (__preload("1rw4z2n6"), import("./retriever-1rw4z2n6.js")).then(async (r) => r.bm25Retriever(await this.loadIndex()))
350
+ (__preload("c1c79eh8"), import("./murmur-c1c79eh8.js")),
351
+ this.options.retriever ?? (__preload("h8nz6jsc"), import("./retriever-h8nz6jsc.js")).then(async (r) => r.bm25Retriever(await this.loadIndex()))
351
352
  ]);
352
353
  const model = this.options.model ?? (async () => {
353
354
  const settings = await this.settings();
@@ -369,6 +370,7 @@ class ChatSession {
369
370
  this.turns.push({ role: "user", content: question });
370
371
  const turn = { role: "assistant", content: "" };
371
372
  this.turns.push(turn);
373
+ this.persist();
372
374
  try {
373
375
  this.engine ??= this.createEngine();
374
376
  const engine = await this.engine.catch((error) => {
@@ -628,8 +630,10 @@ var ERROR_KEYS = {
628
630
  "rate-limit": "errorRate",
629
631
  overloaded: "errorRate"
630
632
  };
633
+ var Base = typeof HTMLElement === "undefined" ? class {
634
+ } : HTMLElement;
631
635
 
632
- class MurmurChat2 extends HTMLElement {
636
+ class MurmurChat2 extends Base {
633
637
  options = {};
634
638
  session = null;
635
639
  t = messagesFor2("en");
@@ -671,7 +675,7 @@ class MurmurChat2 extends HTMLElement {
671
675
  this.launcher.setAttribute("aria-expanded", "true");
672
676
  this.panel.hidden = false;
673
677
  this.session?.persist();
674
- sessionStorage.setItem(this.openKey, "1");
678
+ tabStorage("set", this.openKey);
675
679
  this.input.focus();
676
680
  }
677
681
  close() {
@@ -679,7 +683,7 @@ class MurmurChat2 extends HTMLElement {
679
683
  return;
680
684
  this.launcher.setAttribute("aria-expanded", "false");
681
685
  this.panel.hidden = true;
682
- sessionStorage.removeItem(this.openKey);
686
+ tabStorage("remove", this.openKey);
683
687
  this.launcher.focus();
684
688
  }
685
689
  async ask(question) {
@@ -787,7 +791,7 @@ class MurmurChat2 extends HTMLElement {
787
791
  this.built = true;
788
792
  this.session = new ChatSession({ ...o, lang });
789
793
  this.renderChat();
790
- if (o.open || !this.hasAttribute("inline") && sessionStorage.getItem(this.openKey))
794
+ if (o.open || !this.hasAttribute("inline") && tabStorage("get", this.openKey))
791
795
  this.open();
792
796
  }
793
797
  autosize() {
@@ -1087,6 +1091,17 @@ function fillModels(doc, select, s) {
1087
1091
  select.replaceChildren(...s.models.map((m) => option(doc, m.id, m.id === rec ? `${m.name} ★` : m.name)));
1088
1092
  select.value = s.draft.model;
1089
1093
  }
1094
+ function tabStorage(op, key) {
1095
+ try {
1096
+ if (op === "set")
1097
+ sessionStorage.setItem(key, "1");
1098
+ else if (op === "remove")
1099
+ sessionStorage.removeItem(key);
1100
+ else
1101
+ return sessionStorage.getItem(key) !== null;
1102
+ } catch {}
1103
+ return false;
1104
+ }
1090
1105
  function el(doc, tag, attrs = {}) {
1091
1106
  const node = doc.createElement(tag);
1092
1107
  for (const [k, v] of Object.entries(attrs))
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  bm25Retriever2
3
- } from "./index-z8pn9sdj.js";
3
+ } from "./index-10g918kt.js";
4
4
  import {
5
5
  estimateTokens2,
6
6
  formatSources2,
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  searchQuery2,
3
3
  createMurmur2
4
- } from "./index-fs6gmhz9.js";
5
- import"./index-z8pn9sdj.js";
4
+ } from "./index-ynjdey8j.js";
5
+ import"./index-10g918kt.js";
6
6
  export {
7
7
  createMurmur2 as createMurmur,
8
8
  searchQuery2 as searchQuery
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  passagesOf2,
3
3
  bm25Retriever2
4
- } from "./index-z8pn9sdj.js";
4
+ } from "./index-10g918kt.js";
5
5
  export {
6
6
  bm25Retriever2 as bm25Retriever,
7
7
  passagesOf2 as passagesOf
package/dist/lib/embed.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  __chunks,
3
3
  mountMurmur2
4
- } from "./chunks/index-v9expxwm.js";
5
- __chunks(import.meta.url,["nk2dbk07","v9expxwm","1rw4z2n6","hp2p9tp9","vb9smwta","kaeec41p","wq1d15n7","6re28wc1","z8pn9sdj","1zk822m5","fs6gmhz9"],[["./embed.js",1],["./chunks/index-v9expxwm.js",7],["./chunks/retriever-1rw4z2n6.js",8],["./indexer/index.js",9],["./llm/index.js"],["./chunks/chunk-kaeec41p.js",9],["./chunks/murmur-wq1d15n7.js",10,8],["./chunks/index-6re28wc1.js"],["./chunks/index-z8pn9sdj.js",7],["./chunks/index-1zk822m5.js"],["./chunks/index-fs6gmhz9.js",8,7]],0);
4
+ } from "./chunks/index-4at214g0.js";
5
+ __chunks(import.meta.url,["3qtg95t7","4at214g0","h8nz6jsc","gp7czjd1","vb9smwta","kaeec41p","c1c79eh8","6re28wc1","10g918kt","1zk822m5","ynjdey8j"],[["./embed.js",1],["./chunks/index-4at214g0.js",7],["./chunks/retriever-h8nz6jsc.js",8],["./indexer/index.js",9],["./llm/index.js"],["./chunks/chunk-kaeec41p.js",9],["./chunks/murmur-c1c79eh8.js",10,8],["./chunks/index-6re28wc1.js"],["./chunks/index-10g918kt.js",7],["./chunks/index-1zk822m5.js"],["./chunks/index-ynjdey8j.js",8,7]],0);
6
6
 
7
7
  // src/embed.ts
8
8
  function optionsFromDataset(data, base) {
package/dist/lib/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  passagesOf2,
3
3
  bm25Retriever2
4
- } from "./chunks/index-z8pn9sdj.js";
4
+ } from "./chunks/index-10g918kt.js";
5
5
  import {
6
6
  searchQuery2,
7
7
  createMurmur2
8
- } from "./chunks/index-fs6gmhz9.js";
8
+ } from "./chunks/index-ynjdey8j.js";
9
9
  import {
10
10
  MAX_CHUNK2,
11
11
  splitText2,
@@ -16,7 +16,7 @@ function extractSections(doc, { root = DEFAULT_ROOT, exclude = DEFAULT_EXCLUDE }
16
16
  return { title, sections: [] };
17
17
  const sections = [];
18
18
  let cur = { heading: "", anchor: "", text: "" };
19
- const used = new Set;
19
+ const slugs = new Map;
20
20
  const walk = (node) => {
21
21
  if (node.nodeType === 3) {
22
22
  cur.text += (node.textContent ?? "").replace(/\s+/g, " ");
@@ -31,10 +31,13 @@ function extractSections(doc, { root = DEFAULT_ROOT, exclude = DEFAULT_EXCLUDE }
31
31
  if (/^H[1-3]$/.test(tag)) {
32
32
  sections.push(cur);
33
33
  const heading = (el.textContent ?? "").replace(/\s+/g, " ").trim();
34
- let anchor = el.id || el.closest("[id]")?.id || slugify2(heading);
35
- while (used.has(anchor))
36
- anchor += "-";
37
- used.add(anchor);
34
+ let anchor = el.id || el.closest("[id]")?.id || "";
35
+ if (!anchor) {
36
+ const base = slugify2(heading);
37
+ const n = slugs.get(base) ?? 0;
38
+ slugs.set(base, n + 1);
39
+ anchor = n ? `${base}-${n}` : base;
40
+ }
38
41
  cur = { heading, anchor, text: "" };
39
42
  return;
40
43
  }
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  passagesOf2,
13
13
  bm25Retriever2
14
- } from "../chunks/index-z8pn9sdj.js";
14
+ } from "../chunks/index-10g918kt.js";
15
15
  import {
16
16
  estimateTokens2,
17
17
  formatSources2,
@@ -8,8 +8,8 @@ import {
8
8
  MurmurChat2,
9
9
  defineMurmurChat2,
10
10
  mountMurmur2
11
- } from "../chunks/index-v9expxwm.js";
12
- __chunks(import.meta.url,["7xg7fh2q","v9expxwm","1rw4z2n6","hp2p9tp9","vb9smwta","kaeec41p","wq1d15n7","6re28wc1","z8pn9sdj","1zk822m5","fs6gmhz9"],[["./index.js",1],["../chunks/index-v9expxwm.js",7],["../chunks/retriever-1rw4z2n6.js",8],["../indexer/index.js",9],["../llm/index.js"],["../chunks/chunk-kaeec41p.js",9],["../chunks/murmur-wq1d15n7.js",10,8],["../chunks/index-6re28wc1.js"],["../chunks/index-z8pn9sdj.js",7],["../chunks/index-1zk822m5.js"],["../chunks/index-fs6gmhz9.js",8,7]],0);
11
+ } from "../chunks/index-4at214g0.js";
12
+ __chunks(import.meta.url,["1ykj7t4p","4at214g0","h8nz6jsc","gp7czjd1","vb9smwta","kaeec41p","c1c79eh8","6re28wc1","10g918kt","1zk822m5","ynjdey8j"],[["./index.js",1],["../chunks/index-4at214g0.js",7],["../chunks/retriever-h8nz6jsc.js",8],["../indexer/index.js",9],["../llm/index.js"],["../chunks/chunk-kaeec41p.js",9],["../chunks/murmur-c1c79eh8.js",10,8],["../chunks/index-6re28wc1.js"],["../chunks/index-10g918kt.js",7],["../chunks/index-1zk822m5.js"],["../chunks/index-ynjdey8j.js",8,7]],0);
13
13
  export {
14
14
  MESSAGES2 as MESSAGES,
15
15
  MurmurChat2 as MurmurChat,
@@ -1,6 +1,6 @@
1
1
  import { type LanguageModel } from "ai";
2
- import { type Retriever } from "../rag/retriever";
3
- import type { MurmurIndex, Passage } from "../rag/types";
2
+ import { type Retriever } from "../rag/retriever.js";
3
+ import type { MurmurIndex, Passage } from "../rag/types.js";
4
4
  export interface MurmurOptions {
5
5
  /** The index to answer from; ignored when `retriever` is given. */
6
6
  index?: MurmurIndex;
@@ -1,4 +1,4 @@
1
- import type { WidgetOptions } from "./widget/index";
1
+ import type { WidgetOptions } from "./widget/index.js";
2
2
  /**
3
3
  * The one-line embed: reads the options from the script tag's data attributes and adds the
4
4
  * widget. `<script type="module" src=".../murmur.js" data-index="/murmur-index.json"></script>`
@@ -1,2 +1,2 @@
1
- export { type Answer, createMurmur, type Murmur, type MurmurOptions, searchQuery, type Turn, } from "./core/murmur";
2
- export * from "./rag/index";
1
+ export { type Answer, createMurmur, type Murmur, type MurmurOptions, searchQuery, type Turn, } from "./core/murmur.js";
2
+ export * from "./rag/index.js";
@@ -1,4 +1,4 @@
1
- import { type Section } from "../rag/chunk";
1
+ import { type Section } from "../rag/chunk.js";
2
2
  /** Elements never worth indexing: navigation, chrome, scripts, and murmur itself. */
3
3
  export declare const DEFAULT_EXCLUDE = "script,style,noscript,template,svg,canvas,iframe,nav,header,footer,aside,form,button,dialog,[hidden],[aria-hidden='true'],[data-murmur-ignore],murmur-chat";
4
4
  /** Where the content of a page is looked for, first match wins. */
@@ -1,4 +1,4 @@
1
- import type { PageInput } from "./index";
1
+ import type { PageInput } from "./index.js";
2
2
  /** URL of a file under the site root: `docs/index.html` → `/docs/`. */
3
3
  export declare function urlOf(file: string, rootDir: string, base: string): string;
4
4
  export declare function pageOf(url: string, body: string, kind: string): PageInput;
@@ -1,7 +1,7 @@
1
- import { type Section } from "../rag/chunk";
2
- import type { MurmurIndex } from "../rag/types";
3
- import { type ExtractOptions } from "./extract";
4
- export { DEFAULT_EXCLUDE, DEFAULT_ROOT, type ExtractOptions, extractSections } from "./extract";
1
+ import { type Section } from "../rag/chunk.js";
2
+ import type { MurmurIndex } from "../rag/types.js";
3
+ import { type ExtractOptions } from "./extract.js";
4
+ export { DEFAULT_EXCLUDE, DEFAULT_ROOT, type ExtractOptions, extractSections } from "./extract.js";
5
5
  /** One page to index: give its HTML, its Markdown, or plain text. */
6
6
  export type PageInput = {
7
7
  url: string;
@@ -1,4 +1,4 @@
1
- import type { Chunk, MurmurIndex } from "./types";
1
+ import type { Chunk, MurmurIndex } from "./types.js";
2
2
  /** Longest passage, in characters (about 500 tokens). */
3
3
  export declare const MAX_CHUNK = 2000;
4
4
  /** A titled block of text, as an extractor reads it from a page. */
@@ -1,4 +1,4 @@
1
- import type { Passage } from "./types";
1
+ import type { Passage } from "./types.js";
2
2
  /** Rough token estimate (about 4 characters per token), without a tokenizer. */
3
3
  export declare function estimateTokens(text: string): number;
4
4
  /** Passages between delimiters, as data, numbered from 1; delimiter look-alikes inside are neutralized. */
@@ -1,4 +1,4 @@
1
- export { buildIndex, chunkSections, isMurmurIndex, MAX_CHUNK, markdownSections, type Section, slugify, splitText, } from "./chunk";
2
- export { citedSources, estimateTokens, formatSources, groundingRules, passageHref, SOURCES_RULE, } from "./ground";
3
- export { bm25Retriever, passagesOf, type Retriever, type SearchOptions } from "./retriever";
4
- export type { Chunk, IndexDoc, MurmurIndex, Passage } from "./types";
1
+ export { buildIndex, chunkSections, isMurmurIndex, MAX_CHUNK, markdownSections, type Section, slugify, splitText, } from "./chunk.js";
2
+ export { citedSources, estimateTokens, formatSources, groundingRules, passageHref, SOURCES_RULE, } from "./ground.js";
3
+ export { bm25Retriever, passagesOf, type Retriever, type SearchOptions } from "./retriever.js";
4
+ export type { Chunk, IndexDoc, MurmurIndex, Passage } from "./types.js";
@@ -1,4 +1,4 @@
1
- import type { MurmurIndex, Passage } from "./types";
1
+ import type { MurmurIndex, Passage } from "./types.js";
2
2
  /** Finds the passages that answer a question. Bring your own (embeddings, a search API) to replace BM25. */
3
3
  export interface Retriever {
4
4
  search(query: string, options?: SearchOptions): Promise<Passage[]>;
@@ -1,5 +1,5 @@
1
- import type { LlmSettingsStore } from "../llm/index";
2
- import { type ChatTurn, type WidgetOptions } from "./session";
1
+ import type { LlmSettingsStore } from "../llm/index.js";
2
+ import { type ChatTurn, type WidgetOptions } from "./session.js";
3
3
  /** What `murmur:state` events carry, for pages that want to show what the widget is doing. */
4
4
  export interface MurmurStateDetail {
5
5
  state: "searching" | "streaming" | "done" | "error" | "idle";
@@ -11,7 +11,8 @@ export interface MurmurStateDetail {
11
11
  * `element.configure(options)` before or after it is connected; attributes `inline`,
12
12
  * `position` and `theme` style it.
13
13
  */
14
- export declare class MurmurChat extends HTMLElement {
14
+ declare const Base: typeof HTMLElement;
15
+ export declare class MurmurChat extends Base {
15
16
  private options;
16
17
  private session;
17
18
  private t;
@@ -1,9 +1,9 @@
1
- import { MurmurChat } from "./element";
2
- import type { WidgetOptions } from "./session";
3
- export { MurmurChat, type MurmurStateDetail } from "./element";
4
- export { MESSAGES, type Messages, messagesFor, pickLanguage } from "./i18n";
5
- export { type CitationRenderer, renderMarkdown } from "./markdown";
6
- export { type ChatTurn, SetupNeeded, type WidgetOptions } from "./session";
1
+ import { MurmurChat } from "./element.js";
2
+ import type { WidgetOptions } from "./session.js";
3
+ export { MurmurChat, type MurmurStateDetail } from "./element.js";
4
+ export { MESSAGES, type Messages, messagesFor, pickLanguage } from "./i18n.js";
5
+ export { type CitationRenderer, renderMarkdown } from "./markdown.js";
6
+ export { type ChatTurn, SetupNeeded, type WidgetOptions } from "./session.js";
7
7
  /** Registers `<murmur-chat>` (or another tag name) once. */
8
8
  export declare function defineMurmurChat(tag?: string): typeof MurmurChat;
9
9
  /** Adds a configured widget to the page (the floating bubble, or `inline` inside `target`). */
@@ -1,9 +1,9 @@
1
1
  import type { LanguageModel } from "ai";
2
- import type { Turn } from "../core/murmur";
3
- import type { LlmConfig, LlmSettings, LlmSettingsStore } from "../llm/index";
4
- import type { Retriever } from "../rag/retriever";
5
- import type { MurmurIndex, Passage } from "../rag/types";
6
- import type { Messages } from "./i18n";
2
+ import type { Turn } from "../core/murmur.js";
3
+ import type { LlmConfig, LlmSettings, LlmSettingsStore } from "../llm/index.js";
4
+ import type { Retriever } from "../rag/retriever.js";
5
+ import type { MurmurIndex, Passage } from "../rag/types.js";
6
+ import type { Messages } from "./i18n.js";
7
7
  export interface WidgetOptions {
8
8
  /** URL of a `murmur index` JSON, or the index itself. Default: the page the widget is on. */
9
9
  index?: string | MurmurIndex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "murmur-rag",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "description": "Embeddable AI chat for static sites: one script tag, a mini RAG over your own pages, any LLM through llm-connect (your proxy or the visitor's own key). No backend.",
5
5
  "author": "maxgfr",
6
6
  "license": "MIT",
@@ -90,7 +90,8 @@
90
90
  "test": "bun test tests",
91
91
  "test:e2e": "bun run build && playwright test",
92
92
  "catalog": "llm-models catalog --npm callable --require openai,anthropic,google,mistral --out assets/models.json",
93
- "release": "semantic-release"
93
+ "release": "semantic-release",
94
+ "test:package": "bun run build:lib && bun scripts/check-package.ts"
94
95
  },
95
96
  "dependencies": {
96
97
  "@ai-sdk/anthropic": "^4.0.90",
@@ -105,10 +106,12 @@
105
106
  "minisearch": "^7.2.0"
106
107
  },
107
108
  "devDependencies": {
109
+ "@axe-core/playwright": "^4.14.0",
108
110
  "@biomejs/biome": "^2.6.3",
109
111
  "@playwright/test": "^1.64.1",
110
112
  "@semantic-release/exec": "^7.1.0",
111
113
  "@types/bun": "^1.4.4",
114
+ "conventional-changelog-conventionalcommits": "^9",
112
115
  "semantic-release": "^25.0.9",
113
116
  "typescript": "^7.0.2"
114
117
  }
@@ -1,9 +0,0 @@
1
- import{xt,pt,St}from"./embed-q6y6vgv1.js";var h="script,style,noscript,template,svg,canvas,iframe,nav,header,footer,aside,form,button,dialog,[hidden],[aria-hidden='true'],[data-murmur-ignore],murmur-chat",E="main,article,[role='main'],body",O=/^(P|LI|DT|DD|PRE|BLOCKQUOTE|TABLE|TR|FIGCAPTION|DIV|SECTION|ARTICLE|UL|OL|DL|MAIN|H[1-6])$/;function f(i,{root:l=E,exclude:o=h}={}){let r=l.split(",").map((t)=>i.querySelector(t.trim())).find((t)=>!!t),m=r?.querySelector("h1")?.textContent?.replace(/\s+/g," ").trim()||i.querySelector("title")?.textContent?.trim()||"";if(!r)return{title:m,sections:[]};let u=[],e={heading:"",anchor:"",text:""},x=new Set,d=(t)=>{if(t.nodeType===3){e.text+=(t.textContent??"").replace(/\s+/g," ");return}if(t.nodeType!==1)return;let n=t;if(n.matches(o))return;let s=n.tagName.toUpperCase();if(/^H[1-3]$/.test(s)){u.push(e);let c=(n.textContent??"").replace(/\s+/g," ").trim(),a=n.id||n.closest("[id]")?.id||pt(c);while(x.has(a))a+="-";x.add(a),e={heading:c,anchor:a,text:""};return}if(s==="BR")e.text+=`
2
- `;let p=O.test(s);if(p)e.text+=`
3
-
4
- `;if(s==="LI")e.text+="- ";for(let c of Array.from(n.childNodes))d(c);if(p)e.text+=`
5
-
6
- `};for(let t of Array.from(r.childNodes))d(t);return u.push(e),{title:m,sections:u.map((t)=>({...t,text:t.text.replace(/[ \t]+\n/g,`
7
- `).replace(/\n{3,}/g,`
8
-
9
- `).trim()})).filter((t)=>t.text)}}function S(i,l=i.location?.href??"",o={}){let r=f(i,o);return St([{url:l,title:r.title,sections:r.sections}],o.maxChunk??xt)}export{S as indexDocument};
@@ -1 +0,0 @@
1
- import{It}from"./embed-we24qtes.js";export{It as bm25Retriever};