Spaces:
Running
Running
deploy(hf): sync szl-holdings/a11oy@main derived COPY set
Browse filesReusable Dockerfile-COPY-derived deploy from szl-holdings/a11oy main.
Files: 824 Pruned: 0
Derived from Dockerfile COPY sources (NO hand-maintained allowlist).
Signed-off-by: SZL Holdings <noreply@szlholdings.ai>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- pages/hub.html +200 -24
pages/hub.html
CHANGED
|
@@ -1,41 +1,217 @@
|
|
| 1 |
<!doctype html><html lang="en"><head><meta charset="utf-8">
|
| 2 |
<meta name="viewport" content="width=device-width,initial-scale=1">
|
| 3 |
-
<title>a11oy · Hub —
|
| 4 |
<!-- SPDX-License-Identifier: Apache-2.0 · © 2026 SZL Holdings · Doctrine v12 additive · Signed: Yachay · Co-author: Perplexity Computer Agent -->
|
| 5 |
<style>
|
| 6 |
-
:root{--bg:#0a0b10;--panel:#12141d;--panel2:#171a25;--ink:#e8eaf0;--mut:#9aa0b4;--gold:#d9b35c;--line:#252938;--grn:#3fb950;--amb:#d29922;--red:#f85149;}
|
| 7 |
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
|
| 8 |
a{color:var(--gold);text-decoration:none}a:hover{text-decoration:underline}
|
| 9 |
header{border-bottom:1px solid var(--line);padding:14px 22px;display:flex;align-items:center;gap:14px;background:linear-gradient(180deg,#10121b,#0a0b10)}
|
| 10 |
header .brand{font-weight:700;letter-spacing:.5px;color:var(--gold);font-size:18px}
|
| 11 |
header .tag{color:var(--mut);font-size:12px}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
nav{display:flex;flex-wrap:wrap;gap:8px;padding:10px 22px;border-bottom:1px solid var(--line);background:var(--panel)}
|
| 13 |
nav a{font-size:12.5px;padding:4px 10px;border:1px solid var(--line);border-radius:999px;color:var(--mut)}
|
| 14 |
nav a:hover{border-color:var(--gold);color:var(--gold);text-decoration:none}
|
| 15 |
nav a.active{background:var(--gold);color:#0a0b10;border-color:var(--gold);font-weight:600}
|
| 16 |
-
main{max-width:
|
| 17 |
-
h1{font-size:26px;margin:0 0 4px;color:#fff}h2{font-size:
|
| 18 |
-
.sub{color:var(--mut);margin:0 0
|
| 19 |
-
|
| 20 |
-
.
|
| 21 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
.grid a.tile:hover{border-color:var(--gold);text-decoration:none}
|
| 23 |
-
.grid a.tile .
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
.
|
| 30 |
-
.
|
| 31 |
-
.
|
| 32 |
-
|
| 33 |
-
.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
</style></head><body>
|
| 35 |
-
<header>
|
| 36 |
-
<
|
| 37 |
-
<
|
| 38 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
</main>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
<footer>Doctrine v12 (PURIQ) additive · v11/v12 LOCKED: 749 declarations · 14 axioms · 163 sorries · 13-axis yuyay_v3 · lutar-v18.0.0 @ c7c0ba17 · SLSA L1 (honest) · Khipu signature = DSSE/cosign PLACEHOLDER<br>HfApi direct push only · IP-HOLD a11oy#57 untouched · ADDITIVE / zero-regression · Khipu receipt on every action · Signed <b>Yachay</b> · Co-author Perplexity Computer Agent</footer>
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
<!doctype html><html lang="en"><head><meta charset="utf-8">
|
| 2 |
<meta name="viewport" content="width=device-width,initial-scale=1">
|
| 3 |
+
<title>a11oy · Hub — the single front door</title>
|
| 4 |
<!-- SPDX-License-Identifier: Apache-2.0 · © 2026 SZL Holdings · Doctrine v12 additive · Signed: Yachay · Co-author: Perplexity Computer Agent -->
|
| 5 |
<style>
|
| 6 |
+
:root{--bg:#0a0b10;--panel:#12141d;--panel2:#171a25;--ink:#e8eaf0;--mut:#9aa0b4;--gold:#d9b35c;--line:#252938;--grn:#3fb950;--amb:#d29922;--red:#f85149;--blu:#58a6ff;}
|
| 7 |
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font:15px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
|
| 8 |
a{color:var(--gold);text-decoration:none}a:hover{text-decoration:underline}
|
| 9 |
header{border-bottom:1px solid var(--line);padding:14px 22px;display:flex;align-items:center;gap:14px;background:linear-gradient(180deg,#10121b,#0a0b10)}
|
| 10 |
header .brand{font-weight:700;letter-spacing:.5px;color:var(--gold);font-size:18px}
|
| 11 |
header .tag{color:var(--mut);font-size:12px}
|
| 12 |
+
header .spacer{flex:1}
|
| 13 |
+
.kbtn{display:inline-flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:7px 12px;color:var(--mut);font-size:13px;cursor:pointer}
|
| 14 |
+
.kbtn:hover{border-color:var(--gold);color:var(--gold)}
|
| 15 |
+
.kbtn .kbd{background:#1c2030;border:1px solid var(--line);border-radius:6px;padding:1px 7px;font-family:ui-monospace,monospace;font-size:12px;color:var(--ink)}
|
| 16 |
nav{display:flex;flex-wrap:wrap;gap:8px;padding:10px 22px;border-bottom:1px solid var(--line);background:var(--panel)}
|
| 17 |
nav a{font-size:12.5px;padding:4px 10px;border:1px solid var(--line);border-radius:999px;color:var(--mut)}
|
| 18 |
nav a:hover{border-color:var(--gold);color:var(--gold);text-decoration:none}
|
| 19 |
nav a.active{background:var(--gold);color:#0a0b10;border-color:var(--gold);font-weight:600}
|
| 20 |
+
main{max-width:1080px;margin:0 auto;padding:26px 22px 60px}
|
| 21 |
+
h1{font-size:26px;margin:0 0 4px;color:#fff}h2{font-size:16px;margin:30px 0 12px;color:var(--gold);letter-spacing:.3px}
|
| 22 |
+
.sub{color:var(--mut);margin:0 0 4px;font-size:13.5px}
|
| 23 |
+
/* health ribbon */
|
| 24 |
+
.ribbon{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:20px 0 8px}
|
| 25 |
+
.chip{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:13px 15px;position:relative;overflow:hidden}
|
| 26 |
+
.chip .lbl{color:var(--mut);font-size:11px;text-transform:uppercase;letter-spacing:.5px;margin-bottom:5px}
|
| 27 |
+
.chip .val{font-size:21px;font-weight:700;color:#fff;line-height:1.1}
|
| 28 |
+
.chip .foot{color:var(--mut);font-size:11.5px;margin-top:3px}
|
| 29 |
+
.chip .bar{position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--mut)}
|
| 30 |
+
.chip.g .bar{background:var(--grn)}.chip.a .bar{background:var(--amb)}.chip.r .bar{background:var(--red)}.chip.g .val{color:var(--grn)}.chip.a .val{color:var(--amb)}.chip.r .val{color:var(--red)}
|
| 31 |
+
/* launcher */
|
| 32 |
+
.launch{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:14px;margin:14px 0}
|
| 33 |
+
.launch a{display:block;background:var(--panel2);border:1px solid var(--line);border-radius:14px;padding:16px 17px;color:var(--ink);transition:border-color .12s,transform .12s}
|
| 34 |
+
.launch a:hover{border-color:var(--gold);text-decoration:none;transform:translateY(-2px)}
|
| 35 |
+
.launch .row{display:flex;align-items:center;gap:9px}
|
| 36 |
+
.dot{width:9px;height:9px;border-radius:50%;background:var(--mut);flex:0 0 auto;box-shadow:0 0 0 3px rgba(255,255,255,.03)}
|
| 37 |
+
.dot.g{background:var(--grn);box-shadow:0 0 8px rgba(63,185,80,.6)}.dot.a{background:var(--amb)}.dot.r{background:var(--red)}
|
| 38 |
+
.launch .t{color:#fff;font-weight:600;font-size:15px}
|
| 39 |
+
.launch .d{color:var(--mut);font-size:12.5px;margin-top:7px}
|
| 40 |
+
/* tabs grid */
|
| 41 |
+
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:12px;margin:12px 0}
|
| 42 |
+
.grid a.tile{display:block;background:var(--panel);border:1px solid var(--line);border-radius:11px;padding:13px 15px;color:var(--ink)}
|
| 43 |
.grid a.tile:hover{border-color:var(--gold);text-decoration:none}
|
| 44 |
+
.grid a.tile .row{display:flex;align-items:center;gap:8px}
|
| 45 |
+
.grid a.tile .t{color:var(--gold);font-weight:600;font-size:13.5px}.grid a.tile .d{color:var(--mut);font-size:12px;margin-top:4px}
|
| 46 |
+
.note{border-left:3px solid var(--gold);padding:8px 14px;background:rgba(217,179,92,.06);color:#d8dbe6;font-size:13.5px;margin:16px 0;border-radius:0 8px 8px 0}
|
| 47 |
+
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px}
|
| 48 |
+
footer{border-top:1px solid var(--line);color:var(--mut);font-size:11.5px;padding:18px 22px;line-height:1.7;margin-top:30px}
|
| 49 |
+
/* command palette */
|
| 50 |
+
.pal-wrap{position:fixed;inset:0;background:rgba(4,5,9,.66);backdrop-filter:blur(3px);display:none;align-items:flex-start;justify-content:center;z-index:99}
|
| 51 |
+
.pal-wrap.on{display:flex}
|
| 52 |
+
.pal{width:min(680px,92vw);margin-top:11vh;background:var(--panel);border:1px solid var(--line);border-radius:15px;box-shadow:0 24px 70px rgba(0,0,0,.6);overflow:hidden}
|
| 53 |
+
.pal input{width:100%;border:0;background:transparent;color:var(--ink);font-size:17px;padding:17px 19px;outline:none;border-bottom:1px solid var(--line)}
|
| 54 |
+
.pal input::placeholder{color:var(--mut)}
|
| 55 |
+
.pal .results{max-height:56vh;overflow:auto;padding:7px}
|
| 56 |
+
.pal .grp{color:var(--mut);font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;padding:9px 12px 4px}
|
| 57 |
+
.pal .item{display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:9px;cursor:pointer}
|
| 58 |
+
.pal .item.sel{background:var(--panel2)}
|
| 59 |
+
.pal .item .ic{width:22px;text-align:center;color:var(--gold);font-size:14px;flex:0 0 auto}
|
| 60 |
+
.pal .item .nm{color:var(--ink);font-size:14px}
|
| 61 |
+
.pal .item .ds{color:var(--mut);font-size:12px;margin-left:auto;padding-left:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:44%}
|
| 62 |
+
.pal .item .tagp{font-size:10.5px;color:var(--mut);border:1px solid var(--line);border-radius:999px;padding:1px 8px;margin-left:8px}
|
| 63 |
+
.pal .empty{color:var(--mut);padding:22px;text-align:center;font-size:13.5px}
|
| 64 |
+
.pal .foot{display:flex;gap:16px;color:var(--mut);font-size:11.5px;padding:9px 15px;border-top:1px solid var(--line);background:var(--panel2)}
|
| 65 |
+
.pal .foot .kbd{background:#1c2030;border:1px solid var(--line);border-radius:5px;padding:0 6px;font-family:ui-monospace,monospace}
|
| 66 |
+
.muted{color:var(--mut)}
|
| 67 |
</style></head><body>
|
| 68 |
+
<header>
|
| 69 |
+
<span class="brand">a11oy</span>
|
| 70 |
+
<span class="tag">Brand Orchestration Layer · single front door</span>
|
| 71 |
+
<span class="spacer"></span>
|
| 72 |
+
<button class="kbtn" id="palBtn">Search everything <span class="kbd">⌘K</span></button>
|
| 73 |
+
</header>
|
| 74 |
+
<nav><a href="/hub" class="active">Hub</a><a href="/console">Console</a><a href="/cockpit">Cockpit</a><a href="/console#organism">Organism</a><a href="/a11oy.code">a11oy.code</a><a href="/energy">Energy</a><a href="/audit">Audit</a><a href="/docs">Docs</a><a href="/pricing">Pricing</a><a href="/api-keys">API Keys</a><a href="/sdk">SDK</a><a href="/status">Status</a><a href="/security">Security</a><a href="/compliance">Compliance</a></nav>
|
| 75 |
+
<main>
|
| 76 |
+
<h1>Hub</h1>
|
| 77 |
+
<p class="sub">One place to see the whole organism and jump anywhere. Every number below is a live read — no figure is shown unless the source answered.</p>
|
| 78 |
+
|
| 79 |
+
<div class="ribbon" id="ribbon">
|
| 80 |
+
<div class="chip" id="ch-organs"><div class="bar"></div><div class="lbl">Organs</div><div class="val">…</div><div class="foot">reading engine</div></div>
|
| 81 |
+
<div class="chip" id="ch-mind"><div class="bar"></div><div class="lbl">Mind</div><div class="val">…</div><div class="foot">orchestrator</div></div>
|
| 82 |
+
<div class="chip" id="ch-spine"><div class="bar"></div><div class="lbl">Spine · federated tools</div><div class="val">…</div><div class="foot">reading MCP</div></div>
|
| 83 |
+
<div class="chip" id="ch-const"><div class="bar"></div><div class="lbl">Constellation</div><div class="val">…</div><div class="foot">surfaces reachable</div></div>
|
| 84 |
+
<div class="chip" id="ch-doc"><div class="bar"></div><div class="lbl">Doctrine</div><div class="val">…</div><div class="foot">constitutional lock</div></div>
|
| 85 |
+
</div>
|
| 86 |
+
|
| 87 |
+
<h2>Operate</h2>
|
| 88 |
+
<div class="launch" id="launch"></div>
|
| 89 |
+
|
| 90 |
+
<h2>All surfaces</h2>
|
| 91 |
+
<p class="sub">Live tab manifest — each carries its own honest status. <span class="muted">Press <span class="kbd" style="border:1px solid var(--line);border-radius:5px;padding:0 6px;font-family:ui-monospace,monospace">⌘K</span> to fuzzy-jump to any surface or federated tool.</span></p>
|
| 92 |
+
<div class="grid" id="tabs"><p class="muted">Loading manifest…</p></div>
|
| 93 |
+
|
| 94 |
+
<div class="note">Machine-readable: the tab manifest is JSON at <a href="/api/a11oy/v1/hub/manifest"><code>/api/a11oy/v1/hub/manifest</code></a>, the federated tools at <a href="/api/a11oy/v1/spine"><code>/api/a11oy/v1/spine</code></a>, and the full organism health at <a href="/api/a11oy/v1/engine/status"><code>/api/a11oy/v1/engine/status</code></a> — all Khipu-receipted.</div>
|
| 95 |
</main>
|
| 96 |
+
|
| 97 |
+
<div class="pal-wrap" id="palWrap">
|
| 98 |
+
<div class="pal" role="dialog" aria-label="Command palette">
|
| 99 |
+
<input id="palInput" placeholder="Jump to a surface, organ, or federated tool…" autocomplete="off" spellcheck="false">
|
| 100 |
+
<div class="results" id="palResults"></div>
|
| 101 |
+
<div class="foot"><span><span class="kbd">↑</span> <span class="kbd">↓</span> navigate</span><span><span class="kbd">↵</span> open</span><span><span class="kbd">esc</span> close</span><span class="spacer" style="margin-left:auto">Powered by the live spine</span></div>
|
| 102 |
+
</div>
|
| 103 |
+
</div>
|
| 104 |
+
|
| 105 |
<footer>Doctrine v12 (PURIQ) additive · v11/v12 LOCKED: 749 declarations · 14 axioms · 163 sorries · 13-axis yuyay_v3 · lutar-v18.0.0 @ c7c0ba17 · SLSA L1 (honest) · Khipu signature = DSSE/cosign PLACEHOLDER<br>HfApi direct push only · IP-HOLD a11oy#57 untouched · ADDITIVE / zero-regression · Khipu receipt on every action · Signed <b>Yachay</b> · Co-author Perplexity Computer Agent</footer>
|
| 106 |
+
|
| 107 |
+
<script>
|
| 108 |
+
const $=s=>document.querySelector(s);
|
| 109 |
+
async function getJSON(u){const c=new AbortController();const t=setTimeout(()=>c.abort(),9000);try{const r=await fetch(u,{signal:c.signal});clearTimeout(t);if(!r.ok)throw new Error(r.status);return await r.json();}catch(e){clearTimeout(t);return null;}}
|
| 110 |
+
function setChip(id,cls,val,foot){const el=$(id);if(!el)return;el.className='chip '+cls;el.querySelector('.val').textContent=val;if(foot!=null)el.querySelector('.foot').textContent=foot;}
|
| 111 |
+
|
| 112 |
+
// ---- curated primary surfaces (always present; local to this app) ----
|
| 113 |
+
const SURFACES=[
|
| 114 |
+
{name:'Console',route:'/console',ic:'▤',desc:'Operator console — organism, anatomy map, controls'},
|
| 115 |
+
{name:'Cockpit',route:'/cockpit',ic:'✦',desc:'Live command cockpit — spine, constellation, engine'},
|
| 116 |
+
{name:'Organism',route:'/console#organism',ic:'❋',desc:'The mind + six organs, rendered'},
|
| 117 |
+
{name:'a11oy.code',route:'/a11oy.code',ic:'⌘',desc:'Talk to the orchestrator'},
|
| 118 |
+
{name:'Energy',route:'/energy',ic:'⚡',desc:'Sovereign-compute energy instrumentation'},
|
| 119 |
+
{name:'Audit',route:'/audit',ic:'⛓',desc:'Walk the Khipu DAG — receipts behind every claim'},
|
| 120 |
+
{name:'Docs',route:'/docs',ic:'▦',desc:'Documentation'},
|
| 121 |
+
{name:'Pricing',route:'/pricing',ic:'◈',desc:'Pricing'},
|
| 122 |
+
{name:'API Keys',route:'/api-keys',ic:'⚿',desc:'API keys'},
|
| 123 |
+
{name:'SDK',route:'/sdk',ic:'◇',desc:'SDK'},
|
| 124 |
+
{name:'Status',route:'/status',ic:'◉',desc:'Status'},
|
| 125 |
+
{name:'Security',route:'/security',ic:'⛨',desc:'Security posture'},
|
| 126 |
+
{name:'Compliance',route:'/compliance',ic:'§',desc:'Compliance'},
|
| 127 |
+
{name:'Observability',route:'/observability',ic:'◎',desc:'Observability'}
|
| 128 |
+
];
|
| 129 |
+
// launcher = the six operator entries Rosa asked route to
|
| 130 |
+
const LAUNCH=['Console','Cockpit','Organism','a11oy.code','Energy','Audit'];
|
| 131 |
+
|
| 132 |
+
let PAL_INDEX=[]; // {name,route,ic,desc,group,tag,ext}
|
| 133 |
+
|
| 134 |
+
function renderLaunch(engine,spine){
|
| 135 |
+
const health={};
|
| 136 |
+
if(engine){health['Console']=engine.mind&&engine.mind.status==='ok'?'g':'a';
|
| 137 |
+
health['Organism']=(engine.organs_healthy===engine.organs_total)?'g':(engine.organs_healthy>0?'a':'r');
|
| 138 |
+
health['Energy']=engine.energy&&engine.energy.status==='ok'?'g':'a';}
|
| 139 |
+
health['Cockpit']='g';health['a11oy.code']='g';health['Audit']='g';
|
| 140 |
+
const sub={Spine:spine?(spine.tool_count+' tools'):''};
|
| 141 |
+
const html=LAUNCH.map(n=>{const s=SURFACES.find(x=>x.name===n);const d=health[n]||'g';
|
| 142 |
+
return `<a href="${s.route}"><div class="row"><span class="dot ${d}"></span><span class="t">${s.name}</span></div><div class="d">${s.desc}</div></a>`;}).join('');
|
| 143 |
+
$('#launch').innerHTML=html;
|
| 144 |
+
}
|
| 145 |
+
function renderTabs(man){
|
| 146 |
+
const t=(man&&man.tabs)||[];
|
| 147 |
+
if(!t.length){$('#tabs').innerHTML='<p class="muted">Manifest unreachable.</p>';return;}
|
| 148 |
+
const cls=s=>s==='GREEN'?'g':(s==='AMBER'?'a':(s==='RED'?'r':''));
|
| 149 |
+
$('#tabs').innerHTML=t.map(x=>`<a class="tile" href="${x.route}"><div class="row"><span class="dot ${cls(x.status)}"></span><span class="t">${x.name||x.route}</span></div><div class="d">${x.purpose||''}</div></a>`).join('');
|
| 150 |
+
}
|
| 151 |
+
function buildIndex(spine,man,con){
|
| 152 |
+
const idx=[];
|
| 153 |
+
SURFACES.forEach(s=>idx.push({name:s.name,route:s.route,ic:s.ic,desc:s.desc,group:'Surfaces'}));
|
| 154 |
+
// 25 federated tools from the live spine — the "make it ours" bit
|
| 155 |
+
if(spine&&Array.isArray(spine.tools)){spine.tools.forEach(t=>{const p=t.product||t.group||'';idx.push({name:t.name||t.tool||String(t),route:'/cockpit',ic:'⚙',desc:(t.description||t.summary||'federated tool'),group:'Federated tools',tag:p});});}
|
| 156 |
+
// manifest tabs not already curated
|
| 157 |
+
if(man&&man.tabs){const have=new Set(idx.map(i=>i.route));man.tabs.forEach(x=>{if(!have.has(x.route))idx.push({name:x.name||x.route,route:x.route,ic:'▹',desc:x.purpose||'',group:'Surfaces'});});}
|
| 158 |
+
// constellation surfaces -> external
|
| 159 |
+
if(con&&Array.isArray(con.surfaces)){con.surfaces.forEach(s=>{if(s.url)idx.push({name:s.name||'surface',route:s.url,ic:'◱',desc:(s.kind||'')+(s.blurb?(' — '+s.blurb):''),group:'Constellation',tag:s.group,ext:true});});}
|
| 160 |
+
PAL_INDEX=idx;
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
// ---- fuzzy match (subsequence + contiguous bonus) ----
|
| 164 |
+
function score(q,s){q=q.toLowerCase();s=s.toLowerCase();if(!q)return 0.1;let qi=0,sc=0,run=0,last=-1;for(let i=0;i<s.length&&qi<q.length;i++){if(s[i]===q[qi]){sc+=1+run*0.6+(i===last+1?1.2:0)+(i===0?1.5:0);run++;last=i;qi++;}else run=0;}return qi===q.length?sc:-1;}
|
| 165 |
+
let selIdx=0,curList=[];
|
| 166 |
+
function renderResults(q){
|
| 167 |
+
const scored=PAL_INDEX.map(it=>({it,s:Math.max(score(q,it.name),score(q,(it.tag||'')+' '+it.name)*0.8,score(q,it.desc||'')*0.4)})).filter(x=>x.s>=(q?0.5:0)).sort((a,b)=>b.s-a.s).slice(0,q?40:60);
|
| 168 |
+
curList=scored.map(x=>x.it);selIdx=0;
|
| 169 |
+
if(!curList.length){$('#palResults').innerHTML='<div class="empty">No match. Try “console”, “spine”, “energy”, or a tool name.</div>';return;}
|
| 170 |
+
const groups={};curList.forEach((it,i)=>{(groups[it.group]=groups[it.group]||[]).push({it,i});});
|
| 171 |
+
let html='';for(const g in groups){html+=`<div class="grp">${g}</div>`;groups[g].forEach(({it,i})=>{html+=`<div class="item${i===selIdx?' sel':''}" data-i="${i}"><span class="ic">${it.ic||'▹'}</span><span class="nm">${it.name}</span>${it.tag?`<span class="tagp">${it.tag}</span>`:''}<span class="ds">${it.desc||''}</span></div>`;});}
|
| 172 |
+
$('#palResults').innerHTML=html;
|
| 173 |
+
$('#palResults').querySelectorAll('.item').forEach(el=>{el.onmouseenter=()=>{selIdx=+el.dataset.i;paintSel();};el.onclick=()=>go(curList[+el.dataset.i]);});
|
| 174 |
+
}
|
| 175 |
+
function paintSel(){$('#palResults').querySelectorAll('.item').forEach(el=>el.classList.toggle('sel',+el.dataset.i===selIdx));const s=$('#palResults').querySelector('.item.sel');if(s)s.scrollIntoView({block:'nearest'});}
|
| 176 |
+
function go(it){if(!it)return;if(it.ext){window.open(it.route,'_blank','noopener');}else{window.location.href=it.route;}}
|
| 177 |
+
function openPal(){$('#palWrap').classList.add('on');$('#palInput').value='';renderResults('');$('#palInput').focus();}
|
| 178 |
+
function closePal(){$('#palWrap').classList.remove('on');}
|
| 179 |
+
$('#palBtn').onclick=openPal;
|
| 180 |
+
$('#palWrap').onclick=e=>{if(e.target===$('#palWrap'))closePal();};
|
| 181 |
+
$('#palInput').addEventListener('input',e=>renderResults(e.target.value));
|
| 182 |
+
$('#palInput').addEventListener('keydown',e=>{
|
| 183 |
+
if(e.key==='ArrowDown'){e.preventDefault();selIdx=Math.min(selIdx+1,curList.length-1);paintSel();}
|
| 184 |
+
else if(e.key==='ArrowUp'){e.preventDefault();selIdx=Math.max(selIdx-1,0);paintSel();}
|
| 185 |
+
else if(e.key==='Enter'){e.preventDefault();go(curList[selIdx]);}
|
| 186 |
+
else if(e.key==='Escape'){closePal();}
|
| 187 |
+
});
|
| 188 |
+
document.addEventListener('keydown',e=>{
|
| 189 |
+
if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==='k'){e.preventDefault();$('#palWrap').classList.contains('on')?closePal():openPal();}
|
| 190 |
+
else if(e.key==='/'&&!/input|textarea/i.test((document.activeElement||{}).tagName||'')&&!$('#palWrap').classList.contains('on')){e.preventDefault();openPal();}
|
| 191 |
+
});
|
| 192 |
+
|
| 193 |
+
// ---- boot: four live feeds in parallel ----
|
| 194 |
+
(async()=>{
|
| 195 |
+
const [engine,spine,con,man]=await Promise.all([
|
| 196 |
+
getJSON('/api/a11oy/v1/engine/status'),
|
| 197 |
+
getJSON('/api/a11oy/v1/spine'),
|
| 198 |
+
getJSON('/api/a11oy/v1/constellation'),
|
| 199 |
+
getJSON('/api/a11oy/v1/hub/manifest')
|
| 200 |
+
]);
|
| 201 |
+
// ribbon
|
| 202 |
+
if(engine){
|
| 203 |
+
const oh=engine.organs_healthy,ot=engine.organs_total;
|
| 204 |
+
setChip('#ch-organs',oh===ot?'g':(oh>0?'a':'r'),(oh!=null?`${oh}/${ot}`:'—'),'healthy organs');
|
| 205 |
+
const ms=engine.mind&&engine.mind.status;setChip('#ch-mind',ms==='ok'?'g':(ms?'a':'r'),ms?ms.toUpperCase():'—',engine.mind&&engine.mind.reachable?'reachable':'unreachable');
|
| 206 |
+
const d=engine.doctrine||{};setChip('#ch-doc','g',d.locked!=null?('locked-'+d.locked):'locked',(d.lambda?('Λ '+d.lambda):'')+(d.version?(' · '+d.version):''));
|
| 207 |
+
}else{setChip('#ch-organs','r','—','engine unreachable');setChip('#ch-mind','r','—','engine unreachable');setChip('#ch-doc','a','—','engine unreachable');}
|
| 208 |
+
if(spine){setChip('#ch-spine',spine.reachable?'g':'r',String(spine.tool_count),(spine.by_product?Object.entries(spine.by_product).map(([k,v])=>k+':'+v).join(' · '):'federated'));}
|
| 209 |
+
else setChip('#ch-spine','r','—','MCP unreachable');
|
| 210 |
+
if(con){setChip('#ch-const',con.reachable===con.total?'g':(con.reachable>0?'a':'r'),`${con.reachable}/${con.total}`,'surfaces reachable');}
|
| 211 |
+
else setChip('#ch-const','r','—','probe unreachable');
|
| 212 |
+
renderLaunch(engine,spine);
|
| 213 |
+
renderTabs(man);
|
| 214 |
+
buildIndex(spine,man,con);
|
| 215 |
+
})();
|
| 216 |
+
</script>
|
| 217 |
+
</body></html>
|