loki-mode 9.55.0 → 9.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/actions/issue-to-pr/action.yml +165 -29
- package/.github/workflows/loki-issue-to-pr.yml +137 -24
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/proof-check.sh +9 -0
- package/autonomy/lib/proof-generator.py +12 -3
- package/autonomy/lib/workspace_diff.py +18 -7
- package/autonomy/loki +133 -3
- package/autonomy/run.sh +385 -22
- package/dashboard/__init__.py +1 -1
- package/dashboard/api_keys.py +12 -5
- package/dashboard/build_supervisor.py +25 -1
- package/dashboard/server.py +46 -24
- package/dashboard/static/index.html +57 -57
- package/docs/VERIFIED-COMPLETION-PLAN.md +7 -5
- package/docs/dev/architecture-reference.md +99 -0
- package/docs/dev/project-structure.md +134 -0
- package/docs/dev/release-checklist.md +157 -0
- package/docs/dev/research-foundation.md +29 -0
- package/docs/dev/tmp-cleanup.md +157 -0
- package/docs/environment-variables.md +1 -0
- package/docs/v10/BACKLOG.md +33 -0
- package/docs/v10/BOARD.md +97 -27
- package/docs/v10/DECISIONS.md +43 -0
- package/docs/v10/OPERATING-MODEL.md +47 -0
- package/docs/v10/PROGRESS.md +893 -0
- package/loki-ts/dist/loki.js +326 -325
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/claude.sh +1 -1
- package/providers/model_catalog.json +12 -5
- package/providers/models.sh +1 -1
- package/references/core-workflow.md +1 -1
- package/web-app/dist/assets/{AdminPage-CZrBkzRF.js → AdminPage-Oyx-w2Ch.js} +1 -1
- package/web-app/dist/assets/{Avatar-gQIp6FBI.js → Avatar-D60m65JB.js} +1 -1
- package/web-app/dist/assets/{Badge-D2_fBTFY.js → Badge-CqfZNaem.js} +1 -1
- package/web-app/dist/assets/{Button-D5qDd2ef.js → Button-BqjzE4fz.js} +1 -1
- package/web-app/dist/assets/CockpitPage-Czk7o_ou.js +47 -0
- package/web-app/dist/assets/ComparePage-BEfTrTb1.js +1 -0
- package/web-app/dist/assets/{ErrorBoundary-BRABI-BT.js → ErrorBoundary-BrLk5nkO.js} +1 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-9vEpi5ir.js +1 -0
- package/web-app/dist/assets/{GitHubIssuesPanel-BC5GzKUN.js → GitHubIssuesPanel-D6izZx0w.js} +1 -1
- package/web-app/dist/assets/GitHubPRsPanel-BTkG2FgA.js +17 -0
- package/web-app/dist/assets/{HomePage-D_CDMoen.js → HomePage-nsr4kpN1.js} +2 -2
- package/web-app/dist/assets/{LoginPage-BBNA_N9t.js → LoginPage-BVblQrr9.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CnFRZCMx.js → MagicPage-CmnSyLq7.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CPfLMRlh.js → MetricsPage-BVfwU81j.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-lA0XSGTz.js → NotFoundPage-AYQ6uqqI.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CNAPbr9z.js → ProjectPage-DMnbw9X9.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-CMtm8goN.js → ProjectsPage-CNVTAF2N.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-BhIjVMYE.js → SettingsPage-D1_qasFD.js} +3 -3
- package/web-app/dist/assets/{ShowcasePage-BndtGeYo.js → ShowcasePage-2dBCjLXn.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-euXI-KXE.js → SystemSettingsPage-Djo6IE4u.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-ClUKecun.js → TeamsPage-CY8p-yxD.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-BWHWVk0L.js → TemplatesPage-B6iFgH6t.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-Cv3N3Szf.js → TerminalOutput-B3yzZe-h.js} +1 -1
- package/web-app/dist/assets/{activity-dEhz-bXR.js → activity-CNfAjtRv.js} +1 -1
- package/web-app/dist/assets/{bell-B3XUMq1t.js → bell-CMETsHPH.js} +1 -1
- package/web-app/dist/assets/{bot-X-ssNlwR.js → bot-C9kXvk1i.js} +1 -1
- package/web-app/dist/assets/{check-C_9Nx7kb.js → check-BRK-zLB5.js} +1 -1
- package/web-app/dist/assets/{chevron-left-tvNswo3A.js → chevron-left-CxI5uD4g.js} +1 -1
- package/web-app/dist/assets/{circle-alert-CSB88nEs.js → circle-alert-CVFRPWpv.js} +1 -1
- package/web-app/dist/assets/{clock-C8p2e4NI.js → clock-CLYV8a_x.js} +1 -1
- package/web-app/dist/assets/{cloud-CKp2ZvhG.js → cloud-CiISiIOa.js} +1 -1
- package/web-app/dist/assets/{code-xml-dY70LCHD.js → code-xml-DHsgqwV-.js} +1 -1
- package/web-app/dist/assets/{database-DObn5fmn.js → database-DbvUqtz3.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DSu6n3K3.js → dollar-sign-Ct0lRPHw.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DpCnS73z.js → file-code-corner-D1sjFEh7.js} +1 -1
- package/web-app/dist/assets/{file-plus-D3IPKCf1.js → file-plus-DnmX18Fi.js} +1 -1
- package/web-app/dist/assets/{globe-C9QXkgH_.js → globe-bSpDNgoA.js} +1 -1
- package/web-app/dist/assets/{hammer-D_FtWe1y.js → hammer-Bj41Kvlq.js} +1 -1
- package/web-app/dist/assets/{index-CI54rara.css → index-BfQ0f3-S.css} +1 -1
- package/web-app/dist/assets/{index-Cz7q1bvC.js → index-CxajNJVu.js} +3 -3
- package/web-app/dist/assets/{layers-DsW7jnJX.js → layers-BNtBwYER.js} +1 -1
- package/web-app/dist/assets/{loader-circle-B3HspjKR.js → loader-circle-YY_VZofG.js} +1 -1
- package/web-app/dist/assets/{lock-DSI29pct.js → lock-rpjEPVoC.js} +1 -1
- package/web-app/dist/assets/{package-CLNxtA2x.js → package-desXU6XA.js} +1 -1
- package/web-app/dist/assets/{plus-DyI4WC4_.js → plus-7AoOU-I9.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-D2dv0xA0.js → refresh-cw-oNj-Xn4B.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-CBvihA-a.js → rotate-ccw-DeiFjfVO.js} +1 -1
- package/web-app/dist/assets/{scroll-text-DvoOvAl_.js → scroll-text-Q9AzWiNV.js} +1 -1
- package/web-app/dist/assets/{server-DenWvSUt.js → server-DKgVwfek.js} +1 -1
- package/web-app/dist/assets/{shield-alert-40cX_FvG.js → shield-alert-G6x-bS-I.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-BrjZ6QuV.js → thumbs-up-Qhk0yvw0.js} +1 -1
- package/web-app/dist/assets/{trash-2-C6evwkEH.js → trash-2-D23gvznl.js} +1 -1
- package/web-app/dist/assets/{trending-down-CfbZis3O.js → trending-down-CSQClPrr.js} +1 -1
- package/web-app/dist/assets/{trending-up-DWuEK3WC.js → trending-up-sjMSd1wc.js} +1 -1
- package/web-app/dist/assets/{upload-B9DFBcPG.js → upload-Dchovhld.js} +1 -1
- package/web-app/dist/assets/{usePolling-BryVC-T1.js → usePolling-DwLceXwF.js} +1 -1
- package/web-app/dist/assets/{user-DMRXwZiw.js → user-BqZM8CmD.js} +1 -1
- package/web-app/dist/index.html +2 -2
- package/web-app/server.py +52 -17
- package/web-app/dist/assets/CockpitPage-DVMk2RUK.js +0 -47
- package/web-app/dist/assets/ComparePage-NMLyE1xL.js +0 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-D2LNKqUx.js +0 -1
- package/web-app/dist/assets/GitHubPRsPanel-BSlmoVTS.js +0 -17
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/HomePage-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/HomePage-nsr4kpN1.js","assets/usePolling-DwLceXwF.js","assets/ErrorBoundary-BrLk5nkO.js","assets/TerminalOutput-B3yzZe-h.js","assets/lock-rpjEPVoC.js","assets/EvidenceReceiptPanel-9vEpi5ir.js","assets/Badge-CqfZNaem.js","assets/clock-CLYV8a_x.js","assets/circle-alert-CVFRPWpv.js","assets/check-BRK-zLB5.js","assets/package-desXU6XA.js","assets/cloud-CiISiIOa.js","assets/code-xml-DHsgqwV-.js","assets/hammer-Bj41Kvlq.js","assets/layers-BNtBwYER.js","assets/bell-CMETsHPH.js","assets/file-code-corner-D1sjFEh7.js","assets/ProjectPage-DMnbw9X9.js","assets/Button-BqjzE4fz.js","assets/file-plus-DnmX18Fi.js","assets/activity-CNfAjtRv.js","assets/scroll-text-Q9AzWiNV.js","assets/bot-C9kXvk1i.js","assets/loader-circle-YY_VZofG.js","assets/dollar-sign-Ct0lRPHw.js","assets/refresh-cw-oNj-Xn4B.js","assets/globe-bSpDNgoA.js","assets/trash-2-D23gvznl.js","assets/thumbs-up-Qhk0yvw0.js","assets/upload-Dchovhld.js","assets/plus-7AoOU-I9.js","assets/rotate-ccw-DeiFjfVO.js","assets/trending-up-sjMSd1wc.js","assets/trending-down-CSQClPrr.js","assets/server-DKgVwfek.js","assets/ProjectPage-9CEnUXvW.css","assets/CockpitPage-Czk7o_ou.js","assets/ProjectsPage-CNVTAF2N.js","assets/TemplatesPage-B6iFgH6t.js","assets/chevron-left-CxI5uD4g.js","assets/database-DbvUqtz3.js","assets/SettingsPage-D1_qasFD.js","assets/TeamsPage-CY8p-yxD.js","assets/Avatar-D60m65JB.js","assets/user-BqZM8CmD.js","assets/AdminPage-Oyx-w2Ch.js","assets/shield-alert-G6x-bS-I.js","assets/SystemSettingsPage-Djo6IE4u.js","assets/MetricsPage-BVfwU81j.js","assets/MagicPage-CmnSyLq7.js"])))=>i.map(i=>d[i]);
|
|
2
2
|
var P0=Object.defineProperty;var ep=(i,c,r)=>c in i?P0(i,c,{enumerable:!0,configurable:!0,writable:!0,value:r}):i[c]=r;var Ln=(i,c,r)=>ep(i,typeof c!="symbol"?c+"":c,r);(function(){const c=document.createElement("link").relList;if(c&&c.supports&&c.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))o(d);new MutationObserver(d=>{for(const m of d)if(m.type==="childList")for(const p of m.addedNodes)p.tagName==="LINK"&&p.rel==="modulepreload"&&o(p)}).observe(document,{childList:!0,subtree:!0});function r(d){const m={};return d.integrity&&(m.integrity=d.integrity),d.referrerPolicy&&(m.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?m.credentials="include":d.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function o(d){if(d.ep)return;d.ep=!0;const m=r(d);fetch(d.href,m)}})();function tp(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var Ls={exports:{}},Bn={};/**
|
|
3
3
|
* @license React
|
|
4
4
|
* react-jsx-runtime.production.js
|
|
@@ -353,7 +353,7 @@ Please change the parent <Route path="${q}"> to <Route path="${q==="/"?"*":`${q}
|
|
|
353
353
|
*
|
|
354
354
|
* This source code is licensed under the ISC license.
|
|
355
355
|
* See the LICENSE file in the root directory of this source tree.
|
|
356
|
-
*/const jg=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],Rg=W("zap",jg),ho="/lab/".replace(/\/$/,""),hi=`${window.location.origin}${ho}/api`,Ag=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}${ho}/ws`,k2=ho;function Sm(){const i={"Content-Type":"application/json"};try{const c=localStorage.getItem("pl_auth_token");c&&(i.Authorization=`Bearer ${c}`)}catch{}return i}async function k(i,c){const r=await fetch(`${hi}${i}`,{...c,headers:{...Sm(),...c==null?void 0:c.headers}});if(!r.ok){const d=await r.text().catch(()=>"");throw new Error(`API error ${r.status}: ${r.statusText}${d?` - ${d}`:""}`)}if(!(r.headers.get("content-type")||"").includes("application/json"))throw new Error("API endpoint not available. Please restart the server with the latest version.");return r.json()}const Ba={listProofs:()=>k("/proofs"),proofsSummary:()=>k("/proofs/summary"),getProof:i=>k(`/proofs/${encodeURIComponent(i)}`),startSession:i=>k("/session/start",{method:"POST",body:JSON.stringify(i)}),quickStart:(i,c="claude")=>k("/session/quick-start",{method:"POST",body:JSON.stringify({prompt:i,provider:c})}),stopSession:()=>k("/session/stop",{method:"POST"}),pauseSession:()=>k("/session/pause",{method:"POST"}),resumeSession:()=>k("/session/resume",{method:"POST"}),getPrdPrefill:()=>k("/session/prd-prefill"),getStatus:()=>k("/session/status"),getAgents:()=>k("/session/agents"),getLogs:(i=200)=>k(`/session/logs?lines=${i}`),getMemorySummary:()=>k("/session/memory"),getChecklist:()=>k("/session/checklist"),getFiles:()=>k("/session/files"),getFileContent:i=>k(`/session/files/content?path=${encodeURIComponent(i)}`),getSessionFileContent:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/file?path=${encodeURIComponent(c)}`),getTemplates:()=>k("/templates"),getTemplateContent:i=>k(`/templates/${encodeURIComponent(i)}`),planSession:(i,c)=>k("/session/plan",{method:"POST",body:JSON.stringify({prd:i,provider:c})}),generateReport:(i="markdown")=>k("/session/report",{method:"POST",body:JSON.stringify({format:i})}),shareSession:()=>k("/session/share",{method:"POST"}),getCurrentProvider:()=>k("/provider/current"),setProvider:i=>k("/provider/set",{method:"POST",body:JSON.stringify({provider:i})}),getMetrics:()=>k("/session/metrics"),getSessionsHistory:()=>k("/sessions/history"),getSessionDetail:i=>k(`/sessions/${encodeURIComponent(i)}`),deleteSession:i=>k(`/sessions/${encodeURIComponent(i)}`,{method:"DELETE"}),onboardRepo:i=>k("/session/onboard",{method:"POST",body:JSON.stringify({path:i})}),saveSessionFile:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/file`,{method:"PUT",body:JSON.stringify({path:c,content:r})}),createSessionFile:(i,c,r="")=>k(`/sessions/${encodeURIComponent(i)}/file`,{method:"POST",body:JSON.stringify({path:c,content:r})}),deleteSessionFile:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/file`,{method:"DELETE",body:JSON.stringify({path:c})}),createSessionDirectory:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/directory`,{method:"POST",body:JSON.stringify({path:c})}),reviewProject:i=>k(`/sessions/${encodeURIComponent(i)}/review`,{method:"POST"}),testProject:i=>k(`/sessions/${encodeURIComponent(i)}/test`,{method:"POST"}),explainProject:i=>k(`/sessions/${encodeURIComponent(i)}/explain`,{method:"POST"}),exportProject:i=>k(`/sessions/${encodeURIComponent(i)}/export`,{method:"POST"}),fixProject:i=>k(`/sessions/${encodeURIComponent(i)}/fix`,{method:"POST"}),chatMessage:(i,c,r="quick")=>k(`/sessions/${encodeURIComponent(i)}/chat`,{method:"POST",body:JSON.stringify({message:c,mode:r})}),chatStart:(i,c,r="quick",o)=>k(`/sessions/${encodeURIComponent(i)}/chat`,{method:"POST",body:JSON.stringify({message:c,mode:r,history:o})}),chatPoll:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/chat/${encodeURIComponent(c)}`),chatStreamUrl:(i,c)=>`${hi}/sessions/${encodeURIComponent(i)}/chat/${encodeURIComponent(c)}/stream`,chatCancel:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/chat/${encodeURIComponent(c)}/cancel`,{method:"POST"}),getPreviewInfo:i=>k(`/sessions/${encodeURIComponent(i)}/preview-info`),devserver:{start:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/devserver/start`,{method:"POST",body:JSON.stringify({command:c||null})}),stop:i=>k(`/sessions/${encodeURIComponent(i)}/devserver/stop`,{method:"POST"}),status:i=>k(`/sessions/${encodeURIComponent(i)}/devserver/status`)},getSecrets:()=>k("/secrets"),setSecret:(i,c)=>k("/secrets",{method:"POST",body:JSON.stringify({key:i,value:c})}),deleteSecret:i=>k(`/secrets/${encodeURIComponent(i)}`,{method:"DELETE"}),getServices:i=>k(`/sessions/${encodeURIComponent(i)}/services`),getTeams:()=>k("/teams"),createTeam:i=>k("/teams",{method:"POST",body:JSON.stringify({name:i})}),getTeamMembers:i=>k(`/teams/${encodeURIComponent(i)}/members`),addTeamMember:(i,c,r)=>k(`/teams/${encodeURIComponent(i)}/members`,{method:"POST",body:JSON.stringify({email:c,role:r})}),getCost:()=>k("/cost"),getCostTimeline:()=>k("/cost/timeline"),getAuditLog:()=>k("/audit-log"),getServiceLogs:(i,c,r=50)=>k(`/sessions/${encodeURIComponent(i)}/devserver/logs?${new URLSearchParams({...c?{service:c}:{},tail:String(r)}).toString()}`),getCheckpoints:i=>k(`/sessions/${encodeURIComponent(i)}/checkpoints`),restoreCheckpoint:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/checkpoints/${encodeURIComponent(c)}/restore`,{method:"POST"}),previewChanges:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/chat/preview`,{method:"POST",body:JSON.stringify({message:c})}),searchFiles:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/files/search?q=${encodeURIComponent(c)}`),restartService:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/devserver/restart-service`,{method:"POST",body:JSON.stringify({service:c})}),deployProject:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/deploy`,{method:"POST",body:JSON.stringify({platform:c})}),githubPush:i=>k(`/sessions/${encodeURIComponent(i)}/github/push`,{method:"POST"}),getGitHubIssues:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/issues?${new URLSearchParams({...c?{state:c}:{},...r?{limit:String(r)}:{}}).toString()}`),getGitHubIssue:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/issues/${c}`),fixGitHubIssue:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/issues/${c}/fix`,{method:"POST"}),getGitHubPRs:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/prs?${new URLSearchParams({...c?{state:c}:{},...r?{limit:String(r)}:{}}).toString()}`),getGitHubPR:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}`),getGitHubPRDiff:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}/diff`),reviewGitHubPR:(i,c,r,o)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}/review`,{method:"POST",body:JSON.stringify({action:r,body:o})}),mergeGitHubPR:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}/merge`,{method:"POST",body:JSON.stringify({method:r})}),getWorkflowRuns:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs?${new URLSearchParams({...c?{limit:String(c)}:{}}).toString()}`),getWorkflowRunDetail:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}`),getWorkflowRunLogs:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}/logs`),getWorkflows:i=>k(`/sessions/${encodeURIComponent(i)}/github/actions/workflows`),dispatchWorkflow:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/dispatch`,{method:"POST",body:JSON.stringify({workflow:c,ref:r})}),rerunWorkflow:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}/rerun`,{method:"POST"}),cancelWorkflow:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}/cancel`,{method:"POST"}),importGitHubRepo:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/import`,{method:"POST",body:JSON.stringify({repo:c,...r?{branch:r}:{}})}),getDeployStatus:()=>k("/deploy/status"),connectVercel:i=>k("/deploy/vercel/token",{method:"POST",body:JSON.stringify({token:i})}),connectNetlify:i=>k("/deploy/netlify/token",{method:"POST",body:JSON.stringify({token:i})}),disconnectPlatform:i=>k(`/deploy/${encodeURIComponent(i)}/disconnect`,{method:"POST"}),getMe:()=>k("/auth/me"),getGitHubAuthUrl:()=>k("/auth/github/url"),getGoogleAuthUrl:()=>k("/auth/google/url"),githubCallback:(i,c)=>k("/auth/github/callback",{method:"POST",body:JSON.stringify({code:i,state:c})}),googleCallback:(i,c,r)=>k("/auth/google/callback",{method:"POST",body:JSON.stringify({code:i,state:c,redirect_uri:r||`${window.location.origin}${window.location.pathname}`})}),git:{status:i=>k(`/sessions/${encodeURIComponent(i)}/git/status`),log:(i,c=20)=>k(`/sessions/${encodeURIComponent(i)}/git/log?limit=${c}`),branches:i=>k(`/sessions/${encodeURIComponent(i)}/git/branches`),commit:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/git/commit`,{method:"POST",body:JSON.stringify({message:c,files:r})}),createBranch:(i,c,r=!0)=>k(`/sessions/${encodeURIComponent(i)}/git/branch`,{method:"POST",body:JSON.stringify({name:c,checkout:r})}),checkoutBranch:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/git/checkout`,{method:"POST",body:JSON.stringify({name:c})}),push:i=>k(`/sessions/${encodeURIComponent(i)}/git/push`,{method:"POST"}),pr:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/git/pr`,{method:"POST",body:JSON.stringify({title:c,body:r})})},generateDocs:i=>k(`/sessions/${encodeURIComponent(i)}/docs/generate`,{method:"POST"}),getDocsStatus:i=>k(`/sessions/${encodeURIComponent(i)}/docs/status`),getDocFiles:i=>k(`/sessions/${encodeURIComponent(i)}/docs/files`),getDocFileContent:async(i,c)=>{const r=await fetch(`${hi}/sessions/${encodeURIComponent(i)}/docs/files/${encodeURIComponent(c)}`,{headers:Sm()});if(!r.ok)throw new Error(`API error ${r.status}: ${r.statusText}`);return r.text()},chatImageUpload:async(i,c)=>{const r=new FormData;r.append("image",c);const o=await fetch(`${hi}/sessions/${encodeURIComponent(i)}/chat/image`,{method:"POST",headers:{...(()=>{const d={};try{const m=localStorage.getItem("pl_auth_token");m&&(d.Authorization=`Bearer ${m}`)}catch{}return d})()},body:r});if(!o.ok){const d=await o.text().catch(()=>"");throw new Error(`API error ${o.status}: ${o.statusText}${d?` - ${d}`:""}`)}return o.json()}};class Og{constructor(c){Ln(this,"ws",null);Ln(this,"listeners",new Map);Ln(this,"reconnectTimer",null);Ln(this,"url");this.url=c||Ag}connect(){var c;((c=this.ws)==null?void 0:c.readyState)!==WebSocket.OPEN&&(this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.emit("connected",{message:"WebSocket connected"})},this.ws.onmessage=r=>{try{const o=JSON.parse(r.data);if(o.type==="ping"){this.send({type:"pong"});return}this.emit(o.type,o.data||o)}catch{}},this.ws.onclose=()=>{this.emit("disconnected",{}),this.scheduleReconnect()},this.ws.onerror=()=>{var r;(r=this.ws)==null||r.close()})}scheduleReconnect(){this.reconnectTimer||(this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},3e3))}on(c,r){return this.listeners.has(c)||this.listeners.set(c,new Set),this.listeners.get(c).add(r),()=>{var o;return(o=this.listeners.get(c))==null?void 0:o.delete(r)}}emit(c,r){var o,d;(o=this.listeners.get(c))==null||o.forEach(m=>m(r)),(d=this.listeners.get("*"))==null||d.forEach(m=>m({type:c,data:r}))}send(c){var r;((r=this.ws)==null?void 0:r.readyState)===WebSocket.OPEN&&this.ws.send(JSON.stringify(c))}disconnect(){var c;this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),(c=this.ws)==null||c.close(),this.ws=null}}const Js="pl_auth_token",Em=v.createContext({user:null,loading:!0,login:()=>{},logout:()=>{},isLocalMode:!0});function Mg(i,c,r){c(!1),r({email:i.sub||i.email||"",name:i.name||"",avatar_url:i.avatar||"",authenticated:!0})}function Dg({children:i}){const[c,r]=v.useState(null),[o,d]=v.useState(!0),[m,p]=v.useState(!0),E=ao(),x=kt();v.useEffect(()=>{let H=!1;async function L(){const B=new URLSearchParams(window.location.search),U=B.get("token"),Q=B.get("code");if(U)localStorage.setItem(Js,U),window.history.replaceState({},"",window.location.pathname);else if(Q)try{const q=sessionStorage.getItem("pl_oauth_provider")||"github",I=sessionStorage.getItem("pl_oauth_state")||"";sessionStorage.removeItem("pl_oauth_state"),sessionStorage.removeItem("pl_oauth_provider");let J;if(q==="google"?J=await Ba.googleCallback(Q,I):J=await Ba.githubCallback(Q,I),!H){localStorage.setItem(Js,J.token),window.history.replaceState({},"",window.location.pathname),p(!1),r({email:J.user.email,name:J.user.name,avatar_url:J.user.avatar_url,authenticated:!0}),d(!1);return}}catch{window.history.replaceState({},"",window.location.pathname)}try{const q=await Ba.getMe();if(H)return;q.local_mode?(p(!0),r(null)):q.authenticated?Mg(q,p,r):(p(!1),r(null))}catch{if(H)return;p(!0),r(null)}finally{H||d(!1)}}return L(),()=>{H=!0}},[]);const y=v.useCallback(H=>{H==="github"?Ba.getGitHubAuthUrl().then(L=>{try{const U=new URL(L.url).searchParams.get("state");U&&(sessionStorage.setItem("pl_oauth_state",U),sessionStorage.setItem("pl_oauth_provider","github"))}catch{}window.location.href=L.url}).catch(()=>{}):H==="google"&&Ba.getGoogleAuthUrl().then(L=>{try{const U=new URL(L.url).searchParams.get("state");U&&(sessionStorage.setItem("pl_oauth_state",U),sessionStorage.setItem("pl_oauth_provider","google"))}catch{}window.location.href=L.url}).catch(()=>{})},[]),z=v.useCallback(()=>{localStorage.removeItem(Js),r(null),x.pathname!=="/login"&&E("/login",{replace:!0})},[E,x.pathname]),_=v.useMemo(()=>({user:c,loading:o,login:y,logout:z,isLocalMode:m}),[c,o,y,z,m]);return h.jsx(Em.Provider,{value:_,children:i})}function _m(){return v.useContext(Em)}function Ug(){const[i,c]=v.useState(()=>typeof window>"u"?"light":localStorage.getItem("pl_theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"));v.useEffect(()=>{document.documentElement.classList.toggle("dark",i==="dark"),localStorage.setItem("pl_theme",i)},[i]);const r=v.useCallback(()=>{c(o=>o==="light"?"dark":"light")},[]);return{theme:i,toggleTheme:r,isDark:i==="dark"}}const Tm="pl_discovered_features";function zm(){try{const i=localStorage.getItem(Tm);if(i)return new Set(JSON.parse(i))}catch{}return new Set}function wg(i){try{localStorage.setItem(Tm,JSON.stringify([...i]))}catch{}}function Hg(i){const c=zm();c.has(i)||(c.add(i),wg(c),window.dispatchEvent(new CustomEvent("pl_feature_discovered",{detail:i})))}function kg({feature:i,className:c=""}){const[r,o]=v.useState(!0);return v.useEffect(()=>{o(zm().has(i))},[i]),v.useEffect(()=>{const d=m=>{m.detail===i&&o(!0)};return window.addEventListener("pl_feature_discovered",d),()=>window.removeEventListener("pl_feature_discovered",d)},[i]),r?null:h.jsxs("span",{className:`relative inline-flex ${c}`,"aria-hidden":"true",children:[h.jsx("span",{className:"absolute inline-flex h-2.5 w-2.5 rounded-full bg-primary/40 animate-ping"}),h.jsx("span",{className:"relative inline-flex h-2.5 w-2.5 rounded-full bg-primary"})]})}const Nm="pl_getting_started_steps",Hh="pl_getting_started_dismissed",kh="pl_getting_started_collapsed",Lh=[{id:"create_project",label:"Create your first project",description:"Describe what you want to build or pick a template to get started.",icon:vm},{id:"try_chat",label:"Try the AI chat",description:"Ask the AI to modify, explain, or improve your code.",icon:oo},{id:"preview_app",label:"Preview your app",description:"Open the Preview tab to see your application running live.",icon:pm},{id:"explore_templates",label:"Explore templates",description:"Browse the template gallery for inspiration and quick starts.",icon:so},{id:"deploy_app",label:"Deploy your app",description:"Push your project live with one click using the Deploy tab.",icon:ro}];function Bh(){try{const i=localStorage.getItem(Nm);if(i)return new Set(JSON.parse(i))}catch{}return new Set}function Lg(i){try{localStorage.setItem(Nm,JSON.stringify([...i]))}catch{}}function Bg(){const[i,c]=v.useState(!1),[r,o]=v.useState(!1),[d,m]=v.useState(new Set);v.useEffect(()=>{try{if(localStorage.getItem(Hh)==="1"){c(!0);return}o(localStorage.getItem(kh)==="1")}catch{}m(Bh())},[]),v.useEffect(()=>{const L=()=>m(Bh());return window.addEventListener("pl_step_complete",L),()=>window.removeEventListener("pl_step_complete",L)},[]);const p=v.useCallback(L=>{m(B=>{const U=new Set(B);return U.has(L)?U.delete(L):U.add(L),Lg(U),U})},[]),E=()=>{c(!0);try{localStorage.setItem(Hh,"1")}catch{}},x=()=>{o(L=>{const B=!L;try{localStorage.setItem(kh,B?"1":"0")}catch{}return B})};if(i)return null;const y=d.size,z=Lh.length,_=y/z*100,H=y===z;return h.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-sm overflow-hidden",children:[h.jsxs("button",{onClick:x,className:"w-full flex items-center gap-3 px-4 py-3 text-left hover:bg-hover transition-colors",children:[h.jsx(kv,{size:16,className:"text-primary flex-shrink-0"}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsxs("div",{className:"flex items-center gap-2",children:[h.jsx("span",{className:"text-sm font-heading font-bold text-ink",children:"Getting Started"}),h.jsxs("span",{className:"text-[11px] text-muted-accessible font-mono",children:[y,"/",z]})]}),h.jsx("div",{className:"h-1 bg-border rounded-full mt-1.5 overflow-hidden",children:h.jsx("div",{className:"h-full bg-primary rounded-full transition-all duration-500",style:{width:`${_}%`}})})]}),h.jsx("div",{className:"flex items-center gap-1",children:r?h.jsx(nv,{size:14,className:"text-muted"}):h.jsx(mm,{size:14,className:"text-muted"})})]}),!r&&h.jsxs("div",{className:"border-t border-border",children:[h.jsx("div",{className:"px-3 py-2 space-y-0.5",children:Lh.map(L=>{const B=d.has(L.id),U=L.icon;return h.jsxs("button",{onClick:()=>p(L.id),className:`w-full flex items-start gap-3 px-3 py-2.5 rounded-lg text-left transition-colors ${B?"opacity-60 hover:opacity-80":"hover:bg-hover"}`,children:[h.jsx("div",{className:"mt-0.5 flex-shrink-0",children:B?h.jsx(rv,{size:16,className:"text-success"}):h.jsx(yv,{size:16,className:"text-border"})}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsx("span",{className:`text-xs font-medium ${B?"text-muted line-through":"text-ink"}`,children:L.label}),!B&&h.jsx("p",{className:"text-[11px] text-muted-accessible mt-0.5 leading-relaxed",children:L.description})]}),h.jsx(U,{size:14,className:`flex-shrink-0 mt-0.5 ${B?"text-muted":"text-primary/50"}`})]},L.id)})}),h.jsxs("div",{className:"flex items-center justify-between px-4 py-2.5 border-t border-border",children:[H?h.jsx("span",{className:"text-xs text-success font-medium",children:"All done -- you are ready to build!"}):h.jsx("span",{className:"text-[11px] text-muted",children:"Complete each step to learn the basics."}),h.jsxs("button",{onClick:E,className:"flex items-center gap-1 text-[11px] text-muted hover:text-ink transition-colors",children:[h.jsx(ea,{size:11}),"Dismiss"]})]})]})]})}const qh="pl_sidebar_collapsed",qg=[{to:"/",label:"Home",icon:Ov},{to:"/projects",label:"Projects",icon:_v},{to:"/templates",label:"Templates",icon:so,discoveryFeature:"templates"},{to:"/showcase",label:"Showcase",icon:fo},{to:"/magic",label:"Magic",icon:Tg},{to:"/metrics",label:"Metrics",icon:lv},{to:"/compare",label:"Compare",icon:Rv},{to:"/teams",label:"Teams",icon:xg}],Yg=[{to:"/settings",label:"Settings",icon:xm},{to:"/admin",label:"Admin",icon:ug},{to:"/admin/settings",label:"System",icon:Ng}];function Gg(){const[i,c]=v.useState(typeof window<"u"?window.innerWidth<768:!1);return v.useEffect(()=>{const r=()=>c(window.innerWidth<768);return window.addEventListener("resize",r),()=>window.removeEventListener("resize",r)},[]),i}function Qg({wsConnected:i,version:c,onOpenDocs:r}){const o=Gg(),d=kt(),{theme:m,toggleTheme:p}=Ug(),[E,x]=v.useState(!1),[y,z]=v.useState(()=>{try{return localStorage.getItem(qh)==="1"}catch{return!1}});v.useEffect(()=>{try{localStorage.setItem(qh,y?"1":"0")}catch{}},[y]),v.useEffect(()=>{o&&x(!1)},[d.pathname,o]);const _=o?E:!y,H=_?240:64,L=U=>["flex items-center gap-3 px-3 py-2 text-sm transition-colors rounded-[5px]",!_&&"justify-center",U?"bg-[#553DE9]/8 text-[#553DE9] font-medium border-l-2 border-[#553DE9]":"text-[#36342E] hover:bg-[#F8F4F0]"].filter(Boolean).join(" "),B=h.jsxs("aside",{className:"flex flex-col h-full border-r border-[#ECEAE3] bg-white transition-[width] duration-200",style:{width:H,minWidth:H},children:[h.jsxs("div",{className:"flex items-center justify-between px-4 h-14 border-b border-[#ECEAE3]",children:[_&&h.jsxs("div",{className:"flex flex-col",children:[h.jsx("span",{className:"font-heading text-lg font-bold leading-tight text-[#36342E]",children:"Purple Lab"}),h.jsx("span",{className:"text-xs text-[#6B6960]",children:"Powered by Loki"})]}),o?h.jsx("button",{type:"button","aria-label":E?"Close menu":"Open menu",title:E?"Close menu":"Open menu",onClick:()=>x(!E),className:"inline-flex items-center justify-center w-7 h-7 rounded-[3px] text-[#939084] hover:bg-[#F8F4F0] transition-colors",children:E?h.jsx(ea,{size:16}):h.jsx(Yv,{size:16})}):h.jsx("button",{type:"button","aria-label":y?"Expand sidebar":"Collapse sidebar",title:y?"Expand sidebar":"Collapse sidebar",onClick:()=>z(!y),className:"inline-flex items-center justify-center w-7 h-7 rounded-[3px] text-[#939084] hover:bg-[#F8F4F0] transition-colors",children:y?h.jsx(Iv,{size:16}):h.jsx(Wv,{size:16})})]}),h.jsxs("nav",{className:"flex-1 px-2 py-3 flex flex-col gap-1","aria-label":"Main navigation",children:[qg.map(U=>h.jsxs(yi,{to:U.to,end:U.to==="/",className:({isActive:Q})=>L(Q),title:_?void 0:U.label,onClick:()=>{U.discoveryFeature&&Hg(U.discoveryFeature)},children:[h.jsxs("div",{className:"relative",children:[h.jsx(U.icon,{size:18}),U.discoveryFeature&&h.jsx(kg,{feature:U.discoveryFeature,className:"absolute -top-1 -right-1"})]}),_&&h.jsx("span",{children:U.label})]},U.to)),h.jsx("div",{className:"my-2 border-t border-[#ECEAE3]"}),Yg.map(U=>h.jsxs(yi,{to:U.to,className:({isActive:Q})=>L(Q),title:_?void 0:U.label,children:[h.jsx(U.icon,{size:18}),_&&h.jsx("span",{children:U.label})]},U.to)),_&&h.jsx("div",{className:"mt-3 px-1",children:h.jsx(Bg,{})})]}),h.jsxs("div",{className:"px-3 py-3 border-t border-[#ECEAE3] flex flex-col gap-2",children:[h.jsx(Xg,{collapsed:!_}),h.jsxs("div",{className:["flex items-center gap-2 text-xs",!_&&"justify-center"].filter(Boolean).join(" "),children:[h.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${i?"bg-[#1FC5A8]":"bg-[#C45B5B]"}`}),_&&h.jsx("span",{className:"text-[#6B6960]",children:i?"Connected":"Disconnected"})]}),_&&c&&h.jsxs("span",{className:"text-xs text-[#6B6960]",children:["v",c]}),h.jsxs("button",{onClick:p,title:m==="dark"?"Light mode":"Dark mode",className:["flex items-center gap-2 text-xs text-[#6B6960] hover:text-[#36342E] transition-colors",!_&&"justify-center"].filter(Boolean).join(" "),children:[m==="dark"?h.jsx(mg,{size:14}):h.jsx(Zv,{size:14}),_&&h.jsx("span",{children:m==="dark"?"Light Mode":"Dark Mode"})]}),h.jsxs("button",{onClick:r,className:["flex items-center gap-2 text-xs text-[#6B6960] hover:text-[#36342E] transition-colors",!_&&"justify-center"].filter(Boolean).join(" "),title:_?void 0:"Help & Docs",children:[h.jsx(ym,{size:14}),_&&h.jsx("span",{children:"Help & Docs"})]}),h.jsxs("a",{href:"https://www.autonomi.dev/docs",target:"_blank",rel:"noopener noreferrer",className:["flex items-center gap-2 text-xs text-[#6B6960] hover:text-[#36342E] transition-colors",!_&&"justify-center"].filter(Boolean).join(" "),title:_?void 0:"Documentation",children:[h.jsx(hm,{size:14}),_&&h.jsx("span",{children:"Docs"})]})]})]});return o&&E?h.jsxs(h.Fragment,{children:[h.jsx("div",{className:"fixed inset-0 z-40 bg-ink/20",onClick:()=>x(!1)}),h.jsx("div",{className:"fixed inset-y-0 left-0 z-50",children:B})]}):B}function Xg({collapsed:i}){const{user:c,logout:r,isLocalMode:o}=_m(),[d,m]=v.useState(!1),p=v.useRef(null);return v.useEffect(()=>{function E(x){p.current&&!p.current.contains(x.target)&&m(!1)}if(d)return document.addEventListener("mousedown",E),()=>document.removeEventListener("mousedown",E)},[d]),o||!c?h.jsxs("div",{className:["flex items-center gap-2 text-xs",i&&"justify-center"].filter(Boolean).join(" "),title:i?"Local Mode":void 0,children:[h.jsx(Xv,{size:14,className:"text-[#939084] flex-shrink-0"}),!i&&h.jsx("span",{className:"text-[#939084]",children:"Local Mode"})]}):h.jsxs("div",{className:"relative",ref:p,"data-testid":"user-section",children:[h.jsxs("button",{type:"button",onClick:()=>m(!d),className:["flex items-center gap-2 w-full text-left text-xs rounded-[3px] py-1 px-1 hover:bg-[#F8F4F0] transition-colors",i&&"justify-center"].filter(Boolean).join(" "),title:i?c.name||c.email:void 0,children:[c.avatar_url?h.jsx("img",{src:c.avatar_url,alt:"",className:"w-5 h-5 rounded-full flex-shrink-0"}):h.jsx("div",{className:"w-5 h-5 rounded-full bg-[#553DE9] flex items-center justify-center text-white text-[10px] font-bold flex-shrink-0",children:(c.name||c.email||"?")[0].toUpperCase()}),!i&&h.jsxs(h.Fragment,{children:[h.jsx("span",{className:"text-[#36342E] truncate flex-1",children:c.name||c.email}),h.jsx(mm,{size:12,className:`text-[#939084] transition-transform ${d?"":"rotate-180"}`})]})]}),d&&h.jsxs("div",{className:"absolute bottom-full left-0 mb-1 w-48 bg-white border border-[#ECEAE3] rounded-lg shadow-lg py-1 z-50",children:[h.jsxs("div",{className:"px-3 py-2 border-b border-[#ECEAE3]",children:[h.jsx("p",{className:"text-xs font-medium text-[#36342E] truncate",children:c.name}),h.jsx("p",{className:"text-xs text-[#939084] truncate",children:c.email})]}),h.jsxs(yi,{to:"/settings",onClick:()=>m(!1),className:"flex items-center gap-2 px-3 py-2 text-xs text-[#36342E] hover:bg-[#F8F4F0] transition-colors",children:[h.jsx(xm,{size:14}),"Settings"]}),h.jsxs("button",{type:"button",onClick:()=>{m(!1),r()},className:"flex items-center gap-2 px-3 py-2 text-xs text-[#C45B5B] hover:bg-[#F8F4F0] transition-colors w-full text-left",children:[h.jsx(Bv,{size:14}),"Sign out"]})]})]})}const qa=[];function Vg(i){if(i.key==="Escape"&&qa.length>0){i.preventDefault(),i.stopPropagation();const c=qa[qa.length-1];c()}}let Yh=!1;function Zg(){Yh||(document.addEventListener("keydown",Vg),Yh=!0)}function Jg(i,c){const r=v.useRef(c);r.current=c;const o=v.useCallback(()=>{r.current()},[]);v.useEffect(()=>{if(i)return Zg(),qa.push(o),()=>{const d=qa.indexOf(o);d!==-1&&qa.splice(d,1)}},[i,o])}const Gh=["a[href]","button:not([disabled])","input:not([disabled])","textarea:not([disabled])","select:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(", ");function Kg(i){const c=v.useRef(null),r=v.useRef(null);return v.useEffect(()=>{if(!i)return;r.current=document.activeElement;const o=c.current;if(!o)return;const d=o.querySelectorAll(Gh);d.length>0&&requestAnimationFrame(()=>d[0].focus());const m=p=>{if(p.key!=="Tab")return;const E=o.querySelectorAll(Gh);if(E.length===0)return;const x=E[0],y=E[E.length-1];p.shiftKey?document.activeElement===x&&(p.preventDefault(),y.focus()):document.activeElement===y&&(p.preventDefault(),x.focus())};return document.addEventListener("keydown",m),()=>{document.removeEventListener("keydown",m),r.current&&typeof r.current.focus=="function"&&r.current.focus()}},[i]),c}const Qh="pl_onboarding_complete",Gn=[{icon:vm,title:"Write your spec",description:"Describe what you want to build, or choose a template to get started quickly."},{icon:pg,title:"Use the terminal",description:"Run commands directly in the integrated terminal to install dependencies or debug."},{icon:pm,title:"Preview in real-time",description:"Switch to the Preview tab to see your app running with live reload."},{icon:oo,title:"Iterate with AI Chat",description:"Ask the AI to modify, fix, or explain your code in the chat panel."}];function $g(){const[i,c]=v.useState(!1),[r,o]=v.useState(0),d=Kg(i);Jg(i,()=>{i&&m()}),v.useEffect(()=>{try{localStorage.getItem(Qh)!=="1"&&c(!0)}catch{}},[]);const m=()=>{c(!1);try{localStorage.setItem(Qh,"1")}catch{}},p=()=>{r<Gn.length-1?o(r+1):m()};if(!i)return null;const E=Gn[r],x=E.icon;return h.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-ink/30",children:h.jsxs("div",{ref:d,className:"bg-card rounded-card shadow-card-hover border border-border w-full max-w-sm mx-4",children:[h.jsxs("div",{className:"flex items-center justify-between px-5 pt-5 pb-2",children:[h.jsxs("span",{className:"text-[11px] font-mono text-muted-accessible",children:[r+1," / ",Gn.length]}),h.jsx("button",{onClick:m,className:"text-muted hover:text-ink transition-colors p-1 rounded-btn hover:bg-hover",title:"Skip onboarding",children:h.jsx(ea,{size:14})})]}),h.jsxs("div",{className:"px-5 pb-4 text-center",children:[h.jsx("div",{className:"w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center mx-auto mb-4",children:h.jsx(x,{size:24,className:"text-primary"})}),h.jsx("h3",{className:"text-sm font-heading font-bold text-ink mb-1",children:E.title}),h.jsx("p",{className:"text-xs text-muted-accessible leading-relaxed",children:E.description})]}),h.jsx("div",{className:"flex items-center justify-center gap-1.5 pb-4",children:Gn.map((y,z)=>h.jsx("div",{className:`w-1.5 h-1.5 rounded-full transition-colors ${z===r?"bg-primary":"bg-border"}`},z))}),h.jsxs("div",{className:"flex items-center justify-between px-5 py-3 border-t border-border",children:[h.jsx("button",{onClick:m,className:"text-xs text-muted hover:text-ink transition-colors",children:"Skip"}),h.jsx("button",{onClick:p,className:"inline-flex items-center gap-1.5 px-4 py-1.5 text-xs font-medium rounded-btn bg-primary text-white hover:bg-primary-hover transition-colors",children:r<Gn.length-1?h.jsxs(h.Fragment,{children:["Next",h.jsx(dm,{size:12})]}):"Get Started"})]})]})})}const Xh="pl_product_tour_complete",Wg=[{target:'[data-tour="input-box"]',title:"Describe what you want to build",description:"Type a plain-English description of your project here. The more detail you give, the better the result. You can also paste a spec / PRD or select a template.",position:"bottom"},{target:'[data-tour="template-gallery"]',title:"Start from a template",description:"Browse ready-made templates for SaaS apps, landing pages, dashboards, and more. Each template gives you a head start with a proven structure.",position:"bottom"},{target:'[data-tour="build-progress"]',title:"Watch your project come to life",description:"Once you start a build, this bar tracks each phase: planning, building, testing, and reviewing. You will see real-time progress and cost estimates.",position:"bottom"},{target:'[data-tour="preview-tab"]',title:"Preview your running app",description:"Switch to the Preview tab to see your application running live. Changes appear in real time as the AI iterates on your code.",position:"bottom"},{target:'[data-tour="deploy-tab"]',title:"Deploy with one click",description:"When you are happy with the result, head to the Deploy tab to push your project live. Supports Vercel, Netlify, Railway, and more.",position:"bottom"}];function Fg(i){const c=document.querySelector(i);return c?c.getBoundingClientRect():null}function Ig(i,c){if(!i)return{top:"50%",left:"50%",transform:"translate(-50%, -50%)"};const r=16,o={position:"fixed",zIndex:60};switch(c){case"bottom":o.top=i.bottom+r,o.left=i.left+i.width/2,o.transform="translateX(-50%)";break;case"top":o.bottom=window.innerHeight-i.top+r,o.left=i.left+i.width/2,o.transform="translateX(-50%)";break;case"left":o.top=i.top+i.height/2,o.right=window.innerWidth-i.left+r,o.transform="translateY(-50%)";break;case"right":o.top=i.top+i.height/2,o.left=i.right+r,o.transform="translateY(-50%)";break}return o}function Pg({steps:i=Wg,onComplete:c}){const[r,o]=v.useState(!1),[d,m]=v.useState(0),[p,E]=v.useState(null),x=v.useRef(0);v.useEffect(()=>{try{if(localStorage.getItem(Xh)!=="1"){const B=setTimeout(()=>o(!0),800);return()=>clearTimeout(B)}}catch{}},[]),v.useEffect(()=>{if(!r||!i[d])return;const B=()=>{const U=Fg(i[d].target);E(U),x.current=requestAnimationFrame(B)};return B(),()=>cancelAnimationFrame(x.current)},[r,d,i]);const y=v.useCallback(()=>{o(!1);try{localStorage.setItem(Xh,"1")}catch{}c==null||c()},[c]),z=v.useCallback(()=>{d<i.length-1?m(B=>B+1):y()},[d,i.length,y]),_=v.useCallback(()=>{m(B=>Math.max(0,B-1))},[]);if(v.useEffect(()=>{if(!r)return;const B=U=>{U.key==="Escape"&&y(),U.key==="ArrowRight"&&z(),U.key==="ArrowLeft"&&_()};return window.addEventListener("keydown",B),()=>window.removeEventListener("keydown",B)},[r,y,z,_]),!r||!i[d])return null;const H=i[d],L=8;return h.jsxs("div",{className:"fixed inset-0 z-[55]","aria-modal":"true",role:"dialog",children:[h.jsxs("svg",{className:"absolute inset-0 w-full h-full",onClick:y,style:{zIndex:55},children:[h.jsx("defs",{children:h.jsxs("mask",{id:"tour-spotlight",children:[h.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"white"}),p&&h.jsx("rect",{x:p.left-L,y:p.top-L,width:p.width+L*2,height:p.height+L*2,rx:"8",fill:"black"})]})}),h.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"rgba(0,0,0,0.55)",mask:"url(#tour-spotlight)"})]}),p&&h.jsx("div",{className:"absolute border-2 border-primary rounded-lg pointer-events-none shadow-[0_0_20px_rgba(85,61,233,0.3)]",style:{left:p.left-L,top:p.top-L,width:p.width+L*2,height:p.height+L*2,zIndex:56}}),h.jsxs("div",{className:"w-80 bg-card rounded-xl shadow-2xl border border-border p-0 overflow-hidden",style:{...Ig(p,H.position),zIndex:57},onClick:B=>B.stopPropagation(),children:[h.jsxs("div",{className:"flex items-center justify-between px-4 pt-4 pb-1",children:[h.jsxs("div",{className:"flex items-center gap-2",children:[h.jsx(fo,{size:14,className:"text-primary"}),h.jsxs("span",{className:"text-[11px] font-mono text-muted-accessible",children:["Step ",d+1," of ",i.length]})]}),h.jsx("button",{onClick:y,className:"text-muted hover:text-ink transition-colors p-1 rounded-btn hover:bg-hover",title:"Skip tour",children:h.jsx(ea,{size:14})})]}),h.jsxs("div",{className:"px-4 pb-3",children:[h.jsx("h3",{className:"text-sm font-heading font-bold text-ink mb-1",children:H.title}),h.jsx("p",{className:"text-xs text-muted-accessible leading-relaxed",children:H.description})]}),h.jsx("div",{className:"flex items-center justify-center gap-1.5 pb-3",children:i.map((B,U)=>h.jsx("button",{onClick:()=>m(U),className:`w-2 h-2 rounded-full transition-all ${U===d?"bg-primary scale-110":U<d?"bg-primary/40":"bg-border"}`,"aria-label":`Go to step ${U+1}`},U))}),h.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-t border-border bg-hover/30",children:[h.jsxs("button",{onClick:y,className:"flex items-center gap-1 text-xs text-muted hover:text-ink transition-colors",children:[h.jsx(og,{size:12}),"Skip tour"]}),h.jsxs("div",{className:"flex items-center gap-2",children:[d>0&&h.jsxs("button",{onClick:_,className:"flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-btn text-ink hover:bg-hover transition-colors",children:[h.jsx(fm,{size:12}),"Back"]}),h.jsx("button",{onClick:z,className:"flex items-center gap-1 px-4 py-1.5 text-xs font-medium rounded-btn bg-primary text-white hover:bg-primary-hover transition-colors",children:d<i.length-1?h.jsxs(h.Fragment,{children:["Next",h.jsx(dm,{size:12})]}):"Let's go!"})]})]})]})]})}const Vh="pl_whats_new_version",Ks="6.73.1",e2=[{icon:fo,title:"Product Tour",description:"New step-by-step guided tour for first-time users. Highlights key UI areas so you never feel lost."},{icon:Kv,title:"Contextual Help Tooltips",description:"Hover over the help icons next to complex features to learn what they do without leaving the page."},{icon:gm,title:"Enhanced Keyboard Shortcuts",description:'Press "?" to open the shortcuts overlay. Shortcuts are now grouped by category with search and filtering.'},{icon:Rg,title:"Getting Started Checklist",description:"A friendly checklist guides you through your first project, from writing a spec to deploying your app."},{icon:cg,title:"In-App Documentation",description:"Browse Quick Start guides, FAQ, and template docs right inside Purple Lab, no context switching required."}];function t2(){const[i,c]=v.useState(!1);v.useEffect(()=>{try{if(localStorage.getItem(Vh)!==Ks){const d=setTimeout(()=>c(!0),1200);return()=>clearTimeout(d)}}catch{}},[]);const r=()=>{c(!1);try{localStorage.setItem(Vh,Ks)}catch{}};return i?h.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-ink/30",onClick:r,children:h.jsxs("div",{className:"bg-card rounded-xl shadow-2xl border border-border w-full max-w-md mx-4 overflow-hidden",onClick:o=>o.stopPropagation(),children:[h.jsxs("div",{className:"relative px-6 pt-6 pb-4 text-center border-b border-border bg-gradient-to-b from-primary/5 to-transparent",children:[h.jsx("button",{onClick:r,className:"absolute top-4 right-4 text-muted hover:text-ink transition-colors p-1 rounded-btn hover:bg-hover",title:"Close",children:h.jsx(ea,{size:14})}),h.jsx("div",{className:"w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center mx-auto mb-3",children:h.jsx(zv,{size:24,className:"text-primary"})}),h.jsx("h2",{className:"text-lg font-heading font-bold text-ink",children:"What's New"}),h.jsxs("p",{className:"text-xs text-muted-accessible mt-1",children:["Purple Lab v",Ks]})]}),h.jsx("div",{className:"px-4 py-4 space-y-3 max-h-[320px] overflow-y-auto terminal-scroll",children:e2.map(o=>{const d=o.icon;return h.jsxs("div",{className:"flex items-start gap-3 p-3 rounded-lg hover:bg-hover transition-colors",children:[h.jsx("div",{className:"w-8 h-8 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5",children:h.jsx(d,{size:16,className:"text-primary"})}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsx("h3",{className:"text-sm font-medium text-ink",children:o.title}),h.jsx("p",{className:"text-xs text-muted-accessible leading-relaxed mt-0.5",children:o.description})]})]},o.title)})}),h.jsxs("div",{className:"flex items-center justify-between px-6 py-4 border-t border-border",children:[h.jsxs("a",{href:"https://github.com/asklokesh/loki-mode/blob/main/CHANGELOG.md",target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-1 text-xs text-primary hover:text-primary-hover transition-colors",children:["Full changelog",h.jsx(bv,{size:11})]}),h.jsx("button",{onClick:r,className:"px-5 py-2 text-xs font-medium rounded-btn bg-primary text-white hover:bg-primary-hover transition-colors",children:"Got it!"})]})]})}):null}const $s=[{id:"quick-start",title:"Quick Start",icon:ro,content:`# Quick Start
|
|
356
|
+
*/const jg=[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]],Rg=W("zap",jg),ho="/lab/".replace(/\/$/,""),hi=`${window.location.origin}${ho}/api`,Ag=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}${ho}/ws`,k2=ho;function Sm(){const i={"Content-Type":"application/json"};try{const c=localStorage.getItem("pl_auth_token");c&&(i.Authorization=`Bearer ${c}`)}catch{}return i}async function k(i,c){const r=await fetch(`${hi}${i}`,{...c,headers:{...Sm(),...c==null?void 0:c.headers}});if(!r.ok){const d=await r.text().catch(()=>"");throw new Error(`API error ${r.status}: ${r.statusText}${d?` - ${d}`:""}`)}if(!(r.headers.get("content-type")||"").includes("application/json"))throw new Error("API endpoint not available. Please restart the server with the latest version.");return r.json()}const Ba={listProofs:()=>k("/proofs"),proofsSummary:()=>k("/proofs/summary"),getProof:i=>k(`/proofs/${encodeURIComponent(i)}`),startSession:i=>k("/session/start",{method:"POST",body:JSON.stringify(i)}),quickStart:(i,c="claude")=>k("/session/quick-start",{method:"POST",body:JSON.stringify({prompt:i,provider:c})}),stopSession:()=>k("/session/stop",{method:"POST"}),pauseSession:()=>k("/session/pause",{method:"POST"}),resumeSession:()=>k("/session/resume",{method:"POST"}),getPrdPrefill:()=>k("/session/prd-prefill"),getStatus:()=>k("/session/status"),getAgents:()=>k("/session/agents"),getLogs:(i=200)=>k(`/session/logs?lines=${i}`),getMemorySummary:()=>k("/session/memory"),getChecklist:()=>k("/session/checklist"),getFiles:()=>k("/session/files"),getFileContent:i=>k(`/session/files/content?path=${encodeURIComponent(i)}`),getSessionFileContent:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/file?path=${encodeURIComponent(c)}`),getTemplates:()=>k("/templates"),getTemplateContent:i=>k(`/templates/${encodeURIComponent(i)}`),planSession:(i,c)=>k("/session/plan",{method:"POST",body:JSON.stringify({prd:i,provider:c})}),generateReport:(i="markdown")=>k("/session/report",{method:"POST",body:JSON.stringify({format:i})}),shareSession:()=>k("/session/share",{method:"POST"}),getCurrentProvider:()=>k("/provider/current"),setProvider:i=>k("/provider/set",{method:"POST",body:JSON.stringify({provider:i})}),getMetrics:()=>k("/session/metrics"),getSessionsHistory:()=>k("/sessions/history"),getSessionDetail:i=>k(`/sessions/${encodeURIComponent(i)}`),deleteSession:i=>k(`/sessions/${encodeURIComponent(i)}`,{method:"DELETE"}),onboardRepo:i=>k("/session/onboard",{method:"POST",body:JSON.stringify({path:i})}),saveSessionFile:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/file`,{method:"PUT",body:JSON.stringify({path:c,content:r})}),createSessionFile:(i,c,r="")=>k(`/sessions/${encodeURIComponent(i)}/file`,{method:"POST",body:JSON.stringify({path:c,content:r})}),deleteSessionFile:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/file`,{method:"DELETE",body:JSON.stringify({path:c})}),createSessionDirectory:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/directory`,{method:"POST",body:JSON.stringify({path:c})}),reviewProject:i=>k(`/sessions/${encodeURIComponent(i)}/review`,{method:"POST"}),testProject:i=>k(`/sessions/${encodeURIComponent(i)}/test`,{method:"POST"}),explainProject:i=>k(`/sessions/${encodeURIComponent(i)}/explain`,{method:"POST"}),exportProject:i=>k(`/sessions/${encodeURIComponent(i)}/export`,{method:"POST"}),fixProject:i=>k(`/sessions/${encodeURIComponent(i)}/fix`,{method:"POST"}),chatMessage:(i,c,r="quick")=>k(`/sessions/${encodeURIComponent(i)}/chat`,{method:"POST",body:JSON.stringify({message:c,mode:r})}),chatStart:(i,c,r="quick",o)=>k(`/sessions/${encodeURIComponent(i)}/chat`,{method:"POST",body:JSON.stringify({message:c,mode:r,history:o})}),chatPoll:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/chat/${encodeURIComponent(c)}`),chatStreamUrl:(i,c)=>`${hi}/sessions/${encodeURIComponent(i)}/chat/${encodeURIComponent(c)}/stream`,chatCancel:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/chat/${encodeURIComponent(c)}/cancel`,{method:"POST"}),getPreviewInfo:i=>k(`/sessions/${encodeURIComponent(i)}/preview-info`),devserver:{start:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/devserver/start`,{method:"POST",body:JSON.stringify({command:c||null})}),stop:i=>k(`/sessions/${encodeURIComponent(i)}/devserver/stop`,{method:"POST"}),status:i=>k(`/sessions/${encodeURIComponent(i)}/devserver/status`)},getSecrets:()=>k("/secrets"),setSecret:(i,c)=>k("/secrets",{method:"POST",body:JSON.stringify({key:i,value:c})}),deleteSecret:i=>k(`/secrets/${encodeURIComponent(i)}`,{method:"DELETE"}),getServices:i=>k(`/sessions/${encodeURIComponent(i)}/services`),getTeams:()=>k("/teams"),createTeam:i=>k("/teams",{method:"POST",body:JSON.stringify({name:i})}),getTeamMembers:i=>k(`/teams/${encodeURIComponent(i)}/members`),addTeamMember:(i,c,r)=>k(`/teams/${encodeURIComponent(i)}/members`,{method:"POST",body:JSON.stringify({email:c,role:r})}),getCost:()=>k("/cost"),getCostTimeline:()=>k("/cost/timeline"),getAuditLog:()=>k("/audit-log"),getServiceLogs:(i,c,r=50)=>k(`/sessions/${encodeURIComponent(i)}/devserver/logs?${new URLSearchParams({...c?{service:c}:{},tail:String(r)}).toString()}`),getCheckpoints:i=>k(`/sessions/${encodeURIComponent(i)}/checkpoints`),restoreCheckpoint:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/checkpoints/${encodeURIComponent(c)}/restore`,{method:"POST"}),previewChanges:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/chat/preview`,{method:"POST",body:JSON.stringify({message:c})}),searchFiles:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/files/search?q=${encodeURIComponent(c)}`),restartService:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/devserver/restart-service`,{method:"POST",body:JSON.stringify({service:c})}),deployProject:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/deploy`,{method:"POST",body:JSON.stringify({platform:c})}),githubPush:i=>k(`/sessions/${encodeURIComponent(i)}/github/push`,{method:"POST"}),getGitHubIssues:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/issues?${new URLSearchParams({...c?{state:c}:{},...r?{limit:String(r)}:{}}).toString()}`),getGitHubIssue:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/issues/${c}`),fixGitHubIssue:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/issues/${c}/fix`,{method:"POST"}),getGitHubPRs:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/prs?${new URLSearchParams({...c?{state:c}:{},...r?{limit:String(r)}:{}}).toString()}`),getGitHubPR:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}`),getGitHubPRDiff:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}/diff`),reviewGitHubPR:(i,c,r,o)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}/review`,{method:"POST",body:JSON.stringify({action:r,body:o})}),mergeGitHubPR:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/prs/${c}/merge`,{method:"POST",body:JSON.stringify({method:r})}),getWorkflowRuns:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs?${new URLSearchParams({...c?{limit:String(c)}:{}}).toString()}`),getWorkflowRunDetail:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}`),getWorkflowRunLogs:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}/logs`),getWorkflows:i=>k(`/sessions/${encodeURIComponent(i)}/github/actions/workflows`),dispatchWorkflow:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/dispatch`,{method:"POST",body:JSON.stringify({workflow:c,ref:r})}),rerunWorkflow:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}/rerun`,{method:"POST"}),cancelWorkflow:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/github/actions/runs/${c}/cancel`,{method:"POST"}),importGitHubRepo:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/github/import`,{method:"POST",body:JSON.stringify({repo:c,...r?{branch:r}:{}})}),getDeployStatus:()=>k("/deploy/status"),connectVercel:i=>k("/deploy/vercel/token",{method:"POST",body:JSON.stringify({token:i})}),connectNetlify:i=>k("/deploy/netlify/token",{method:"POST",body:JSON.stringify({token:i})}),disconnectPlatform:i=>k(`/deploy/${encodeURIComponent(i)}/disconnect`,{method:"POST"}),getMe:()=>k("/auth/me"),getGitHubAuthUrl:()=>k("/auth/github/url"),getGoogleAuthUrl:()=>k("/auth/google/url"),githubCallback:(i,c)=>k("/auth/github/callback",{method:"POST",body:JSON.stringify({code:i,state:c})}),googleCallback:(i,c,r)=>k("/auth/google/callback",{method:"POST",body:JSON.stringify({code:i,state:c,redirect_uri:r||`${window.location.origin}${window.location.pathname}`})}),git:{status:i=>k(`/sessions/${encodeURIComponent(i)}/git/status`),log:(i,c=20)=>k(`/sessions/${encodeURIComponent(i)}/git/log?limit=${c}`),branches:i=>k(`/sessions/${encodeURIComponent(i)}/git/branches`),commit:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/git/commit`,{method:"POST",body:JSON.stringify({message:c,files:r})}),createBranch:(i,c,r=!0)=>k(`/sessions/${encodeURIComponent(i)}/git/branch`,{method:"POST",body:JSON.stringify({name:c,checkout:r})}),checkoutBranch:(i,c)=>k(`/sessions/${encodeURIComponent(i)}/git/checkout`,{method:"POST",body:JSON.stringify({name:c})}),push:i=>k(`/sessions/${encodeURIComponent(i)}/git/push`,{method:"POST"}),pr:(i,c,r)=>k(`/sessions/${encodeURIComponent(i)}/git/pr`,{method:"POST",body:JSON.stringify({title:c,body:r})})},generateDocs:i=>k(`/sessions/${encodeURIComponent(i)}/docs/generate`,{method:"POST"}),getDocsStatus:i=>k(`/sessions/${encodeURIComponent(i)}/docs/status`),getDocFiles:i=>k(`/sessions/${encodeURIComponent(i)}/docs/files`),getDocFileContent:async(i,c)=>{const r=await fetch(`${hi}/sessions/${encodeURIComponent(i)}/docs/files/${encodeURIComponent(c)}`,{headers:Sm()});if(!r.ok)throw new Error(`API error ${r.status}: ${r.statusText}`);return r.text()},chatImageUpload:async(i,c)=>{const r=new FormData;r.append("image",c);const o=await fetch(`${hi}/sessions/${encodeURIComponent(i)}/chat/image`,{method:"POST",headers:{...(()=>{const d={};try{const m=localStorage.getItem("pl_auth_token");m&&(d.Authorization=`Bearer ${m}`)}catch{}return d})()},body:r});if(!o.ok){const d=await o.text().catch(()=>"");throw new Error(`API error ${o.status}: ${o.statusText}${d?` - ${d}`:""}`)}return o.json()}};class Og{constructor(c){Ln(this,"ws",null);Ln(this,"listeners",new Map);Ln(this,"reconnectTimer",null);Ln(this,"url");this.url=c||Ag}connect(){var c;((c=this.ws)==null?void 0:c.readyState)!==WebSocket.OPEN&&(this.ws=new WebSocket(this.url),this.ws.onopen=()=>{this.emit("connected",{message:"WebSocket connected"})},this.ws.onmessage=r=>{try{const o=JSON.parse(r.data);if(o.type==="ping"){this.send({type:"pong"});return}this.emit(o.type,o.data||o)}catch{}},this.ws.onclose=()=>{this.emit("disconnected",{}),this.scheduleReconnect()},this.ws.onerror=()=>{var r;(r=this.ws)==null||r.close()})}scheduleReconnect(){this.reconnectTimer||(this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.connect()},3e3))}on(c,r){return this.listeners.has(c)||this.listeners.set(c,new Set),this.listeners.get(c).add(r),()=>{var o;return(o=this.listeners.get(c))==null?void 0:o.delete(r)}}emit(c,r){var o,d;(o=this.listeners.get(c))==null||o.forEach(m=>m(r)),(d=this.listeners.get("*"))==null||d.forEach(m=>m({type:c,data:r}))}send(c){var r;((r=this.ws)==null?void 0:r.readyState)===WebSocket.OPEN&&this.ws.send(JSON.stringify(c))}disconnect(){var c;this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),(c=this.ws)==null||c.close(),this.ws=null}}const Js="pl_auth_token",Em=v.createContext({user:null,loading:!0,login:()=>{},logout:()=>{},isLocalMode:!0});function Mg(i,c,r){c(!1),r({email:i.sub||i.email||"",name:i.name||"",avatar_url:i.avatar||"",authenticated:!0})}function Dg({children:i}){const[c,r]=v.useState(null),[o,d]=v.useState(!0),[m,p]=v.useState(!0),E=ao(),x=kt();v.useEffect(()=>{let H=!1;async function L(){const B=new URLSearchParams(window.location.search),U=B.get("token"),Q=B.get("code");if(U)localStorage.setItem(Js,U),window.history.replaceState({},"",window.location.pathname);else if(Q)try{const q=sessionStorage.getItem("pl_oauth_provider")||"github",I=sessionStorage.getItem("pl_oauth_state")||"";sessionStorage.removeItem("pl_oauth_state"),sessionStorage.removeItem("pl_oauth_provider");let J;if(q==="google"?J=await Ba.googleCallback(Q,I):J=await Ba.githubCallback(Q,I),!H){localStorage.setItem(Js,J.token),window.history.replaceState({},"",window.location.pathname),p(!1),r({email:J.user.email,name:J.user.name,avatar_url:J.user.avatar_url,authenticated:!0}),d(!1);return}}catch{window.history.replaceState({},"",window.location.pathname)}try{const q=await Ba.getMe();if(H)return;q.local_mode?(p(!0),r(null)):q.authenticated?Mg(q,p,r):(p(!1),r(null))}catch{if(H)return;p(!0),r(null)}finally{H||d(!1)}}return L(),()=>{H=!0}},[]);const y=v.useCallback(H=>{H==="github"?Ba.getGitHubAuthUrl().then(L=>{try{const U=new URL(L.url).searchParams.get("state");U&&(sessionStorage.setItem("pl_oauth_state",U),sessionStorage.setItem("pl_oauth_provider","github"))}catch{}window.location.href=L.url}).catch(()=>{}):H==="google"&&Ba.getGoogleAuthUrl().then(L=>{try{const U=new URL(L.url).searchParams.get("state");U&&(sessionStorage.setItem("pl_oauth_state",U),sessionStorage.setItem("pl_oauth_provider","google"))}catch{}window.location.href=L.url}).catch(()=>{})},[]),z=v.useCallback(()=>{localStorage.removeItem(Js),r(null),x.pathname!=="/login"&&E("/login",{replace:!0})},[E,x.pathname]),_=v.useMemo(()=>({user:c,loading:o,login:y,logout:z,isLocalMode:m}),[c,o,y,z,m]);return h.jsx(Em.Provider,{value:_,children:i})}function _m(){return v.useContext(Em)}function Ug(){const[i,c]=v.useState(()=>typeof window>"u"?"light":localStorage.getItem("pl_theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"));v.useEffect(()=>{document.documentElement.classList.toggle("dark",i==="dark"),localStorage.setItem("pl_theme",i)},[i]);const r=v.useCallback(()=>{c(o=>o==="light"?"dark":"light")},[]);return{theme:i,toggleTheme:r,isDark:i==="dark"}}const Tm="pl_discovered_features";function zm(){try{const i=localStorage.getItem(Tm);if(i)return new Set(JSON.parse(i))}catch{}return new Set}function wg(i){try{localStorage.setItem(Tm,JSON.stringify([...i]))}catch{}}function Hg(i){const c=zm();c.has(i)||(c.add(i),wg(c),window.dispatchEvent(new CustomEvent("pl_feature_discovered",{detail:i})))}function kg({feature:i,className:c=""}){const[r,o]=v.useState(!0);return v.useEffect(()=>{o(zm().has(i))},[i]),v.useEffect(()=>{const d=m=>{m.detail===i&&o(!0)};return window.addEventListener("pl_feature_discovered",d),()=>window.removeEventListener("pl_feature_discovered",d)},[i]),r?null:h.jsxs("span",{className:`relative inline-flex ${c}`,"aria-hidden":"true",children:[h.jsx("span",{className:"absolute inline-flex h-2.5 w-2.5 rounded-full bg-primary/40 animate-ping"}),h.jsx("span",{className:"relative inline-flex h-2.5 w-2.5 rounded-full bg-primary"})]})}const Nm="pl_getting_started_steps",Hh="pl_getting_started_dismissed",kh="pl_getting_started_collapsed",Lh=[{id:"create_project",label:"Create your first project",description:"Describe what you want to build or pick a template to get started.",icon:vm},{id:"try_chat",label:"Try the AI chat",description:"Ask the AI to modify, explain, or improve your code.",icon:oo},{id:"preview_app",label:"Preview your app",description:"Open the Preview tab to see your application running live.",icon:pm},{id:"explore_templates",label:"Explore templates",description:"Browse the template gallery for inspiration and quick starts.",icon:so},{id:"deploy_app",label:"Deploy your app",description:"Push your project live with one click using the Deploy tab.",icon:ro}];function Bh(){try{const i=localStorage.getItem(Nm);if(i)return new Set(JSON.parse(i))}catch{}return new Set}function Lg(i){try{localStorage.setItem(Nm,JSON.stringify([...i]))}catch{}}function Bg(){const[i,c]=v.useState(!1),[r,o]=v.useState(!1),[d,m]=v.useState(new Set);v.useEffect(()=>{try{if(localStorage.getItem(Hh)==="1"){c(!0);return}o(localStorage.getItem(kh)==="1")}catch{}m(Bh())},[]),v.useEffect(()=>{const L=()=>m(Bh());return window.addEventListener("pl_step_complete",L),()=>window.removeEventListener("pl_step_complete",L)},[]);const p=v.useCallback(L=>{m(B=>{const U=new Set(B);return U.has(L)?U.delete(L):U.add(L),Lg(U),U})},[]),E=()=>{c(!0);try{localStorage.setItem(Hh,"1")}catch{}},x=()=>{o(L=>{const B=!L;try{localStorage.setItem(kh,B?"1":"0")}catch{}return B})};if(i)return null;const y=d.size,z=Lh.length,_=y/z*100,H=y===z;return h.jsxs("div",{className:"bg-card border border-border rounded-xl shadow-sm overflow-hidden",children:[h.jsxs("button",{onClick:x,className:"w-full flex items-center gap-3 px-4 py-3 text-left hover:bg-hover transition-colors",children:[h.jsx(kv,{size:16,className:"text-primary flex-shrink-0"}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsxs("div",{className:"flex items-center gap-2",children:[h.jsx("span",{className:"text-sm font-heading font-bold text-ink",children:"Getting Started"}),h.jsxs("span",{className:"text-[11px] text-muted-accessible font-mono",children:[y,"/",z]})]}),h.jsx("div",{className:"h-1 bg-border rounded-full mt-1.5 overflow-hidden",children:h.jsx("div",{className:"h-full bg-primary rounded-full transition-all duration-500",style:{width:`${_}%`}})})]}),h.jsx("div",{className:"flex items-center gap-1",children:r?h.jsx(nv,{size:14,className:"text-muted"}):h.jsx(mm,{size:14,className:"text-muted"})})]}),!r&&h.jsxs("div",{className:"border-t border-border",children:[h.jsx("div",{className:"px-3 py-2 space-y-0.5",children:Lh.map(L=>{const B=d.has(L.id),U=L.icon;return h.jsxs("button",{onClick:()=>p(L.id),className:`w-full flex items-start gap-3 px-3 py-2.5 rounded-lg text-left transition-colors ${B?"opacity-60 hover:opacity-80":"hover:bg-hover"}`,children:[h.jsx("div",{className:"mt-0.5 flex-shrink-0",children:B?h.jsx(rv,{size:16,className:"text-success"}):h.jsx(yv,{size:16,className:"text-border"})}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsx("span",{className:`text-xs font-medium ${B?"text-muted line-through":"text-ink"}`,children:L.label}),!B&&h.jsx("p",{className:"text-[11px] text-muted-accessible mt-0.5 leading-relaxed",children:L.description})]}),h.jsx(U,{size:14,className:`flex-shrink-0 mt-0.5 ${B?"text-muted":"text-primary/50"}`})]},L.id)})}),h.jsxs("div",{className:"flex items-center justify-between px-4 py-2.5 border-t border-border",children:[H?h.jsx("span",{className:"text-xs text-success font-medium",children:"All done -- you are ready to build!"}):h.jsx("span",{className:"text-[11px] text-muted",children:"Complete each step to learn the basics."}),h.jsxs("button",{onClick:E,className:"flex items-center gap-1 text-[11px] text-muted hover:text-ink transition-colors",children:[h.jsx(ea,{size:11}),"Dismiss"]})]})]})]})}const qh="pl_sidebar_collapsed",qg=[{to:"/",label:"Home",icon:Ov},{to:"/projects",label:"Projects",icon:_v},{to:"/templates",label:"Templates",icon:so,discoveryFeature:"templates"},{to:"/showcase",label:"Showcase",icon:fo},{to:"/magic",label:"Magic",icon:Tg},{to:"/metrics",label:"Metrics",icon:lv},{to:"/compare",label:"Compare",icon:Rv},{to:"/teams",label:"Teams",icon:xg}],Yg=[{to:"/settings",label:"Settings",icon:xm},{to:"/admin",label:"Admin",icon:ug},{to:"/admin/settings",label:"System",icon:Ng}];function Gg(){const[i,c]=v.useState(typeof window<"u"?window.innerWidth<768:!1);return v.useEffect(()=>{const r=()=>c(window.innerWidth<768);return window.addEventListener("resize",r),()=>window.removeEventListener("resize",r)},[]),i}function Qg({wsConnected:i,version:c,onOpenDocs:r}){const o=Gg(),d=kt(),{theme:m,toggleTheme:p}=Ug(),[E,x]=v.useState(!1),[y,z]=v.useState(()=>{try{return localStorage.getItem(qh)==="1"}catch{return!1}});v.useEffect(()=>{try{localStorage.setItem(qh,y?"1":"0")}catch{}},[y]),v.useEffect(()=>{o&&x(!1)},[d.pathname,o]);const _=o?E:!y,H=_?240:64,L=U=>["flex items-center gap-3 px-3 py-2 text-sm transition-colors rounded-[5px]",!_&&"justify-center",U?"bg-[#553DE9]/8 text-[#553DE9] font-medium border-l-2 border-[#553DE9]":"text-[#36342E] hover:bg-[#F8F4F0]"].filter(Boolean).join(" "),B=h.jsxs("aside",{className:"flex flex-col h-full border-r border-[#ECEAE3] bg-white transition-[width] duration-200",style:{width:H,minWidth:H},children:[h.jsxs("div",{className:"flex items-center justify-between px-4 h-14 border-b border-[#ECEAE3]",children:[_&&h.jsxs("div",{className:"flex flex-col",children:[h.jsx("span",{className:"font-heading text-lg font-bold leading-tight text-[#36342E]",children:"Purple Lab"}),h.jsx("span",{className:"text-xs text-[#6B6960]",children:"Powered by Loki"})]}),o?h.jsx("button",{type:"button","aria-label":E?"Close menu":"Open menu",title:E?"Close menu":"Open menu",onClick:()=>x(!E),className:"inline-flex items-center justify-center w-7 h-7 rounded-[3px] text-[#939084] hover:bg-[#F8F4F0] transition-colors",children:E?h.jsx(ea,{size:16}):h.jsx(Yv,{size:16})}):h.jsx("button",{type:"button","aria-label":y?"Expand sidebar":"Collapse sidebar",title:y?"Expand sidebar":"Collapse sidebar",onClick:()=>z(!y),className:"inline-flex items-center justify-center w-7 h-7 rounded-[3px] text-[#939084] hover:bg-[#F8F4F0] transition-colors",children:y?h.jsx(Iv,{size:16}):h.jsx(Wv,{size:16})})]}),h.jsxs("nav",{className:"flex-1 px-2 py-3 flex flex-col gap-1","aria-label":"Main navigation",children:[qg.map(U=>h.jsxs(yi,{to:U.to,end:U.to==="/",className:({isActive:Q})=>L(Q),title:_?void 0:U.label,onClick:()=>{U.discoveryFeature&&Hg(U.discoveryFeature)},children:[h.jsxs("div",{className:"relative",children:[h.jsx(U.icon,{size:18}),U.discoveryFeature&&h.jsx(kg,{feature:U.discoveryFeature,className:"absolute -top-1 -right-1"})]}),_&&h.jsx("span",{children:U.label})]},U.to)),h.jsx("div",{className:"my-2 border-t border-[#ECEAE3]"}),Yg.map(U=>h.jsxs(yi,{to:U.to,className:({isActive:Q})=>L(Q),title:_?void 0:U.label,children:[h.jsx(U.icon,{size:18}),_&&h.jsx("span",{children:U.label})]},U.to)),_&&h.jsx("div",{className:"mt-3 px-1",children:h.jsx(Bg,{})})]}),h.jsxs("div",{className:"px-3 py-3 border-t border-[#ECEAE3] flex flex-col gap-2",children:[h.jsx(Xg,{collapsed:!_}),h.jsxs("div",{className:["flex items-center gap-2 text-xs",!_&&"justify-center"].filter(Boolean).join(" "),children:[h.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${i?"bg-[#1FC5A8]":"bg-[#C45B5B]"}`}),_&&h.jsx("span",{className:"text-[#6B6960]",children:i?"Connected":"Disconnected"})]}),_&&c&&h.jsxs("span",{className:"text-xs text-[#6B6960]",children:["v",c]}),h.jsxs("button",{onClick:p,title:m==="dark"?"Light mode":"Dark mode",className:["flex items-center gap-2 text-xs text-[#6B6960] hover:text-[#36342E] transition-colors",!_&&"justify-center"].filter(Boolean).join(" "),children:[m==="dark"?h.jsx(mg,{size:14}):h.jsx(Zv,{size:14}),_&&h.jsx("span",{children:m==="dark"?"Light Mode":"Dark Mode"})]}),h.jsxs("button",{onClick:r,className:["flex items-center gap-2 text-xs text-[#6B6960] hover:text-[#36342E] transition-colors",!_&&"justify-center"].filter(Boolean).join(" "),title:_?void 0:"Help & Docs",children:[h.jsx(ym,{size:14}),_&&h.jsx("span",{children:"Help & Docs"})]}),h.jsxs("a",{href:"https://www.autonomi.dev/docs",target:"_blank",rel:"noopener noreferrer",className:["flex items-center gap-2 text-xs text-[#6B6960] hover:text-[#36342E] transition-colors",!_&&"justify-center"].filter(Boolean).join(" "),title:_?void 0:"Documentation",children:[h.jsx(hm,{size:14}),_&&h.jsx("span",{children:"Docs"})]})]})]});return o&&E?h.jsxs(h.Fragment,{children:[h.jsx("div",{className:"fixed inset-0 z-40 bg-ink/20",onClick:()=>x(!1)}),h.jsx("div",{className:"fixed inset-y-0 left-0 z-50",children:B})]}):B}function Xg({collapsed:i}){const{user:c,logout:r,isLocalMode:o}=_m(),[d,m]=v.useState(!1),p=v.useRef(null);return v.useEffect(()=>{function E(x){p.current&&!p.current.contains(x.target)&&m(!1)}if(d)return document.addEventListener("mousedown",E),()=>document.removeEventListener("mousedown",E)},[d]),o||!c?h.jsxs("div",{className:["flex items-center gap-2 text-xs",i&&"justify-center"].filter(Boolean).join(" "),title:i?"Local Mode":void 0,children:[h.jsx(Xv,{size:14,className:"text-[#939084] flex-shrink-0"}),!i&&h.jsx("span",{className:"text-[#939084]",children:"Local Mode"})]}):h.jsxs("div",{className:"relative",ref:p,"data-testid":"user-section",children:[h.jsxs("button",{type:"button",onClick:()=>m(!d),className:["flex items-center gap-2 w-full text-left text-xs rounded-[3px] py-1 px-1 hover:bg-[#F8F4F0] transition-colors",i&&"justify-center"].filter(Boolean).join(" "),title:i?c.name||c.email:void 0,children:[c.avatar_url?h.jsx("img",{src:c.avatar_url,alt:"",className:"w-5 h-5 rounded-full flex-shrink-0"}):h.jsx("div",{className:"w-5 h-5 rounded-full bg-[#553DE9] flex items-center justify-center text-white text-[10px] font-bold flex-shrink-0",children:(c.name||c.email||"?")[0].toUpperCase()}),!i&&h.jsxs(h.Fragment,{children:[h.jsx("span",{className:"text-[#36342E] truncate flex-1",children:c.name||c.email}),h.jsx(mm,{size:12,className:`text-[#939084] transition-transform ${d?"":"rotate-180"}`})]})]}),d&&h.jsxs("div",{className:"absolute bottom-full left-0 mb-1 w-48 bg-white border border-[#ECEAE3] rounded-lg shadow-lg py-1 z-50",children:[h.jsxs("div",{className:"px-3 py-2 border-b border-[#ECEAE3]",children:[h.jsx("p",{className:"text-xs font-medium text-[#36342E] truncate",children:c.name}),h.jsx("p",{className:"text-xs text-[#939084] truncate",children:c.email})]}),h.jsxs(yi,{to:"/settings",onClick:()=>m(!1),className:"flex items-center gap-2 px-3 py-2 text-xs text-[#36342E] hover:bg-[#F8F4F0] transition-colors",children:[h.jsx(xm,{size:14}),"Settings"]}),h.jsxs("button",{type:"button",onClick:()=>{m(!1),r()},className:"flex items-center gap-2 px-3 py-2 text-xs text-[#C45B5B] hover:bg-[#F8F4F0] transition-colors w-full text-left",children:[h.jsx(Bv,{size:14}),"Sign out"]})]})]})}const qa=[];function Vg(i){if(i.key==="Escape"&&qa.length>0){i.preventDefault(),i.stopPropagation();const c=qa[qa.length-1];c()}}let Yh=!1;function Zg(){Yh||(document.addEventListener("keydown",Vg),Yh=!0)}function Jg(i,c){const r=v.useRef(c);r.current=c;const o=v.useCallback(()=>{r.current()},[]);v.useEffect(()=>{if(i)return Zg(),qa.push(o),()=>{const d=qa.indexOf(o);d!==-1&&qa.splice(d,1)}},[i,o])}const Gh=["a[href]","button:not([disabled])","input:not([disabled])","textarea:not([disabled])","select:not([disabled])",'[tabindex]:not([tabindex="-1"])'].join(", ");function Kg(i){const c=v.useRef(null),r=v.useRef(null);return v.useEffect(()=>{if(!i)return;r.current=document.activeElement;const o=c.current;if(!o)return;const d=o.querySelectorAll(Gh);d.length>0&&requestAnimationFrame(()=>d[0].focus());const m=p=>{if(p.key!=="Tab")return;const E=o.querySelectorAll(Gh);if(E.length===0)return;const x=E[0],y=E[E.length-1];p.shiftKey?document.activeElement===x&&(p.preventDefault(),y.focus()):document.activeElement===y&&(p.preventDefault(),x.focus())};return document.addEventListener("keydown",m),()=>{document.removeEventListener("keydown",m),r.current&&typeof r.current.focus=="function"&&r.current.focus()}},[i]),c}const Qh="pl_onboarding_complete",Gn=[{icon:vm,title:"Write your spec",description:"Describe what you want to build, or choose a template to get started quickly."},{icon:pg,title:"Use the terminal",description:"Run commands directly in the integrated terminal to install dependencies or debug."},{icon:pm,title:"Preview in real-time",description:"Switch to the Preview tab to see your app running with live reload."},{icon:oo,title:"Iterate with AI Chat",description:"Ask the AI to modify, fix, or explain your code in the chat panel."}];function $g(){const[i,c]=v.useState(!1),[r,o]=v.useState(0),d=Kg(i);Jg(i,()=>{i&&m()}),v.useEffect(()=>{try{localStorage.getItem(Qh)!=="1"&&c(!0)}catch{}},[]);const m=()=>{c(!1);try{localStorage.setItem(Qh,"1")}catch{}},p=()=>{r<Gn.length-1?o(r+1):m()};if(!i)return null;const E=Gn[r],x=E.icon;return h.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-ink/30",children:h.jsxs("div",{ref:d,className:"bg-card rounded-card shadow-card-hover border border-border w-full max-w-sm mx-4",children:[h.jsxs("div",{className:"flex items-center justify-between px-5 pt-5 pb-2",children:[h.jsxs("span",{className:"text-[11px] font-mono text-muted-accessible",children:[r+1," / ",Gn.length]}),h.jsx("button",{onClick:m,className:"text-muted hover:text-ink transition-colors p-1 rounded-btn hover:bg-hover",title:"Skip onboarding",children:h.jsx(ea,{size:14})})]}),h.jsxs("div",{className:"px-5 pb-4 text-center",children:[h.jsx("div",{className:"w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center mx-auto mb-4",children:h.jsx(x,{size:24,className:"text-primary"})}),h.jsx("h3",{className:"text-sm font-heading font-bold text-ink mb-1",children:E.title}),h.jsx("p",{className:"text-xs text-muted-accessible leading-relaxed",children:E.description})]}),h.jsx("div",{className:"flex items-center justify-center gap-1.5 pb-4",children:Gn.map((y,z)=>h.jsx("div",{className:`w-1.5 h-1.5 rounded-full transition-colors ${z===r?"bg-primary":"bg-border"}`},z))}),h.jsxs("div",{className:"flex items-center justify-between px-5 py-3 border-t border-border",children:[h.jsx("button",{onClick:m,className:"text-xs text-muted hover:text-ink transition-colors",children:"Skip"}),h.jsx("button",{onClick:p,className:"inline-flex items-center gap-1.5 px-4 py-1.5 text-xs font-medium rounded-btn bg-primary text-white hover:bg-primary-hover transition-colors",children:r<Gn.length-1?h.jsxs(h.Fragment,{children:["Next",h.jsx(dm,{size:12})]}):"Get Started"})]})]})})}const Xh="pl_product_tour_complete",Wg=[{target:'[data-tour="input-box"]',title:"Describe what you want to build",description:"Type a plain-English description of your project here. The more detail you give, the better the result. You can also paste a spec / PRD or select a template.",position:"bottom"},{target:'[data-tour="template-gallery"]',title:"Start from a template",description:"Browse ready-made templates for SaaS apps, landing pages, dashboards, and more. Each template gives you a head start with a proven structure.",position:"bottom"},{target:'[data-tour="build-progress"]',title:"Watch your project come to life",description:"Once you start a build, this bar tracks each phase: planning, building, testing, and reviewing. You will see real-time progress and cost estimates.",position:"bottom"},{target:'[data-tour="preview-tab"]',title:"Preview your running app",description:"Switch to the Preview tab to see your application running live. Changes appear in real time as the AI iterates on your code.",position:"bottom"},{target:'[data-tour="deploy-tab"]',title:"Deploy with one click",description:"When you are happy with the result, head to the Deploy tab to push your project live. Supports Vercel, Netlify, Railway, and more.",position:"bottom"}];function Fg(i){const c=document.querySelector(i);return c?c.getBoundingClientRect():null}function Ig(i,c){if(!i)return{top:"50%",left:"50%",transform:"translate(-50%, -50%)"};const r=16,o={position:"fixed",zIndex:60};switch(c){case"bottom":o.top=i.bottom+r,o.left=i.left+i.width/2,o.transform="translateX(-50%)";break;case"top":o.bottom=window.innerHeight-i.top+r,o.left=i.left+i.width/2,o.transform="translateX(-50%)";break;case"left":o.top=i.top+i.height/2,o.right=window.innerWidth-i.left+r,o.transform="translateY(-50%)";break;case"right":o.top=i.top+i.height/2,o.left=i.right+r,o.transform="translateY(-50%)";break}return o}function Pg({steps:i=Wg,onComplete:c}){const[r,o]=v.useState(!1),[d,m]=v.useState(0),[p,E]=v.useState(null),x=v.useRef(0);v.useEffect(()=>{try{if(localStorage.getItem(Xh)!=="1"){const B=setTimeout(()=>o(!0),800);return()=>clearTimeout(B)}}catch{}},[]),v.useEffect(()=>{if(!r||!i[d])return;const B=()=>{const U=Fg(i[d].target);E(U),x.current=requestAnimationFrame(B)};return B(),()=>cancelAnimationFrame(x.current)},[r,d,i]);const y=v.useCallback(()=>{o(!1);try{localStorage.setItem(Xh,"1")}catch{}c==null||c()},[c]),z=v.useCallback(()=>{d<i.length-1?m(B=>B+1):y()},[d,i.length,y]),_=v.useCallback(()=>{m(B=>Math.max(0,B-1))},[]);if(v.useEffect(()=>{if(!r)return;const B=U=>{U.key==="Escape"&&y(),U.key==="ArrowRight"&&z(),U.key==="ArrowLeft"&&_()};return window.addEventListener("keydown",B),()=>window.removeEventListener("keydown",B)},[r,y,z,_]),!r||!i[d])return null;const H=i[d],L=8;return h.jsxs("div",{className:"fixed inset-0 z-[55]","aria-modal":"true",role:"dialog",children:[h.jsxs("svg",{className:"absolute inset-0 w-full h-full",onClick:y,style:{zIndex:55},children:[h.jsx("defs",{children:h.jsxs("mask",{id:"tour-spotlight",children:[h.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"white"}),p&&h.jsx("rect",{x:p.left-L,y:p.top-L,width:p.width+L*2,height:p.height+L*2,rx:"8",fill:"black"})]})}),h.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:"rgba(0,0,0,0.55)",mask:"url(#tour-spotlight)"})]}),p&&h.jsx("div",{className:"absolute border-2 border-primary rounded-lg pointer-events-none shadow-[0_0_20px_rgba(85,61,233,0.3)]",style:{left:p.left-L,top:p.top-L,width:p.width+L*2,height:p.height+L*2,zIndex:56}}),h.jsxs("div",{className:"w-80 bg-card rounded-xl shadow-2xl border border-border p-0 overflow-hidden",style:{...Ig(p,H.position),zIndex:57},onClick:B=>B.stopPropagation(),children:[h.jsxs("div",{className:"flex items-center justify-between px-4 pt-4 pb-1",children:[h.jsxs("div",{className:"flex items-center gap-2",children:[h.jsx(fo,{size:14,className:"text-primary"}),h.jsxs("span",{className:"text-[11px] font-mono text-muted-accessible",children:["Step ",d+1," of ",i.length]})]}),h.jsx("button",{onClick:y,className:"text-muted hover:text-ink transition-colors p-1 rounded-btn hover:bg-hover",title:"Skip tour",children:h.jsx(ea,{size:14})})]}),h.jsxs("div",{className:"px-4 pb-3",children:[h.jsx("h3",{className:"text-sm font-heading font-bold text-ink mb-1",children:H.title}),h.jsx("p",{className:"text-xs text-muted-accessible leading-relaxed",children:H.description})]}),h.jsx("div",{className:"flex items-center justify-center gap-1.5 pb-3",children:i.map((B,U)=>h.jsx("button",{onClick:()=>m(U),className:`w-2 h-2 rounded-full transition-all ${U===d?"bg-primary scale-110":U<d?"bg-primary/40":"bg-border"}`,"aria-label":`Go to step ${U+1}`},U))}),h.jsxs("div",{className:"flex items-center justify-between px-4 py-3 border-t border-border bg-hover/30",children:[h.jsxs("button",{onClick:y,className:"flex items-center gap-1 text-xs text-muted hover:text-ink transition-colors",children:[h.jsx(og,{size:12}),"Skip tour"]}),h.jsxs("div",{className:"flex items-center gap-2",children:[d>0&&h.jsxs("button",{onClick:_,className:"flex items-center gap-1 px-3 py-1.5 text-xs font-medium rounded-btn text-ink hover:bg-hover transition-colors",children:[h.jsx(fm,{size:12}),"Back"]}),h.jsx("button",{onClick:z,className:"flex items-center gap-1 px-4 py-1.5 text-xs font-medium rounded-btn bg-primary text-white hover:bg-primary-hover transition-colors",children:d<i.length-1?h.jsxs(h.Fragment,{children:["Next",h.jsx(dm,{size:12})]}):"Let's go!"})]})]})]})]})}const Vh="pl_whats_new_version",Ks="9.55.0",e2=[{icon:fo,title:"Product Tour",description:"New step-by-step guided tour for first-time users. Highlights key UI areas so you never feel lost."},{icon:Kv,title:"Contextual Help Tooltips",description:"Hover over the help icons next to complex features to learn what they do without leaving the page."},{icon:gm,title:"Enhanced Keyboard Shortcuts",description:'Press "?" to open the shortcuts overlay. Shortcuts are now grouped by category with search and filtering.'},{icon:Rg,title:"Getting Started Checklist",description:"A friendly checklist guides you through your first project, from writing a spec to deploying your app."},{icon:cg,title:"In-App Documentation",description:"Browse Quick Start guides, FAQ, and template docs right inside Purple Lab, no context switching required."}];function t2(){const[i,c]=v.useState(!1);v.useEffect(()=>{try{if(localStorage.getItem(Vh)!==Ks){const d=setTimeout(()=>c(!0),1200);return()=>clearTimeout(d)}}catch{}},[]);const r=()=>{c(!1);try{localStorage.setItem(Vh,Ks)}catch{}};return i?h.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-ink/30",onClick:r,children:h.jsxs("div",{className:"bg-card rounded-xl shadow-2xl border border-border w-full max-w-md mx-4 overflow-hidden",onClick:o=>o.stopPropagation(),children:[h.jsxs("div",{className:"relative px-6 pt-6 pb-4 text-center border-b border-border bg-gradient-to-b from-primary/5 to-transparent",children:[h.jsx("button",{onClick:r,className:"absolute top-4 right-4 text-muted hover:text-ink transition-colors p-1 rounded-btn hover:bg-hover",title:"Close",children:h.jsx(ea,{size:14})}),h.jsx("div",{className:"w-12 h-12 rounded-full bg-primary/10 flex items-center justify-center mx-auto mb-3",children:h.jsx(zv,{size:24,className:"text-primary"})}),h.jsx("h2",{className:"text-lg font-heading font-bold text-ink",children:"What's New"}),h.jsxs("p",{className:"text-xs text-muted-accessible mt-1",children:["Purple Lab v",Ks]})]}),h.jsx("div",{className:"px-4 py-4 space-y-3 max-h-[320px] overflow-y-auto terminal-scroll",children:e2.map(o=>{const d=o.icon;return h.jsxs("div",{className:"flex items-start gap-3 p-3 rounded-lg hover:bg-hover transition-colors",children:[h.jsx("div",{className:"w-8 h-8 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5",children:h.jsx(d,{size:16,className:"text-primary"})}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsx("h3",{className:"text-sm font-medium text-ink",children:o.title}),h.jsx("p",{className:"text-xs text-muted-accessible leading-relaxed mt-0.5",children:o.description})]})]},o.title)})}),h.jsxs("div",{className:"flex items-center justify-between px-6 py-4 border-t border-border",children:[h.jsxs("a",{href:"https://github.com/asklokesh/loki-mode/blob/main/CHANGELOG.md",target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-1 text-xs text-primary hover:text-primary-hover transition-colors",children:["Full changelog",h.jsx(bv,{size:11})]}),h.jsx("button",{onClick:r,className:"px-5 py-2 text-xs font-medium rounded-btn bg-primary text-white hover:bg-primary-hover transition-colors",children:"Got it!"})]})]})}):null}const $s=[{id:"quick-start",title:"Quick Start",icon:ro,content:`# Quick Start
|
|
357
357
|
|
|
358
358
|
**1. Create a project**
|
|
359
359
|
Click "New Project" on the home page, or type a description in the input box and press Enter.
|
|
@@ -435,4 +435,4 @@ Reason, Act, Reflect, Verify -- the AI's thinking process. It plans what to do (
|
|
|
435
435
|
from { opacity: 0; transform: translateX(100%); }
|
|
436
436
|
to { opacity: 1; transform: translateX(0); }
|
|
437
437
|
}
|
|
438
|
-
`}),h.jsx("span",{className:`flex-shrink-0 mt-0.5 ${p.icon}`,children:h.jsx(p.IconComponent,{size:18})}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsx("p",{className:"text-sm font-medium text-[#201515] dark:text-[#E8E6E3]",children:o}),d&&h.jsx("p",{className:"text-xs text-[#6B6960] dark:text-[#8A8880] mt-0.5",children:d})]}),h.jsx("button",{onClick:x,className:"flex-shrink-0 text-[#939084] hover:text-[#36342E] dark:hover:text-[#E8E6E3] transition-colors","aria-label":"Dismiss notification",children:h.jsx(ea,{size:14})})]})}function m2({notifications:i,onDismiss:c}){return i.length===0?null:h.jsx("div",{className:"fixed top-4 right-4 z-[9999] flex flex-col gap-2 pointer-events-none","aria-live":"polite",children:i.map(r=>h.jsx(h2,{notification:r,onDismiss:c},r.id))})}const Rm=v.createContext({notify:()=>"",dismiss:()=>{},dismissAll:()=>{}});let y2=0;function p2({children:i}){const[c,r]=v.useState([]),o=v.useCallback(E=>{const x=`notif-${++y2}-${Date.now()}`,y={...E,id:x};if(r(z=>[...z,y]),document.hidden&&"Notification"in window)if(Notification.permission==="granted")try{new Notification(E.title,{body:E.message||""})}catch{}else Notification.permission!=="denied"&&Notification.requestPermission().then(z=>{if(z==="granted")try{new Notification(E.title,{body:E.message||""})}catch{}});return x},[]),d=v.useCallback(E=>{r(x=>x.filter(y=>y.id!==E))},[]),m=v.useCallback(()=>{r([])},[]),p=v.useMemo(()=>({notify:o,dismiss:d,dismissAll:m}),[o,d,m]);return h.jsxs(Rm.Provider,{value:p,children:[i,h.jsx(m2,{notifications:c,onDismiss:d})]})}function L2(){return v.useContext(Rm)}function Fs({children:i}){const{user:c,loading:r,isLocalMode:o}=_m();return r?h.jsx("div",{className:"h-screen bg-[#FAF9F6] flex items-center justify-center text-[#6B6960] text-sm",children:"Loading..."}):o?h.jsx(h.Fragment,{children:i}):c?h.jsx(h.Fragment,{children:i}):h.jsx(o1,{to:"/login",replace:!0})}function pi({variant:i="text",width:c,height:r,className:o=""}){const d="animate-pulse bg-[#ECEAE3]/60 rounded";if(i==="circle"){const m=c||"2rem";return h.jsx("div",{className:`${d} rounded-full flex-shrink-0 ${o}`,style:{width:m,height:m}})}return i==="block"?h.jsx("div",{className:`${d} rounded-btn ${o}`,style:{width:c||"100%",height:r||"4rem"}}):h.jsx("div",{className:`${d} rounded-btn ${o}`,style:{width:c||"100%",height:r||"0.75rem"}})}function B2(){return h.jsx("div",{className:"p-4 space-y-3",children:[...Array(12)].map((i,c)=>h.jsxs("div",{className:"flex items-center gap-3",children:[h.jsx(pi,{variant:"text",width:"1.5rem",height:"10px",className:"flex-shrink-0 opacity-40"}),h.jsx(pi,{variant:"text",width:`${20+Math.random()*60}%`,height:"10px"})]},c))})}typeof window<"u"&&window.addEventListener("beforeunload",i=>{delete i.returnValue});const v2=v.lazy(()=>tt(()=>import("./HomePage-
|
|
438
|
+
`}),h.jsx("span",{className:`flex-shrink-0 mt-0.5 ${p.icon}`,children:h.jsx(p.IconComponent,{size:18})}),h.jsxs("div",{className:"flex-1 min-w-0",children:[h.jsx("p",{className:"text-sm font-medium text-[#201515] dark:text-[#E8E6E3]",children:o}),d&&h.jsx("p",{className:"text-xs text-[#6B6960] dark:text-[#8A8880] mt-0.5",children:d})]}),h.jsx("button",{onClick:x,className:"flex-shrink-0 text-[#939084] hover:text-[#36342E] dark:hover:text-[#E8E6E3] transition-colors","aria-label":"Dismiss notification",children:h.jsx(ea,{size:14})})]})}function m2({notifications:i,onDismiss:c}){return i.length===0?null:h.jsx("div",{className:"fixed top-4 right-4 z-[9999] flex flex-col gap-2 pointer-events-none","aria-live":"polite",children:i.map(r=>h.jsx(h2,{notification:r,onDismiss:c},r.id))})}const Rm=v.createContext({notify:()=>"",dismiss:()=>{},dismissAll:()=>{}});let y2=0;function p2({children:i}){const[c,r]=v.useState([]),o=v.useCallback(E=>{const x=`notif-${++y2}-${Date.now()}`,y={...E,id:x};if(r(z=>[...z,y]),document.hidden&&"Notification"in window)if(Notification.permission==="granted")try{new Notification(E.title,{body:E.message||""})}catch{}else Notification.permission!=="denied"&&Notification.requestPermission().then(z=>{if(z==="granted")try{new Notification(E.title,{body:E.message||""})}catch{}});return x},[]),d=v.useCallback(E=>{r(x=>x.filter(y=>y.id!==E))},[]),m=v.useCallback(()=>{r([])},[]),p=v.useMemo(()=>({notify:o,dismiss:d,dismissAll:m}),[o,d,m]);return h.jsxs(Rm.Provider,{value:p,children:[i,h.jsx(m2,{notifications:c,onDismiss:d})]})}function L2(){return v.useContext(Rm)}function Fs({children:i}){const{user:c,loading:r,isLocalMode:o}=_m();return r?h.jsx("div",{className:"h-screen bg-[#FAF9F6] flex items-center justify-center text-[#6B6960] text-sm",children:"Loading..."}):o?h.jsx(h.Fragment,{children:i}):c?h.jsx(h.Fragment,{children:i}):h.jsx(o1,{to:"/login",replace:!0})}function pi({variant:i="text",width:c,height:r,className:o=""}){const d="animate-pulse bg-[#ECEAE3]/60 rounded";if(i==="circle"){const m=c||"2rem";return h.jsx("div",{className:`${d} rounded-full flex-shrink-0 ${o}`,style:{width:m,height:m}})}return i==="block"?h.jsx("div",{className:`${d} rounded-btn ${o}`,style:{width:c||"100%",height:r||"4rem"}}):h.jsx("div",{className:`${d} rounded-btn ${o}`,style:{width:c||"100%",height:r||"0.75rem"}})}function B2(){return h.jsx("div",{className:"p-4 space-y-3",children:[...Array(12)].map((i,c)=>h.jsxs("div",{className:"flex items-center gap-3",children:[h.jsx(pi,{variant:"text",width:"1.5rem",height:"10px",className:"flex-shrink-0 opacity-40"}),h.jsx(pi,{variant:"text",width:`${20+Math.random()*60}%`,height:"10px"})]},c))})}typeof window<"u"&&window.addEventListener("beforeunload",i=>{delete i.returnValue});const v2=v.lazy(()=>tt(()=>import("./HomePage-nsr4kpN1.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]))),g2=v.lazy(()=>tt(()=>import("./ProjectPage-DMnbw9X9.js").then(i=>i.P),__vite__mapDeps([17,2,18,3,4,10,16,19,7,20,21,22,9,23,13,24,25,8,26,27,28,29,30,31,12,32,14,33,34,35]))),b2=v.lazy(()=>tt(()=>import("./CockpitPage-Czk7o_ou.js"),__vite__mapDeps([36,2,28,9,7,24,29,23]))),x2=v.lazy(()=>tt(()=>import("./ProjectsPage-CNVTAF2N.js"),__vite__mapDeps([37,18,6,7,8,9,1,25,30,27]))),S2=v.lazy(()=>tt(()=>import("./TemplatesPage-B6iFgH6t.js"),__vite__mapDeps([38,18,1,39,7,14,9,10,26,34,22,40,30]))),E2=v.lazy(()=>tt(()=>import("./SettingsPage-D1_qasFD.js"),__vite__mapDeps([41,31,13,11,23,9,8]))),_2=v.lazy(()=>tt(()=>import("./LoginPage-BVblQrr9.js"),[])),T2=v.lazy(()=>tt(()=>import("./TeamsPage-CY8p-yxD.js"),__vite__mapDeps([42,18,43,4,20,44,7,16,19,13,30]))),z2=v.lazy(()=>tt(()=>import("./AdminPage-Oyx-w2Ch.js"),__vite__mapDeps([45,18,32,7,43,20,25,26,39,9,24,44,40,4,21,46]))),N2=v.lazy(()=>tt(()=>import("./SystemSettingsPage-Djo6IE4u.js"),__vite__mapDeps([47,34,13,15,40,46]))),C2=v.lazy(()=>tt(()=>import("./MetricsPage-BVfwU81j.js"),__vite__mapDeps([48,5,24,14,32,33]))),j2=v.lazy(()=>tt(()=>import("./ShowcasePage-2dBCjLXn.js"),[])),R2=v.lazy(()=>tt(()=>import("./MagicPage-CmnSyLq7.js"),__vite__mapDeps([49,29,8,23,12]))),A2=v.lazy(()=>tt(()=>import("./ComparePage-BEfTrTb1.js"),[])),O2=v.lazy(()=>tt(()=>import("./NotFoundPage-AYQ6uqqI.js"),[]));function et(){return h.jsxs("div",{className:"h-screen bg-[#FAF9F6] flex flex-col items-center justify-center gap-3",children:[h.jsx(pi,{variant:"block",width:"200px",height:"24px"}),h.jsx(pi,{variant:"text",width:"140px",height:"12px",className:"opacity-50"})]})}function M2(){return h.jsx(Dg,{children:h.jsx(p2,{children:h.jsxs(d1,{children:[h.jsx(Ke,{path:"/login",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(_2,{})})}),h.jsx(Ke,{path:"/project/:sessionId/cockpit",element:h.jsx(Fs,{children:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(b2,{})})})}),h.jsx(Ke,{path:"/project/:sessionId",element:h.jsx(Fs,{children:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(g2,{})})})}),h.jsxs(Ke,{element:h.jsx(Fs,{children:h.jsx(f2,{})}),children:[h.jsx(Ke,{path:"/",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(v2,{})})}),h.jsx(Ke,{path:"/projects",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(x2,{})})}),h.jsx(Ke,{path:"/templates",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(S2,{})})}),h.jsx(Ke,{path:"/settings",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(E2,{})})}),h.jsx(Ke,{path:"/teams",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(T2,{})})}),h.jsx(Ke,{path:"/metrics",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(C2,{})})}),h.jsx(Ke,{path:"/showcase",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(j2,{})})}),h.jsx(Ke,{path:"/magic",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(R2,{})})}),h.jsx(Ke,{path:"/compare",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(A2,{})})}),h.jsx(Ke,{path:"/admin",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(z2,{})})}),h.jsx(Ke,{path:"/admin/settings",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(N2,{})})}),h.jsx(Ke,{path:"*",element:h.jsx(v.Suspense,{fallback:h.jsx(et,{}),children:h.jsx(O2,{})})})]})]})})})}const D2="/lab/".replace(/\/$/,"")||"/";fp.createRoot(document.getElementById("root")).render(h.jsx(v.StrictMode,{children:h.jsx(H1,{basename:D2,children:h.jsx(M2,{})})}));export{Kv as $,dm as A,hm as B,ym as C,Wv as D,bv as E,vm as F,Cv as G,B2 as H,Dv as I,fm as J,gm as K,so as L,oo as M,pi as N,H2 as O,bm as P,vv as Q,ro as R,ug as S,gg as T,xg as U,Og as V,w2 as W,ea as X,yv as Y,Rg as Z,tt as _,Ba as a,_m as a0,L2 as a1,_v as a2,sm as a3,Ov as a4,Tg as a5,dg as b,W as c,r2 as d,k2 as e,Ng as f,mm as g,nv as h,pg as i,h as j,hv as k,rv as l,lg as m,Kg as n,Jg as o,wh as p,sv as q,v as r,og as s,Xv as t,ao as u,fo as v,lv as w,cg as x,pm as y,xm as z};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./index-
|
|
1
|
+
import{r as e}from"./index-CxajNJVu.js";function m(s,u=2e3,a=!0){const[c,l]=e.useState(null),[f,o]=e.useState(null),[i,d]=e.useState(!0),r=e.useRef(!0),n=e.useCallback(async()=>{try{const t=await s();r.current&&(l(t),o(null))}catch(t){r.current&&o(t instanceof Error?t.message:"Unknown error")}finally{r.current&&d(!1)}},[s]);return e.useEffect(()=>{if(r.current=!0,!a)return;n();const t=setInterval(n,u);return()=>{r.current=!1,clearInterval(t)}},[n,u,a]),{data:c,error:f,loading:i,refresh:n}}export{m as u};
|
package/web-app/dist/index.html
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
9
|
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
|
10
|
-
<script type="module" crossorigin src="/lab/assets/index-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/lab/assets/index-
|
|
10
|
+
<script type="module" crossorigin src="/lab/assets/index-CxajNJVu.js"></script>
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/lab/assets/index-BfQ0f3-S.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body class="bg-background text-ink font-sans antialiased">
|
|
14
14
|
<div id="root"></div>
|
package/web-app/server.py
CHANGED
|
@@ -3638,7 +3638,25 @@ async def get_metrics() -> JSONResponse:
|
|
|
3638
3638
|
|
|
3639
3639
|
|
|
3640
3640
|
def _infer_session_status(entry: Path) -> str:
|
|
3641
|
-
"""Infer session status from project directory contents.
|
|
3641
|
+
"""Infer session status from project directory contents.
|
|
3642
|
+
|
|
3643
|
+
Returns "unknown" (rather than guessing "completed") whenever the only
|
|
3644
|
+
evidence is a state file that has simply gone stale, or a directory that
|
|
3645
|
+
merely contains a source file -- neither is a clean-exit marker, and both
|
|
3646
|
+
used to be misreported as "completed".
|
|
3647
|
+
"""
|
|
3648
|
+
# Phase/status strings that describe a run no longer in flight. Anything
|
|
3649
|
+
# else (a RARV step, "running", a custom in-progress label, ...) is only
|
|
3650
|
+
# trustworthy while the state file is fresh -- once it goes stale we no
|
|
3651
|
+
# longer know if the process is still alive, so we must not keep
|
|
3652
|
+
# reporting it as active, and we must not guess "completed" either.
|
|
3653
|
+
_TERMINAL_STATUSES = {"completed", "failed", "paused", "stopped", "cancelled"}
|
|
3654
|
+
|
|
3655
|
+
# Set when dashboard-state.json had a non-idle phase we could not trust
|
|
3656
|
+
# outright (stale and not a terminal phase), so a directory-contents
|
|
3657
|
+
# guess below must not silently overrule it either.
|
|
3658
|
+
saw_untrusted_activity = False
|
|
3659
|
+
|
|
3642
3660
|
# 1. Check .loki/dashboard-state.json for explicit phase
|
|
3643
3661
|
# BUG-INT-002 fix: CLI writes dashboard-state.json, not state/session.json
|
|
3644
3662
|
state_file = entry / ".loki" / "dashboard-state.json"
|
|
@@ -3648,15 +3666,19 @@ def _infer_session_status(entry: Path) -> str:
|
|
|
3648
3666
|
st = json.load(f)
|
|
3649
3667
|
phase = st.get("phase", "")
|
|
3650
3668
|
if phase and phase != "idle":
|
|
3651
|
-
|
|
3652
|
-
|
|
3669
|
+
if phase.lower() in _TERMINAL_STATUSES:
|
|
3670
|
+
return phase
|
|
3671
|
+
# Active-looking phase: only trustworthy while fresh. Staleness
|
|
3672
|
+
# means "we can't tell if this is still running" -- it is not
|
|
3673
|
+
# evidence the run finished cleanly, so fall through instead
|
|
3674
|
+
# of returning or guessing "completed".
|
|
3653
3675
|
try:
|
|
3654
3676
|
mtime = state_file.stat().st_mtime
|
|
3655
|
-
if time.time() - mtime
|
|
3656
|
-
return
|
|
3677
|
+
if time.time() - mtime <= 300: # fresh enough to trust
|
|
3678
|
+
return phase
|
|
3657
3679
|
except OSError:
|
|
3658
|
-
|
|
3659
|
-
|
|
3680
|
+
return phase
|
|
3681
|
+
saw_untrusted_activity = True
|
|
3660
3682
|
except (json.JSONDecodeError, OSError):
|
|
3661
3683
|
pass
|
|
3662
3684
|
|
|
@@ -3671,18 +3693,28 @@ def _infer_session_status(entry: Path) -> str:
|
|
|
3671
3693
|
return "completed"
|
|
3672
3694
|
if st.get("status"):
|
|
3673
3695
|
status_val = st["status"]
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3696
|
+
if status_val.lower() in _TERMINAL_STATUSES:
|
|
3697
|
+
return status_val
|
|
3698
|
+
# Active-looking status: only trustworthy while fresh.
|
|
3699
|
+
# A stale one is unknown, not completed -- the process may
|
|
3700
|
+
# have died mid-run without recording why.
|
|
3701
|
+
try:
|
|
3702
|
+
mtime = sf.stat().st_mtime
|
|
3703
|
+
if time.time() - mtime > 300: # 5 minutes stale
|
|
3704
|
+
return "unknown"
|
|
3705
|
+
except OSError:
|
|
3706
|
+
pass
|
|
3682
3707
|
return status_val
|
|
3683
3708
|
except (json.JSONDecodeError, OSError):
|
|
3684
3709
|
pass
|
|
3685
3710
|
|
|
3711
|
+
# Neither state file gave a definitive, still-trustworthy answer, but one
|
|
3712
|
+
# of them showed activity we couldn't corroborate. We know *something*
|
|
3713
|
+
# was in flight, not whether it finished -- that is "unknown", not a
|
|
3714
|
+
# guess drawn from directory contents.
|
|
3715
|
+
if saw_untrusted_activity:
|
|
3716
|
+
return "unknown"
|
|
3717
|
+
|
|
3686
3718
|
# 3. Infer from file contents
|
|
3687
3719
|
files = set()
|
|
3688
3720
|
try:
|
|
@@ -3699,7 +3731,9 @@ def _infer_session_status(entry: Path) -> str:
|
|
|
3699
3731
|
has_prd = "PRD.md" in files or "prd.md" in files
|
|
3700
3732
|
|
|
3701
3733
|
if has_source:
|
|
3702
|
-
|
|
3734
|
+
# A source file is not a completion marker -- it says nothing about
|
|
3735
|
+
# whether the run finished, failed, or is still in progress.
|
|
3736
|
+
return "unknown"
|
|
3703
3737
|
if has_prd and len(files) <= 2:
|
|
3704
3738
|
return "started"
|
|
3705
3739
|
if has_prd:
|
|
@@ -7387,7 +7421,8 @@ async def github_get_pr(session_id: str, pr_number: int) -> JSONResponse:
|
|
|
7387
7421
|
None, lambda: _run_gh([
|
|
7388
7422
|
"pr", "view", str(pr_number),
|
|
7389
7423
|
"--repo", repo,
|
|
7390
|
-
"--json", "number,title,body,state,author,comments,reviews,files,additions,deletions,commits"
|
|
7424
|
+
"--json", "number,title,body,state,author,comments,reviews,files,additions,deletions,commits,"
|
|
7425
|
+
"headRefName,baseRefName,changedFiles,reviewDecision,statusCheckRollup",
|
|
7391
7426
|
], cwd=str(target))
|
|
7392
7427
|
)
|
|
7393
7428
|
if result.returncode != 0:
|