const STORAGE_KEY = "aurask.portal.session"; const TAB_KEY = "aurask.portal.activeTab"; const app = document.querySelector("#app"); const state = { config: null, sessionToken: window.localStorage.getItem(STORAGE_KEY) || "", profile: null, activeTab: window.localStorage.getItem(TAB_KEY) || "workflows", loading: true, error: "", }; function detectApiBase() { if (window.location.protocol === "file:") return "http://127.0.0.1:8080"; if (["127.0.0.1", "localhost"].includes(window.location.hostname)) return "http://127.0.0.1:8080"; return `${window.location.origin}/api`; } function normalizeApiBase(url) { return (url || detectApiBase()).replace(/\/$/, ""); } async function request(path, options = {}) { const headers = new Headers(options.headers || {}); headers.set("Accept", "application/json"); if (options.body !== undefined) headers.set("Content-Type", "application/json"); if (state.sessionToken) headers.set("Authorization", `Bearer ${state.sessionToken}`); const response = await fetch(`${normalizeApiBase(state.config?.public_api_base_url)}${path}`, { ...options, headers, body: options.body !== undefined ? JSON.stringify(options.body) : undefined, }); const payload = await response.json().catch(() => ({})); if (!response.ok) { const message = payload?.error?.message || payload?.message || "Request failed"; const error = new Error(message); error.status = response.status; error.payload = payload; throw error; } return payload; } function persistSession(token) { state.sessionToken = token || ""; if (state.sessionToken) { window.localStorage.setItem(STORAGE_KEY, state.sessionToken); } else { window.localStorage.removeItem(STORAGE_KEY); } } function setTab(tab) { state.activeTab = tab; window.localStorage.setItem(TAB_KEY, tab); render(); } function initials(label) { return (label || "AU") .split(/\s+/) .filter(Boolean) .slice(0, 2) .map((part) => part[0]?.toUpperCase()) .join(""); } function escapeHtml(value) { return String(value || "") .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function withEmbedContext(baseUrl) { if (!baseUrl) return ""; const url = new URL(baseUrl, window.location.origin); if (state.profile?.tenant?.id) url.searchParams.set("tenant_id", state.profile.tenant.id); if (state.profile?.workspace?.id) url.searchParams.set("workspace_id", state.profile.workspace.id); url.searchParams.set("source", "aurask-protal"); return url.toString(); } function ensureSigninRoute() { if (state.profile) return; if (window.location.pathname !== "/signin") { window.history.replaceState({}, "", "/signin"); } } function ensureDashboardRoute() { if (!state.profile) return; if (!window.location.pathname.startsWith("/app")) { window.history.replaceState({}, "", "/app"); } } async function bootstrap() { state.loading = true; render(); try { const activeApiBase = detectApiBase(); const localHost = window.location.protocol === "file:" || ["127.0.0.1", "localhost"].includes(window.location.hostname); state.config = await fetch(`${activeApiBase}/auth/config`).then((response) => response.json()); state.config.public_api_base_url = normalizeApiBase(localHost ? activeApiBase : state.config.public_api_base_url || activeApiBase); if (state.sessionToken) { try { state.profile = await request("/auth/session"); ensureDashboardRoute(); } catch (error) { persistSession(""); state.profile = null; } } if (!state.profile) ensureSigninRoute(); } catch (error) { state.error = error.message || "Failed to load Aurask configuration"; } finally { state.loading = false; render(); mountGoogleButton(); } } async function signInWithGoogle(idToken) { state.error = ""; render(); try { const payload = await request("/auth/google/login", { method: "POST", body: { id_token: idToken }, }); persistSession(payload.token); state.profile = payload; ensureDashboardRoute(); } catch (error) { state.error = error.message || "Google sign-in failed"; render(); } } async function logout() { try { await request("/auth/logout", { method: "POST" }); } catch (error) { console.warn("Logout request failed", error); } persistSession(""); state.profile = null; ensureSigninRoute(); render(); mountGoogleButton(); } function mountGoogleButton() { const googleBox = document.querySelector("#googleButton"); if (!googleBox || !state.config?.auth?.google?.enabled || !state.config?.auth?.google?.client_id) return; if (!window.google?.accounts?.id) return; googleBox.innerHTML = ""; window.google.accounts.id.initialize({ client_id: state.config.auth.google.client_id, callback: ({ credential }) => signInWithGoogle(credential), }); window.google.accounts.id.renderButton(googleBox, { theme: "outline", size: "large", shape: "pill", text: "signup_with", width: 320, }); } function renderStatusPills() { if (!state.config) return ""; return `
API: ${escapeHtml(state.config.public_api_base_url)} Web: ${escapeHtml(state.config.public_base_url)} DevCloud API Image Ready
`; } function renderSignin() { const googleConfig = state.config?.auth?.google || {}; const googleEnabled = Boolean(googleConfig.enabled && googleConfig.client_id); app.innerHTML = `
A

Aurask

Ship AI workflows with private knowledge, safer by default.

Sign in to open your personal workspace, manage Langflow workflows, and use AnythingLLM knowledge bases from one portal.

${renderStatusPills()}
${googleEnabled ? '
' : ''} ${ googleEnabled ? '' : '' } ${state.error ? `

${escapeHtml(state.error)}

` : ""}
`; } function renderDashboard() { const user = state.profile?.user || {}; const tenant = state.profile?.tenant || {}; const workspace = state.profile?.workspace || {}; const quota = state.profile?.quota || {}; const config = state.profile?.config || state.config || {}; const langflowUrl = withEmbedContext(config.embeds?.langflow_url); const anythingllmUrl = withEmbedContext(config.embeds?.anythingllm_url); app.innerHTML = `
A

Aurask Workspace

${escapeHtml(tenant.name || "Aurask")}

${user.avatar_url ? `${escapeHtml(user.display_name || user.email)}` : `${escapeHtml(initials(user.display_name || user.email))}`} ${escapeHtml(user.display_name || user.email || "Profile")}
${escapeHtml(user.display_name || user.email || "")} ${escapeHtml(user.email || "")}
Tenant ${escapeHtml(tenant.name || "")}
Workspace ${escapeHtml(workspace.name || "")}
Plan ${escapeHtml(quota.plan_code || "")} TBU ${escapeHtml(String(quota.available_tbu ?? 0))} Knowledge Bases ${escapeHtml(String(quota.knowledge_bases ?? 0))}

Workflow Studio

Langflow

Open in new tab

Knowledge Base

AnythingLLM

Open in new tab
${state.error ? `
${escapeHtml(state.error)}
` : ""}
`; document.querySelectorAll("[data-tab]").forEach((button) => { button.addEventListener("click", () => setTab(button.dataset.tab)); }); document.querySelector("#logoutButton")?.addEventListener("click", logout); } function renderLoading() { app.innerHTML = `

Loading Aurask...

`; } function render() { if (state.loading) { renderLoading(); return; } if (state.profile) { renderDashboard(); return; } renderSignin(); } window.addEventListener("popstate", render); if (state.sessionToken) { document.addEventListener("visibilitychange", async () => { if (document.visibilityState !== "visible" || !state.profile) return; try { state.profile = await request("/auth/session"); render(); } catch (error) { persistSession(""); state.profile = null; state.error = "Your Aurask session has expired. Please sign in again."; ensureSigninRoute(); render(); mountGoogleButton(); } }); } const googleScript = document.createElement("script"); googleScript.src = "https://accounts.google.com/gsi/client"; googleScript.async = true; googleScript.defer = true; googleScript.onload = mountGoogleButton; document.head.appendChild(googleScript); bootstrap();