loki-mode 9.54.2 → 9.56.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.
Files changed (109) hide show
  1. package/.github/actions/issue-to-pr/action.yml +165 -29
  2. package/.github/workflows/loki-issue-to-pr.yml +137 -24
  3. package/README.md +1 -1
  4. package/SKILL.md +2 -2
  5. package/VERSION +1 -1
  6. package/autonomy/completion-council.sh +110 -34
  7. package/autonomy/crash.sh +6 -6
  8. package/autonomy/lib/done-recognition.sh +7 -0
  9. package/autonomy/lib/prd-enrich.sh +7 -0
  10. package/autonomy/lib/proof-check.sh +9 -0
  11. package/autonomy/lib/proof-generator.py +12 -3
  12. package/autonomy/lib/proof-verify.py +93 -21
  13. package/autonomy/lib/voter-agents.sh +7 -0
  14. package/autonomy/lib/workspace_diff.py +18 -7
  15. package/autonomy/loki +537 -122
  16. package/autonomy/quickstart.sh +7 -0
  17. package/autonomy/run.sh +956 -37
  18. package/autonomy/verify.sh +114 -8
  19. package/bin/loki +12 -0
  20. package/dashboard/__init__.py +1 -1
  21. package/dashboard/api_keys.py +12 -5
  22. package/dashboard/build_supervisor.py +25 -1
  23. package/dashboard/server.py +46 -24
  24. package/dashboard/static/index.html +57 -57
  25. package/docs/INSTALLATION.md +6 -5
  26. package/docs/VERIFIED-COMPLETION-PLAN.md +7 -5
  27. package/docs/air-gapped.md +39 -17
  28. package/docs/enterprise/security.md +10 -13
  29. package/docs/environment-variables.md +2 -0
  30. package/docs/exit-codes.md +76 -2
  31. package/docs/v10/BACKLOG.md +56 -0
  32. package/docs/v10/BOARD.md +118 -32
  33. package/docs/v10/CONTROL.md +36 -0
  34. package/docs/v10/DECISIONS.md +74 -0
  35. package/docs/v10/METRICS.md +78 -1
  36. package/docs/v10/PROGRESS.md +928 -0
  37. package/loki-ts/dist/loki.js +331 -327
  38. package/mcp/__init__.py +1 -1
  39. package/package.json +1 -1
  40. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  41. package/providers/claude.sh +1 -1
  42. package/providers/loader.sh +10 -0
  43. package/providers/model_catalog.json +12 -5
  44. package/providers/models.sh +1 -1
  45. package/references/core-workflow.md +1 -1
  46. package/tools/receipt-attest.py +1 -1
  47. package/web-app/dist/assets/{AdminPage-CZrBkzRF.js → AdminPage-Oyx-w2Ch.js} +1 -1
  48. package/web-app/dist/assets/{Avatar-gQIp6FBI.js → Avatar-D60m65JB.js} +1 -1
  49. package/web-app/dist/assets/{Badge-D2_fBTFY.js → Badge-CqfZNaem.js} +1 -1
  50. package/web-app/dist/assets/{Button-D5qDd2ef.js → Button-BqjzE4fz.js} +1 -1
  51. package/web-app/dist/assets/CockpitPage-Czk7o_ou.js +47 -0
  52. package/web-app/dist/assets/ComparePage-BEfTrTb1.js +1 -0
  53. package/web-app/dist/assets/{ErrorBoundary-BRABI-BT.js → ErrorBoundary-BrLk5nkO.js} +1 -1
  54. package/web-app/dist/assets/EvidenceReceiptPanel-9vEpi5ir.js +1 -0
  55. package/web-app/dist/assets/{GitHubIssuesPanel-BC5GzKUN.js → GitHubIssuesPanel-D6izZx0w.js} +1 -1
  56. package/web-app/dist/assets/GitHubPRsPanel-BTkG2FgA.js +17 -0
  57. package/web-app/dist/assets/{HomePage-D_CDMoen.js → HomePage-nsr4kpN1.js} +2 -2
  58. package/web-app/dist/assets/{LoginPage-BBNA_N9t.js → LoginPage-BVblQrr9.js} +1 -1
  59. package/web-app/dist/assets/{MagicPage-CnFRZCMx.js → MagicPage-CmnSyLq7.js} +1 -1
  60. package/web-app/dist/assets/{MetricsPage-CPfLMRlh.js → MetricsPage-BVfwU81j.js} +1 -1
  61. package/web-app/dist/assets/{NotFoundPage-lA0XSGTz.js → NotFoundPage-AYQ6uqqI.js} +1 -1
  62. package/web-app/dist/assets/{ProjectPage-CNAPbr9z.js → ProjectPage-DMnbw9X9.js} +3 -3
  63. package/web-app/dist/assets/{ProjectsPage-CMtm8goN.js → ProjectsPage-CNVTAF2N.js} +1 -1
  64. package/web-app/dist/assets/{SettingsPage-BhIjVMYE.js → SettingsPage-D1_qasFD.js} +3 -3
  65. package/web-app/dist/assets/{ShowcasePage-BndtGeYo.js → ShowcasePage-2dBCjLXn.js} +1 -1
  66. package/web-app/dist/assets/{SystemSettingsPage-euXI-KXE.js → SystemSettingsPage-Djo6IE4u.js} +1 -1
  67. package/web-app/dist/assets/{TeamsPage-ClUKecun.js → TeamsPage-CY8p-yxD.js} +1 -1
  68. package/web-app/dist/assets/{TemplatesPage-BWHWVk0L.js → TemplatesPage-B6iFgH6t.js} +1 -1
  69. package/web-app/dist/assets/{TerminalOutput-Cv3N3Szf.js → TerminalOutput-B3yzZe-h.js} +1 -1
  70. package/web-app/dist/assets/{activity-dEhz-bXR.js → activity-CNfAjtRv.js} +1 -1
  71. package/web-app/dist/assets/{bell-B3XUMq1t.js → bell-CMETsHPH.js} +1 -1
  72. package/web-app/dist/assets/{bot-X-ssNlwR.js → bot-C9kXvk1i.js} +1 -1
  73. package/web-app/dist/assets/{check-C_9Nx7kb.js → check-BRK-zLB5.js} +1 -1
  74. package/web-app/dist/assets/{chevron-left-tvNswo3A.js → chevron-left-CxI5uD4g.js} +1 -1
  75. package/web-app/dist/assets/{circle-alert-CSB88nEs.js → circle-alert-CVFRPWpv.js} +1 -1
  76. package/web-app/dist/assets/{clock-C8p2e4NI.js → clock-CLYV8a_x.js} +1 -1
  77. package/web-app/dist/assets/{cloud-CKp2ZvhG.js → cloud-CiISiIOa.js} +1 -1
  78. package/web-app/dist/assets/{code-xml-dY70LCHD.js → code-xml-DHsgqwV-.js} +1 -1
  79. package/web-app/dist/assets/{database-DObn5fmn.js → database-DbvUqtz3.js} +1 -1
  80. package/web-app/dist/assets/{dollar-sign-DSu6n3K3.js → dollar-sign-Ct0lRPHw.js} +1 -1
  81. package/web-app/dist/assets/{file-code-corner-DpCnS73z.js → file-code-corner-D1sjFEh7.js} +1 -1
  82. package/web-app/dist/assets/{file-plus-D3IPKCf1.js → file-plus-DnmX18Fi.js} +1 -1
  83. package/web-app/dist/assets/{globe-C9QXkgH_.js → globe-bSpDNgoA.js} +1 -1
  84. package/web-app/dist/assets/{hammer-D_FtWe1y.js → hammer-Bj41Kvlq.js} +1 -1
  85. package/web-app/dist/assets/{index-CI54rara.css → index-BfQ0f3-S.css} +1 -1
  86. package/web-app/dist/assets/{index-Cz7q1bvC.js → index-CxajNJVu.js} +3 -3
  87. package/web-app/dist/assets/{layers-DsW7jnJX.js → layers-BNtBwYER.js} +1 -1
  88. package/web-app/dist/assets/{loader-circle-B3HspjKR.js → loader-circle-YY_VZofG.js} +1 -1
  89. package/web-app/dist/assets/{lock-DSI29pct.js → lock-rpjEPVoC.js} +1 -1
  90. package/web-app/dist/assets/{package-CLNxtA2x.js → package-desXU6XA.js} +1 -1
  91. package/web-app/dist/assets/{plus-DyI4WC4_.js → plus-7AoOU-I9.js} +1 -1
  92. package/web-app/dist/assets/{refresh-cw-D2dv0xA0.js → refresh-cw-oNj-Xn4B.js} +1 -1
  93. package/web-app/dist/assets/{rotate-ccw-CBvihA-a.js → rotate-ccw-DeiFjfVO.js} +1 -1
  94. package/web-app/dist/assets/{scroll-text-DvoOvAl_.js → scroll-text-Q9AzWiNV.js} +1 -1
  95. package/web-app/dist/assets/{server-DenWvSUt.js → server-DKgVwfek.js} +1 -1
  96. package/web-app/dist/assets/{shield-alert-40cX_FvG.js → shield-alert-G6x-bS-I.js} +1 -1
  97. package/web-app/dist/assets/{thumbs-up-BrjZ6QuV.js → thumbs-up-Qhk0yvw0.js} +1 -1
  98. package/web-app/dist/assets/{trash-2-C6evwkEH.js → trash-2-D23gvznl.js} +1 -1
  99. package/web-app/dist/assets/{trending-down-CfbZis3O.js → trending-down-CSQClPrr.js} +1 -1
  100. package/web-app/dist/assets/{trending-up-DWuEK3WC.js → trending-up-sjMSd1wc.js} +1 -1
  101. package/web-app/dist/assets/{upload-B9DFBcPG.js → upload-Dchovhld.js} +1 -1
  102. package/web-app/dist/assets/{usePolling-BryVC-T1.js → usePolling-DwLceXwF.js} +1 -1
  103. package/web-app/dist/assets/{user-DMRXwZiw.js → user-BqZM8CmD.js} +1 -1
  104. package/web-app/dist/index.html +2 -2
  105. package/web-app/server.py +52 -17
  106. package/web-app/dist/assets/CockpitPage-DVMk2RUK.js +0 -47
  107. package/web-app/dist/assets/ComparePage-NMLyE1xL.js +0 -1
  108. package/web-app/dist/assets/EvidenceReceiptPanel-D2LNKqUx.js +0 -1
  109. 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-D_CDMoen.js","assets/usePolling-BryVC-T1.js","assets/ErrorBoundary-BRABI-BT.js","assets/TerminalOutput-Cv3N3Szf.js","assets/lock-DSI29pct.js","assets/EvidenceReceiptPanel-D2LNKqUx.js","assets/Badge-D2_fBTFY.js","assets/clock-C8p2e4NI.js","assets/circle-alert-CSB88nEs.js","assets/check-C_9Nx7kb.js","assets/package-CLNxtA2x.js","assets/cloud-CKp2ZvhG.js","assets/code-xml-dY70LCHD.js","assets/hammer-D_FtWe1y.js","assets/layers-DsW7jnJX.js","assets/bell-B3XUMq1t.js","assets/file-code-corner-DpCnS73z.js","assets/ProjectPage-CNAPbr9z.js","assets/Button-D5qDd2ef.js","assets/file-plus-D3IPKCf1.js","assets/activity-dEhz-bXR.js","assets/scroll-text-DvoOvAl_.js","assets/bot-X-ssNlwR.js","assets/loader-circle-B3HspjKR.js","assets/dollar-sign-DSu6n3K3.js","assets/refresh-cw-D2dv0xA0.js","assets/globe-C9QXkgH_.js","assets/trash-2-C6evwkEH.js","assets/thumbs-up-BrjZ6QuV.js","assets/upload-B9DFBcPG.js","assets/plus-DyI4WC4_.js","assets/rotate-ccw-CBvihA-a.js","assets/trending-up-DWuEK3WC.js","assets/trending-down-CfbZis3O.js","assets/server-DenWvSUt.js","assets/ProjectPage-9CEnUXvW.css","assets/CockpitPage-DVMk2RUK.js","assets/ProjectsPage-CMtm8goN.js","assets/TemplatesPage-BWHWVk0L.js","assets/chevron-left-tvNswo3A.js","assets/database-DObn5fmn.js","assets/SettingsPage-BhIjVMYE.js","assets/TeamsPage-ClUKecun.js","assets/Avatar-gQIp6FBI.js","assets/user-DMRXwZiw.js","assets/AdminPage-CZrBkzRF.js","assets/shield-alert-40cX_FvG.js","assets/SystemSettingsPage-euXI-KXE.js","assets/MetricsPage-CPfLMRlh.js","assets/MagicPage-CnFRZCMx.js"])))=>i.map(i=>d[i]);
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-D_CDMoen.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-CNAPbr9z.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-DVMk2RUK.js"),__vite__mapDeps([36,2,28,9,7,24,29,23]))),x2=v.lazy(()=>tt(()=>import("./ProjectsPage-CMtm8goN.js"),__vite__mapDeps([37,18,6,7,8,9,1,25,30,27]))),S2=v.lazy(()=>tt(()=>import("./TemplatesPage-BWHWVk0L.js"),__vite__mapDeps([38,18,1,39,7,14,9,10,26,34,22,40,30]))),E2=v.lazy(()=>tt(()=>import("./SettingsPage-BhIjVMYE.js"),__vite__mapDeps([41,31,13,11,23,9,8]))),_2=v.lazy(()=>tt(()=>import("./LoginPage-BBNA_N9t.js"),[])),T2=v.lazy(()=>tt(()=>import("./TeamsPage-ClUKecun.js"),__vite__mapDeps([42,18,43,4,20,44,7,16,19,13,30]))),z2=v.lazy(()=>tt(()=>import("./AdminPage-CZrBkzRF.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-euXI-KXE.js"),__vite__mapDeps([47,34,13,15,40,46]))),C2=v.lazy(()=>tt(()=>import("./MetricsPage-CPfLMRlh.js"),__vite__mapDeps([48,5,24,14,32,33]))),j2=v.lazy(()=>tt(()=>import("./ShowcasePage-BndtGeYo.js"),[])),R2=v.lazy(()=>tt(()=>import("./MagicPage-CnFRZCMx.js"),__vite__mapDeps([49,29,8,23,12]))),A2=v.lazy(()=>tt(()=>import("./ComparePage-NMLyE1xL.js"),[])),O2=v.lazy(()=>tt(()=>import("./NotFoundPage-lA0XSGTz.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,yv as V,w2 as W,ea as X,Og 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};
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,4 +1,4 @@
1
- import{c as a}from"./index-Cz7q1bvC.js";/**
1
+ import{c as a}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-Cz7q1bvC.js";/**
1
+ import{c}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-Cz7q1bvC.js";/**
1
+ import{c}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-Cz7q1bvC.js";/**
1
+ import{c as a}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-Cz7q1bvC.js";/**
1
+ import{c as e}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-Cz7q1bvC.js";/**
1
+ import{c as e}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-Cz7q1bvC.js";/**
1
+ import{c as e}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-Cz7q1bvC.js";/**
1
+ import{c as a}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-Cz7q1bvC.js";/**
1
+ import{c as e}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-Cz7q1bvC.js";/**
1
+ import{c as e}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-Cz7q1bvC.js";/**
1
+ import{c}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-Cz7q1bvC.js";/**
1
+ import{c as a}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as n}from"./index-Cz7q1bvC.js";/**
1
+ import{c as n}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-Cz7q1bvC.js";/**
1
+ import{c as e}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-Cz7q1bvC.js";/**
1
+ import{c as a}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as e}from"./index-Cz7q1bvC.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};
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};
@@ -1,4 +1,4 @@
1
- import{c}from"./index-Cz7q1bvC.js";/**
1
+ import{c}from"./index-CxajNJVu.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -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-Cz7q1bvC.js"></script>
11
- <link rel="stylesheet" crossorigin href="/lab/assets/index-CI54rara.css">
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
- # Verify the session is actually still running by checking
3652
- # if dashboard-state.json was modified recently (within last 5 min)
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 > 300: # 5 minutes stale
3656
- return "completed" # Process died, mark as completed
3677
+ if time.time() - mtime <= 300: # fresh enough to trust
3678
+ return phase
3657
3679
  except OSError:
3658
- pass
3659
- return phase
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
- # If status indicates active work, verify freshness
3675
- if status_val in ("running", "in_progress", "planning"):
3676
- try:
3677
- mtime = sf.stat().st_mtime
3678
- if time.time() - mtime > 300: # 5 minutes stale
3679
- return "completed"
3680
- except OSError:
3681
- pass
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
- return "completed"
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: