wiki-plugin-similarity 0.4.0 → 0.4.1

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.
@@ -1,4 +1,4 @@
1
- /* wiki-plugin-similarity - 0.4.0 - Wed, 10 Jun 2026 23:23:44 GMT */
1
+ /* wiki-plugin-similarity - 0.4.1 - Thu, 11 Jun 2026 00:11:14 GMT */
2
2
  (()=>{var A={high:.78,medium:.68,low:.58},I=A.medium,z=10,F=t=>{let e=[],i=null,s=null,o="search",x=!1,b=!1,L=null,y=null,d=(m,w)=>m===w||m.startsWith(w)&&/^[\s:]/.test(m.slice(w.length)),n=(m,w)=>m.slice(w.length).replace(/^\s*:?\s*/,"").trim();for(let m of t.split(`
3
3
  `)){let w=m.trim();if(!w||w.startsWith("#"))continue;let p=w.toUpperCase();if(d(p,"LIVE")){x=!0;continue}if(d(p,"AUTHOR")){!e.length&&o==="search"&&(o="author");continue}if(d(p,"REPORT")){o==="search"&&(o="report");continue}if(d(p,"BUILD")){o==="search"&&(o="build");continue}if(d(p,"FORCE")){b=!0;continue}if(d(p,"GHOST")){L=n(w,"GHOST"),o==="search"&&(o="ghost");continue}if(d(p,"BUTTON")){y=n(w,"BUTTON");continue}if(d(p,"LIST")){!e.length&&o==="search"&&(o="list");continue}if(d(p,"SIMILAR")){let r=n(p,"SIMILAR").toLowerCase();i=A[r]||I,!e.length&&o==="search"&&(o="similar");continue}if(d(p,"THRESHOLD")){let r=n(w,"THRESHOLD");i=A[r.toLowerCase()]??(parseFloat(r)||I);continue}if(d(p,"LIMIT")){s=parseInt(n(w,"LIMIT"))||z;continue}e.push(["PUBLIC","LOCAL","PRIVATE"].includes(p)?p:w)}return{mode:o,specs:e,threshold:i??I,limit:s??z,live:x,force:b,ghostUrl:L,label:y}},J=t=>t.includes("*")||t.includes("?"),W=t=>t==="PUBLIC"||t==="LOCAL"||t==="PRIVATE",K=t=>t.toLowerCase().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,""),D=new Map,Y=async(t,e)=>{if(D.has(t))return D.get(t);let i=`${e}/system/indexed-domains.json?pattern=${encodeURIComponent(t)}`,s=await fetch(i);if(!s.ok)throw new Error(`indexed-domains failed: ${s.status}`);let o=await s.json();return D.set(t,o),o},Q=async(t,e)=>{t.length||(t=[window.location.hostname]);let i=new Set,s=[];for(let o of t)if(o==="*"||J(o)||W(o))for(let x of await Y(o,e))i.has(x.domain)||(i.add(x.domain),s.push(x));else i.has(o)||(i.add(o),s.push({domain:o,page_count:null}));return s},O=new Map,X=()=>{let t=window.location.hostname;return t==="localhost"||t.endsWith(".localhost")||t==="127.0.0.1"},Z=t=>X()?`${window.location.origin}/system/semantic-vectors.json?domain=${encodeURIComponent(t)}`:`${window.location.protocol}//${t}/system/semantic-vectors.json`,q=async t=>{if(O.has(t))return O.get(t);let e=await fetch(Z(t));if(!e.ok)return[];let i=await e.json();return O.set(t,i),i},M=async(t,e)=>{let i=await fetch(`${e}/system/embed.json?text=${encodeURIComponent(t)}`);if(!i.ok)throw new Error(`embed failed: ${i.status}`);return(await i.json()).vector},tt=async(t,e)=>{let s=(await q(e)).find(o=>o.slug===t);return s?s.vector:null},U=(t,e,{threshold:i,limit:s,excludeSlug:o,excludeDomain:x})=>{let b=[];for(let{domain:L,pages:y}of e)for(let{slug:d,title:n,vector:m}of y){if(d===o&&L===x)continue;let w=0;for(let p=0;p<t.length;p++)w+=t[p]*m[p];w>=i&&b.push({domain:L,slug:d,title:n,score:w})}return b.sort((L,y)=>y.score-L.score),b.slice(0,s)},H=async(t,e)=>{let i=await Q(t,e);return(await Promise.all(i.map(async({domain:o})=>({domain:o,pages:await q(o)})))).filter(o=>o.pages.length>0)},N=t=>`sim-cache-${t}`,et=t=>{try{let e=JSON.parse(localStorage.getItem(N(t.id))||"null");return e?.text===(t.text||"")?e:null}catch{return null}},R=(t,e)=>{try{localStorage.setItem(N(t.id),JSON.stringify({text:t.text||"",ts:Date.now(),...e}))}catch{}},st=t=>{let e=Math.floor((Date.now()-t)/1e3);return e<60?`${e}s ago`:e<3600?`${Math.floor(e/60)}m ago`:e<86400?`${Math.floor(e/3600)}h ago`:`${Math.floor(e/86400)}d ago`},T=`
4
4
  .sim-form { display:flex; gap:6px; margin-bottom:8px; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-similarity",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Federated Wiki plugin — semantic similarity search across wiki domains using prebuilt vector indexes",
5
5
  "keywords": [
6
6
  "wiki",
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "type": "markdown",
11
11
  "id": "a3f7c8d2e1b94056",
12
- "text": "**Version:** 0.4.0 — [GitHub](https://github.com/Hitchhikers-Guide-to-the-Galaxy/wiki-plugin-similarity) · [npm](https://www.npmjs.com/package/wiki-plugin-similarity)"
12
+ "text": "**Version:** 0.4.1 — [GitHub](https://github.com/Hitchhikers-Guide-to-the-Galaxy/wiki-plugin-similarity) · [npm](https://www.npmjs.com/package/wiki-plugin-similarity)"
13
13
  },
14
14
  {
15
15
  "type": "similarity",
@@ -44,7 +44,7 @@
44
44
  {
45
45
  "type": "markdown",
46
46
  "id": "4f91a3b2d8e05c11",
47
- "text": "**Search** (default) — interactive form; results appear inline as scored links. Shift-click a result to append it at the end of the lineup instead of truncating.\n\n**Similar** — runs on page load using the current page's pre-computed vector (no embed call if already indexed). Ranked *Similar Pages* list.\n\n**List** — table of indexed domains with page counts; supports scopes, globs, and `LIMIT`.\n\n**Author** — same search, but opens a ghost page with `# Similar Pages` ([[wiki links]], deduplicated) and `# Reference Links` (all results as reference items with scores).\n\n**Report** — posts to the farm API's `/search-report`: candidates from semantic scan ∪ title matching, stubs dropped, forks and near-duplicates bundled under the strongest copy with a one-click lineup link, ranked by semantic × richness × recency + title boost. Opens as a ghost page. *(localhost only — needs the FastAPI service.)*\n\n**Build** — a button that triggers semantic index building via `/build-index.json`; the build report opens as a ghost page. Add `FORCE` to re-embed fresh domains. *(localhost only.)*\n\n**Ghost** — a generic button: `GHOST <url>` fetches any endpoint returning fedwiki page JSON and opens it as a ghost page. Caption set with `BUTTON <text>`."
47
+ "text": "**Search** (default) — interactive form; results appear inline as scored links. Shift-click a result to append it at the end of the lineup instead of truncating.\n\n**Similar** — runs on page load using the current page's pre-computed vector (no embed call if already indexed). Ranked *Similar Pages* list.\n\n**List** — table of indexed domains with page counts; supports scopes, globs, and `LIMIT`.\n\n**Author** — same search, but opens a ghost page with `# Similar Pages` ([[wiki links]], deduplicated) and `# Reference Links` (all results as reference items with scores).\n\n**Report** — posts to the farm API's `/search-report`: candidates from semantic scan ∪ title matching, stubs dropped, forks and near-duplicates bundled under the strongest copy with a one-click lineup link, ranked by semantic × richness × recency + title boost. Opens as a ghost page. *(localhost only — needs the FastAPI service.)*\n\n**Build** — a button that triggers semantic index building via `/build-index.json`; the build report opens as a ghost page. Add `FORCE` to re-embed fresh domains. *(localhost only.)*\n\n**Ghost** — a generic button: `GHOST <url>` fetches any endpoint returning fedwiki page JSON and opens it as a ghost page. Caption set with `BUTTON <text>`. Example: the *Farm Roster Report* button fetches `/farm-rosters.json`, which rosters every farm domain by scope with per-section error rosters for unserved domains."
48
48
  },
49
49
  {
50
50
  "type": "markdown",