diff --git a/static/assets/webapp-1e2_m1ss.js b/static/assets/webapp-1e2_m1ss.js deleted file mode 100644 index 45e9da8..0000000 --- a/static/assets/webapp-1e2_m1ss.js +++ /dev/null @@ -1,379 +0,0 @@ -(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={modules:[{id:`rust`,label:`Rust core`,loaded:!1,detail:`TypeScript fallback active`},{id:`cpp`,label:`C++ route core`,loaded:!1,detail:`TypeScript fallback active`},{id:`go`,label:`Go status core`,loaded:!1,detail:`TypeScript fallback active`}],scoreCatalog(e){return Math.max(0,Math.min(100,70+e.publicCount*2+e.gatedCount-e.degradedCount*12))},routeWeight(e,t){return e*10+t*7}};function t(e){return new URL(`${import.meta.env?.BASE_URL??`./`}${e}`,window.location.href)}async function n(e){let n=await fetch(t(e));if(!n.ok)return null;let r=await n.arrayBuffer();return(await WebAssembly.instantiate(r,{})).instance.exports}function r(e,t){if(!e)return null;for(let n of t){let t=e[n];if(typeof t==`function`)return(...e)=>Number(t(...e))}return null}async function i(){try{let e=await fetch(t(`wasm/modules.json`));if(!e.ok)return new Map;let n=await e.json();return new Map((n.modules??[]).map(e=>[e.id,e]))}catch{return new Map}}function a(t,n){let r=e.modules.find(e=>e.id===t)??e.modules[0],i=n.get(t)?.detail;return i?{...r,detail:i}:r}async function o(){let t=await i(),o=[],s=e.scoreCatalog,c=e.routeWeight;if(t.get(`rust`)?.status===`built`)try{let e=r(await n(`wasm/cxllm_rust_core.wasm`),[`cxllm_signal_score`]);e?(s=t=>e(t.publicCount,t.gatedCount,t.degradedCount),o.push({id:`rust`,label:`Rust core`,loaded:!0,detail:`Catalog signal scoring`})):o.push(a(`rust`,t))}catch{o.push(a(`rust`,t))}else o.push(a(`rust`,t));if(t.get(`cpp`)?.status===`built`)try{let e=r(await n(`wasm/cxllm_cpp_core.wasm`),[`cxllm_route_weight`,`_cxllm_route_weight`]);e?(c=(t,n)=>e(t,n),o.push({id:`cpp`,label:`C++ route core`,loaded:!0,detail:`Endpoint weighting`})):o.push(a(`cpp`,t))}catch{o.push(a(`cpp`,t))}else o.push(a(`cpp`,t));let l=t.get(`go`)?.status===`built`;return o.push(l?{id:`go`,label:`Go status core`,loaded:!0,detail:`Go Wasm artifact available`}:a(`go`,t)),{modules:o,scoreCatalog:s,routeWeight:c}}var s=`cxllm:nav:section`,c=`cxllm:nav:devpane`,l=`cxllm:sidebar:collapsed`;function ee(e){return e===`members`||e===`webapp`||e===`api`||e===`mcp`?e:`landing`}function te(e){switch(e){case`api`:case`mcp`:return`developer`;case`webapp`:return`services`;case`members`:return`overview`;default:return`overview`}}function ne(e){let t=new URLSearchParams(window.location.search).get(`section`),n=localStorage.getItem(s)??null;return{target:e,section:u(t)?t:e===`api`||e===`mcp`?`developer`:u(n)?n:te(e),devPane:e===`api`?`api`:e===`mcp`||localStorage.getItem(c)===`mcp`?`mcp`:`api`,query:``,sidebarCollapsed:localStorage.getItem(l)===`1`}}function u(e){return e===`overview`||e===`services`||e===`developer`||e===`agent`}function re(e){try{localStorage.setItem(s,e)}catch{}}function ie(e){try{localStorage.setItem(c,e)}catch{}}function ae(e){try{localStorage.setItem(l,e?`1`:`0`)}catch{}}var d=`cxllm:session:v1`,f=6e4;function p(){try{let e=sessionStorage.getItem(d);if(!e)return null;let t=JSON.parse(e);return Date.now()-t.ts>f?null:t}catch{return null}}function m(e){try{sessionStorage.setItem(d,JSON.stringify({ts:Date.now(),value:e}))}catch{}}async function oe(e=!1){if(!e){let e=p();if(e)return e.value}let t=window.location.host;if(t===`127.0.0.1`||t.startsWith(`127.0.0.1:`)||t.startsWith(`localhost`)){let e=new URLSearchParams(window.location.search),t=e.get(`signed-in`)===`1`?{authenticated:!0,username:e.get(`user`)||`dev`,email:`dev@cxllm.io`}:{authenticated:!1};return m(t),t}try{let e=new AbortController,t=setTimeout(()=>e.abort(),3e3),n=await fetch(`/outpost.goauthentik.io/auth/caddy`,{method:`GET`,credentials:`include`,signal:e.signal});if(clearTimeout(t),n.status===200){let e={authenticated:!0,username:n.headers.get(`X-Authentik-Username`)||void 0,email:n.headers.get(`X-Authentik-Email`)||void 0,groups:(n.headers.get(`X-Authentik-Groups`)||``).split(`|`).filter(Boolean)};return m(e),e}}catch{}let n={authenticated:!1};return m(n),n}function se(e){return`https://auth.cxllm.io/if/flow/default-authentication-flow/?next=${encodeURIComponent(e??`https://web.cxllm.io/`)}`}function h(e){return String(e??``).replace(/&/g,`&`).replace(//g,`>`).replace(/"/g,`"`).replace(/'/g,`'`)}function g(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}var _=e=>``,v={overview:_(``),services:_(``),developer:_(``),agent:_(``),workspace:_(``),ops:_(``),account:_(``),collapse:_(``),expand:_(``),search:_(``),open:_(``),copy:_(``),pulse:_(``),signin:_(``),signout:_(``)},y={domain:`cxllm.io`,home:[{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:null,deprecated:!1,description:`CxAI agent control plane (cxai-mcp HTTP sidecar: status, tools, events).`,endpointGroups:[`status`,`tools`,`events`],expected:[200],health:[{expect:[200],path:`/status`},{expect:[200,401,302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`agent.cxllm.io`,hosts:[`agent.cxllm.io`],id:`agent`,kind:`agent`,landing:!1,membersSpa:!0,name:`CxAI Agent`,notes:`CxAI control plane: cxai-mcp HTTP sidecar (status, tools registry, /events tail).`,probe:`https://agent.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI Agent`,upstreamPort:8082,url:`https://agent.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:null,deprecated:!1,description:`Data flywheel and ML operations surface.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mlrun.cxllm.io`,hosts:[`mlrun.cxllm.io`],id:`mlrun`,kind:`ml-dashboard`,landing:!1,membersSpa:!0,name:`MLRun`,notes:`Static ML/data-flywheel page until a live MLRun UI container is promoted.`,probe:`https://mlrun.cxllm.io/healthz`,replacement:null,source:`cx-ml/web`,title:`MLRun`,upstreamPort:null,url:`https://mlrun.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`}],landing:[{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:null,deprecated:!1,description:`Legacy Crow UI for operator workflows.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`webapp.cxllm.io`,hosts:[`webapp.cxllm.io`],id:`webapp`,kind:`web`,landing:!0,membersSpa:!0,name:`CxWebApp`,notes:`Legacy Crow C++ operator UI; currently managed outside cxllm-cloud compose.`,probe:`https://webapp.cxllm.io/api/health`,replacement:null,source:`CxWebApp`,title:`CxWebApp`,upstreamPort:8085,url:`https://webapp.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-green`,composeService:null,deprecated:!1,description:`Members workspace and authenticated service console.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`web.cxllm.io`,hosts:[`web.cxllm.io`],id:`web`,kind:`spa`,landing:!0,membersSpa:!1,name:`Members SPA`,notes:`Static members workspace deployed to /srv/cxai/web and protected by Authentik at the edge.`,probe:`https://web.cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/cxllm-web`,title:`Members SPA`,upstreamPort:null,url:`https://web.cxllm.io/`},{auth:`public-idp`,badge:`public`,badgeClass:`public`,color:`sb-purple`,composeService:`authentik-server`,deprecated:!1,description:`Identity, SSO, MFA, and access policies.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/-/health/ready/`},{expect:[200],path:`/-/health/live/`}],host:`auth.cxllm.io`,hosts:[`auth.cxllm.io`],id:`auth`,kind:`identity`,landing:!0,membersSpa:!0,name:`Authentik IdP`,notes:`Identity provider and embedded forward-auth outpost.`,probe:`https://auth.cxllm.io/-/health/ready/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Authentik IdP`,upstreamPort:9e3,url:`https://auth.cxllm.io/`},{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`aws-iam`,badge:`AWS IAM`,badgeClass:`api`,color:`sb-purple`,composeService:null,deprecated:!1,description:`AWS-backed object storage, CloudFront keys, and IAM access.`,endpointGroups:[`s3`,`cloudfront`,`iam`],expected:[],health:[],host:`AWS S3`,hosts:[],id:`aws-storage`,kind:`object-storage-cloud`,landing:!0,membersSpa:!0,name:`AWS Storage`,notes:`Primary object storage is AWS-backed and configured from the local CxAWS config directory; credentials are never embedded in static assets.`,probe:`https://console.aws.amazon.com/s3/home`,replacement:null,source:`CxAI/projects/CxAWS/config`,title:`AWS Storage`,upstreamPort:null,url:`https://console.aws.amazon.com/s3/home`},{auth:`docker-basic-auth`,badge:`basic`,badgeClass:`basic`,color:`sb-amber`,composeService:null,deprecated:!1,description:`Private container image registry.`,endpointGroups:[],expected:[401],health:[{expect:[401],path:`/v2/`}],host:`registry.cxllm.io`,hosts:[`registry.cxllm.io`],id:`registry`,kind:`registry`,landing:!0,membersSpa:!1,name:`Container Registry`,notes:`Docker registry; 401 is the expected unauthenticated health result.`,probe:`https://registry.cxllm.io/v2/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Container Registry`,upstreamPort:5e3,url:`https://registry.cxllm.io/`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`}],manifestSchemaVersion:1,members:[{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:`cxllm-landing`,deprecated:!1,description:`Public marketing front door.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`}],host:`cxllm.io`,hosts:[`cxllm.io`,`www.cxllm.io`,`app.cxllm.io`],id:`landing`,kind:`web`,landing:!1,membersSpa:!0,name:`CxLLM Landing`,notes:`Public marketing and console landing served by the cxllm-landing container.`,probe:`https://cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/app`,title:`CxLLM Landing`,upstreamPort:8086,url:`https://cxllm.io/`},{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:null,deprecated:!1,description:`Legacy Crow UI for operator workflows.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`webapp.cxllm.io`,hosts:[`webapp.cxllm.io`],id:`webapp`,kind:`web`,landing:!0,membersSpa:!0,name:`CxWebApp`,notes:`Legacy Crow C++ operator UI; currently managed outside cxllm-cloud compose.`,probe:`https://webapp.cxllm.io/api/health`,replacement:null,source:`CxWebApp`,title:`CxWebApp`,upstreamPort:8085,url:`https://webapp.cxllm.io/`},{auth:`public-idp`,badge:`public`,badgeClass:`public`,color:`sb-purple`,composeService:`authentik-server`,deprecated:!1,description:`Identity, SSO, MFA, and access policies.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/-/health/ready/`},{expect:[200],path:`/-/health/live/`}],host:`auth.cxllm.io`,hosts:[`auth.cxllm.io`],id:`auth`,kind:`identity`,landing:!0,membersSpa:!0,name:`Authentik IdP`,notes:`Identity provider and embedded forward-auth outpost.`,probe:`https://auth.cxllm.io/-/health/ready/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Authentik IdP`,upstreamPort:9e3,url:`https://auth.cxllm.io/`},{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:null,deprecated:!1,description:`CxAI agent control plane (cxai-mcp HTTP sidecar: status, tools, events).`,endpointGroups:[`status`,`tools`,`events`],expected:[200],health:[{expect:[200],path:`/status`},{expect:[200,401,302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`agent.cxllm.io`,hosts:[`agent.cxllm.io`],id:`agent`,kind:`agent`,landing:!1,membersSpa:!0,name:`CxAI Agent`,notes:`CxAI control plane: cxai-mcp HTTP sidecar (status, tools registry, /events tail).`,probe:`https://agent.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI Agent`,upstreamPort:8082,url:`https://agent.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`aws-iam`,badge:`AWS IAM`,badgeClass:`api`,color:`sb-purple`,composeService:null,deprecated:!1,description:`AWS-backed object storage, CloudFront keys, and IAM access.`,endpointGroups:[`s3`,`cloudfront`,`iam`],expected:[],health:[],host:`AWS S3`,hosts:[],id:`aws-storage`,kind:`object-storage-cloud`,landing:!0,membersSpa:!0,name:`AWS Storage`,notes:`Primary object storage is AWS-backed and configured from the local CxAWS config directory; credentials are never embedded in static assets.`,probe:`https://console.aws.amazon.com/s3/home`,replacement:null,source:`CxAI/projects/CxAWS/config`,title:`AWS Storage`,upstreamPort:null,url:`https://console.aws.amazon.com/s3/home`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-red`,composeService:`cxai-rust`,deprecated:!1,description:`Rust integration runtime.`,endpointGroups:[`health`,`version`,`metrics`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`rust.cxllm.io`,hosts:[`rust.cxllm.io`],id:`rust`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Rust Runtime`,notes:`Rust integration shim.`,probe:`https://rust.cxllm.io/healthz`,replacement:null,source:`CxAI Base/cargo`,title:`Rust Runtime`,upstreamPort:8089,url:`https://rust.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`cxai-go`,deprecated:!1,description:`Go integration runtime.`,endpointGroups:[`health`,`version`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`go.cxllm.io`,hosts:[`go.cxllm.io`],id:`go`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Go Runtime`,notes:`Go implementation of the integration API.`,probe:`https://go.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-go`,title:`Go Runtime`,upstreamPort:8088,url:`https://go.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`cxai-maven`,deprecated:!1,description:`Java integration runtime.`,endpointGroups:[`health`,`version`,`metrics`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`java.cxllm.io`,hosts:[`java.cxllm.io`],id:`java`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Java Runtime`,notes:`Java/Maven implementation of the integration API.`,probe:`https://java.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-maven`,title:`Java Runtime`,upstreamPort:8090,url:`https://java.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:null,deprecated:!1,description:`Data flywheel and ML operations surface.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mlrun.cxllm.io`,hosts:[`mlrun.cxllm.io`],id:`mlrun`,kind:`ml-dashboard`,landing:!1,membersSpa:!0,name:`MLRun`,notes:`Static ML/data-flywheel page until a live MLRun UI container is promoted.`,probe:`https://mlrun.cxllm.io/healthz`,replacement:null,source:`cx-ml/web`,title:`MLRun`,upstreamPort:null,url:`https://mlrun.cxllm.io/`}],schemaVersion:1,services:[{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:`cxllm-landing`,deprecated:!1,description:`Public marketing front door.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`}],host:`cxllm.io`,hosts:[`cxllm.io`,`www.cxllm.io`,`app.cxllm.io`],id:`landing`,kind:`web`,landing:!1,membersSpa:!0,name:`CxLLM Landing`,notes:`Public marketing and console landing served by the cxllm-landing container.`,probe:`https://cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/app`,title:`CxLLM Landing`,upstreamPort:8086,url:`https://cxllm.io/`},{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:null,deprecated:!1,description:`Legacy Crow UI for operator workflows.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`webapp.cxllm.io`,hosts:[`webapp.cxllm.io`],id:`webapp`,kind:`web`,landing:!0,membersSpa:!0,name:`CxWebApp`,notes:`Legacy Crow C++ operator UI; currently managed outside cxllm-cloud compose.`,probe:`https://webapp.cxllm.io/api/health`,replacement:null,source:`CxWebApp`,title:`CxWebApp`,upstreamPort:8085,url:`https://webapp.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-green`,composeService:null,deprecated:!1,description:`Members workspace and authenticated service console.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`web.cxllm.io`,hosts:[`web.cxllm.io`],id:`web`,kind:`spa`,landing:!0,membersSpa:!1,name:`Members SPA`,notes:`Static members workspace deployed to /srv/cxai/web and protected by Authentik at the edge.`,probe:`https://web.cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/cxllm-web`,title:`Members SPA`,upstreamPort:null,url:`https://web.cxllm.io/`},{auth:`public-idp`,badge:`public`,badgeClass:`public`,color:`sb-purple`,composeService:`authentik-server`,deprecated:!1,description:`Identity, SSO, MFA, and access policies.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/-/health/ready/`},{expect:[200],path:`/-/health/live/`}],host:`auth.cxllm.io`,hosts:[`auth.cxllm.io`],id:`auth`,kind:`identity`,landing:!0,membersSpa:!0,name:`Authentik IdP`,notes:`Identity provider and embedded forward-auth outpost.`,probe:`https://auth.cxllm.io/-/health/ready/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Authentik IdP`,upstreamPort:9e3,url:`https://auth.cxllm.io/`},{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:null,deprecated:!1,description:`CxAI agent control plane (cxai-mcp HTTP sidecar: status, tools, events).`,endpointGroups:[`status`,`tools`,`events`],expected:[200],health:[{expect:[200],path:`/status`},{expect:[200,401,302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`agent.cxllm.io`,hosts:[`agent.cxllm.io`],id:`agent`,kind:`agent`,landing:!1,membersSpa:!0,name:`CxAI Agent`,notes:`CxAI control plane: cxai-mcp HTTP sidecar (status, tools registry, /events tail).`,probe:`https://agent.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI Agent`,upstreamPort:8082,url:`https://agent.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`aws-iam`,badge:`AWS IAM`,badgeClass:`api`,color:`sb-purple`,composeService:null,deprecated:!1,description:`AWS-backed object storage, CloudFront keys, and IAM access.`,endpointGroups:[`s3`,`cloudfront`,`iam`],expected:[],health:[],host:`AWS S3`,hosts:[],id:`aws-storage`,kind:`object-storage-cloud`,landing:!0,membersSpa:!0,name:`AWS Storage`,notes:`Primary object storage is AWS-backed and configured from the local CxAWS config directory; credentials are never embedded in static assets.`,probe:`https://console.aws.amazon.com/s3/home`,replacement:null,source:`CxAI/projects/CxAWS/config`,title:`AWS Storage`,upstreamPort:null,url:`https://console.aws.amazon.com/s3/home`},{auth:`docker-basic-auth`,badge:`basic`,badgeClass:`basic`,color:`sb-amber`,composeService:null,deprecated:!1,description:`Private container image registry.`,endpointGroups:[],expected:[401],health:[{expect:[401],path:`/v2/`}],host:`registry.cxllm.io`,hosts:[`registry.cxllm.io`],id:`registry`,kind:`registry`,landing:!0,membersSpa:!1,name:`Container Registry`,notes:`Docker registry; 401 is the expected unauthenticated health result.`,probe:`https://registry.cxllm.io/v2/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Container Registry`,upstreamPort:5e3,url:`https://registry.cxllm.io/`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-red`,composeService:`cxai-rust`,deprecated:!1,description:`Rust integration runtime.`,endpointGroups:[`health`,`version`,`metrics`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`rust.cxllm.io`,hosts:[`rust.cxllm.io`],id:`rust`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Rust Runtime`,notes:`Rust integration shim.`,probe:`https://rust.cxllm.io/healthz`,replacement:null,source:`CxAI Base/cargo`,title:`Rust Runtime`,upstreamPort:8089,url:`https://rust.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`cxai-go`,deprecated:!1,description:`Go integration runtime.`,endpointGroups:[`health`,`version`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`go.cxllm.io`,hosts:[`go.cxllm.io`],id:`go`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Go Runtime`,notes:`Go implementation of the integration API.`,probe:`https://go.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-go`,title:`Go Runtime`,upstreamPort:8088,url:`https://go.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`cxai-maven`,deprecated:!1,description:`Java integration runtime.`,endpointGroups:[`health`,`version`,`metrics`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`java.cxllm.io`,hosts:[`java.cxllm.io`],id:`java`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Java Runtime`,notes:`Java/Maven implementation of the integration API.`,probe:`https://java.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-maven`,title:`Java Runtime`,upstreamPort:8090,url:`https://java.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:null,deprecated:!1,description:`Data flywheel and ML operations surface.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mlrun.cxllm.io`,hosts:[`mlrun.cxllm.io`],id:`mlrun`,kind:`ml-dashboard`,landing:!1,membersSpa:!0,name:`MLRun`,notes:`Static ML/data-flywheel page until a live MLRun UI container is promoted.`,probe:`https://mlrun.cxllm.io/healthz`,replacement:null,source:`cx-ml/web`,title:`MLRun`,upstreamPort:null,url:`https://mlrun.cxllm.io/`}],source:`manifest/cxllm-services.json`},ce=[{id:`overview`,label:`Overview`,icon:`overview`},{id:`services`,label:`Services`,icon:`services`},{id:`developer`,label:`Developer`,icon:`developer`},{id:`agent`,label:`Agent`,icon:`agent`}],le=[{id:`web`,label:`Console`,href:`https://web.cxllm.io/`},{id:`files`,label:`Files`,href:`https://files.cxllm.io/`},{id:`code`,label:`Code`,href:`https://code.cxllm.io/`}],ue=[{id:`scale`,label:`Scale`,href:`https://scale.cxllm.io/`},{id:`monitor`,label:`Monitor`,href:`https://monitor.cxllm.io/`},{id:`mlrun`,label:`MLRun`,href:`https://mlrun.cxllm.io/`}];function de(e,t,n){let r=e.sidebarCollapsed,i=n.modules.filter(e=>e.loaded).length,a=n.modules.length;return` - - `}function b(e,t,n){return` -
- ${h(t)} -
- ${n.map(e=>` - - ${h(e.label)} - ${v.open} - - `).join(``)} -
-
- `}function fe(e){return e.authenticated?` -
- Account -
- - - Identity${v.open} - - - Sign out${v.signout} - -
-
- `:` -
- Account - -
- `}var pe={overview:`Overview`,services:`Services`,developer:`Developer`,agent:`Agent`};function x(e,t){let n=e.section===`developer`?` / ${e.devPane.toUpperCase()}`:``;return` -
-
- cxllm - ${h(pe[e.section]??e.section)}${h(n)} -
- - ${me(t)} -
- `}function me(e){if(!e.authenticated)return` - - ${v.signin} - Sign in - - `;let t=e.username||e.email||`you`,n=t.slice(0,1).toUpperCase();return` - - - ${h(t)} - - `}var S=new Map,he=15e3;async function C(e,t={}){let n=`${t.credentials??`omit`}|${e}`;if(t.cache!==!1){let e=S.get(n);if(e&&Date.now()-e.tsr.abort(),t.timeoutMs??5e3),a=performance.now(),o;try{let n=await fetch(e,{method:`GET`,mode:`cors`,credentials:t.credentials??`omit`,signal:r.signal,headers:{Accept:`application/json, text/plain;q=0.5, */*;q=0.1`}});o={url:e,ok:n.ok,status:n.status,latencyMs:Math.round(performance.now()-a)}}catch(t){o={url:e,ok:!1,status:0,latencyMs:Math.round(performance.now()-a),error:t instanceof Error?t.message:String(t)}}finally{clearTimeout(i)}return S.set(n,{ts:Date.now(),value:o}),o}var w=ge();function ge(){let e=window.location.host;return e.startsWith(`127.0.0.1`)||e.startsWith(`localhost`)?``:`https://mcp.cxllm.io`}async function T(e=document){let t=e.querySelector(`[data-role="agent-badge"]`);if(!t)return;if(!w){t.innerHTML=`agent local`;return}let n=await C(`${w}/status`,{timeoutMs:4e3});t.innerHTML=`${n.ok?`agent ${n.status}`:`agent down`}`}function _e(e=3e4){T();let t=window.setInterval(()=>void T(),e);return()=>window.clearInterval(t)}function ve(e){let{runtime:t,session:n}=e,r=y.services.length,i=y.services.filter(e=>e.auth===`public`||e.auth===`public-idp`).length,a=r-i,o=t.scoreCatalog({publicCount:i,gatedCount:a,degradedCount:y.services.filter(e=>!e.probe).length}),s=t.modules.filter(e=>e.loaded).length;return` -
-
-

CxLLM service fabric

-

A coherent surface for inference, agents, and operations.

-

- ${n.authenticated?`Welcome back, ${h(n.username||n.email||`operator`)}. Your workspace is wired into the CxAI control plane.`:`Public catalog view. Sign in to access the full members console, MCP, and CxAI agent.`} -

-
- -
- ${E(`Services`,r,`across the fabric`)} - ${E(`Public`,i,`no sign-in required`)} - ${E(`Gated`,a,`Authentik forward-auth`)} - ${E(`Signal`,o,`${s}/${t.modules.length} wasm modules loaded`)} -
- -
-
-

Today

-

Live health for the three pillars.

-
-
- ${D(`api`,`API`,`https://api.cxllm.io/status`)} - ${D(`mcp`,`MCP`,`https://mcp.cxllm.io/status`)} - ${D(`agent`,`Agent`,`https://mcp.cxllm.io/status`)} -
-
- -
-
-

Wasm runtime

-

Rust, C++, and Go modules instantiated in the browser.

-
-
    - ${t.modules.map(e=>` -
  • - - ${h(e.label)} - ${e.loaded?`loaded`:`fallback`} - ${h(e.detail)} -
  • - `).join(``)} -
-
-
- `}function E(e,t,n){return` -
- ${t} - ${h(e)} - ${h(n)} -
- `}function D(e,t,n){return` -
-
- - ${h(t)} - -
-

${h(n)}

-
- `}async function O(e){let t=e.querySelectorAll(`[data-today]`);await Promise.all(Array.from(t).map(async e=>{let t=e.dataset.probe;if(!t)return;let n=await C(t,{timeoutMs:4e3}),r=e.querySelector(`.cx-dot`),i=e.querySelector(`[data-role="latency"]`);r&&(r.className=`cx-dot ${n.ok?`ok`:`err`}`),i&&(i.textContent=n.ok?`${n.status} · ${n.latencyMs}ms`:n.error||`status ${n.status}`)}))}function k(e){let t=e.query.trim().toLowerCase(),n=y.services.filter(e=>!e.deprecated).filter(e=>t?[e.title,e.host,e.description,e.id,e.kind,e.auth].join(` `).toLowerCase().includes(t):!0),r=M(n,e=>e.kind||`service`),i=Array.from(r.keys()).sort();return` -
-
-
-

Catalog

-

Services

-

${n.length} active surfaces across the cxllm.io fabric.

-
-
- ${i.map(e=>{let t=r.get(e)||[];return` -
-
-

${h(N(e))}

- ${t.length} -
-
    - ${t.map(j).join(``)} -
-
- `}).join(``)} -
- `}async function A(e){let t=e.querySelectorAll(`[data-probe-url]`);await Promise.all(Array.from(t).map(async e=>{let t=e.dataset.probeUrl;if(!t)return;let n=await C(t,{timeoutMs:4e3}),r=e.querySelector(`.cx-dot`),i=e.querySelector(`[data-role="probe-meta"]`);r&&(r.className=`cx-dot ${n.ok?`ok`:`err`}`),i&&(i.textContent=n.ok?`${n.status} · ${n.latencyMs}ms`:n.error||`status ${n.status}`)}))}function j(e){let t=e.url||(e.host?`https://${e.host}/`:`#`),n=e.probe||``;return` -
  • - ${h(e.title.slice(0,2).toUpperCase())} -
    - ${h(e.title)} - ${h(e.description||e.notes||e.host)} -
    -
    - ${h(e.host||`local`)} - ${h(e.badge||e.auth||`SSO`)} -
    -
    - - -
    -
    - ${v.open} -
    -
  • - `}function M(e,t){let n=new Map;for(let r of e){let e=t(r),i=n.get(e)||[];i.push(r),n.set(e,i)}return n}function N(e){return{api:`Inference API`,mcp:`Model Context Protocol`,ide:`Developer tools`,files:`Storage & files`,storage:`Object storage`,identity:`Identity`,monitoring:`Operations`,spa:`Web surfaces`,service:`Other services`}[e]||e.replace(/(^|\s)\S/g,e=>e.toUpperCase())}function P(e,t){return` -
    - ${e.map(F).join(``)} -
    - `}function F(e){let t=`f-${e.name}`,n=``,r=e.description?`${h(e.description)}`:``,i=``;switch(e.type){case`boolean`:return i=``,`
    ${i}${r}
    `;case`number`:i=``;break;case`enum`:i=``;break;case`json`:i=``;break;default:i=(e.rows??1)>1?``:``}return`
    ${n}${i}${r}
    `}function I(e,t){let n=document.querySelector(`[data-form-id="${e}"]`),r={},i=[];if(!n)return{values:r,errors:[`form not mounted`]};for(let e of t){let t=n.elements.namedItem(e.name);if(!t)continue;if(e.type===`boolean`){r[e.name]=t.checked;continue}let a=(t.value??``).trim();if(!a){e.required&&i.push(`${e.label||e.name} is required`);continue}if(e.type===`number`){let t=Number(a);Number.isNaN(t)?i.push(`${e.label||e.name} must be a number`):r[e.name]=t;continue}if(e.type===`json`){try{r[e.name]=JSON.parse(a)}catch{i.push(`${e.label||e.name} must be valid JSON`)}continue}r[e.name]=a}return{values:r,errors:i}}function ye(e){let t=[`curl -sS -X ${e.method} \\`,` '${e.url}' \\`];return e.bearerEnv&&t.push(` -H "Authorization: Bearer $${e.bearerEnv}" \\`),t.push(` -H 'Content-Type: application/json'`),e.body!==void 0&&t.push(` \\\n -d '${JSON.stringify(e.body)}'`),t.join(` -`)}function L(e){let t={"Content-Type":`application/json`};return e.bearerEnv&&(t.Authorization=`Bearer \${process.env.${e.bearerEnv}}`),[`const res = await fetch(${JSON.stringify(e.url)}, {`,` method: ${JSON.stringify(e.method)},`,` headers: ${JSON.stringify(t,null,2).replace(/\n/g,` - `)},`,e.body===void 0?``:` body: JSON.stringify(${JSON.stringify(e.body,null,2).replace(/\n/g,` - `)}),`,`});`,`const data = await res.json();`,`console.log(data);`].filter(Boolean).join(` -`)}function be(e){let t=[`import os`,`import httpx`,``,`headers = {"Content-Type": "application/json"}`];return e.bearerEnv&&t.push(`headers["Authorization"] = f"Bearer {os.environ['${e.bearerEnv}']}"`),e.body===void 0?t.push(`r = httpx.${e.method.toLowerCase()}(${JSON.stringify(e.url)}, headers=headers, timeout=60)`):(t.push(`payload = ${JSON.stringify(e.body,null,4)}`),t.push(`r = httpx.${e.method.toLowerCase()}(${JSON.stringify(e.url)}, headers=headers, json=payload, timeout=60)`)),t.push(`r.raise_for_status()`,`print(r.json())`),t.join(` -`)}var R=xe(`api`);function xe(e){let t=window.location.host;return t.startsWith(`127.0.0.1`)||t.startsWith(`localhost`)?``:`https://${e}.cxllm.io`}var z=[{id:`status`,label:`GET /status`,description:`Public liveness probe (no auth).`,method:`GET`,path:`/status`,fields:[],publicProbe:!0},{id:`models`,label:`GET /v1/models`,description:`List available chat/embedding models.`,method:`GET`,path:`/v1/models`,fields:[]},{id:`chat`,label:`POST /v1/chat/completions`,description:`OpenAI-compatible chat completion.`,method:`POST`,path:`/v1/chat/completions`,fields:[{name:`model`,label:`Model`,type:`string`,required:!0,default:`gpt-4o-mini`},{name:`prompt`,label:`User message`,type:`string`,rows:4,required:!0,placeholder:`Say hello in three languages.`},{name:`temperature`,label:`Temperature`,type:`number`,default:.7}],body:e=>({model:e.model,messages:[{role:`user`,content:e.prompt}],temperature:e.temperature})},{id:`embeddings`,label:`POST /v1/embeddings`,description:`Vector embeddings for retrieval.`,method:`POST`,path:`/v1/embeddings`,fields:[{name:`model`,label:`Model`,type:`string`,required:!0,default:`text-embedding-3-small`},{name:`input`,label:`Input text`,type:`string`,rows:3,required:!0,default:`hello world`}],body:e=>({model:e.model,input:e.input})}];function Se(e){return` -
    - -
    - ${B(z[0],e)} -
    -
    - `}async function Ce(e,t){let n=e.querySelectorAll(`[data-op]`),r=e.querySelector(`[data-role="dev-main"]`);n.forEach(e=>{e.addEventListener(`click`,()=>{n.forEach(e=>e.classList.remove(`is-active`)),e.classList.add(`is-active`),n.forEach(t=>t.setAttribute(`aria-selected`,t===e?`true`:`false`));let i=z.find(t=>t.id===e.dataset.op);i&&r&&(r.innerHTML=B(i,t),V(r,i,t))})}),r&&V(r,z[0],t)}function B(e,t){let n=`${R||`https://api.cxllm.io`}${e.path}`,r=e.body?e.body(Object.fromEntries(e.fields.map(e=>[e.name,e.default]))):void 0,i=t.authenticated||e.publicProbe;return` -
    -
    -

    ${h(e.label)}

    -

    ${h(e.description)}

    -

    ${h(e.method)} ${h(n)}

    -
    - ${e.fields.length?`
    ${P(e.fields,`api-${e.id}`)}
    `:``} -
    -
    - Run - ${i?e.publicProbe?`Public probe`:`Uses your Authentik session cookie.`:`Sign in to enable.`} -
    -
    - - ${i?``:`Sign in`} -
    -
    // Result will appear here.
    -
    -
    -
    Snippets
    -
    -
    curl
    -
    ${h(ye({method:e.method,url:n,body:r,bearerEnv:`CXLLM_API_KEY`}))}
    -
    -
    -
    TypeScript
    -
    ${h(L({method:e.method,url:n,body:r,bearerEnv:`CXLLM_API_KEY`}))}
    -
    -
    -
    Python
    -
    ${h(be({method:e.method,url:n,body:r,bearerEnv:`CXLLM_API_KEY`}))}
    -
    -
    -
    - `}function V(e,t,n){let r=e.querySelector(`[data-op-run="${t.id}"]`),i=e.querySelector(`[data-role="op-output"]`);!r||!i||r.addEventListener(`click`,async()=>{i.textContent=`// Calling…`;let{values:e,errors:r}=I(`api-${t.id}`,t.fields);if(r.length){i.textContent=`// validation:\n${r.join(` -`)}`;return}try{let r=`${R||`https://api.cxllm.io`}${t.path}`,a={method:t.method,credentials:n.authenticated?`include`:`omit`,headers:{Accept:`application/json`}};t.method===`POST`&&(a.headers={...a.headers,"Content-Type":`application/json`},a.body=JSON.stringify(t.body?t.body(e):e));let o=await fetch(r,a),s=(o.headers.get(`content-type`)||``).includes(`application/json`)?await o.json():await o.text();i.textContent=`// ${o.status} ${o.statusText}\n${typeof s==`string`?s:g(s)}`}catch(e){i.textContent=`// error: ${e instanceof Error?e.message:String(e)}`}})}var H=(()=>{let e=window.location.host;return e.startsWith(`127.0.0.1`)||e.startsWith(`localhost`)?`http://127.0.0.1:8082`:`https://mcp.cxllm.io`})();function we(e){return` -
    - -
    -
    -
    - cxai-mcp - ${h(H)} -
    -

    ${e.authenticated?`Pick a tool on the left to render its schema-driven form and call it live.`:`Anonymous view. Tools list loads, but invocations need a signed-in session.`}

    -
    -
    -
    /events tail
    -
    // connecting…
    -
    -
    -
    - `}async function Te(e,t){let n=e.querySelector(`[data-role="tool-list"]`),r=e.querySelector(`[data-role="mcp-main"]`),i=e.querySelector(`[data-role="reload-tools"]`);if(!n||!r)return;await U(n,r,t),i?.addEventListener(`click`,()=>void U(n,r,t));let a=e.querySelector(`[data-role="events-tail"]`);a&&De(a,t)}async function U(e,t,n){try{let r=await fetch(`${H}/tools`,{credentials:n.authenticated?`include`:`omit`,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`status ${r.status}`);let i=await r.json(),a=Array.isArray(i)?i:Array.isArray(i?.tools)?i.tools:[];if(!a.length){e.innerHTML=`
  • no tools registered
  • `;return}e.innerHTML=a.map((e,t)=>` -
  • - -
  • - `).join(``);let o=e.querySelectorAll(`[data-tool]`);o.forEach(e=>{e.addEventListener(`click`,()=>{o.forEach(e=>e.classList.remove(`is-active`)),e.classList.add(`is-active`);let r=a.find(t=>t.name===e.dataset.tool);r&&W(t,r,n)})}),W(t,a[0],n)}catch(t){e.innerHTML=`
  • error: ${h(t instanceof Error?t.message:String(t))}
  • `}}function W(e,t,n){let r=Ee(t),i=n.authenticated;e.innerHTML=` -
    -
    - ${h(t.name)} - POST ${h(H)}/tools/${h(t.name)} -
    -

    ${h(t.description||``)}

    -
    - ${r.length?`
    ${P(r,`mcp-${t.name}`)}
    `:``} -
    -
    Run${i?"Calls /tools/${name} with your session cookie.":`Sign in to enable.`}
    -
    - -
    -
    // Result will appear here.
    -
    - `;let a=e.querySelector(`[data-mcp-run]`),o=e.querySelector(`[data-role="mcp-output"]`);a?.addEventListener(`click`,async()=>{if(!o)return;o.textContent=`// Invoking…`;let{values:e,errors:n}=I(`mcp-${t.name}`,r);if(n.length){o.textContent=`// validation:\n${n.join(` -`)}`;return}try{let n=await fetch(`${H}/tools/${encodeURIComponent(t.name)}`,{method:`POST`,credentials:`include`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify(e)}),r=(n.headers.get(`content-type`)||``).includes(`application/json`)?await n.json():await n.text();o.textContent=`// ${n.status} ${n.statusText}\n${typeof r==`string`?r:g(r)}`}catch(e){o.textContent=`// error: ${e instanceof Error?e.message:String(e)}`}})}function Ee(e){let t=e.schema?.properties||{},n=new Set(e.schema?.required||[]);return Object.entries(t).map(([e,t])=>{let r=(t.type||`string`).toLowerCase(),i=`string`;return r===`number`||r===`integer`?i=`number`:r===`boolean`?i=`boolean`:r===`object`||r===`array`?i=`json`:t.enum&&t.enum.length&&(i=`enum`),{name:e,label:e,type:i,required:n.has(e),default:t.default,description:t.description,options:t.enum,rows:i===`json`?6:i===`string`?2:1}})}function De(e,t){try{let n=`${H}/events`,r=new EventSource(n,{withCredentials:t.authenticated}),i=[];e.textContent=`// connected`,r.onmessage=t=>{i.push(`${new Date().toLocaleTimeString()} ${t.data}`),i.length>20&&i.shift(),e.textContent=i.join(` -`)},r.onerror=()=>{e.textContent+=`\n// stream error (${new Date().toLocaleTimeString()})`,r.close()}}catch(t){e.textContent=`// events unavailable: ${t instanceof Error?t.message:String(t)}`}}function Oe(e,t){let n=e.devPane,r=n===`mcp`?we(t):Se(t);return` -
    -
    -
    -

    Developer

    -

    Build against CxLLM

    -

    ${t.authenticated?`Live, authenticated calls. Forms run against your session.`:`Anonymous view. Snippets only — sign in to run live requests.`}

    -
    -
    - ${G(`api`,`API`,n===`api`)} - ${G(`mcp`,`MCP`,n===`mcp`)} -
    -
    -
    ${r}
    -
    - `}async function ke(e,t,n){t.devPane===`mcp`?await Te(e,n):await Ce(e,n)}function G(e,t,n){return``}var K=(()=>{let e=window.location.host;return e.startsWith(`127.0.0.1`)||e.startsWith(`localhost`)?`http://127.0.0.1:8082`:`https://mcp.cxllm.io`})();function Ae(e){return` -
    -
    -
    -

    CxAI

    -

    Agent control plane

    -

    cxai-mcp sidecar status, registered tools, and recent activity.${e.authenticated?``:` Sign in for live tool invocations.`}

    -
    -
    - -
    -

    Status

    -
    // loading…
    -
    - -
    -

    Tools

    Registered with cxai-mcp.
    -
    • loading…
    -
    - -
    -

    Activity

    /events tail (last 20).
    -
    // connecting…
    -
    -
    - `}async function je(e,t){let n=e.querySelector(`[data-role="agent-status"]`),r=e.querySelector(`[data-role="agent-status-meta"]`),i=e.querySelector(`[data-role="agent-tools"]`),a=e.querySelector(`[data-role="agent-events"]`);if(n&&r){let e=await C(`${K}/status`,{timeoutMs:4e3});if(r.textContent=e.ok?`${e.status} · ${e.latencyMs}ms`:e.error||`status ${e.status}`,e.ok)try{let e=await fetch(`${K}/status`,{credentials:t.authenticated?`include`:`omit`}),r=await e.json().catch(()=>null);n.textContent=r?g(r):`// status ${e.status}`}catch(e){n.textContent=`// error: ${e instanceof Error?e.message:String(e)}`}else n.textContent=`// unavailable (${e.error||e.status})`}if(i)try{let e=await(await fetch(`${K}/tools`,{credentials:t.authenticated?`include`:`omit`})).json(),n=Array.isArray(e)?e:Array.isArray(e?.tools)?e.tools:[];i.innerHTML=n.length?n.map(e=>` -
  • - ${h(e.name)} - ${h(e.description||``)} -
  • - `).join(``):`
  • no tools registered
  • `}catch(e){i.innerHTML=`
  • error: ${h(e instanceof Error?e.message:String(e))}
  • `}if(a)try{let e=new EventSource(`${K}/events`,{withCredentials:t.authenticated}),n=[];a.textContent=`// connected`,e.onmessage=e=>{n.push(`${new Date().toLocaleTimeString()} ${e.data}`),n.length>20&&n.shift(),a.textContent=n.join(` -`)},e.onerror=()=>{a.textContent+=`\n// stream error (${new Date().toLocaleTimeString()})`,e.close()}}catch(e){a.textContent=`// events unavailable: ${e instanceof Error?e.message:String(e)}`}}var q,J,Y,X;async function Z(){if((q.target===`members`||q.target===`webapp`)&&!Y.authenticated){Me();return}X.innerHTML=` -
    - ${de(q,Y,J)} -
    - ${x(q,Y)} -
    - ${Q()} -
    -
    -
    - `,Ne(),T(X),await $()}function Q(){switch(q.section){case`services`:return k(q);case`developer`:return Oe(q,Y);case`agent`:return Ae(Y);default:return ve({state:q,session:Y,runtime:J})}}async function $(){let e=X.querySelector(`[data-role="workspace-body"]`);if(e)switch(q.section){case`services`:await A(e);break;case`developer`:await ke(e,q,Y);break;case`agent`:await je(e,Y);break;default:await O(e);break}}function Me(){X.innerHTML=` -
    -
    -

    CxLLM

    -

    Sign in to continue

    -

    The ${q.target===`webapp`?`operator console`:`members workspace`} is protected by Authentik. Sign in to access services, developer tools, and the CxAI agent.

    - Sign in with Authentik -

    ← Back to public landing

    -
    -
    - `}function Ne(){X.querySelectorAll(`[data-section]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=e.dataset.section;!t||t===q.section||(q.section=t,re(t),Pe(),Z())})}),X.querySelectorAll(`[data-dev-pane]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=e.dataset.devPane;!t||t===q.devPane||(q.devPane=t,ie(t),Z())})}),X.querySelector(`[data-role="search"]`)?.addEventListener(`input`,e=>{if(q.query=e.currentTarget.value,q.section===`services`){let e=X.querySelector(`[data-role="workspace-body"]`);e&&(e.innerHTML=Q(),$())}}),X.querySelector(`[data-action="toggle-sidebar"]`)?.addEventListener(`click`,()=>{q.sidebarCollapsed=!q.sidebarCollapsed,ae(q.sidebarCollapsed),Z()}),document.addEventListener(`keydown`,e=>{(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`&&(e.preventDefault(),X.querySelector(`[data-role="search"]`)?.focus())},{once:!0})}function Pe(){try{let e=new URL(window.location.href);e.searchParams.set(`section`,q.section),window.history.replaceState(null,``,e)}catch{}}async function Fe(){let e=document.querySelector(`#cxllm-root`);e&&(X=e,q=ne(ee(e.dataset.cxTarget)),[Y,J]=await Promise.all([oe(),o()]),await Z(),_e())}Fe(); \ No newline at end of file diff --git a/static/assets/webapp-CF_wSRqt.js b/static/assets/webapp-CF_wSRqt.js new file mode 100644 index 0000000..c41c8f1 --- /dev/null +++ b/static/assets/webapp-CF_wSRqt.js @@ -0,0 +1,379 @@ +(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={modules:[{id:`rust`,label:`Rust core`,loaded:!1,detail:`TypeScript fallback active`},{id:`cpp`,label:`C++ route core`,loaded:!1,detail:`TypeScript fallback active`},{id:`go`,label:`Go status core`,loaded:!1,detail:`TypeScript fallback active`},{id:`cxedge`,label:`cxedge runtime`,loaded:!1,detail:`cxedge shim not available`}],scoreCatalog(e){return Math.max(0,Math.min(100,70+e.publicCount*2+e.gatedCount-e.degradedCount*12))},routeWeight(e,t){return e*10+t*7},cxedgeVersion:null,cxedgeCapabilities:0};function t(e){return new URL(`${import.meta.env?.BASE_URL??`./`}${e}`,window.location.href)}async function n(e){let n=await fetch(t(e));if(!n.ok)return null;let r=await n.arrayBuffer();return(await WebAssembly.instantiate(r,{})).instance.exports}function r(e,t){if(!e)return null;for(let n of t){let t=e[n];if(typeof t==`function`)return(...e)=>Number(t(...e))}return null}async function i(){try{let e=await fetch(t(`wasm/modules.json`));if(!e.ok)return new Map;let n=await e.json();return new Map((n.modules??[]).map(e=>[e.id,e]))}catch{return new Map}}function a(t,n){let r=e.modules.find(e=>e.id===t)??e.modules[0],i=n.get(t)?.detail;return i?{...r,detail:i}:r}async function o(){let t=await i(),o=[],s=e.scoreCatalog,c=e.routeWeight;if(t.get(`rust`)?.status===`built`)try{let e=r(await n(`wasm/cxllm_rust_core.wasm`),[`cxllm_signal_score`]);e?(s=t=>e(t.publicCount,t.gatedCount,t.degradedCount),o.push({id:`rust`,label:`Rust core`,loaded:!0,detail:`Catalog signal scoring`})):o.push(a(`rust`,t))}catch{o.push(a(`rust`,t))}else o.push(a(`rust`,t));if(t.get(`cpp`)?.status===`built`)try{let e=r(await n(`wasm/cxllm_cpp_core.wasm`),[`cxllm_route_weight`,`_cxllm_route_weight`]);e?(c=(t,n)=>e(t,n),o.push({id:`cpp`,label:`C++ route core`,loaded:!0,detail:`Endpoint weighting`})):o.push(a(`cpp`,t))}catch{o.push(a(`cpp`,t))}else o.push(a(`cpp`,t));let l=t.get(`go`)?.status===`built`;o.push(l?{id:`go`,label:`Go status core`,loaded:!0,detail:`Go Wasm artifact available`}:a(`go`,t));let u=null,d=0;if(t.get(`cxedge`)?.status===`built`)try{let e=await n(`wasm/cxllm_cxedge_core.wasm`),i=r(e,[`cxedge_version`,`_cxedge_version`]),s=r(e,[`cxedge_version_len`,`_cxedge_version_len`]),c=r(e,[`cxedge_capabilities`,`_cxedge_capabilities`]);if(e&&i&&s&&c){let t=e.memory,n=i(),r=s();if(t&&n>0&&r>0){let e=new Uint8Array(t.buffer,n,r);u=new TextDecoder().decode(e)}d=c(),o.push({id:`cxedge`,label:`cxedge runtime`,loaded:!0,detail:u?`v${u} (caps=0x${d.toString(16)})`:`loaded`})}else o.push(a(`cxedge`,t))}catch{o.push(a(`cxedge`,t))}else o.push(a(`cxedge`,t));return{modules:o,scoreCatalog:s,routeWeight:c,cxedgeVersion:u,cxedgeCapabilities:d}}var s=`cxllm:nav:section`,c=`cxllm:nav:devpane`,l=`cxllm:sidebar:collapsed`;function u(e){return e===`members`||e===`webapp`||e===`api`||e===`mcp`?e:`landing`}function d(e){switch(e){case`api`:case`mcp`:return`developer`;case`webapp`:return`services`;case`members`:return`overview`;default:return`overview`}}function ee(e){let t=new URLSearchParams(window.location.search).get(`section`),n=localStorage.getItem(s)??null;return{target:e,section:f(t)?t:e===`api`||e===`mcp`?`developer`:f(n)?n:d(e),devPane:e===`api`?`api`:e===`mcp`||localStorage.getItem(c)===`mcp`?`mcp`:`api`,query:``,sidebarCollapsed:localStorage.getItem(l)===`1`}}function f(e){return e===`overview`||e===`services`||e===`developer`||e===`agent`}function te(e){try{localStorage.setItem(s,e)}catch{}}function ne(e){try{localStorage.setItem(c,e)}catch{}}function p(e){try{localStorage.setItem(l,e?`1`:`0`)}catch{}}var m=`cxllm:session:v1`,re=6e4;function ie(){try{let e=sessionStorage.getItem(m);if(!e)return null;let t=JSON.parse(e);return Date.now()-t.ts>re?null:t}catch{return null}}function h(e){try{sessionStorage.setItem(m,JSON.stringify({ts:Date.now(),value:e}))}catch{}}async function ae(e=!1){if(!e){let e=ie();if(e)return e.value}let t=window.location.host;if(t===`127.0.0.1`||t.startsWith(`127.0.0.1:`)||t.startsWith(`localhost`)){let e=new URLSearchParams(window.location.search),t=e.get(`signed-in`)===`1`?{authenticated:!0,username:e.get(`user`)||`dev`,email:`dev@cxllm.io`}:{authenticated:!1};return h(t),t}try{let e=new AbortController,t=setTimeout(()=>e.abort(),3e3),n=await fetch(`/outpost.goauthentik.io/auth/caddy`,{method:`GET`,credentials:`include`,signal:e.signal});if(clearTimeout(t),n.status===200){let e={authenticated:!0,username:n.headers.get(`X-Authentik-Username`)||void 0,email:n.headers.get(`X-Authentik-Email`)||void 0,groups:(n.headers.get(`X-Authentik-Groups`)||``).split(`|`).filter(Boolean)};return h(e),e}}catch{}let n={authenticated:!1};return h(n),n}function oe(e){return`https://auth.cxllm.io/if/flow/default-authentication-flow/?next=${encodeURIComponent(e??`https://web.cxllm.io/`)}`}function g(e){return String(e??``).replace(/&/g,`&`).replace(//g,`>`).replace(/"/g,`"`).replace(/'/g,`'`)}function _(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}var v=e=>``,y={overview:v(``),services:v(``),developer:v(``),agent:v(``),workspace:v(``),ops:v(``),account:v(``),collapse:v(``),expand:v(``),search:v(``),open:v(``),copy:v(``),pulse:v(``),signin:v(``),signout:v(``)},b={domain:`cxllm.io`,home:[{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:null,deprecated:!1,description:`CxAI agent control plane (cxai-mcp HTTP sidecar: status, tools, events).`,endpointGroups:[`status`,`tools`,`events`],expected:[200],health:[{expect:[200],path:`/status`},{expect:[200,401,302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`agent.cxllm.io`,hosts:[`agent.cxllm.io`],id:`agent`,kind:`agent`,landing:!1,membersSpa:!0,name:`CxAI Agent`,notes:`CxAI control plane: cxai-mcp HTTP sidecar (status, tools registry, /events tail).`,probe:`https://agent.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI Agent`,upstreamPort:8082,url:`https://agent.cxllm.io/`},{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-red`,composeService:null,deprecated:!1,description:`cxedge WebAssembly runtime: release downloads, docs, Homebrew tap pointer.`,endpointGroups:[`downloads`,`docs`],expected:[200],health:[{expect:[200],path:`/`},{expect:[200],path:`/healthz`}],host:`cxedge.cxllm.io`,hosts:[`cxedge.cxllm.io`],id:`cxedge`,kind:`runtime-downloads`,landing:!0,membersSpa:!1,name:`cxedge`,notes:`Static landing for the cxedge WebAssembly runtime fork: release downloads, docs, and the cxai/cxedge Homebrew tap pointer.`,probe:`https://cxedge.cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/cxedge`,title:`cxedge`,upstreamPort:null,url:`https://cxedge.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:null,deprecated:!1,description:`Data flywheel and ML operations surface.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mlrun.cxllm.io`,hosts:[`mlrun.cxllm.io`],id:`mlrun`,kind:`ml-dashboard`,landing:!1,membersSpa:!0,name:`MLRun`,notes:`Static ML/data-flywheel page until a live MLRun UI container is promoted.`,probe:`https://mlrun.cxllm.io/healthz`,replacement:null,source:`cx-ml/web`,title:`MLRun`,upstreamPort:null,url:`https://mlrun.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`}],landing:[{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:null,deprecated:!1,description:`Legacy Crow UI for operator workflows.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`webapp.cxllm.io`,hosts:[`webapp.cxllm.io`],id:`webapp`,kind:`web`,landing:!0,membersSpa:!0,name:`CxWebApp`,notes:`Legacy Crow C++ operator UI; currently managed outside cxllm-cloud compose.`,probe:`https://webapp.cxllm.io/api/health`,replacement:null,source:`CxWebApp`,title:`CxWebApp`,upstreamPort:8085,url:`https://webapp.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-green`,composeService:null,deprecated:!1,description:`Members workspace and authenticated service console.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`web.cxllm.io`,hosts:[`web.cxllm.io`],id:`web`,kind:`spa`,landing:!0,membersSpa:!1,name:`Members SPA`,notes:`Static members workspace deployed to /srv/cxai/web and protected by Authentik at the edge.`,probe:`https://web.cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/cxllm-web`,title:`Members SPA`,upstreamPort:null,url:`https://web.cxllm.io/`},{auth:`public-idp`,badge:`public`,badgeClass:`public`,color:`sb-purple`,composeService:`authentik-server`,deprecated:!1,description:`Identity, SSO, MFA, and access policies.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/-/health/ready/`},{expect:[200],path:`/-/health/live/`}],host:`auth.cxllm.io`,hosts:[`auth.cxllm.io`],id:`auth`,kind:`identity`,landing:!0,membersSpa:!0,name:`Authentik IdP`,notes:`Identity provider and embedded forward-auth outpost.`,probe:`https://auth.cxllm.io/-/health/ready/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Authentik IdP`,upstreamPort:9e3,url:`https://auth.cxllm.io/`},{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-red`,composeService:null,deprecated:!1,description:`cxedge WebAssembly runtime: release downloads, docs, Homebrew tap pointer.`,endpointGroups:[`downloads`,`docs`],expected:[200],health:[{expect:[200],path:`/`},{expect:[200],path:`/healthz`}],host:`cxedge.cxllm.io`,hosts:[`cxedge.cxllm.io`],id:`cxedge`,kind:`runtime-downloads`,landing:!0,membersSpa:!1,name:`cxedge`,notes:`Static landing for the cxedge WebAssembly runtime fork: release downloads, docs, and the cxai/cxedge Homebrew tap pointer.`,probe:`https://cxedge.cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/cxedge`,title:`cxedge`,upstreamPort:null,url:`https://cxedge.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`aws-iam`,badge:`AWS IAM`,badgeClass:`api`,color:`sb-purple`,composeService:null,deprecated:!1,description:`AWS-backed object storage, CloudFront keys, and IAM access.`,endpointGroups:[`s3`,`cloudfront`,`iam`],expected:[],health:[],host:`AWS S3`,hosts:[],id:`aws-storage`,kind:`object-storage-cloud`,landing:!0,membersSpa:!0,name:`AWS Storage`,notes:`Primary object storage is AWS-backed and configured from the local CxAWS config directory; credentials are never embedded in static assets.`,probe:`https://console.aws.amazon.com/s3/home`,replacement:null,source:`CxAI/projects/CxAWS/config`,title:`AWS Storage`,upstreamPort:null,url:`https://console.aws.amazon.com/s3/home`},{auth:`docker-basic-auth`,badge:`basic`,badgeClass:`basic`,color:`sb-amber`,composeService:null,deprecated:!1,description:`Private container image registry.`,endpointGroups:[],expected:[401],health:[{expect:[401],path:`/v2/`}],host:`registry.cxllm.io`,hosts:[`registry.cxllm.io`],id:`registry`,kind:`registry`,landing:!0,membersSpa:!1,name:`Container Registry`,notes:`Docker registry; 401 is the expected unauthenticated health result.`,probe:`https://registry.cxllm.io/v2/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Container Registry`,upstreamPort:5e3,url:`https://registry.cxllm.io/`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`}],manifestSchemaVersion:1,members:[{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:`cxllm-landing`,deprecated:!1,description:`Public marketing front door.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`}],host:`cxllm.io`,hosts:[`cxllm.io`,`www.cxllm.io`,`app.cxllm.io`],id:`landing`,kind:`web`,landing:!1,membersSpa:!0,name:`CxLLM Landing`,notes:`Public marketing and console landing served by the cxllm-landing container.`,probe:`https://cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/app`,title:`CxLLM Landing`,upstreamPort:8086,url:`https://cxllm.io/`},{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:null,deprecated:!1,description:`Legacy Crow UI for operator workflows.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`webapp.cxllm.io`,hosts:[`webapp.cxllm.io`],id:`webapp`,kind:`web`,landing:!0,membersSpa:!0,name:`CxWebApp`,notes:`Legacy Crow C++ operator UI; currently managed outside cxllm-cloud compose.`,probe:`https://webapp.cxllm.io/api/health`,replacement:null,source:`CxWebApp`,title:`CxWebApp`,upstreamPort:8085,url:`https://webapp.cxllm.io/`},{auth:`public-idp`,badge:`public`,badgeClass:`public`,color:`sb-purple`,composeService:`authentik-server`,deprecated:!1,description:`Identity, SSO, MFA, and access policies.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/-/health/ready/`},{expect:[200],path:`/-/health/live/`}],host:`auth.cxllm.io`,hosts:[`auth.cxllm.io`],id:`auth`,kind:`identity`,landing:!0,membersSpa:!0,name:`Authentik IdP`,notes:`Identity provider and embedded forward-auth outpost.`,probe:`https://auth.cxllm.io/-/health/ready/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Authentik IdP`,upstreamPort:9e3,url:`https://auth.cxllm.io/`},{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:null,deprecated:!1,description:`CxAI agent control plane (cxai-mcp HTTP sidecar: status, tools, events).`,endpointGroups:[`status`,`tools`,`events`],expected:[200],health:[{expect:[200],path:`/status`},{expect:[200,401,302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`agent.cxllm.io`,hosts:[`agent.cxllm.io`],id:`agent`,kind:`agent`,landing:!1,membersSpa:!0,name:`CxAI Agent`,notes:`CxAI control plane: cxai-mcp HTTP sidecar (status, tools registry, /events tail).`,probe:`https://agent.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI Agent`,upstreamPort:8082,url:`https://agent.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`aws-iam`,badge:`AWS IAM`,badgeClass:`api`,color:`sb-purple`,composeService:null,deprecated:!1,description:`AWS-backed object storage, CloudFront keys, and IAM access.`,endpointGroups:[`s3`,`cloudfront`,`iam`],expected:[],health:[],host:`AWS S3`,hosts:[],id:`aws-storage`,kind:`object-storage-cloud`,landing:!0,membersSpa:!0,name:`AWS Storage`,notes:`Primary object storage is AWS-backed and configured from the local CxAWS config directory; credentials are never embedded in static assets.`,probe:`https://console.aws.amazon.com/s3/home`,replacement:null,source:`CxAI/projects/CxAWS/config`,title:`AWS Storage`,upstreamPort:null,url:`https://console.aws.amazon.com/s3/home`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-red`,composeService:`cxai-rust`,deprecated:!1,description:`Rust integration runtime.`,endpointGroups:[`health`,`version`,`metrics`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`rust.cxllm.io`,hosts:[`rust.cxllm.io`],id:`rust`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Rust Runtime`,notes:`Rust integration shim.`,probe:`https://rust.cxllm.io/healthz`,replacement:null,source:`CxAI Base/cargo`,title:`Rust Runtime`,upstreamPort:8089,url:`https://rust.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`cxai-go`,deprecated:!1,description:`Go integration runtime.`,endpointGroups:[`health`,`version`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`go.cxllm.io`,hosts:[`go.cxllm.io`],id:`go`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Go Runtime`,notes:`Go implementation of the integration API.`,probe:`https://go.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-go`,title:`Go Runtime`,upstreamPort:8088,url:`https://go.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`cxai-maven`,deprecated:!1,description:`Java integration runtime.`,endpointGroups:[`health`,`version`,`metrics`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`java.cxllm.io`,hosts:[`java.cxllm.io`],id:`java`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Java Runtime`,notes:`Java/Maven implementation of the integration API.`,probe:`https://java.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-maven`,title:`Java Runtime`,upstreamPort:8090,url:`https://java.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:null,deprecated:!1,description:`Data flywheel and ML operations surface.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mlrun.cxllm.io`,hosts:[`mlrun.cxllm.io`],id:`mlrun`,kind:`ml-dashboard`,landing:!1,membersSpa:!0,name:`MLRun`,notes:`Static ML/data-flywheel page until a live MLRun UI container is promoted.`,probe:`https://mlrun.cxllm.io/healthz`,replacement:null,source:`cx-ml/web`,title:`MLRun`,upstreamPort:null,url:`https://mlrun.cxllm.io/`}],schemaVersion:1,services:[{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:`cxllm-landing`,deprecated:!1,description:`Public marketing front door.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`}],host:`cxllm.io`,hosts:[`cxllm.io`,`www.cxllm.io`,`app.cxllm.io`],id:`landing`,kind:`web`,landing:!1,membersSpa:!0,name:`CxLLM Landing`,notes:`Public marketing and console landing served by the cxllm-landing container.`,probe:`https://cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/app`,title:`CxLLM Landing`,upstreamPort:8086,url:`https://cxllm.io/`},{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-green`,composeService:null,deprecated:!1,description:`Legacy Crow UI for operator workflows.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`webapp.cxllm.io`,hosts:[`webapp.cxllm.io`],id:`webapp`,kind:`web`,landing:!0,membersSpa:!0,name:`CxWebApp`,notes:`Legacy Crow C++ operator UI; currently managed outside cxllm-cloud compose.`,probe:`https://webapp.cxllm.io/api/health`,replacement:null,source:`CxWebApp`,title:`CxWebApp`,upstreamPort:8085,url:`https://webapp.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-green`,composeService:null,deprecated:!1,description:`Members workspace and authenticated service console.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`web.cxllm.io`,hosts:[`web.cxllm.io`],id:`web`,kind:`spa`,landing:!0,membersSpa:!1,name:`Members SPA`,notes:`Static members workspace deployed to /srv/cxai/web and protected by Authentik at the edge.`,probe:`https://web.cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/cxllm-web`,title:`Members SPA`,upstreamPort:null,url:`https://web.cxllm.io/`},{auth:`public-idp`,badge:`public`,badgeClass:`public`,color:`sb-purple`,composeService:`authentik-server`,deprecated:!1,description:`Identity, SSO, MFA, and access policies.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/-/health/ready/`},{expect:[200],path:`/-/health/live/`}],host:`auth.cxllm.io`,hosts:[`auth.cxllm.io`],id:`auth`,kind:`identity`,landing:!0,membersSpa:!0,name:`Authentik IdP`,notes:`Identity provider and embedded forward-auth outpost.`,probe:`https://auth.cxllm.io/-/health/ready/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Authentik IdP`,upstreamPort:9e3,url:`https://auth.cxllm.io/`},{auth:`hybrid-status-public-rest-authentik`,badge:`API key`,badgeClass:`api`,color:`sb-green`,composeService:null,deprecated:!1,description:`OpenAI-compatible inference, embeddings, and tools.`,endpointGroups:[`status`,`models`,`chat`,`embeddings`,`docs`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/docs`},{expect:[302],path:`/v1/models`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`api.cxllm.io`,hosts:[`api.cxllm.io`],id:`api`,kind:`api`,landing:!0,membersSpa:!0,name:`CxAI API`,notes:`Currently proxies to cxai-mcp on 8082; swap to the Python API on 8080 when that runtime is promoted.`,probe:`https://api.cxllm.io/status`,replacement:null,source:`CxAI Base/api`,title:`CxAI API`,upstreamPort:8082,url:`https://api.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:null,deprecated:!1,description:`Model Context Protocol gateway for agents.`,endpointGroups:[`mcp`,`tools`,`resources`,`prompts`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/status`},{expect:[302],path:`/mcp`},{expect:[302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mcp.cxllm.io`,hosts:[`mcp.cxllm.io`],id:`mcp`,kind:`mcp`,landing:!0,membersSpa:!0,name:`CxAI MCP`,notes:`MCP HTTP surface for agents and IDE tools.`,probe:`https://mcp.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI MCP`,upstreamPort:8082,url:`https://mcp.cxllm.io/`},{auth:`authentik-forward-auth-status-public`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:null,deprecated:!1,description:`CxAI agent control plane (cxai-mcp HTTP sidecar: status, tools, events).`,endpointGroups:[`status`,`tools`,`events`],expected:[200],health:[{expect:[200],path:`/status`},{expect:[200,401,302],path:`/tools`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`agent.cxllm.io`,hosts:[`agent.cxllm.io`],id:`agent`,kind:`agent`,landing:!1,membersSpa:!0,name:`CxAI Agent`,notes:`CxAI control plane: cxai-mcp HTTP sidecar (status, tools registry, /events tail).`,probe:`https://agent.cxllm.io/status`,replacement:null,source:`CxAI/_agent/mcp-server`,title:`CxAI Agent`,upstreamPort:8082,url:`https://agent.cxllm.io/`},{auth:`public`,badge:`public`,badgeClass:`public`,color:`sb-red`,composeService:null,deprecated:!1,description:`cxedge WebAssembly runtime: release downloads, docs, Homebrew tap pointer.`,endpointGroups:[`downloads`,`docs`],expected:[200],health:[{expect:[200],path:`/`},{expect:[200],path:`/healthz`}],host:`cxedge.cxllm.io`,hosts:[`cxedge.cxllm.io`],id:`cxedge`,kind:`runtime-downloads`,landing:!0,membersSpa:!1,name:`cxedge`,notes:`Static landing for the cxedge WebAssembly runtime fork: release downloads, docs, and the cxai/cxedge Homebrew tap pointer.`,probe:`https://cxedge.cxllm.io/healthz`,replacement:null,source:`host/cxllm-stack/cxedge`,title:`cxedge`,upstreamPort:null,url:`https://cxedge.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`code-server`,deprecated:!1,description:`VS Code in the browser.`,endpointGroups:[],expected:[302],health:[{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`code.cxllm.io`,hosts:[`code.cxllm.io`],id:`code`,kind:`ide`,landing:!0,membersSpa:!0,name:`code-server`,notes:`Browser VS Code gated by Authentik edge auth.`,probe:`https://code.cxllm.io/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`code-server`,upstreamPort:8443,url:`https://code.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`scale-dashboard`,deprecated:!1,description:`Tailscale machines, routes, Serve, and Funnel behind Authentik.`,endpointGroups:[`tailscale`,`machines`,`routes`,`serve`,`funnel`,`authentik`],expected:[302],health:[{expect:[302],path:`/`},{expect:[302],path:`/healthz`},{expect:[302],path:`/api/tailscale/status`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`scale.cxllm.io`,hosts:[`scale.cxllm.io`],id:`scale`,kind:`tailnet-ops`,landing:!0,membersSpa:!0,name:`Scale`,notes:`Authentik-gated Tailscale machine, app, route, Serve, and Funnel operations dashboard.`,probe:`https://scale.cxllm.io/healthz`,replacement:null,source:`scale`,title:`Scale`,upstreamPort:8091,url:`https://scale.cxllm.io/`},{auth:`nextcloud-oidc`,badge:`SSO`,badgeClass:``,color:`sb-purple`,composeService:`nextcloud`,deprecated:!1,description:`Nextcloud files, shares, and team folders.`,endpointGroups:[],expected:[200,302],health:[{expect:[200,302],path:`/status.php`}],host:`files.cxllm.io`,hosts:[`files.cxllm.io`],id:`files`,kind:`files`,landing:!0,membersSpa:!0,name:`Files`,notes:`Nextcloud workspace.`,probe:`https://files.cxllm.io/status.php`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Files`,upstreamPort:8081,url:`https://files.cxllm.io/`},{auth:`aws-iam`,badge:`AWS IAM`,badgeClass:`api`,color:`sb-purple`,composeService:null,deprecated:!1,description:`AWS-backed object storage, CloudFront keys, and IAM access.`,endpointGroups:[`s3`,`cloudfront`,`iam`],expected:[],health:[],host:`AWS S3`,hosts:[],id:`aws-storage`,kind:`object-storage-cloud`,landing:!0,membersSpa:!0,name:`AWS Storage`,notes:`Primary object storage is AWS-backed and configured from the local CxAWS config directory; credentials are never embedded in static assets.`,probe:`https://console.aws.amazon.com/s3/home`,replacement:null,source:`CxAI/projects/CxAWS/config`,title:`AWS Storage`,upstreamPort:null,url:`https://console.aws.amazon.com/s3/home`},{auth:`docker-basic-auth`,badge:`basic`,badgeClass:`basic`,color:`sb-amber`,composeService:null,deprecated:!1,description:`Private container image registry.`,endpointGroups:[],expected:[401],health:[{expect:[401],path:`/v2/`}],host:`registry.cxllm.io`,hosts:[`registry.cxllm.io`],id:`registry`,kind:`registry`,landing:!0,membersSpa:!1,name:`Container Registry`,notes:`Docker registry; 401 is the expected unauthenticated health result.`,probe:`https://registry.cxllm.io/v2/`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Container Registry`,upstreamPort:5e3,url:`https://registry.cxllm.io/`},{auth:`grafana-oidc`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`grafana`,deprecated:!1,description:`Grafana dashboards, metrics, and alerts.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/api/health`}],host:`monitor.cxllm.io`,hosts:[`monitor.cxllm.io`],id:`monitor`,kind:`observability`,landing:!0,membersSpa:!0,name:`Grafana`,notes:`Grafana dashboards and alerts.`,probe:`https://monitor.cxllm.io/api/health`,replacement:null,source:`host/cxllm-stack/compose.yaml`,title:`Grafana`,upstreamPort:3e3,url:`https://monitor.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-red`,composeService:`cxai-rust`,deprecated:!1,description:`Rust integration runtime.`,endpointGroups:[`health`,`version`,`metrics`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`rust.cxllm.io`,hosts:[`rust.cxllm.io`],id:`rust`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Rust Runtime`,notes:`Rust integration shim.`,probe:`https://rust.cxllm.io/healthz`,replacement:null,source:`CxAI Base/cargo`,title:`Rust Runtime`,upstreamPort:8089,url:`https://rust.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-blue`,composeService:`cxai-go`,deprecated:!1,description:`Go integration runtime.`,endpointGroups:[`health`,`version`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`go.cxllm.io`,hosts:[`go.cxllm.io`],id:`go`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Go Runtime`,notes:`Go implementation of the integration API.`,probe:`https://go.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-go`,title:`Go Runtime`,upstreamPort:8088,url:`https://go.cxllm.io/`},{auth:`authentik-forward-auth-health-public`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:`cxai-maven`,deprecated:!1,description:`Java integration runtime.`,endpointGroups:[`health`,`version`,`metrics`,`huggingface`,`operations`,`governance`,`agentic`,`tasks`,`infer`,`git`,`tool-use`],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[200],path:`/version`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`java.cxllm.io`,hosts:[`java.cxllm.io`],id:`java`,kind:`runtime`,landing:!1,membersSpa:!0,name:`Java Runtime`,notes:`Java/Maven implementation of the integration API.`,probe:`https://java.cxllm.io/healthz`,replacement:null,source:`CxAI Base/apps/cxai-maven`,title:`Java Runtime`,upstreamPort:8090,url:`https://java.cxllm.io/`},{auth:`authentik-forward-auth`,badge:`SSO`,badgeClass:``,color:`sb-amber`,composeService:null,deprecated:!1,description:`Data flywheel and ML operations surface.`,endpointGroups:[],expected:[200],health:[{expect:[200],path:`/healthz`},{expect:[200],path:`/readyz`},{expect:[302],path:`/`},{expect:[204],path:`/outpost.goauthentik.io/ping`}],host:`mlrun.cxllm.io`,hosts:[`mlrun.cxllm.io`],id:`mlrun`,kind:`ml-dashboard`,landing:!1,membersSpa:!0,name:`MLRun`,notes:`Static ML/data-flywheel page until a live MLRun UI container is promoted.`,probe:`https://mlrun.cxllm.io/healthz`,replacement:null,source:`cx-ml/web`,title:`MLRun`,upstreamPort:null,url:`https://mlrun.cxllm.io/`}],source:`manifest/cxllm-services.json`},se=[{id:`overview`,label:`Overview`,icon:`overview`},{id:`services`,label:`Services`,icon:`services`},{id:`developer`,label:`Developer`,icon:`developer`},{id:`agent`,label:`Agent`,icon:`agent`}],ce=[{id:`web`,label:`Console`,href:`https://web.cxllm.io/`},{id:`files`,label:`Files`,href:`https://files.cxllm.io/`},{id:`code`,label:`Code`,href:`https://code.cxllm.io/`}],le=[{id:`scale`,label:`Scale`,href:`https://scale.cxllm.io/`},{id:`monitor`,label:`Monitor`,href:`https://monitor.cxllm.io/`},{id:`mlrun`,label:`MLRun`,href:`https://mlrun.cxllm.io/`}];function ue(e,t,n){let r=e.sidebarCollapsed,i=n.modules.filter(e=>e.loaded).length,a=n.modules.length;return` + + `}function x(e,t,n){return` +
    + ${g(t)} +
    + ${n.map(e=>` + + ${g(e.label)} + ${y.open} + + `).join(``)} +
    +
    + `}function de(e){return e.authenticated?` +
    + Account +
    + + + Identity${y.open} + + + Sign out${y.signout} + +
    +
    + `:` +
    + Account + +
    + `}var fe={overview:`Overview`,services:`Services`,developer:`Developer`,agent:`Agent`};function S(e,t){let n=e.section===`developer`?` / ${e.devPane.toUpperCase()}`:``;return` +
    +
    + cxllm + ${g(fe[e.section]??e.section)}${g(n)} +
    + + ${pe(t)} +
    + `}function pe(e){if(!e.authenticated)return` + + ${y.signin} + Sign in + + `;let t=e.username||e.email||`you`,n=t.slice(0,1).toUpperCase();return` + + + ${g(t)} + + `}var C=new Map,me=15e3;async function w(e,t={}){let n=`${t.credentials??`omit`}|${e}`;if(t.cache!==!1){let e=C.get(n);if(e&&Date.now()-e.tsr.abort(),t.timeoutMs??5e3),a=performance.now(),o;try{let n=await fetch(e,{method:`GET`,mode:`cors`,credentials:t.credentials??`omit`,signal:r.signal,headers:{Accept:`application/json, text/plain;q=0.5, */*;q=0.1`}});o={url:e,ok:n.ok,status:n.status,latencyMs:Math.round(performance.now()-a)}}catch(t){o={url:e,ok:!1,status:0,latencyMs:Math.round(performance.now()-a),error:t instanceof Error?t.message:String(t)}}finally{clearTimeout(i)}return C.set(n,{ts:Date.now(),value:o}),o}var T=he();function he(){let e=window.location.host;return e.startsWith(`127.0.0.1`)||e.startsWith(`localhost`)?``:`https://mcp.cxllm.io`}async function E(e=document){let t=e.querySelector(`[data-role="agent-badge"]`);if(!t)return;if(!T){t.innerHTML=`agent local`;return}let n=await w(`${T}/status`,{timeoutMs:4e3});t.innerHTML=`${n.ok?`agent ${n.status}`:`agent down`}`}function ge(e=3e4){E();let t=window.setInterval(()=>void E(),e);return()=>window.clearInterval(t)}function _e(e){let{runtime:t,session:n}=e,r=b.services.length,i=b.services.filter(e=>e.auth===`public`||e.auth===`public-idp`).length,a=r-i,o=t.scoreCatalog({publicCount:i,gatedCount:a,degradedCount:b.services.filter(e=>!e.probe).length}),s=t.modules.filter(e=>e.loaded).length;return` +
    +
    +

    CxLLM service fabric

    +

    A coherent surface for inference, agents, and operations.

    +

    + ${n.authenticated?`Welcome back, ${g(n.username||n.email||`operator`)}. Your workspace is wired into the CxAI control plane.`:`Public catalog view. Sign in to access the full members console, MCP, and CxAI agent.`} +

    +
    + +
    + ${D(`Services`,r,`across the fabric`)} + ${D(`Public`,i,`no sign-in required`)} + ${D(`Gated`,a,`Authentik forward-auth`)} + ${D(`Signal`,o,`${s}/${t.modules.length} wasm modules loaded`)} +
    + +
    +
    +

    Today

    +

    Live health for the three pillars.

    +
    +
    + ${O(`api`,`API`,`https://api.cxllm.io/status`)} + ${O(`mcp`,`MCP`,`https://mcp.cxllm.io/status`)} + ${O(`agent`,`Agent`,`https://mcp.cxllm.io/status`)} +
    +
    + +
    +
    +

    Wasm runtime

    +

    Rust, C++, and Go modules instantiated in the browser.

    +
    +
      + ${t.modules.map(e=>` +
    • + + ${g(e.label)} + ${e.loaded?`loaded`:`fallback`} + ${g(e.detail)} +
    • + `).join(``)} +
    +
    +
    + `}function D(e,t,n){return` +
    + ${t} + ${g(e)} + ${g(n)} +
    + `}function O(e,t,n){return` +
    +
    + + ${g(t)} + +
    +

    ${g(n)}

    +
    + `}async function k(e){let t=e.querySelectorAll(`[data-today]`);await Promise.all(Array.from(t).map(async e=>{let t=e.dataset.probe;if(!t)return;let n=await w(t,{timeoutMs:4e3}),r=e.querySelector(`.cx-dot`),i=e.querySelector(`[data-role="latency"]`);r&&(r.className=`cx-dot ${n.ok?`ok`:`err`}`),i&&(i.textContent=n.ok?`${n.status} · ${n.latencyMs}ms`:n.error||`status ${n.status}`)}))}function A(e){let t=e.query.trim().toLowerCase(),n=b.services.filter(e=>!e.deprecated).filter(e=>t?[e.title,e.host,e.description,e.id,e.kind,e.auth].join(` `).toLowerCase().includes(t):!0),r=N(n,e=>e.kind||`service`),i=Array.from(r.keys()).sort();return` +
    +
    +
    +

    Catalog

    +

    Services

    +

    ${n.length} active surfaces across the cxllm.io fabric.

    +
    +
    + ${i.map(e=>{let t=r.get(e)||[];return` +
    +
    +

    ${g(P(e))}

    + ${t.length} +
    +
      + ${t.map(M).join(``)} +
    +
    + `}).join(``)} +
    + `}async function j(e){let t=e.querySelectorAll(`[data-probe-url]`);await Promise.all(Array.from(t).map(async e=>{let t=e.dataset.probeUrl;if(!t)return;let n=await w(t,{timeoutMs:4e3}),r=e.querySelector(`.cx-dot`),i=e.querySelector(`[data-role="probe-meta"]`);r&&(r.className=`cx-dot ${n.ok?`ok`:`err`}`),i&&(i.textContent=n.ok?`${n.status} · ${n.latencyMs}ms`:n.error||`status ${n.status}`)}))}function M(e){let t=e.url||(e.host?`https://${e.host}/`:`#`),n=e.probe||``;return` +
  • + ${g(e.title.slice(0,2).toUpperCase())} +
    + ${g(e.title)} + ${g(e.description||e.notes||e.host)} +
    +
    + ${g(e.host||`local`)} + ${g(e.badge||e.auth||`SSO`)} +
    +
    + + +
    +
    + ${y.open} +
    +
  • + `}function N(e,t){let n=new Map;for(let r of e){let e=t(r),i=n.get(e)||[];i.push(r),n.set(e,i)}return n}function P(e){return{api:`Inference API`,mcp:`Model Context Protocol`,ide:`Developer tools`,files:`Storage & files`,storage:`Object storage`,identity:`Identity`,monitoring:`Operations`,spa:`Web surfaces`,service:`Other services`}[e]||e.replace(/(^|\s)\S/g,e=>e.toUpperCase())}function F(e,t){return` +
    + ${e.map(I).join(``)} +
    + `}function I(e){let t=`f-${e.name}`,n=``,r=e.description?`${g(e.description)}`:``,i=``;switch(e.type){case`boolean`:return i=``,`
    ${i}${r}
    `;case`number`:i=``;break;case`enum`:i=``;break;case`json`:i=``;break;default:i=(e.rows??1)>1?``:``}return`
    ${n}${i}${r}
    `}function L(e,t){let n=document.querySelector(`[data-form-id="${e}"]`),r={},i=[];if(!n)return{values:r,errors:[`form not mounted`]};for(let e of t){let t=n.elements.namedItem(e.name);if(!t)continue;if(e.type===`boolean`){r[e.name]=t.checked;continue}let a=(t.value??``).trim();if(!a){e.required&&i.push(`${e.label||e.name} is required`);continue}if(e.type===`number`){let t=Number(a);Number.isNaN(t)?i.push(`${e.label||e.name} must be a number`):r[e.name]=t;continue}if(e.type===`json`){try{r[e.name]=JSON.parse(a)}catch{i.push(`${e.label||e.name} must be valid JSON`)}continue}r[e.name]=a}return{values:r,errors:i}}function ve(e){let t=[`curl -sS -X ${e.method} \\`,` '${e.url}' \\`];return e.bearerEnv&&t.push(` -H "Authorization: Bearer $${e.bearerEnv}" \\`),t.push(` -H 'Content-Type: application/json'`),e.body!==void 0&&t.push(` \\\n -d '${JSON.stringify(e.body)}'`),t.join(` +`)}function ye(e){let t={"Content-Type":`application/json`};return e.bearerEnv&&(t.Authorization=`Bearer \${process.env.${e.bearerEnv}}`),[`const res = await fetch(${JSON.stringify(e.url)}, {`,` method: ${JSON.stringify(e.method)},`,` headers: ${JSON.stringify(t,null,2).replace(/\n/g,` + `)},`,e.body===void 0?``:` body: JSON.stringify(${JSON.stringify(e.body,null,2).replace(/\n/g,` + `)}),`,`});`,`const data = await res.json();`,`console.log(data);`].filter(Boolean).join(` +`)}function be(e){let t=[`import os`,`import httpx`,``,`headers = {"Content-Type": "application/json"}`];return e.bearerEnv&&t.push(`headers["Authorization"] = f"Bearer {os.environ['${e.bearerEnv}']}"`),e.body===void 0?t.push(`r = httpx.${e.method.toLowerCase()}(${JSON.stringify(e.url)}, headers=headers, timeout=60)`):(t.push(`payload = ${JSON.stringify(e.body,null,4)}`),t.push(`r = httpx.${e.method.toLowerCase()}(${JSON.stringify(e.url)}, headers=headers, json=payload, timeout=60)`)),t.push(`r.raise_for_status()`,`print(r.json())`),t.join(` +`)}var R=xe(`api`);function xe(e){let t=window.location.host;return t.startsWith(`127.0.0.1`)||t.startsWith(`localhost`)?``:`https://${e}.cxllm.io`}var z=[{id:`status`,label:`GET /status`,description:`Public liveness probe (no auth).`,method:`GET`,path:`/status`,fields:[],publicProbe:!0},{id:`models`,label:`GET /v1/models`,description:`List available chat/embedding models.`,method:`GET`,path:`/v1/models`,fields:[]},{id:`chat`,label:`POST /v1/chat/completions`,description:`OpenAI-compatible chat completion.`,method:`POST`,path:`/v1/chat/completions`,fields:[{name:`model`,label:`Model`,type:`string`,required:!0,default:`gpt-4o-mini`},{name:`prompt`,label:`User message`,type:`string`,rows:4,required:!0,placeholder:`Say hello in three languages.`},{name:`temperature`,label:`Temperature`,type:`number`,default:.7}],body:e=>({model:e.model,messages:[{role:`user`,content:e.prompt}],temperature:e.temperature})},{id:`embeddings`,label:`POST /v1/embeddings`,description:`Vector embeddings for retrieval.`,method:`POST`,path:`/v1/embeddings`,fields:[{name:`model`,label:`Model`,type:`string`,required:!0,default:`text-embedding-3-small`},{name:`input`,label:`Input text`,type:`string`,rows:3,required:!0,default:`hello world`}],body:e=>({model:e.model,input:e.input})}];function Se(e){return` +
    + +
    + ${B(z[0],e)} +
    +
    + `}async function Ce(e,t){let n=e.querySelectorAll(`[data-op]`),r=e.querySelector(`[data-role="dev-main"]`);n.forEach(e=>{e.addEventListener(`click`,()=>{n.forEach(e=>e.classList.remove(`is-active`)),e.classList.add(`is-active`),n.forEach(t=>t.setAttribute(`aria-selected`,t===e?`true`:`false`));let i=z.find(t=>t.id===e.dataset.op);i&&r&&(r.innerHTML=B(i,t),V(r,i,t))})}),r&&V(r,z[0],t)}function B(e,t){let n=`${R||`https://api.cxllm.io`}${e.path}`,r=e.body?e.body(Object.fromEntries(e.fields.map(e=>[e.name,e.default]))):void 0,i=t.authenticated||e.publicProbe;return` +
    +
    +

    ${g(e.label)}

    +

    ${g(e.description)}

    +

    ${g(e.method)} ${g(n)}

    +
    + ${e.fields.length?`
    ${F(e.fields,`api-${e.id}`)}
    `:``} +
    +
    + Run + ${i?e.publicProbe?`Public probe`:`Uses your Authentik session cookie.`:`Sign in to enable.`} +
    +
    + + ${i?``:`Sign in`} +
    +
    // Result will appear here.
    +
    +
    +
    Snippets
    +
    +
    curl
    +
    ${g(ve({method:e.method,url:n,body:r,bearerEnv:`CXLLM_API_KEY`}))}
    +
    +
    +
    TypeScript
    +
    ${g(ye({method:e.method,url:n,body:r,bearerEnv:`CXLLM_API_KEY`}))}
    +
    +
    +
    Python
    +
    ${g(be({method:e.method,url:n,body:r,bearerEnv:`CXLLM_API_KEY`}))}
    +
    +
    +
    + `}function V(e,t,n){let r=e.querySelector(`[data-op-run="${t.id}"]`),i=e.querySelector(`[data-role="op-output"]`);!r||!i||r.addEventListener(`click`,async()=>{i.textContent=`// Calling…`;let{values:e,errors:r}=L(`api-${t.id}`,t.fields);if(r.length){i.textContent=`// validation:\n${r.join(` +`)}`;return}try{let r=`${R||`https://api.cxllm.io`}${t.path}`,a={method:t.method,credentials:n.authenticated?`include`:`omit`,headers:{Accept:`application/json`}};t.method===`POST`&&(a.headers={...a.headers,"Content-Type":`application/json`},a.body=JSON.stringify(t.body?t.body(e):e));let o=await fetch(r,a),s=(o.headers.get(`content-type`)||``).includes(`application/json`)?await o.json():await o.text();i.textContent=`// ${o.status} ${o.statusText}\n${typeof s==`string`?s:_(s)}`}catch(e){i.textContent=`// error: ${e instanceof Error?e.message:String(e)}`}})}var H=(()=>{let e=window.location.host;return e.startsWith(`127.0.0.1`)||e.startsWith(`localhost`)?`http://127.0.0.1:8082`:`https://mcp.cxllm.io`})();function we(e){return` +
    + +
    +
    +
    + cxai-mcp + ${g(H)} +
    +

    ${e.authenticated?`Pick a tool on the left to render its schema-driven form and call it live.`:`Anonymous view. Tools list loads, but invocations need a signed-in session.`}

    +
    +
    +
    /events tail
    +
    // connecting…
    +
    +
    +
    + `}async function Te(e,t){let n=e.querySelector(`[data-role="tool-list"]`),r=e.querySelector(`[data-role="mcp-main"]`),i=e.querySelector(`[data-role="reload-tools"]`);if(!n||!r)return;await U(n,r,t),i?.addEventListener(`click`,()=>void U(n,r,t));let a=e.querySelector(`[data-role="events-tail"]`);a&&De(a,t)}async function U(e,t,n){try{let r=await fetch(`${H}/tools`,{credentials:n.authenticated?`include`:`omit`,headers:{Accept:`application/json`}});if(!r.ok)throw Error(`status ${r.status}`);let i=await r.json(),a=Array.isArray(i)?i:Array.isArray(i?.tools)?i.tools:[];if(!a.length){e.innerHTML=`
  • no tools registered
  • `;return}e.innerHTML=a.map((e,t)=>` +
  • + +
  • + `).join(``);let o=e.querySelectorAll(`[data-tool]`);o.forEach(e=>{e.addEventListener(`click`,()=>{o.forEach(e=>e.classList.remove(`is-active`)),e.classList.add(`is-active`);let r=a.find(t=>t.name===e.dataset.tool);r&&W(t,r,n)})}),W(t,a[0],n)}catch(t){e.innerHTML=`
  • error: ${g(t instanceof Error?t.message:String(t))}
  • `}}function W(e,t,n){let r=Ee(t),i=n.authenticated;e.innerHTML=` +
    +
    + ${g(t.name)} + POST ${g(H)}/tools/${g(t.name)} +
    +

    ${g(t.description||``)}

    +
    + ${r.length?`
    ${F(r,`mcp-${t.name}`)}
    `:``} +
    +
    Run${i?"Calls /tools/${name} with your session cookie.":`Sign in to enable.`}
    +
    + +
    +
    // Result will appear here.
    +
    + `;let a=e.querySelector(`[data-mcp-run]`),o=e.querySelector(`[data-role="mcp-output"]`);a?.addEventListener(`click`,async()=>{if(!o)return;o.textContent=`// Invoking…`;let{values:e,errors:n}=L(`mcp-${t.name}`,r);if(n.length){o.textContent=`// validation:\n${n.join(` +`)}`;return}try{let n=await fetch(`${H}/tools/${encodeURIComponent(t.name)}`,{method:`POST`,credentials:`include`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify(e)}),r=(n.headers.get(`content-type`)||``).includes(`application/json`)?await n.json():await n.text();o.textContent=`// ${n.status} ${n.statusText}\n${typeof r==`string`?r:_(r)}`}catch(e){o.textContent=`// error: ${e instanceof Error?e.message:String(e)}`}})}function Ee(e){let t=e.schema?.properties||{},n=new Set(e.schema?.required||[]);return Object.entries(t).map(([e,t])=>{let r=(t.type||`string`).toLowerCase(),i=`string`;return r===`number`||r===`integer`?i=`number`:r===`boolean`?i=`boolean`:r===`object`||r===`array`?i=`json`:t.enum&&t.enum.length&&(i=`enum`),{name:e,label:e,type:i,required:n.has(e),default:t.default,description:t.description,options:t.enum,rows:i===`json`?6:i===`string`?2:1}})}function De(e,t){try{let n=`${H}/events`,r=new EventSource(n,{withCredentials:t.authenticated}),i=[];e.textContent=`// connected`,r.onmessage=t=>{i.push(`${new Date().toLocaleTimeString()} ${t.data}`),i.length>20&&i.shift(),e.textContent=i.join(` +`)},r.onerror=()=>{e.textContent+=`\n// stream error (${new Date().toLocaleTimeString()})`,r.close()}}catch(t){e.textContent=`// events unavailable: ${t instanceof Error?t.message:String(t)}`}}function Oe(e,t){let n=e.devPane,r=n===`mcp`?we(t):Se(t);return` +
    +
    +
    +

    Developer

    +

    Build against CxLLM

    +

    ${t.authenticated?`Live, authenticated calls. Forms run against your session.`:`Anonymous view. Snippets only — sign in to run live requests.`}

    +
    +
    + ${G(`api`,`API`,n===`api`)} + ${G(`mcp`,`MCP`,n===`mcp`)} +
    +
    +
    ${r}
    +
    + `}async function ke(e,t,n){t.devPane===`mcp`?await Te(e,n):await Ce(e,n)}function G(e,t,n){return``}var K=(()=>{let e=window.location.host;return e.startsWith(`127.0.0.1`)||e.startsWith(`localhost`)?`http://127.0.0.1:8082`:`https://mcp.cxllm.io`})();function Ae(e){return` +
    +
    +
    +

    CxAI

    +

    Agent control plane

    +

    cxai-mcp sidecar status, registered tools, and recent activity.${e.authenticated?``:` Sign in for live tool invocations.`}

    +
    +
    + +
    +

    Status

    +
    // loading…
    +
    + +
    +

    Tools

    Registered with cxai-mcp.
    +
    • loading…
    +
    + +
    +

    Activity

    /events tail (last 20).
    +
    // connecting…
    +
    +
    + `}async function je(e,t){let n=e.querySelector(`[data-role="agent-status"]`),r=e.querySelector(`[data-role="agent-status-meta"]`),i=e.querySelector(`[data-role="agent-tools"]`),a=e.querySelector(`[data-role="agent-events"]`);if(n&&r){let e=await w(`${K}/status`,{timeoutMs:4e3});if(r.textContent=e.ok?`${e.status} · ${e.latencyMs}ms`:e.error||`status ${e.status}`,e.ok)try{let e=await fetch(`${K}/status`,{credentials:t.authenticated?`include`:`omit`}),r=await e.json().catch(()=>null);n.textContent=r?_(r):`// status ${e.status}`}catch(e){n.textContent=`// error: ${e instanceof Error?e.message:String(e)}`}else n.textContent=`// unavailable (${e.error||e.status})`}if(i)try{let e=await(await fetch(`${K}/tools`,{credentials:t.authenticated?`include`:`omit`})).json(),n=Array.isArray(e)?e:Array.isArray(e?.tools)?e.tools:[];i.innerHTML=n.length?n.map(e=>` +
  • + ${g(e.name)} + ${g(e.description||``)} +
  • + `).join(``):`
  • no tools registered
  • `}catch(e){i.innerHTML=`
  • error: ${g(e instanceof Error?e.message:String(e))}
  • `}if(a)try{let e=new EventSource(`${K}/events`,{withCredentials:t.authenticated}),n=[];a.textContent=`// connected`,e.onmessage=e=>{n.push(`${new Date().toLocaleTimeString()} ${e.data}`),n.length>20&&n.shift(),a.textContent=n.join(` +`)},e.onerror=()=>{a.textContent+=`\n// stream error (${new Date().toLocaleTimeString()})`,e.close()}}catch(e){a.textContent=`// events unavailable: ${e instanceof Error?e.message:String(e)}`}}var q,J,Y,X;async function Z(){if((q.target===`members`||q.target===`webapp`)&&!Y.authenticated){Me();return}X.innerHTML=` +
    + ${ue(q,Y,J)} +
    + ${S(q,Y)} +
    + ${Q()} +
    +
    +
    + `,Ne(),E(X),await $()}function Q(){switch(q.section){case`services`:return A(q);case`developer`:return Oe(q,Y);case`agent`:return Ae(Y);default:return _e({state:q,session:Y,runtime:J})}}async function $(){let e=X.querySelector(`[data-role="workspace-body"]`);if(e)switch(q.section){case`services`:await j(e);break;case`developer`:await ke(e,q,Y);break;case`agent`:await je(e,Y);break;default:await k(e);break}}function Me(){X.innerHTML=` +
    +
    +

    CxLLM

    +

    Sign in to continue

    +

    The ${q.target===`webapp`?`operator console`:`members workspace`} is protected by Authentik. Sign in to access services, developer tools, and the CxAI agent.

    + Sign in with Authentik +

    ← Back to public landing

    +
    +
    + `}function Ne(){X.querySelectorAll(`[data-section]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=e.dataset.section;!t||t===q.section||(q.section=t,te(t),Pe(),Z())})}),X.querySelectorAll(`[data-dev-pane]`).forEach(e=>{e.addEventListener(`click`,()=>{let t=e.dataset.devPane;!t||t===q.devPane||(q.devPane=t,ne(t),Z())})}),X.querySelector(`[data-role="search"]`)?.addEventListener(`input`,e=>{if(q.query=e.currentTarget.value,q.section===`services`){let e=X.querySelector(`[data-role="workspace-body"]`);e&&(e.innerHTML=Q(),$())}}),X.querySelector(`[data-action="toggle-sidebar"]`)?.addEventListener(`click`,()=>{q.sidebarCollapsed=!q.sidebarCollapsed,p(q.sidebarCollapsed),Z()}),document.addEventListener(`keydown`,e=>{(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`&&(e.preventDefault(),X.querySelector(`[data-role="search"]`)?.focus())},{once:!0})}function Pe(){try{let e=new URL(window.location.href);e.searchParams.set(`section`,q.section),window.history.replaceState(null,``,e)}catch{}}async function Fe(){let e=document.querySelector(`#cxllm-root`);e&&(X=e,q=ee(u(e.dataset.cxTarget)),[Y,J]=await Promise.all([ae(),o()]),await Z(),ge())}Fe(); \ No newline at end of file diff --git a/static/index.html b/static/index.html index 818dceb..d5c9395 100644 --- a/static/index.html +++ b/static/index.html @@ -4,7 +4,7 @@ CxWebApp - + diff --git a/static/wasm/cxllm_cpp_core 2.wasm b/static/wasm/cxllm_cpp_core 2.wasm new file mode 100755 index 0000000..09af1ae Binary files /dev/null and b/static/wasm/cxllm_cpp_core 2.wasm differ diff --git a/static/wasm/cxllm_cpp_core 3.wasm b/static/wasm/cxllm_cpp_core 3.wasm new file mode 100755 index 0000000..09af1ae Binary files /dev/null and b/static/wasm/cxllm_cpp_core 3.wasm differ diff --git a/static/wasm/cxllm_cxedge_core 2.wasm b/static/wasm/cxllm_cxedge_core 2.wasm new file mode 100755 index 0000000..30ad0cb Binary files /dev/null and b/static/wasm/cxllm_cxedge_core 2.wasm differ diff --git a/static/wasm/cxllm_cxedge_core.wasm b/static/wasm/cxllm_cxedge_core.wasm new file mode 100755 index 0000000..30ad0cb Binary files /dev/null and b/static/wasm/cxllm_cxedge_core.wasm differ diff --git a/static/wasm/cxllm_go_core 2.wasm b/static/wasm/cxllm_go_core 2.wasm new file mode 100755 index 0000000..4cd207e Binary files /dev/null and b/static/wasm/cxllm_go_core 2.wasm differ diff --git a/static/wasm/cxllm_go_core 3.wasm b/static/wasm/cxllm_go_core 3.wasm new file mode 100755 index 0000000..4cd207e Binary files /dev/null and b/static/wasm/cxllm_go_core 3.wasm differ diff --git a/static/wasm/cxllm_rust_core 2.wasm b/static/wasm/cxllm_rust_core 2.wasm new file mode 100755 index 0000000..da52d1a Binary files /dev/null and b/static/wasm/cxllm_rust_core 2.wasm differ diff --git a/static/wasm/cxllm_rust_core 3.wasm b/static/wasm/cxllm_rust_core 3.wasm new file mode 100755 index 0000000..da52d1a Binary files /dev/null and b/static/wasm/cxllm_rust_core 3.wasm differ diff --git a/static/wasm/modules.json b/static/wasm/modules.json index 3a0ec53..31866f8 100644 --- a/static/wasm/modules.json +++ b/static/wasm/modules.json @@ -15,6 +15,11 @@ "id": "go", "status": "built", "detail": "cxllm_go_core.wasm" + }, + { + "id": "cxedge", + "status": "built", + "detail": "cxllm_cxedge_core.wasm via emcc (v0.0.0-cxedge)" } ] } diff --git a/static/wasm/wasm_exec 2.js b/static/wasm/wasm_exec 2.js new file mode 100644 index 0000000..d71af9e --- /dev/null +++ b/static/wasm/wasm_exec 2.js @@ -0,0 +1,575 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +"use strict"; + +(() => { + const enosys = () => { + const err = new Error("not implemented"); + err.code = "ENOSYS"; + return err; + }; + + if (!globalThis.fs) { + let outputBuf = ""; + globalThis.fs = { + constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 }, // unused + writeSync(fd, buf) { + outputBuf += decoder.decode(buf); + const nl = outputBuf.lastIndexOf("\n"); + if (nl != -1) { + console.log(outputBuf.substring(0, nl)); + outputBuf = outputBuf.substring(nl + 1); + } + return buf.length; + }, + write(fd, buf, offset, length, position, callback) { + if (offset !== 0 || length !== buf.length || position !== null) { + callback(enosys()); + return; + } + const n = this.writeSync(fd, buf); + callback(null, n); + }, + chmod(path, mode, callback) { callback(enosys()); }, + chown(path, uid, gid, callback) { callback(enosys()); }, + close(fd, callback) { callback(enosys()); }, + fchmod(fd, mode, callback) { callback(enosys()); }, + fchown(fd, uid, gid, callback) { callback(enosys()); }, + fstat(fd, callback) { callback(enosys()); }, + fsync(fd, callback) { callback(null); }, + ftruncate(fd, length, callback) { callback(enosys()); }, + lchown(path, uid, gid, callback) { callback(enosys()); }, + link(path, link, callback) { callback(enosys()); }, + lstat(path, callback) { callback(enosys()); }, + mkdir(path, perm, callback) { callback(enosys()); }, + open(path, flags, mode, callback) { callback(enosys()); }, + read(fd, buffer, offset, length, position, callback) { callback(enosys()); }, + readdir(path, callback) { callback(enosys()); }, + readlink(path, callback) { callback(enosys()); }, + rename(from, to, callback) { callback(enosys()); }, + rmdir(path, callback) { callback(enosys()); }, + stat(path, callback) { callback(enosys()); }, + symlink(path, link, callback) { callback(enosys()); }, + truncate(path, length, callback) { callback(enosys()); }, + unlink(path, callback) { callback(enosys()); }, + utimes(path, atime, mtime, callback) { callback(enosys()); }, + }; + } + + if (!globalThis.process) { + globalThis.process = { + getuid() { return -1; }, + getgid() { return -1; }, + geteuid() { return -1; }, + getegid() { return -1; }, + getgroups() { throw enosys(); }, + pid: -1, + ppid: -1, + umask() { throw enosys(); }, + cwd() { throw enosys(); }, + chdir() { throw enosys(); }, + } + } + + if (!globalThis.path) { + globalThis.path = { + resolve(...pathSegments) { + return pathSegments.join("/"); + } + } + } + + if (!globalThis.crypto) { + throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"); + } + + if (!globalThis.performance) { + throw new Error("globalThis.performance is not available, polyfill required (performance.now only)"); + } + + if (!globalThis.TextEncoder) { + throw new Error("globalThis.TextEncoder is not available, polyfill required"); + } + + if (!globalThis.TextDecoder) { + throw new Error("globalThis.TextDecoder is not available, polyfill required"); + } + + const encoder = new TextEncoder("utf-8"); + const decoder = new TextDecoder("utf-8"); + + globalThis.Go = class { + constructor() { + this.argv = ["js"]; + this.env = {}; + this.exit = (code) => { + if (code !== 0) { + console.warn("exit code:", code); + } + }; + this._exitPromise = new Promise((resolve) => { + this._resolveExitPromise = resolve; + }); + this._pendingEvent = null; + this._scheduledTimeouts = new Map(); + this._nextCallbackTimeoutID = 1; + + const setInt64 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); + } + + const setInt32 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + } + + const getInt64 = (addr) => { + const low = this.mem.getUint32(addr + 0, true); + const high = this.mem.getInt32(addr + 4, true); + return low + high * 4294967296; + } + + const loadValue = (addr) => { + const f = this.mem.getFloat64(addr, true); + if (f === 0) { + return undefined; + } + if (!isNaN(f)) { + return f; + } + + const id = this.mem.getUint32(addr, true); + return this._values[id]; + } + + const storeValue = (addr, v) => { + const nanHead = 0x7FF80000; + + if (typeof v === "number" && v !== 0) { + if (isNaN(v)) { + this.mem.setUint32(addr + 4, nanHead, true); + this.mem.setUint32(addr, 0, true); + return; + } + this.mem.setFloat64(addr, v, true); + return; + } + + if (v === undefined) { + this.mem.setFloat64(addr, 0, true); + return; + } + + let id = this._ids.get(v); + if (id === undefined) { + id = this._idPool.pop(); + if (id === undefined) { + id = this._values.length; + } + this._values[id] = v; + this._goRefCounts[id] = 0; + this._ids.set(v, id); + } + this._goRefCounts[id]++; + let typeFlag = 0; + switch (typeof v) { + case "object": + if (v !== null) { + typeFlag = 1; + } + break; + case "string": + typeFlag = 2; + break; + case "symbol": + typeFlag = 3; + break; + case "function": + typeFlag = 4; + break; + } + this.mem.setUint32(addr + 4, nanHead | typeFlag, true); + this.mem.setUint32(addr, id, true); + } + + const loadSlice = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + return new Uint8Array(this._inst.exports.mem.buffer, array, len); + } + + const loadSliceOfValues = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + const a = new Array(len); + for (let i = 0; i < len; i++) { + a[i] = loadValue(array + i * 8); + } + return a; + } + + const loadString = (addr) => { + const saddr = getInt64(addr + 0); + const len = getInt64(addr + 8); + return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); + } + + const testCallExport = (a, b) => { + this._inst.exports.testExport0(); + return this._inst.exports.testExport(a, b); + } + + const timeOrigin = Date.now() - performance.now(); + this.importObject = { + _gotest: { + add: (a, b) => a + b, + callExport: testCallExport, + }, + gojs: { + // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) + // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported + // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). + // This changes the SP, thus we have to update the SP used by the imported function. + + // func wasmExit(code int32) + "runtime.wasmExit": (sp) => { + sp >>>= 0; + const code = this.mem.getInt32(sp + 8, true); + this.exited = true; + delete this._inst; + delete this._values; + delete this._goRefCounts; + delete this._ids; + delete this._idPool; + this.exit(code); + }, + + // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) + "runtime.wasmWrite": (sp) => { + sp >>>= 0; + const fd = getInt64(sp + 8); + const p = getInt64(sp + 16); + const n = this.mem.getInt32(sp + 24, true); + fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); + }, + + // func resetMemoryDataView() + "runtime.resetMemoryDataView": (sp) => { + sp >>>= 0; + this.mem = new DataView(this._inst.exports.mem.buffer); + }, + + // func nanotime1() int64 + "runtime.nanotime1": (sp) => { + sp >>>= 0; + setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); + }, + + // func walltime() (sec int64, nsec int32) + "runtime.walltime": (sp) => { + sp >>>= 0; + const msec = (new Date).getTime(); + setInt64(sp + 8, msec / 1000); + this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); + }, + + // func scheduleTimeoutEvent(delay int64) int32 + "runtime.scheduleTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this._nextCallbackTimeoutID; + this._nextCallbackTimeoutID++; + this._scheduledTimeouts.set(id, setTimeout( + () => { + this._resume(); + while (this._scheduledTimeouts.has(id)) { + // for some reason Go failed to register the timeout event, log and try again + // (temporary workaround for https://github.com/golang/go/issues/28975) + console.warn("scheduleTimeoutEvent: missed timeout event"); + this._resume(); + } + }, + getInt64(sp + 8), + )); + this.mem.setInt32(sp + 16, id, true); + }, + + // func clearTimeoutEvent(id int32) + "runtime.clearTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this.mem.getInt32(sp + 8, true); + clearTimeout(this._scheduledTimeouts.get(id)); + this._scheduledTimeouts.delete(id); + }, + + // func getRandomData(r []byte) + "runtime.getRandomData": (sp) => { + sp >>>= 0; + crypto.getRandomValues(loadSlice(sp + 8)); + }, + + // func finalizeRef(v ref) + "syscall/js.finalizeRef": (sp) => { + sp >>>= 0; + const id = this.mem.getUint32(sp + 8, true); + this._goRefCounts[id]--; + if (this._goRefCounts[id] === 0) { + const v = this._values[id]; + this._values[id] = null; + this._ids.delete(v); + this._idPool.push(id); + } + }, + + // func stringVal(value string) ref + "syscall/js.stringVal": (sp) => { + sp >>>= 0; + storeValue(sp + 24, loadString(sp + 8)); + }, + + // func valueGet(v ref, p string) ref + "syscall/js.valueGet": (sp) => { + sp >>>= 0; + const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 32, result); + }, + + // func valueSet(v ref, p string, x ref) + "syscall/js.valueSet": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); + }, + + // func valueDelete(v ref, p string) + "syscall/js.valueDelete": (sp) => { + sp >>>= 0; + Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); + }, + + // func valueIndex(v ref, i int) ref + "syscall/js.valueIndex": (sp) => { + sp >>>= 0; + storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); + }, + + // valueSetIndex(v ref, i int, x ref) + "syscall/js.valueSetIndex": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); + }, + + // func valueCall(v ref, m string, args []ref) (ref, bool) + "syscall/js.valueCall": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const m = Reflect.get(v, loadString(sp + 16)); + const args = loadSliceOfValues(sp + 32); + const result = Reflect.apply(m, v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, result); + this.mem.setUint8(sp + 64, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, err); + this.mem.setUint8(sp + 64, 0); + } + }, + + // func valueInvoke(v ref, args []ref) (ref, bool) + "syscall/js.valueInvoke": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.apply(v, undefined, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueNew(v ref, args []ref) (ref, bool) + "syscall/js.valueNew": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.construct(v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueLength(v ref) int + "syscall/js.valueLength": (sp) => { + sp >>>= 0; + setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); + }, + + // valuePrepareString(v ref) (ref, int) + "syscall/js.valuePrepareString": (sp) => { + sp >>>= 0; + const str = encoder.encode(String(loadValue(sp + 8))); + storeValue(sp + 16, str); + setInt64(sp + 24, str.length); + }, + + // valueLoadString(v ref, b []byte) + "syscall/js.valueLoadString": (sp) => { + sp >>>= 0; + const str = loadValue(sp + 8); + loadSlice(sp + 16).set(str); + }, + + // func valueInstanceOf(v ref, t ref) bool + "syscall/js.valueInstanceOf": (sp) => { + sp >>>= 0; + this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0); + }, + + // func copyBytesToGo(dst []byte, src ref) (int, bool) + "syscall/js.copyBytesToGo": (sp) => { + sp >>>= 0; + const dst = loadSlice(sp + 8); + const src = loadValue(sp + 32); + if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + // func copyBytesToJS(dst ref, src []byte) (int, bool) + "syscall/js.copyBytesToJS": (sp) => { + sp >>>= 0; + const dst = loadValue(sp + 8); + const src = loadSlice(sp + 16); + if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + "debug": (value) => { + console.log(value); + }, + } + }; + } + + async run(instance) { + if (!(instance instanceof WebAssembly.Instance)) { + throw new Error("Go.run: WebAssembly.Instance expected"); + } + this._inst = instance; + this.mem = new DataView(this._inst.exports.mem.buffer); + this._values = [ // JS values that Go currently has references to, indexed by reference id + NaN, + 0, + null, + true, + false, + globalThis, + this, + ]; + this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id + this._ids = new Map([ // mapping from JS values to reference ids + [0, 1], + [null, 2], + [true, 3], + [false, 4], + [globalThis, 5], + [this, 6], + ]); + this._idPool = []; // unused ids that have been garbage collected + this.exited = false; // whether the Go program has exited + + // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. + let offset = 4096; + + const strPtr = (str) => { + const ptr = offset; + const bytes = encoder.encode(str + "\0"); + new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); + offset += bytes.length; + if (offset % 8 !== 0) { + offset += 8 - (offset % 8); + } + return ptr; + }; + + const argc = this.argv.length; + + const argvPtrs = []; + this.argv.forEach((arg) => { + argvPtrs.push(strPtr(arg)); + }); + argvPtrs.push(0); + + const keys = Object.keys(this.env).sort(); + keys.forEach((key) => { + argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); + }); + argvPtrs.push(0); + + const argv = offset; + argvPtrs.forEach((ptr) => { + this.mem.setUint32(offset, ptr, true); + this.mem.setUint32(offset + 4, 0, true); + offset += 8; + }); + + // The linker guarantees global data starts from at least wasmMinDataAddr. + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. + const wasmMinDataAddr = 4096 + 8192; + if (offset >= wasmMinDataAddr) { + throw new Error("total length of command line and environment variables exceeds limit"); + } + + this._inst.exports.run(argc, argv); + if (this.exited) { + this._resolveExitPromise(); + } + await this._exitPromise; + } + + _resume() { + if (this.exited) { + throw new Error("Go program has already exited"); + } + this._inst.exports.resume(); + if (this.exited) { + this._resolveExitPromise(); + } + } + + _makeFuncWrapper(id) { + const go = this; + return function () { + const event = { id: id, this: this, args: arguments }; + go._pendingEvent = event; + go._resume(); + return event.result; + }; + } + } +})(); diff --git a/static/wasm/wasm_exec 3.js b/static/wasm/wasm_exec 3.js new file mode 100644 index 0000000..d71af9e --- /dev/null +++ b/static/wasm/wasm_exec 3.js @@ -0,0 +1,575 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +"use strict"; + +(() => { + const enosys = () => { + const err = new Error("not implemented"); + err.code = "ENOSYS"; + return err; + }; + + if (!globalThis.fs) { + let outputBuf = ""; + globalThis.fs = { + constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 }, // unused + writeSync(fd, buf) { + outputBuf += decoder.decode(buf); + const nl = outputBuf.lastIndexOf("\n"); + if (nl != -1) { + console.log(outputBuf.substring(0, nl)); + outputBuf = outputBuf.substring(nl + 1); + } + return buf.length; + }, + write(fd, buf, offset, length, position, callback) { + if (offset !== 0 || length !== buf.length || position !== null) { + callback(enosys()); + return; + } + const n = this.writeSync(fd, buf); + callback(null, n); + }, + chmod(path, mode, callback) { callback(enosys()); }, + chown(path, uid, gid, callback) { callback(enosys()); }, + close(fd, callback) { callback(enosys()); }, + fchmod(fd, mode, callback) { callback(enosys()); }, + fchown(fd, uid, gid, callback) { callback(enosys()); }, + fstat(fd, callback) { callback(enosys()); }, + fsync(fd, callback) { callback(null); }, + ftruncate(fd, length, callback) { callback(enosys()); }, + lchown(path, uid, gid, callback) { callback(enosys()); }, + link(path, link, callback) { callback(enosys()); }, + lstat(path, callback) { callback(enosys()); }, + mkdir(path, perm, callback) { callback(enosys()); }, + open(path, flags, mode, callback) { callback(enosys()); }, + read(fd, buffer, offset, length, position, callback) { callback(enosys()); }, + readdir(path, callback) { callback(enosys()); }, + readlink(path, callback) { callback(enosys()); }, + rename(from, to, callback) { callback(enosys()); }, + rmdir(path, callback) { callback(enosys()); }, + stat(path, callback) { callback(enosys()); }, + symlink(path, link, callback) { callback(enosys()); }, + truncate(path, length, callback) { callback(enosys()); }, + unlink(path, callback) { callback(enosys()); }, + utimes(path, atime, mtime, callback) { callback(enosys()); }, + }; + } + + if (!globalThis.process) { + globalThis.process = { + getuid() { return -1; }, + getgid() { return -1; }, + geteuid() { return -1; }, + getegid() { return -1; }, + getgroups() { throw enosys(); }, + pid: -1, + ppid: -1, + umask() { throw enosys(); }, + cwd() { throw enosys(); }, + chdir() { throw enosys(); }, + } + } + + if (!globalThis.path) { + globalThis.path = { + resolve(...pathSegments) { + return pathSegments.join("/"); + } + } + } + + if (!globalThis.crypto) { + throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"); + } + + if (!globalThis.performance) { + throw new Error("globalThis.performance is not available, polyfill required (performance.now only)"); + } + + if (!globalThis.TextEncoder) { + throw new Error("globalThis.TextEncoder is not available, polyfill required"); + } + + if (!globalThis.TextDecoder) { + throw new Error("globalThis.TextDecoder is not available, polyfill required"); + } + + const encoder = new TextEncoder("utf-8"); + const decoder = new TextDecoder("utf-8"); + + globalThis.Go = class { + constructor() { + this.argv = ["js"]; + this.env = {}; + this.exit = (code) => { + if (code !== 0) { + console.warn("exit code:", code); + } + }; + this._exitPromise = new Promise((resolve) => { + this._resolveExitPromise = resolve; + }); + this._pendingEvent = null; + this._scheduledTimeouts = new Map(); + this._nextCallbackTimeoutID = 1; + + const setInt64 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); + } + + const setInt32 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + } + + const getInt64 = (addr) => { + const low = this.mem.getUint32(addr + 0, true); + const high = this.mem.getInt32(addr + 4, true); + return low + high * 4294967296; + } + + const loadValue = (addr) => { + const f = this.mem.getFloat64(addr, true); + if (f === 0) { + return undefined; + } + if (!isNaN(f)) { + return f; + } + + const id = this.mem.getUint32(addr, true); + return this._values[id]; + } + + const storeValue = (addr, v) => { + const nanHead = 0x7FF80000; + + if (typeof v === "number" && v !== 0) { + if (isNaN(v)) { + this.mem.setUint32(addr + 4, nanHead, true); + this.mem.setUint32(addr, 0, true); + return; + } + this.mem.setFloat64(addr, v, true); + return; + } + + if (v === undefined) { + this.mem.setFloat64(addr, 0, true); + return; + } + + let id = this._ids.get(v); + if (id === undefined) { + id = this._idPool.pop(); + if (id === undefined) { + id = this._values.length; + } + this._values[id] = v; + this._goRefCounts[id] = 0; + this._ids.set(v, id); + } + this._goRefCounts[id]++; + let typeFlag = 0; + switch (typeof v) { + case "object": + if (v !== null) { + typeFlag = 1; + } + break; + case "string": + typeFlag = 2; + break; + case "symbol": + typeFlag = 3; + break; + case "function": + typeFlag = 4; + break; + } + this.mem.setUint32(addr + 4, nanHead | typeFlag, true); + this.mem.setUint32(addr, id, true); + } + + const loadSlice = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + return new Uint8Array(this._inst.exports.mem.buffer, array, len); + } + + const loadSliceOfValues = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + const a = new Array(len); + for (let i = 0; i < len; i++) { + a[i] = loadValue(array + i * 8); + } + return a; + } + + const loadString = (addr) => { + const saddr = getInt64(addr + 0); + const len = getInt64(addr + 8); + return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); + } + + const testCallExport = (a, b) => { + this._inst.exports.testExport0(); + return this._inst.exports.testExport(a, b); + } + + const timeOrigin = Date.now() - performance.now(); + this.importObject = { + _gotest: { + add: (a, b) => a + b, + callExport: testCallExport, + }, + gojs: { + // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) + // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported + // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). + // This changes the SP, thus we have to update the SP used by the imported function. + + // func wasmExit(code int32) + "runtime.wasmExit": (sp) => { + sp >>>= 0; + const code = this.mem.getInt32(sp + 8, true); + this.exited = true; + delete this._inst; + delete this._values; + delete this._goRefCounts; + delete this._ids; + delete this._idPool; + this.exit(code); + }, + + // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) + "runtime.wasmWrite": (sp) => { + sp >>>= 0; + const fd = getInt64(sp + 8); + const p = getInt64(sp + 16); + const n = this.mem.getInt32(sp + 24, true); + fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); + }, + + // func resetMemoryDataView() + "runtime.resetMemoryDataView": (sp) => { + sp >>>= 0; + this.mem = new DataView(this._inst.exports.mem.buffer); + }, + + // func nanotime1() int64 + "runtime.nanotime1": (sp) => { + sp >>>= 0; + setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); + }, + + // func walltime() (sec int64, nsec int32) + "runtime.walltime": (sp) => { + sp >>>= 0; + const msec = (new Date).getTime(); + setInt64(sp + 8, msec / 1000); + this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); + }, + + // func scheduleTimeoutEvent(delay int64) int32 + "runtime.scheduleTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this._nextCallbackTimeoutID; + this._nextCallbackTimeoutID++; + this._scheduledTimeouts.set(id, setTimeout( + () => { + this._resume(); + while (this._scheduledTimeouts.has(id)) { + // for some reason Go failed to register the timeout event, log and try again + // (temporary workaround for https://github.com/golang/go/issues/28975) + console.warn("scheduleTimeoutEvent: missed timeout event"); + this._resume(); + } + }, + getInt64(sp + 8), + )); + this.mem.setInt32(sp + 16, id, true); + }, + + // func clearTimeoutEvent(id int32) + "runtime.clearTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this.mem.getInt32(sp + 8, true); + clearTimeout(this._scheduledTimeouts.get(id)); + this._scheduledTimeouts.delete(id); + }, + + // func getRandomData(r []byte) + "runtime.getRandomData": (sp) => { + sp >>>= 0; + crypto.getRandomValues(loadSlice(sp + 8)); + }, + + // func finalizeRef(v ref) + "syscall/js.finalizeRef": (sp) => { + sp >>>= 0; + const id = this.mem.getUint32(sp + 8, true); + this._goRefCounts[id]--; + if (this._goRefCounts[id] === 0) { + const v = this._values[id]; + this._values[id] = null; + this._ids.delete(v); + this._idPool.push(id); + } + }, + + // func stringVal(value string) ref + "syscall/js.stringVal": (sp) => { + sp >>>= 0; + storeValue(sp + 24, loadString(sp + 8)); + }, + + // func valueGet(v ref, p string) ref + "syscall/js.valueGet": (sp) => { + sp >>>= 0; + const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 32, result); + }, + + // func valueSet(v ref, p string, x ref) + "syscall/js.valueSet": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); + }, + + // func valueDelete(v ref, p string) + "syscall/js.valueDelete": (sp) => { + sp >>>= 0; + Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); + }, + + // func valueIndex(v ref, i int) ref + "syscall/js.valueIndex": (sp) => { + sp >>>= 0; + storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); + }, + + // valueSetIndex(v ref, i int, x ref) + "syscall/js.valueSetIndex": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); + }, + + // func valueCall(v ref, m string, args []ref) (ref, bool) + "syscall/js.valueCall": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const m = Reflect.get(v, loadString(sp + 16)); + const args = loadSliceOfValues(sp + 32); + const result = Reflect.apply(m, v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, result); + this.mem.setUint8(sp + 64, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, err); + this.mem.setUint8(sp + 64, 0); + } + }, + + // func valueInvoke(v ref, args []ref) (ref, bool) + "syscall/js.valueInvoke": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.apply(v, undefined, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueNew(v ref, args []ref) (ref, bool) + "syscall/js.valueNew": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.construct(v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueLength(v ref) int + "syscall/js.valueLength": (sp) => { + sp >>>= 0; + setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); + }, + + // valuePrepareString(v ref) (ref, int) + "syscall/js.valuePrepareString": (sp) => { + sp >>>= 0; + const str = encoder.encode(String(loadValue(sp + 8))); + storeValue(sp + 16, str); + setInt64(sp + 24, str.length); + }, + + // valueLoadString(v ref, b []byte) + "syscall/js.valueLoadString": (sp) => { + sp >>>= 0; + const str = loadValue(sp + 8); + loadSlice(sp + 16).set(str); + }, + + // func valueInstanceOf(v ref, t ref) bool + "syscall/js.valueInstanceOf": (sp) => { + sp >>>= 0; + this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0); + }, + + // func copyBytesToGo(dst []byte, src ref) (int, bool) + "syscall/js.copyBytesToGo": (sp) => { + sp >>>= 0; + const dst = loadSlice(sp + 8); + const src = loadValue(sp + 32); + if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + // func copyBytesToJS(dst ref, src []byte) (int, bool) + "syscall/js.copyBytesToJS": (sp) => { + sp >>>= 0; + const dst = loadValue(sp + 8); + const src = loadSlice(sp + 16); + if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + "debug": (value) => { + console.log(value); + }, + } + }; + } + + async run(instance) { + if (!(instance instanceof WebAssembly.Instance)) { + throw new Error("Go.run: WebAssembly.Instance expected"); + } + this._inst = instance; + this.mem = new DataView(this._inst.exports.mem.buffer); + this._values = [ // JS values that Go currently has references to, indexed by reference id + NaN, + 0, + null, + true, + false, + globalThis, + this, + ]; + this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id + this._ids = new Map([ // mapping from JS values to reference ids + [0, 1], + [null, 2], + [true, 3], + [false, 4], + [globalThis, 5], + [this, 6], + ]); + this._idPool = []; // unused ids that have been garbage collected + this.exited = false; // whether the Go program has exited + + // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. + let offset = 4096; + + const strPtr = (str) => { + const ptr = offset; + const bytes = encoder.encode(str + "\0"); + new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); + offset += bytes.length; + if (offset % 8 !== 0) { + offset += 8 - (offset % 8); + } + return ptr; + }; + + const argc = this.argv.length; + + const argvPtrs = []; + this.argv.forEach((arg) => { + argvPtrs.push(strPtr(arg)); + }); + argvPtrs.push(0); + + const keys = Object.keys(this.env).sort(); + keys.forEach((key) => { + argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); + }); + argvPtrs.push(0); + + const argv = offset; + argvPtrs.forEach((ptr) => { + this.mem.setUint32(offset, ptr, true); + this.mem.setUint32(offset + 4, 0, true); + offset += 8; + }); + + // The linker guarantees global data starts from at least wasmMinDataAddr. + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. + const wasmMinDataAddr = 4096 + 8192; + if (offset >= wasmMinDataAddr) { + throw new Error("total length of command line and environment variables exceeds limit"); + } + + this._inst.exports.run(argc, argv); + if (this.exited) { + this._resolveExitPromise(); + } + await this._exitPromise; + } + + _resume() { + if (this.exited) { + throw new Error("Go program has already exited"); + } + this._inst.exports.resume(); + if (this.exited) { + this._resolveExitPromise(); + } + } + + _makeFuncWrapper(id) { + const go = this; + return function () { + const event = { id: id, this: this, args: arguments }; + go._pendingEvent = event; + go._resume(); + return event.result; + }; + } + } +})();