loki-mode 6.41.0 → 6.42.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.
@@ -0,0 +1,321 @@
1
+ # PRD: Purple Lab Platform -- Hosted Autonomous Development IDE
2
+
3
+ ## Vision
4
+
5
+ Purple Lab becomes a hosted development platform like Replit, but for autonomous AI-powered development. Users describe what they want, agents build it, and they can browse/edit/preview/deploy -- all from the browser. Autonomi manages the infrastructure, storage, and compute. No CLI installation needed.
6
+
7
+ ## Key Insight
8
+
9
+ Loki Mode already has 75+ commands and 120+ API endpoints. The platform doesn't need new capabilities -- it needs to surface existing ones through a production-grade web interface that matches or exceeds Replit's UX.
10
+
11
+ ---
12
+
13
+ ## Architecture: Local vs Hosted
14
+
15
+ **Current (Local):** User installs CLI, runs `loki start`, views results locally.
16
+
17
+ **Platform (Hosted):** User opens purplelab.dev (or app.autonomi.dev), types a prompt or picks a template, agents build on Autonomi infrastructure, user browses/edits/deploys from browser. Backend is the same server.py + run.sh, containerized per-workspace.
18
+
19
+ **Per-workspace container model:**
20
+ - Each project gets an isolated container (Docker or Firecracker)
21
+ - Container runs: Purple Lab server + loki CLI + language runtimes
22
+ - Persistent volume for project files
23
+ - Ephemeral compute for builds (scale to zero when idle)
24
+ - WebSocket proxy for real-time terminal/logs/preview
25
+
26
+ ---
27
+
28
+ ## Page Structure
29
+
30
+ ### Page 1: Home (landing)
31
+ **URL:** `/`
32
+
33
+ **Layout:** Sidebar + main content (like Replit)
34
+
35
+ **Left sidebar:**
36
+ - Workspace name / avatar
37
+ - Navigation: Home, Projects, Templates, Integrations, Settings
38
+ - Bottom: Docs, Changelog, version
39
+
40
+ **Main content:**
41
+ - Prompt input: "Describe what you want to build..." with Plan toggle
42
+ - Category shortcuts: Website, API, CLI, Mobile, Bot, Data Pipeline (maps to Loki templates)
43
+ - Example prompts: rotated from curated list
44
+ - Recent Projects: card grid with thumbnail, name, date, status, file count
45
+
46
+ **Loki features surfaced:**
47
+ - `loki init` templates -> category shortcuts
48
+ - `loki plan` -> Plan toggle (shows estimate before building)
49
+ - `loki start` -> Submit prompt
50
+ - Session history -> Recent Projects
51
+
52
+ ---
53
+
54
+ ### Page 2: Projects List
55
+ **URL:** `/projects`
56
+
57
+ **Layout:** Sidebar + grid/list
58
+
59
+ - Search and filter (status, date, provider, complexity)
60
+ - Project cards: thumbnail (screenshot or file tree preview), name, status badge, date, file count, provider used
61
+ - Actions: Open, Delete, Duplicate, Export
62
+ - Sorting: newest first, name, status
63
+
64
+ **Loki features surfaced:**
65
+ - Session history API -> project list
66
+ - `loki export` -> Export action
67
+ - `loki share` -> Share as Gist action
68
+
69
+ ---
70
+
71
+ ### Page 3: Workspace (IDE)
72
+ **URL:** `/project/:id`
73
+
74
+ **Layout:** Full-screen IDE (already built in v6.41.0, needs enhancement)
75
+
76
+ **Left panel: File Explorer**
77
+ - File tree (exists)
78
+ - Search files (Cmd+P, exists)
79
+ - New file/folder (exists)
80
+ - Git status indicators (show modified/added/untracked via colors)
81
+
82
+ **Center panel: Editor**
83
+ - Monaco editor (exists)
84
+ - Tabs (exists)
85
+ - Save with Cmd+S (exists)
86
+ - Unsaved indicator (exists)
87
+
88
+ **Right panel: Preview**
89
+ - Live preview iframe (exists, needs enhancement)
90
+ - URL bar with current path
91
+ - Back/Forward/Refresh buttons
92
+ - Open in new tab button
93
+ - Auto-refresh on save (exists)
94
+
95
+ **Bottom panel: Activity (NEW)**
96
+ - Tabs: Terminal | Agent Log | Build Output | Quality Gates | AI Chat
97
+ - **Terminal tab:** Real-time loki session output (already streamed via WebSocket)
98
+ - **Agent Log tab:** Shows which agents are active, what they're working on (uses `/api/agents` and `/api/session/agents`)
99
+ - **Build Output tab:** Structured build phases -- RARV cycle visualization, iteration count, current phase
100
+ - **Quality Gates tab:** 9-gate status display (uses existing checklist/quality endpoints)
101
+ - **AI Chat tab:** Send messages to iterate on the project ("fix the login page", "add dark mode") -- triggers `loki start` with the prompt as PRD amendment
102
+
103
+ **Header toolbar:**
104
+ - Project name + status
105
+ - Provider selector: Claude / Codex / Gemini (uses `loki provider set`)
106
+ - Mode selector: Quick (3 iterations) / Standard (5) / Max (8+) -- maps to complexity tiers
107
+ - Run button (re-run build with current PRD)
108
+ - Stop/Pause/Resume buttons (exist)
109
+ - Share button -> GitHub Gist (`loki share`)
110
+ - Deploy button (future: `loki deploy`)
111
+ - Settings gear -> project config
112
+
113
+ ---
114
+
115
+ ### Page 4: Templates Gallery
116
+ **URL:** `/templates`
117
+
118
+ **Layout:** Grid of 22 template cards
119
+
120
+ Each card:
121
+ - Template name and description
122
+ - Category badge (Simple / Standard / Complex)
123
+ - Preview thumbnail
124
+ - "Use Template" button -> pre-fills PRD and navigates to Home
125
+
126
+ **Loki features surfaced:**
127
+ - All 22 `templates/*.md` files
128
+ - `loki plan` -> shows estimate on hover/click
129
+ - `loki init` -> scaffolds project
130
+
131
+ ---
132
+
133
+ ### Page 5: Integrations
134
+ **URL:** `/integrations`
135
+
136
+ **Layout:** List of integration cards
137
+
138
+ Integrations available:
139
+ - **GitHub**: Connect repo, import issues, create PRs (`loki github`, `loki run`)
140
+ - **Jira**: Bidirectional sync (`LOKI_JIRA_*` env vars)
141
+ - **Linear**: Issue sync (`LOKI_LINEAR_*` env vars)
142
+ - **Slack**: Notifications + slash commands (`LOKI_SLACK_*`)
143
+ - **Teams**: Adaptive Cards notifications (`LOKI_TEAMS_*`)
144
+ - **OpenTelemetry**: Trace export (`loki telemetry`)
145
+
146
+ Each card: name, description, status (Connected/Not configured), Configure button
147
+
148
+ ---
149
+
150
+ ### Page 6: Settings
151
+ **URL:** `/settings`
152
+
153
+ Sections:
154
+ - **Profile:** Name, email, avatar
155
+ - **Provider:** Default provider selection, API keys, model preferences
156
+ - **Enterprise:** Token management, OIDC/SSO config, audit log access
157
+ - **Notifications:** Email/Slack/Teams triggers
158
+ - **Billing:** Usage stats, cost tracking (uses `loki metrics` and `/api/cost`)
159
+
160
+ ---
161
+
162
+ ## Workspace Features Detail
163
+
164
+ ### AI Chat Panel (Key differentiator from Replit)
165
+
166
+ This is the "Loki way" -- instead of just editing code, users can talk to the AI to iterate:
167
+
168
+ **Input:** Text prompt at bottom of workspace (like Replit's Agent chat)
169
+ **Behavior:**
170
+ 1. User types "add a dark mode toggle"
171
+ 2. Purple Lab creates amendment to PRD
172
+ 3. Runs `loki start` in the background (or uses `loki quick` for small changes)
173
+ 4. Real-time agent activity streams to Agent Log tab
174
+ 5. File tree updates as agents create/modify files
175
+ 6. Preview auto-refreshes when build completes
176
+ 7. User can continue iterating
177
+
178
+ **This maps to Replit's "Agent modes":**
179
+ - **Quick mode** (like Lite): `loki quick "<prompt>"` -- 3 iterations, fast
180
+ - **Standard mode** (like Autonomous): `loki start` -- full RARV cycle
181
+ - **Max mode** (like Max): `loki start --complexity complex` -- extended iterations
182
+
183
+ ### Quality Gates Panel
184
+
185
+ Shows the 9 Loki quality gates in real-time:
186
+ 1. Static Analysis (CodeQL/ESLint)
187
+ 2. 3-Reviewer Blind Review
188
+ 3. Anti-Sycophancy Check
189
+ 4. Severity Blocking (Critical/High)
190
+ 5. Test Coverage (>80%)
191
+ 6. Security Scan (OWASP)
192
+ 7. Performance Check
193
+ 8. Mock Detector
194
+ 9. Mutation Detector
195
+
196
+ Each gate: name, status (pass/fail/pending), details expandable
197
+
198
+ ### Agent Activity
199
+
200
+ Real-time grid showing which of the 41 agent types are active:
201
+ - Agent name, type, swarm, model tier (Opus/Sonnet/Haiku)
202
+ - Current task
203
+ - Status (working/idle/completed)
204
+ - Duration
205
+
206
+ ### Memory System Viewer
207
+
208
+ Browse what the AI has learned across sessions:
209
+ - Episodic memory: specific interactions
210
+ - Semantic memory: generalized patterns
211
+ - Procedural memory: learned skills
212
+ - Token economics: discovery vs read efficiency
213
+
214
+ ### Code Review Panel
215
+
216
+ When quality gates run, show results:
217
+ - Findings by severity (Critical/High/Medium/Low)
218
+ - File + line links (click to jump in editor)
219
+ - Suggested fixes
220
+ - Approve/Reject actions
221
+
222
+ ---
223
+
224
+ ## API Endpoints Needed (New)
225
+
226
+ Most features use existing endpoints. New ones needed for hosted platform:
227
+
228
+ 1. `POST /api/workspace/create` -- create new workspace (container)
229
+ 2. `DELETE /api/workspace/:id` -- destroy workspace
230
+ 3. `GET /api/workspace/:id/status` -- container health
231
+ 4. `POST /api/chat` -- send AI chat message (triggers loki quick/start)
232
+ 5. `GET /api/templates` -- already exists
233
+ 6. `POST /api/project/duplicate` -- clone a project
234
+ 7. `POST /api/project/export` -- export as zip
235
+ 8. `GET /api/project/:id/screenshot` -- generate thumbnail (headless browser or placeholder)
236
+
237
+ ---
238
+
239
+ ## Implementation Phases
240
+
241
+ ### Phase 1: Platform Shell (1 week)
242
+ - Sidebar navigation with page routing
243
+ - Home page with prompt input + category shortcuts + recent projects
244
+ - Projects list page with cards
245
+ - Templates gallery page
246
+ - Settings page shell
247
+
248
+ ### Phase 2: Enhanced Workspace (1 week)
249
+ - Bottom activity panel with tabs (Terminal, Agents, Build, Quality, Chat)
250
+ - AI Chat input that triggers builds
251
+ - Quality gates real-time display
252
+ - Agent activity grid
253
+ - Preview URL bar with navigation
254
+ - Mode selector (Quick/Standard/Max)
255
+
256
+ ### Phase 3: Hosted Infrastructure (2 weeks)
257
+ - Per-workspace container orchestration
258
+ - Persistent storage per project
259
+ - User authentication (OIDC/email)
260
+ - Usage metering and billing hooks
261
+ - Custom domain for previews (project-id.purplelab.dev)
262
+
263
+ ### Phase 4: Polish (1 week)
264
+ - Project thumbnails/screenshots
265
+ - Integrations settings page
266
+ - Memory system browser
267
+ - Code review panel
268
+ - Onboarding flow for new users
269
+
270
+ ---
271
+
272
+ ## What We Already Have vs What's New
273
+
274
+ | Feature | Status | Source |
275
+ |---------|--------|--------|
276
+ | Monaco editor | DONE | v6.40.0 |
277
+ | File tree + CRUD | DONE | v6.40.0 |
278
+ | Tabs | DONE | v6.41.0 |
279
+ | Quick Open (Cmd+P) | DONE | v6.41.0 |
280
+ | Live preview | DONE | v6.39.0 |
281
+ | Preview auto-refresh | DONE | v6.41.0 |
282
+ | URL routing | DONE | v6.39.0 |
283
+ | Session persistence | DONE | v6.39.0 |
284
+ | Resizable panes | DONE | v6.40.0 |
285
+ | Error boundaries | DONE | v6.38.4 |
286
+ | WebSocket real-time | DONE | v6.36.0 |
287
+ | Session history | DONE | v6.36.1 |
288
+ | Provider selection | DONE | v6.35.0 |
289
+ | Template gallery | EXISTS (API) | Needs UI page |
290
+ | Quality gates display | EXISTS (API) | Needs panel |
291
+ | Agent activity | EXISTS (API) | Needs panel |
292
+ | Memory browser | EXISTS (API) | Needs panel |
293
+ | Code review | EXISTS (API) | Needs panel |
294
+ | AI Chat | NEEDS BUILD | New component |
295
+ | Sidebar navigation | NEEDS BUILD | New layout |
296
+ | Projects list page | NEEDS BUILD | New page |
297
+ | Settings page | NEEDS BUILD | New page |
298
+ | Bottom activity panel | NEEDS BUILD | New component |
299
+ | Container orchestration | NEEDS BUILD | Infrastructure |
300
+
301
+ ---
302
+
303
+ ## Design Language
304
+
305
+ Match Autonomi design system (already used in Purple Lab):
306
+ - Light bg: #FFFEFB, card: #FFFFFF, accent: #553DE9
307
+ - Font: Inter (body), JetBrains Mono (code), DM Serif Display (headings)
308
+ - Glass effect on panels
309
+ - Rounded corners (xl/2xl)
310
+ - Minimal, clean, professional -- not flashy
311
+
312
+ ---
313
+
314
+ ## Success Metrics
315
+
316
+ - User can go from prompt to working preview in under 5 minutes
317
+ - Page refresh at any point preserves full state
318
+ - Preview renders all relative assets correctly
319
+ - Quality gates visible in real-time during builds
320
+ - AI chat iteration feels natural (no context loss between prompts)
321
+ - 95%+ uptime for hosted workspaces
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '6.41.0'
60
+ __version__ = '6.42.0'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loki-mode",
3
- "version": "6.41.0",
3
+ "version": "6.42.0",
4
4
  "description": "Loki Mode by Autonomi - Multi-agent autonomous startup system for Claude Code, Codex CLI, and Gemini CLI",
5
5
  "keywords": [
6
6
  "agent",
@@ -0,0 +1,6 @@
1
+ import{c as m,r,j as e}from"./index-ABzvlaPu.js";import{C as g,a as p}from"./clock-BZGjjvpN.js";/**
2
+ * @license lucide-react v0.577.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const y=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]],C=m("circle-alert",y);function k(t,a=2e3,l=!0){const[o,i]=r.useState(null),[f,u]=r.useState(null),[x,d]=r.useState(!0),s=r.useRef(!0),c=r.useCallback(async()=>{try{const n=await t();s.current&&(i(n),u(null))}catch(n){s.current&&u(n instanceof Error?n.message:"Unknown error")}finally{s.current&&d(!1)}},[t]);return r.useEffect(()=>{if(s.current=!0,!l)return;c();const n=setInterval(c,a);return()=>{s.current=!1,clearInterval(n)}},[c,a,l]),{data:o,error:f,loading:x,refresh:c}}const b={completed:"bg-[#1FC5A8]/10 text-[#1FC5A8]",running:"bg-[#553DE9]/10 text-[#553DE9]",failed:"bg-[#C45B5B]/10 text-[#C45B5B]",started:"bg-[#D4A03C]/10 text-[#D4A03C]",empty:"bg-[#F8F4F0] text-[#6B6960]",version:"bg-[#553DE9]/10 text-[#553DE9]"};function j({status:t}){switch(t){case"completed":return e.jsx(p,{size:12});case"running":return e.jsxs("span",{className:"relative flex h-2 w-2",children:[e.jsx("span",{className:"animate-ping motion-reduce:animate-none absolute inline-flex h-full w-full rounded-full bg-current opacity-75"}),e.jsx("span",{className:"relative inline-flex rounded-full h-2 w-2 bg-current"})]});case"failed":return e.jsx(C,{size:12});case"started":return e.jsx(g,{size:12});default:return null}}function B({status:t,children:a,className:l=""}){return e.jsxs("span",{className:["inline-flex items-center gap-1 rounded-btn px-2.5 py-0.5 text-xs font-semibold",b[t],l].filter(Boolean).join(" "),children:[e.jsx(j,{status:t}),a]})}export{B,k as u};
@@ -0,0 +1 @@
1
+ import{r as p,j as t}from"./index-ABzvlaPu.js";const m={primary:"bg-[#553DE9] text-white hover:bg-[#4432c4] shadow-button rounded-btn",secondary:"border border-[#553DE9] text-[#553DE9] hover:bg-[#E8E4FD] bg-transparent rounded-btn",ghost:"text-[#36342E] hover:bg-[#F8F4F0] rounded-btn",danger:"bg-[#C45B5B]/10 text-[#C45B5B] border border-[#C45B5B]/20 hover:bg-[#C45B5B]/20 rounded-btn"},b={sm:"px-3 py-1.5 text-xs",md:"px-4 py-2 text-sm",lg:"px-6 py-3 text-base"},u={sm:14,md:16,lg:18};function h({size:e}){return t.jsxs("svg",{className:"animate-spin",width:e,height:e,viewBox:"0 0 24 24",fill:"none",children:[t.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),t.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"})]})}const B=p.forwardRef(({variant:e="primary",size:o="md",icon:n,iconRight:i,loading:r=!1,disabled:a,className:c="",children:l,...x},d)=>{const s=u[o];return t.jsxs("button",{ref:d,disabled:a||r,className:["inline-flex items-center justify-center gap-2 font-medium transition-colors",m[e],b[o],(a||r)&&"opacity-60 cursor-not-allowed",c].filter(Boolean).join(" "),...x,children:[r?t.jsx(h,{size:s}):n?t.jsx(n,{size:s}):null,l,i&&!r&&t.jsx(i,{size:s})]})});B.displayName="Button";export{B};
@@ -0,0 +1 @@
1
+ import{j as s}from"./index-ABzvlaPu.js";const n={none:"p-0",sm:"p-3",md:"p-4",lg:"p-6"};function p({hover:e=!1,padding:d="md",className:t="",children:a,onClick:r}){return s.jsx("div",{role:r?"button":void 0,tabIndex:r?0:void 0,onClick:r,onKeyDown:r?o=>{(o.key==="Enter"||o.key===" ")&&(o.preventDefault(),r())}:void 0,className:["bg-white border border-[#ECEAE3] rounded-[5px] shadow-card",e&&"hover:shadow-card-hover transition-shadow duration-200",r&&"cursor-pointer",n[d],t].filter(Boolean).join(" "),children:a})}export{p as C};
@@ -0,0 +1,33 @@
1
+ import{c as W,j as e,r as l,a as h,u as fe,b as be}from"./index-ABzvlaPu.js";import{u as $,B as ge}from"./Badge-Cv068X_w.js";import{E as L,T as je}from"./TerminalOutput-jc4B3JYH.js";import"./clock-BZGjjvpN.js";/**
2
+ * @license lucide-react v0.577.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const ve=[["rect",{x:"14",y:"3",width:"5",height:"18",rx:"1",key:"kaeet6"}],["rect",{x:"5",y:"3",width:"5",height:"18",rx:"1",key:"1wsw3u"}]],Ne=W("pause",ve);/**
7
+ * @license lucide-react v0.577.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const ye=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]],we=W("play",ye);/**
12
+ * @license lucide-react v0.577.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const ke=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],Se=W("square",ke);function Ce(t){if(t<60)return`${Math.round(t)}s`;if(t<3600)return`${Math.floor(t/60)}m ${Math.round(t%60)}s`;const s=Math.floor(t/3600),n=Math.floor(t%3600/60);return`${s}h ${n}m`}function Ee(t,s){if(!t||t<=0)return"--";const n={simple:{opus:1,haiku:1,total:3},standard:{opus:2,haiku:2,total:5},complex:{opus:3,haiku:3,total:8}},r=n[s]||n.standard;return t<=r.opus?"Opus":t>r.total-r.haiku?"Haiku":"Sonnet"}function Pe({status:t,prdSummary:s,onStop:n,onPause:r,onResume:a,isPaused:i}){const c=t?Ee(t.iteration??0,t.complexity||"standard"):"--",d=i??(t==null?void 0:t.paused)??!1;return e.jsxs("div",{className:"card px-5 py-3 flex items-center gap-6 text-sm",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted uppercase tracking-wider font-medium",children:"Phase"}),e.jsx("span",{className:"font-mono font-semibold text-ink",children:(t==null?void 0:t.phase)||"idle"})]}),e.jsx("div",{className:"w-px h-5 bg-border"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted uppercase tracking-wider font-medium",children:"Complexity"}),e.jsx("span",{className:`font-mono font-semibold ${(t==null?void 0:t.complexity)==="complex"?"text-warning":(t==null?void 0:t.complexity)==="simple"?"text-success":"text-ink"}`,children:(t==null?void 0:t.complexity)||"standard"})]}),e.jsx("div",{className:"w-px h-5 bg-border"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted uppercase tracking-wider font-medium",children:"Model"}),e.jsx("span",{className:`font-mono font-semibold px-2 py-0.5 rounded-md text-xs ${c==="Opus"?"bg-primary/10 text-primary":c==="Haiku"?"bg-success/10 text-success":"bg-primary/10 text-primary"}`,children:c})]}),e.jsx("div",{className:"w-px h-5 bg-border"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-xs text-muted uppercase tracking-wider font-medium",children:"Tasks"}),e.jsx("span",{className:"font-mono text-ink",children:t!=null&&t.current_task?e.jsx("span",{className:"text-xs",children:t.current_task}):e.jsx("span",{className:"text-muted",children:"--"})}),((t==null?void 0:t.pending_tasks)??0)>0&&e.jsxs("span",{className:"text-xs text-primary font-mono",children:["+",t==null?void 0:t.pending_tasks," pending"]})]}),s&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"w-px h-5 bg-border"}),e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:"text-xs text-muted uppercase tracking-wider font-medium flex-shrink-0",children:"Building"}),e.jsx("span",{className:"text-xs font-mono text-ink truncate max-w-[220px]",title:s,children:s.length>60?s.slice(0,60)+"...":s})]})]}),e.jsx("div",{className:"flex-1"}),((t==null?void 0:t.uptime)??0)>0&&e.jsx("span",{className:"font-mono text-xs text-muted",children:Ce((t==null?void 0:t.uptime)??0)}),(r||a)&&e.jsxs("button",{onClick:d?a:r,className:"flex items-center gap-1.5 px-4 py-1.5 rounded-btn text-xs font-semibold border border-warning/30 text-warning hover:bg-warning/10 transition-colors",children:[d?e.jsx(we,{size:14}):e.jsx(Ne,{size:14}),d?"Resume":"Pause"]}),n&&e.jsxs("button",{onClick:n,className:"flex items-center gap-1.5 px-4 py-1.5 rounded-btn text-xs font-semibold bg-danger/10 text-danger border border-danger/20 hover:bg-danger/20 transition-colors",children:[e.jsx(Se,{size:14}),"Stop"]})]})}function _e({status:t}){const s=[{label:"Iteration",value:t?t.iteration.toString():"--",color:"text-primary"},{label:"Agents",value:t?t.running_agents.toString():"--",color:t&&t.running_agents>0?"text-success":"text-muted"},{label:"Pending",value:t?t.pending_tasks.toString():"--",color:t&&t.pending_tasks>0?"text-warning":"text-muted"},{label:"Provider",value:(t==null?void 0:t.provider)||"--",color:"text-primary"}];return e.jsx("div",{className:"grid grid-cols-4 gap-3",children:s.map(n=>e.jsxs("div",{className:"card p-4 text-center",children:[e.jsx("div",{className:`text-2xl font-bold font-mono ${n.color}`,children:n.value}),e.jsx("div",{className:"text-xs text-muted font-medium mt-1 uppercase tracking-wider",children:n.label})]},n.label))})}function Fe({plan:t,loading:s,onConfirm:n,onCancel:r}){return e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/30 backdrop-blur-sm",children:e.jsxs("div",{className:"card w-full max-w-lg mx-4 p-6 rounded-card shadow-card-hover",children:[e.jsx("h2",{className:"text-lg font-bold text-ink mb-4",children:"Build Estimate"}),s?e.jsxs("div",{className:"flex flex-col items-center py-8 gap-3",children:[e.jsx("div",{className:"w-8 h-8 border-2 border-primary border-t-transparent rounded-full animate-spin"}),e.jsx("p",{className:"text-sm text-muted",children:"Analyzing PRD..."})]}):t?e.jsxs(e.Fragment,{children:[t.returncode!==0&&e.jsxs("div",{className:"mb-4 px-3 py-2 rounded-btn bg-warning/10 border border-warning/20 text-warning text-xs",children:["loki plan exited with code ",t.returncode," - showing partial results"]}),e.jsxs("div",{className:"grid grid-cols-2 gap-3 mb-4",children:[e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Complexity"}),e.jsx("div",{className:"text-base font-bold text-ink capitalize",children:t.complexity})]}),e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Est. Cost"}),e.jsx("div",{className:"text-base font-bold text-ink",children:t.cost_estimate})]}),e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Iterations"}),e.jsx("div",{className:"text-base font-bold text-ink",children:t.iterations})]}),e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Phases"}),e.jsx("div",{className:"text-xs text-ink capitalize",children:t.phases.join(", ")})]})]}),t.output_text&&e.jsxs("details",{className:"mb-4",children:[e.jsx("summary",{className:"text-xs text-muted cursor-pointer hover:text-ink transition-colors",children:"Raw output"}),e.jsx("pre",{className:"mt-2 text-[10px] font-mono text-muted-accessible bg-black/5 rounded-card p-3 overflow-auto max-h-40 whitespace-pre-wrap",children:t.output_text})]}),e.jsxs("div",{className:"flex gap-3 justify-end",children:[e.jsx("button",{onClick:r,className:"px-4 py-2 text-sm font-medium text-muted hover:text-ink transition-colors",children:"Cancel"}),e.jsx("button",{onClick:n,className:"px-5 py-2 rounded-card text-sm font-semibold bg-primary text-white hover:bg-primary/90 transition-all shadow-button",children:"Start Build"})]})]}):e.jsx("div",{className:"text-sm text-muted py-4",children:"No plan data available."})]})})}function Le({onSubmit:t,running:s,error:n,provider:r,onProviderChange:a}){const[i,c]=l.useState(""),[d,x]=l.useState(""),[b,f]=l.useState("claude"),[j,m]=l.useState(""),g=r??b,[v,N]=l.useState(!1),[w,k]=l.useState([]),[R,o]=l.useState(!1),[y,S]=l.useState(!1),[_,A]=l.useState(!1),[M,T]=l.useState(null),[C,D]=l.useState(!1),[z,E]=l.useState(!1);l.useEffect(()=>{h.getTemplates().then(u=>{k(u),o(!1)}).catch(()=>{k([]),o(!0)})},[]),l.useEffect(()=>{const u=localStorage.getItem("loki-prd-draft");u&&c(u),h.getPrdPrefill().then(({content:P})=>{P&&c(P)}).catch(()=>{})},[]),l.useEffect(()=>{i.trim()?localStorage.setItem("loki-prd-draft",i):localStorage.removeItem("loki-prd-draft")},[i]),l.useEffect(()=>{const u=P=>{i.trim()&&P.preventDefault()};return window.addEventListener("beforeunload",u),()=>window.removeEventListener("beforeunload",u)},[i]);const U=l.useCallback(async(u,P)=>{x(P),N(!1);try{const q=await h.getTemplateContent(u);c(q.content)}catch{c(`# ${P}
17
+
18
+ ## Overview
19
+
20
+ Describe your project here...
21
+
22
+ ## Features
23
+
24
+ - Feature 1
25
+ - Feature 2
26
+ - Feature 3
27
+
28
+ ## Technical Requirements
29
+
30
+ - Requirement 1
31
+ - Requirement 2
32
+ `)}},[]),O=async()=>{if(!(!i.trim()||C)){D(!0),T(null),E(!0);try{const u=await h.planSession(i,g);T(u)}catch{T({complexity:"unknown",cost_estimate:"N/A",iterations:0,phases:[],output_text:"Failed to run loki plan. The CLI may not be available.",returncode:1})}finally{D(!1)}}},B=async()=>{if(!(!i.trim()||s||y)){E(!1),S(!0);try{await t(i,g,j.trim()||void 0,_?"quick":void 0)}finally{S(!1)}}};return e.jsxs(e.Fragment,{children:[z&&e.jsx(Fe,{plan:M,loading:C,onConfirm:B,onCancel:()=>E(!1)}),e.jsxs("div",{className:"card p-6 flex flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"Product Requirements"}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsxs("div",{className:"relative",children:[e.jsx("button",{onClick:()=>N(!v),className:"text-xs font-medium px-3 py-1.5 rounded-card border border-primary/20 text-primary hover:bg-primary/5 transition-colors",children:d||"Templates"}),v&&e.jsx("div",{className:"absolute right-0 top-full mt-1 w-56 card rounded-card overflow-hidden z-20 shadow-card-hover",children:e.jsxs("div",{className:"py-1 max-h-64 overflow-y-auto terminal-scroll",children:[R&&e.jsx("div",{className:"px-3 py-2 text-xs text-warning border-b border-warning/10",children:"Could not load templates from server. Check that the backend is running."}),!R&&w.length===0&&e.jsx("div",{className:"px-3 py-2 text-xs text-muted",children:"Loading..."}),w.map(u=>e.jsx("button",{onClick:()=>U(u.filename,u.name),className:"w-full text-left px-3 py-2 text-sm text-ink hover:bg-primary/5 transition-colors",children:u.name},u.filename))]})})]})})]}),e.jsx("textarea",{value:i,onChange:u=>c(u.target.value),placeholder:"Paste your PRD here, or select a template above to get started...",className:"flex-1 min-h-[280px] w-full bg-card rounded-card border border-border-light px-4 py-3 text-sm font-mono text-ink placeholder:text-primary/60 resize-none focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary/30 transition-all",spellCheck:!1}),e.jsxs("div",{className:"mt-3",children:[e.jsx("label",{className:"block text-xs text-muted font-medium mb-1 uppercase tracking-wider",children:"Project Directory"}),e.jsx("input",{type:"text",value:j,onChange:u=>m(u.target.value),placeholder:"Leave blank to auto-create, or type a path (e.g. /Users/you/my-project)",className:"w-full bg-card rounded-card border border-border-light px-4 py-2 text-sm font-mono text-ink placeholder:text-primary/60/70 focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary/30 transition-all",spellCheck:!1}),e.jsx("p",{className:"text-[10px] text-muted-accessible mt-1",children:"Type a path or leave blank to auto-create under ~/purple-lab-projects/"})]}),n&&e.jsx("div",{className:"mt-3 px-3 py-2 rounded-btn bg-danger/10 border border-danger/20 text-danger text-xs font-medium",children:n}),e.jsxs("div",{className:"flex items-center gap-3 mt-4",children:[e.jsxs("button",{onClick:()=>A(!_),title:"Quick Mode: 3 iterations max, faster builds",className:`flex items-center gap-1.5 px-3 py-1.5 rounded-card text-xs font-semibold border transition-all ${_?"bg-primary/10 border-primary/30 text-primary":"border-border-light text-muted hover:text-ink hover:bg-card"}`,children:[e.jsx("span",{className:`w-1.5 h-1.5 rounded-full ${_?"bg-primary":"bg-muted/40"}`}),"Quick"]}),e.jsx("div",{className:"flex-1"}),e.jsxs("span",{className:"text-xs text-muted font-mono",children:[i.length.toLocaleString()," chars"]}),e.jsx("button",{onClick:O,disabled:!i.trim()||s||C,className:`px-4 py-2.5 rounded-card text-sm font-semibold border transition-all ${!i.trim()||s||C?"border-border text-muted/40 cursor-not-allowed":"border-primary/30 text-primary hover:bg-primary/5"}`,children:C?"Analyzing...":"Estimate"}),e.jsx("button",{onClick:B,disabled:!i.trim()||s||y,className:`px-6 py-2.5 rounded-card text-sm font-semibold transition-all ${!i.trim()||s||y?"bg-primary/10 text-muted cursor-not-allowed":"bg-primary text-white hover:bg-primary/90 shadow-button"}`,children:y?"Starting...":s?"Building...":"Start Build"})]})]})]})}const I=[{key:"reason",label:"Reason",description:"Analyzing task, planning approach"},{key:"act",label:"Act",description:"Implementing changes, writing code"},{key:"reflect",label:"Reflect",description:"Reviewing output, self-critique"},{key:"verify",label:"Verify",description:"Testing, validation, quality gates"}];function Re(t){if(!t)return"reason";const s=t.toLowerCase();return s.includes("reason")||s.includes("plan")?"reason":s.includes("act")||s.includes("implement")||s.includes("code")?"act":s.includes("reflect")||s.includes("review")?"reflect":s.includes("verify")||s.includes("test")||s.includes("check")?"verify":"idle"}function $e({currentPhase:t,iteration:s}){const n=Re(t);return e.jsxs("div",{className:"card p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"RARV Cycle"}),e.jsxs("span",{className:"font-mono text-xs text-muted",children:["Iteration ",s]})]}),e.jsx("div",{className:"flex items-center justify-center mb-5",children:e.jsxs("svg",{viewBox:"0 0 120 120",className:"w-28 h-28",children:[I.map((r,a)=>{const i=r.key===n,c=n!=="idle"&&I.findIndex(f=>f.key===n)>a,d=(a*90-90)*(Math.PI/180),x=60+40*Math.cos(d),b=60+40*Math.sin(d);return e.jsxs("g",{children:[a<I.length-1&&e.jsx("line",{x1:x,y1:b,x2:60+40*Math.cos(((a+1)*90-90)*(Math.PI/180)),y2:60+40*Math.sin(((a+1)*90-90)*(Math.PI/180)),stroke:c?"#553DE9":"#ECEAE3",strokeWidth:c?2:1,strokeDasharray:c?"none":"4 3"}),a===I.length-1&&e.jsx("line",{x1:x,y1:b,x2:60+40*Math.cos(-90*(Math.PI/180)),y2:60+40*Math.sin(-90*(Math.PI/180)),stroke:"#ECEAE3",strokeWidth:1,strokeDasharray:"4 3"}),e.jsx("circle",{cx:x,cy:b,r:i?14:10,fill:i||c?"#553DE9":"#E8E4FD",stroke:i?"#4432c4":c?"#553DE9":"#ECEAE3",strokeWidth:i?3:1.5,className:i?"phase-active":""}),e.jsx("text",{x,y:b+(a===0?-20:a===2?24:0),textAnchor:"middle",className:"text-[9px] font-semibold fill-ink",dx:a===1?22:a===3?-22:0,children:r.label[0]})]},r.key)}),e.jsx("text",{x:"60",y:"64",textAnchor:"middle",className:"text-lg font-bold font-mono fill-primary",children:s})]})}),e.jsx("div",{className:"space-y-2",children:I.map(r=>{const a=r.key===n;return e.jsxs("div",{className:`flex items-center gap-3 px-3 py-2 rounded-card transition-all duration-200 ${a?"bg-primary/8 border border-primary/20":"opacity-50"}`,children:[e.jsx("div",{className:`w-2.5 h-2.5 rounded-full flex-shrink-0 ${a?"bg-primary phase-active":"bg-border"}`}),e.jsxs("div",{children:[e.jsx("span",{className:`text-sm font-semibold ${a?"text-primary":"text-muted"}`,children:r.label}),a&&e.jsx("p",{className:"text-xs text-muted mt-0.5",children:r.description})]})]},r.key)})})]})}const H={architect:"bg-primary/10 text-primary border-primary/20",developer:"bg-primary/10 text-primary border-primary/20",tester:"bg-success/10 text-success border-success/20",reviewer:"bg-warning/10 text-warning border-warning/20",planner:"bg-primary/60/20 text-ink border-primary/60/30",default:"bg-border/30 text-muted border-border/50"};function Me(t){if(!t)return H.default;const s=t.toLowerCase();for(const[n,r]of Object.entries(H))if(s.includes(n))return r;return H.default}function Te({agents:t,loading:s}){const n=(t==null?void 0:t.filter(a=>a.alive))||[],r=(t==null?void 0:t.filter(a=>!a.alive))||[];return e.jsxs("div",{className:"card p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"Agents"}),e.jsxs("span",{className:"font-mono text-xs text-muted",children:[n.length," active"]})]}),s&&!t&&e.jsx("div",{className:"text-center py-8 text-muted text-sm",children:"Loading agents..."}),!s&&(t==null?void 0:t.length)===0&&e.jsxs("div",{className:"text-center py-8",children:[e.jsx("p",{className:"text-muted text-sm",children:"No agents running"}),e.jsx("p",{className:"text-primary/60 text-xs mt-1",children:"Start a build to spawn agents"})]}),n.length>0&&e.jsx("div",{className:"space-y-2 mb-4",children:n.map(a=>e.jsx(Q,{agent:a},a.id))}),r.length>0&&e.jsxs("details",{className:"mt-3",children:[e.jsxs("summary",{className:"text-xs text-muted cursor-pointer hover:text-ink transition-colors",children:[r.length," completed"]}),e.jsx("div",{className:"space-y-1.5 mt-2",children:r.slice(0,10).map(a=>e.jsx(Q,{agent:a,compact:!0},a.id))})]})]})}function Q({agent:t,compact:s}){const n=Me(t.type||t.name||"");return s?e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1 rounded-btn bg-hover text-xs",children:[e.jsx("div",{className:"w-1.5 h-1.5 rounded-full bg-muted/30"}),e.jsx("span",{className:"font-medium text-muted truncate",children:t.name||t.id}),e.jsx("span",{className:"text-primary/60 ml-auto",children:t.type})]}):e.jsxs("div",{className:`flex items-start gap-3 px-3 py-2.5 rounded-card border ${n}`,children:[e.jsx("div",{className:"flex-shrink-0 mt-0.5",children:e.jsx("div",{className:`w-2.5 h-2.5 rounded-full ${t.alive?"bg-success phase-active":"bg-muted/30"}`})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm font-semibold truncate",children:t.name||t.id}),t.type&&e.jsx("span",{className:"text-[10px] font-mono font-medium opacity-70",children:t.type})]}),t.task&&e.jsx("p",{className:"text-xs opacity-70 mt-0.5 truncate",children:t.task}),t.status&&t.status!=="unknown"&&e.jsx("span",{className:"inline-block text-[10px] font-mono mt-1 opacity-60",children:t.status})]}),t.pid&&e.jsxs("span",{className:"text-[10px] font-mono text-muted-accessible flex-shrink-0",children:["PID ",t.pid]})]})}const Ie={pass:{badge:"bg-success/10 text-success border-success/20",dot:"bg-success",label:"Pass"},fail:{badge:"bg-danger/10 text-danger border-danger/20",dot:"bg-danger",label:"Fail"},skip:{badge:"bg-muted/10 text-muted border-muted/20",dot:"bg-muted/40",label:"Skip"},pending:{badge:"bg-warning/10 text-warning border-warning/20",dot:"bg-warning",label:"Pending"}};function Ae({item:t}){const[s,n]=l.useState(!1),r=Ie[t.status];return e.jsxs("div",{className:`border rounded-card overflow-hidden ${r.badge}`,children:[e.jsxs("button",{type:"button",className:"w-full flex items-center gap-3 px-3 py-2.5 text-left",onClick:()=>t.details&&n(!s),children:[e.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${r.dot}`}),e.jsx("span",{className:"text-sm font-medium flex-1 truncate",children:t.label}),e.jsx("span",{className:"text-[10px] font-mono font-semibold uppercase tracking-wider flex-shrink-0",children:r.label}),t.details&&e.jsx("span",{className:"text-xs text-muted/60 flex-shrink-0",children:s?"v":">"})]}),s&&t.details&&e.jsx("div",{className:"px-3 pb-2.5 pt-0",children:e.jsx("p",{className:"text-xs font-mono opacity-70 leading-relaxed",children:t.details})})]})}function De({checklist:t,loading:s}){const n=t&&t.total>0?t.passed/t.total*100:0;return e.jsxs("div",{className:"card p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"Quality Gates"}),t&&e.jsxs("span",{className:"font-mono text-xs text-muted",children:[t.passed,"/",t.total," passed"]})]}),s&&!t&&e.jsx("div",{className:"text-center py-8 text-muted text-sm",children:"Loading gates..."}),!s&&!t&&e.jsxs("div",{className:"text-center py-8",children:[e.jsx("p",{className:"text-muted text-sm",children:"No quality gate data"}),e.jsx("p",{className:"text-primary/60 text-xs mt-1",children:"Gates run during verification phase"})]}),t&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center gap-4 mb-3 text-xs",children:[e.jsxs("span",{className:"text-success font-medium",children:[t.passed," passed"]}),t.failed>0&&e.jsxs("span",{className:"text-danger font-medium",children:[t.failed," failed"]}),t.skipped>0&&e.jsxs("span",{className:"text-muted",children:[t.skipped," skipped"]}),t.pending>0&&e.jsxs("span",{className:"text-warning",children:[t.pending," pending"]})]}),e.jsx("div",{className:"w-full h-2 bg-charcoal/10 rounded-full overflow-hidden mb-4",children:e.jsx("div",{className:"h-full bg-success rounded-full transition-all duration-500",style:{width:`${n}%`}})}),e.jsx("div",{className:"space-y-2 max-h-[400px] overflow-y-auto terminal-scroll",children:t.items.map(r=>e.jsx(Ae,{item:r},r.id))})]})]})}const Be={".py":"bg-success",".ts":"bg-primary",".tsx":"bg-primary",".md":"bg-warning",".sh":"bg-primary"};function ze(t){const s=t.substring(t.lastIndexOf("."));return Be[s]||"bg-muted"}function Ue(t){return t==null?"":t<1024?`${t}B`:t<1024*1024?`${(t/1024).toFixed(1)}KB`:`${(t/(1024*1024)).toFixed(1)}MB`}const G=100;function J({node:t,depth:s,onSelectFile:n,selectedPath:r}){const[a,i]=l.useState(!1),[c,d]=l.useState(G),x=t.type==="directory",b=t.path===r,f=x&&a?t.children??[]:[],j=f.length>c;return e.jsxs("div",{children:[e.jsxs("button",{type:"button",className:`w-full flex items-center gap-2 px-2 py-1 rounded-btn text-left text-sm transition-colors hover:bg-hover ${b?"bg-primary/10 text-primary":"text-ink"}`,style:{paddingLeft:`${s*16+8}px`},onClick:()=>{x?(i(!a),a&&d(G)):n(t.path)},children:[x?e.jsx("span",{className:"font-mono text-xs text-muted w-3 flex-shrink-0",children:a?"v":">"}):e.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${ze(t.name)}`}),e.jsx("span",{className:`truncate ${x?"font-medium":"font-mono text-xs"}`,children:t.name}),!x&&t.size!==void 0&&e.jsx("span",{className:"ml-auto text-[10px] font-mono text-muted-accessible flex-shrink-0",children:Ue(t.size)})]}),f.length>0&&e.jsxs("div",{children:[f.slice(0,c).map(m=>e.jsx(J,{node:m,depth:s+1,onSelectFile:n,selectedPath:r},m.path)),j&&e.jsxs("button",{type:"button",className:"w-full text-left text-xs text-primary hover:text-primary/80 py-1 transition-colors",style:{paddingLeft:`${(s+1)*16+8}px`},onClick:()=>d(m=>m+G),children:["Show more (",f.length-c," remaining)"]})]})]})}function Oe({files:t,loading:s}){const[n,r]=l.useState(null),[a,i]=l.useState(null),[c,d]=l.useState(!1),[x,b]=l.useState(null),f=l.useCallback(async m=>{i(null),r(m),d(!0),b(null);try{const g=await h.getFileContent(m);i(g.content)}catch(g){const v=g instanceof Error?g.message:"Unknown error",N=g instanceof TypeError||v==="Request timeout",w=v.includes("404")||v.includes("not found")||v.includes("Not found");b(N?"Network error - server may be unreachable":w?"File not found - it may have been deleted or renamed":v),i(null)}finally{d(!1)}},[]),j=l.useCallback(m=>{f(m)},[f]);return e.jsxs("div",{className:"card p-6 flex flex-col",style:{minHeight:"300px"},children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"File Browser"}),e.jsx("span",{className:"font-mono text-xs text-muted",children:".loki/"})]}),s&&!t&&e.jsx("div",{className:"text-center py-8 text-muted text-sm",children:"Loading files..."}),!s&&(!t||t.length===0)&&e.jsxs("div",{className:"text-center py-8",children:[e.jsx("p",{className:"text-muted text-sm",children:"No project files found"}),e.jsx("p",{className:"text-primary/60 text-xs mt-1",children:"Start a session to generate .loki/ state"})]}),t&&t.length>0&&e.jsxs("div",{className:"flex gap-4 flex-1 min-h-0",children:[e.jsx("div",{className:"w-1/2 overflow-y-auto terminal-scroll pr-2",children:t.map(m=>e.jsx(J,{node:m,depth:0,onSelectFile:j,selectedPath:n},m.path))}),e.jsxs("div",{className:"w-1/2 bg-charcoal/5 rounded-card p-3 overflow-hidden flex flex-col",children:[!n&&e.jsx("div",{className:"flex-1 flex items-center justify-center text-muted text-xs",children:"Select a file to preview"}),n&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"text-xs font-mono text-primary mb-2 truncate",children:n}),e.jsx("div",{className:"flex-1 overflow-y-auto terminal-scroll",children:c?e.jsx("div",{className:"text-muted text-xs",children:"Loading..."}):x?e.jsxs("div",{className:"flex flex-col items-center justify-center gap-2 py-6",children:[e.jsx("p",{className:"text-danger text-xs font-medium",children:"Failed to load file"}),e.jsx("p",{className:"text-muted-accessible text-[10px] text-center max-w-[200px] break-words",children:x}),e.jsx("button",{type:"button",onClick:()=>n&&f(n),className:"mt-1 px-3 py-1 text-[10px] font-semibold rounded-btn border border-primary/20 text-primary hover:bg-primary/5 transition-colors",children:"Retry"})]}):e.jsx("pre",{className:"text-xs font-mono text-ink whitespace-pre-wrap break-words leading-relaxed",children:a})})]})]})]})]})}const K=5e5;function Y(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}K`:t.toString()}function qe(t){if(!t)return"Never";try{const s=new Date(t),r=new Date().getTime()-s.getTime(),a=Math.floor(r/(1e3*60*60));return a<1?"Just now":a<24?`${a}h ago`:`${Math.floor(a/24)}d ago`}catch{return t}}function He({memory:t,loading:s}){const n=t?[{label:"Episodic",count:t.episodic_count,color:"text-primary",bg:"bg-primary/10",border:"border-primary/20"},{label:"Semantic",count:t.semantic_count,color:"text-success",bg:"bg-success/10",border:"border-success/20"},{label:"Skills",count:t.skill_count,color:"text-warning",bg:"bg-warning/10",border:"border-warning/20"}]:[],r=t?Math.min(t.total_tokens/K*100,100):0;return e.jsxs("div",{className:"card p-6",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"Memory System"}),t&&e.jsx("span",{className:"font-mono text-xs text-muted",children:qe(t.last_consolidation)})]}),s&&!t&&e.jsx("div",{className:"text-center py-8 text-muted text-sm",children:"Loading memory..."}),!s&&!t&&e.jsxs("div",{className:"text-center py-8",children:[e.jsx("p",{className:"text-muted text-sm",children:"No memory data available"}),e.jsx("p",{className:"text-primary/60 text-xs mt-1",children:"Memory populates during autonomous runs"})]}),t&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"grid grid-cols-3 gap-3 mb-4",children:n.map(a=>e.jsxs("div",{className:`${a.bg} border ${a.border} rounded-card p-3 text-center`,children:[e.jsx("div",{className:`text-2xl font-bold font-mono ${a.color}`,children:a.count}),e.jsx("div",{className:"text-[10px] text-muted-accessible font-medium mt-1 uppercase tracking-wider",children:a.label})]},a.label))}),e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1.5",children:[e.jsx("span",{className:"text-xs text-muted font-medium",children:"Token Usage"}),e.jsxs("span",{className:"text-xs font-mono text-ink",children:[Y(t.total_tokens)," / ",Y(K)]})]}),e.jsx("div",{className:"w-full h-2 bg-charcoal/10 rounded-full overflow-hidden",children:e.jsx("div",{className:`h-full rounded-full transition-all duration-500 ${r>80?"bg-danger":r>50?"bg-warning":"bg-info"}`,style:{width:`${r}%`}})})]}),e.jsxs("div",{className:"mt-3 flex items-center justify-between text-xs",children:[e.jsx("span",{className:"text-muted",children:"Last Consolidation"}),e.jsx("span",{className:"font-mono text-ink",children:t.last_consolidation?new Date(t.last_consolidation).toLocaleString():"Never"})]})]})]})}function Ge({visible:t}){const[s,n]=l.useState("markdown"),[r,a]=l.useState(null),[i,c]=l.useState(null),[d,x]=l.useState(!1),[b,f]=l.useState(!1),[j,m]=l.useState(null),[g,v]=l.useState(!1);if(!t)return null;const N=async()=>{x(!0),m(null),a(null),c(null);try{const o=await h.generateReport(s);a(o)}catch(o){m(o instanceof Error?o.message:"Failed to generate report")}finally{x(!1)}},w=async()=>{f(!0),m(null);try{const o=await h.shareSession();c(o)}catch(o){m(o instanceof Error?o.message:"Failed to share session")}finally{f(!1)}},k=async o=>{try{await navigator.clipboard.writeText(o),v(!0),setTimeout(()=>v(!1),2e3)}catch{}},R=()=>{if(!r)return;const o=new Blob([r.content],{type:s==="html"?"text/html":"text/markdown"}),y=URL.createObjectURL(o),S=document.createElement("a");S.href=y,S.download=`loki-report.${s==="html"?"html":"md"}`,S.click(),URL.revokeObjectURL(y)};return e.jsxs("div",{className:"card p-4 rounded-card",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"Session Report"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"flex items-center gap-1 card rounded-card p-1",children:["markdown","html"].map(o=>e.jsx("button",{onClick:()=>n(o),className:`px-3 py-1 text-xs font-semibold rounded-btn transition-all ${s===o?"bg-primary text-white shadow-sm":"text-muted hover:text-ink hover:bg-hover"}`,children:o.toUpperCase()},o))}),e.jsx("button",{onClick:N,disabled:d,className:"px-4 py-1.5 rounded-card text-xs font-semibold bg-primary text-white hover:bg-primary/90 disabled:opacity-50 transition-all",children:d?"Generating...":"Generate Report"})]})]}),j&&e.jsx("div",{className:"mb-3 px-3 py-2 rounded-btn bg-danger/10 border border-danger/20 text-danger text-xs",children:j}),r&&e.jsxs("div",{className:"mt-3",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[e.jsxs("span",{className:"text-xs text-muted",children:["Report generated (",r.format,")"]}),e.jsx("div",{className:"flex-1"}),e.jsx("button",{onClick:()=>k(r.content),className:"px-3 py-1 text-xs font-medium text-muted hover:text-ink border border-border-light rounded-btn hover:bg-hover transition-all",children:g?"Copied":"Copy"}),e.jsx("button",{onClick:R,className:"px-3 py-1 text-xs font-medium text-muted hover:text-ink border border-border-light rounded-btn hover:bg-hover transition-all",children:"Download"}),e.jsx("button",{onClick:w,disabled:b,className:"px-3 py-1 text-xs font-medium bg-primary/10 text-primary border border-primary/20 rounded-btn hover:bg-primary/20 disabled:opacity-50 transition-all",children:b?"Sharing...":"Share as Gist"})]}),i&&e.jsxs("div",{className:"mb-2 flex items-center gap-2 px-3 py-2 rounded-btn bg-success/10 border border-success/20",children:[e.jsx("span",{className:"text-xs text-success font-medium",children:"Shared:"}),i.url?e.jsx("a",{href:i.url,target:"_blank",rel:"noopener noreferrer",className:"text-xs text-primary underline flex-1 truncate",children:i.url}):e.jsx("span",{className:"text-xs text-muted flex-1",children:"No URL returned"}),i.url&&e.jsx("button",{onClick:()=>k(i.url),className:"text-xs text-muted hover:text-ink",children:"Copy URL"})]}),e.jsx("pre",{className:"text-[11px] font-mono text-ink bg-black/5 rounded-card p-3 overflow-auto max-h-64 whitespace-pre-wrap terminal-scroll",children:r.content||"(empty report)"})]})]})}function Z({visible:t}){const s=l.useCallback(()=>h.getMetrics(),[]),{data:n,loading:r}=$(s,15e3,t);return t?e.jsxs("div",{className:"card p-4 rounded-card",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider",children:"Session Metrics"}),r&&e.jsx("div",{className:"w-4 h-4 border-2 border-primary border-t-transparent rounded-full animate-spin"})]}),n?e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Iterations"}),e.jsx("div",{className:"text-xl font-bold text-ink",children:n.iterations??0})]}),e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Gate Pass Rate"}),e.jsx("div",{className:"text-xl font-bold text-ink",children:typeof n.quality_gate_pass_rate=="number"?`${n.quality_gate_pass_rate.toFixed(0)}%`:"N/A"})]}),e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Tokens Used"}),e.jsx("div",{className:"text-xl font-bold text-ink",children:(n.tokens_used??0).toLocaleString()})]}),e.jsxs("div",{className:"card rounded-card p-3",children:[e.jsx("div",{className:"text-[10px] font-semibold text-muted-accessible uppercase tracking-wider mb-1",children:"Time Elapsed"}),e.jsx("div",{className:"text-xl font-bold text-ink",children:n.time_elapsed||"N/A"})]})]}):e.jsx("div",{className:"text-sm text-muted py-4 text-center",children:r?"Loading metrics...":"No metrics available"})]}):null}function We(t){switch(t){case"completed":case"complete":case"done":return"completed";case"in_progress":return"running";case"started":return"started";case"error":case"failed":return"failed";default:return"empty"}}const Ve={completed:"Completed",complete:"Completed",done:"Completed",in_progress:"In Progress",started:"Started",error:"Failed",failed:"Failed",empty:"Empty"};function Qe({onLoadSession:t}){const s=l.useCallback(()=>h.getSessionsHistory(),[]),{data:n,loading:r}=$(s,6e4,!0);return r&&!n?e.jsxs("div",{className:"card p-4 rounded-card",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider mb-3",children:"Past Builds"}),e.jsx("div",{className:"text-sm text-muted",children:"Loading..."})]}):!n||n.length===0?null:e.jsxs("div",{className:"card p-4 rounded-card",children:[e.jsx("h3",{className:"text-sm font-semibold text-ink uppercase tracking-wider mb-3",children:"Past Builds"}),e.jsx("div",{className:"flex flex-col gap-2 max-h-64 overflow-y-auto terminal-scroll",children:n.map(a=>{const i=a.file_count;return e.jsxs("button",{onClick:()=>t==null?void 0:t(a),className:"text-left px-4 py-3 rounded-card card hover:bg-hover transition-all group cursor-pointer",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("span",{className:"text-[10px] font-mono text-muted-accessible",children:a.date}),e.jsxs("div",{className:"flex items-center gap-2",children:[i!==void 0&&i>0&&e.jsxs("span",{className:"text-[10px] font-mono text-muted-accessible",children:[i," files"]}),e.jsx(ge,{status:We(a.status),children:Ve[a.status]||a.status})]})]}),e.jsx("div",{className:"text-xs text-ink truncate group-hover:text-primary transition-colors",children:a.prd_snippet||a.id}),e.jsx("div",{className:"text-[10px] font-mono text-muted-accessible mt-0.5 truncate",children:a.path})]},a.id)})})]})}function Xe(){const t=fe(),[s,n]=l.useState(null),[r,a]=l.useState(()=>sessionStorage.getItem("pl_running")==="1"),[i,c]=l.useState(!1),[d,x]=l.useState(()=>sessionStorage.getItem("pl_prd")),[b,f]=l.useState(!1),[j,m]=l.useState(!1),[g,v]=l.useState(!1),[N,w]=l.useState(()=>sessionStorage.getItem("pl_tab")||"terminal"),[k,R]=l.useState(()=>sessionStorage.getItem("pl_provider")||"claude"),[o,y]=l.useState(null),[S,_]=l.useState(null),[A,M]=l.useState(null),T=l.useCallback(p=>{if(!p){y(null),_(null),M(null);return}y(p.status),_(p.agents),M(p.logs),a(p.status.running??!1),c(p.status.paused??!1)},[]),{connected:C,subscribe:D}=be(T),z=l.useCallback(()=>h.getStatus(),[]),{data:E}=$(z,3e4,!C);l.useEffect(()=>{o===null&&E!==null&&(a(E.running??!1),c(E.paused??!1))},[E,o]),l.useEffect(()=>{sessionStorage.setItem("pl_running",r?"1":"0"),r&&f(!0)},[r]),l.useEffect(()=>{d?sessionStorage.setItem("pl_prd",d):sessionStorage.removeItem("pl_prd")},[d]),l.useEffect(()=>{sessionStorage.setItem("pl_provider",k)},[k]),l.useEffect(()=>{sessionStorage.setItem("pl_tab",N)},[N]);const U=l.useCallback(()=>h.getMemorySummary(),[]),O=l.useCallback(()=>h.getChecklist(),[]),B=l.useCallback(()=>h.getFiles(),[]),{data:u,loading:P}=$(U,3e4,r),{data:q,loading:X}=$(O,3e4,r),{data:ee,loading:te}=$(B,3e4,r),F=o??E,se=S,ae=A,re=S===null,ne=A===null,le=l.useCallback(async(p,ue,pe,he)=>{n(null),f(!1),m(!1),w("terminal");try{await h.startSession({prd:p,provider:ue,projectDir:pe,mode:he}),x(p)}catch(V){n(V instanceof Error?V.message:"Failed to start session")}},[]),ie=l.useCallback(async()=>{try{(await h.stopSession()).stopped&&(a(!1),c(!1),x(null),y(null),_(null),M(null))}catch{a(!1),c(!1),x(null)}sessionStorage.removeItem("pl_running"),sessionStorage.removeItem("pl_prd"),sessionStorage.removeItem("pl_tab")},[]),ce=l.useCallback(p=>{t(`/project/${p.id}`)},[t]),oe=l.useCallback(p=>{R(p)},[]),de=l.useCallback(async()=>{try{await h.pauseSession(),c(!0)}catch{}},[]),xe=l.useCallback(async()=>{try{await h.resumeSession(),c(!1)}catch{}},[]),me=d&&d.replace(/^#+\s*/gm,"").split(`
33
+ `).find(p=>p.trim().length>0)||null;return e.jsxs("div",{className:"min-h-screen bg-[#FAF9F6] relative",children:[e.jsx("div",{className:"pattern-nodes"}),e.jsx("div",{className:"max-w-[1920px] mx-auto px-6 py-6 relative z-10",children:r?e.jsxs(e.Fragment,{children:[e.jsx(L,{name:"ControlBar",children:e.jsx(Pe,{status:F,prdSummary:me,onStop:ie,onPause:de,onResume:xe,isPaused:i})}),e.jsx("div",{className:"mt-4",children:e.jsx(L,{name:"StatusOverview",children:e.jsx(_e,{status:F})})}),e.jsxs("div",{className:"mt-4 grid grid-cols-12 gap-6",style:{height:"calc(100vh - 340px)",minHeight:"400px"},children:[e.jsx("div",{className:"col-span-3 flex flex-col gap-6",children:e.jsx(L,{name:"PhaseVisualizer",children:e.jsx($e,{currentPhase:(F==null?void 0:F.phase)||"idle",iteration:(F==null?void 0:F.iteration)||0})})}),e.jsxs("div",{className:"col-span-5 flex flex-col gap-0 min-h-0",children:[e.jsxs("div",{className:"flex items-center gap-1 mb-2 flex-shrink-0",children:[e.jsx("button",{onClick:()=>w("terminal"),className:`px-3 py-1.5 text-xs font-semibold rounded-lg transition-all ${N==="terminal"?"bg-[#553DE9] text-white":"text-[#6B6960] hover:text-[#36342E] hover:bg-[#F8F4F0]"}`,children:"Terminal"}),e.jsx("button",{onClick:()=>w("metrics"),className:`px-3 py-1.5 text-xs font-semibold rounded-lg transition-all ${N==="metrics"?"bg-[#553DE9] text-white":"text-[#6B6960] hover:text-[#36342E] hover:bg-[#F8F4F0]"}`,children:"Metrics"})]}),e.jsx("div",{className:"flex-1 min-h-0",children:e.jsx(L,{name:"Terminal",children:N==="terminal"?e.jsx(je,{logs:ae,loading:ne,subscribe:D}):e.jsx(Z,{visible:!0})})})]}),e.jsxs("div",{className:"col-span-4 flex flex-col gap-6 overflow-y-auto",children:[e.jsx(L,{name:"AgentDashboard",children:e.jsx(Te,{agents:se,loading:re})}),e.jsx(L,{name:"QualityGates",children:e.jsx(De,{checklist:q,loading:X})})]})]}),e.jsxs("div",{className:"mt-6 grid grid-cols-12 gap-6",children:[e.jsx("div",{className:"col-span-6",children:e.jsx(L,{name:"FileBrowser",children:e.jsx(Oe,{files:ee,loading:te})})}),e.jsx("div",{className:"col-span-6",children:e.jsx(L,{name:"MemoryViewer",children:e.jsx(He,{memory:u,loading:P})})})]})]}):e.jsxs("div",{className:"flex flex-col items-center",children:[e.jsxs("div",{className:"text-center mt-8 mb-8",children:[e.jsx("h2",{className:"font-heading text-h1 text-[#36342E]",children:"Describe it. Build it. Ship it."}),e.jsx("p",{className:"text-[#6B6960] mt-2 text-base max-w-lg mx-auto",children:"Paste a PRD or pick a template. Purple Lab spins up autonomous agents to build your project from scratch."})]}),e.jsx("div",{className:"w-full max-w-3xl",children:e.jsx(Le,{onSubmit:le,running:r,error:s,provider:k,onProviderChange:oe})}),b&&!r&&e.jsxs("div",{className:"w-full max-w-3xl mt-4 flex flex-col gap-4",children:[e.jsx("button",{onClick:async()=>{try{const p=await h.getSessionsHistory();p.length>0&&t(`/project/${p[0].id}`)}catch{}},className:"w-full px-6 py-4 rounded-card text-base font-bold bg-[#553DE9] text-white hover:bg-[#553DE9]/90 transition-all shadow-lg shadow-[#553DE9]/20",children:"View Project -- Browse Files and Preview"}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{onClick:()=>m(!j),className:"px-4 py-2 rounded-card text-sm font-semibold border border-[#553DE9]/30 text-[#553DE9] hover:bg-[#553DE9]/5 transition-all",children:j?"Hide Report":"Report"}),e.jsx("button",{onClick:()=>v(!g),className:"px-4 py-2 rounded-card text-sm font-semibold border border-[#ECEAE3] text-[#6B6960] hover:text-[#36342E] hover:bg-[#F8F4F0] transition-all",children:g?"Hide Metrics":"Metrics"})]}),e.jsx(Ge,{visible:j}),e.jsx(Z,{visible:g})]}),e.jsx("div",{className:"w-full max-w-3xl mt-4",children:e.jsx(Qe,{onLoadSession:ce})}),e.jsxs("div",{className:"mt-6 text-xs text-[#6B6960] flex items-center gap-2",children:[e.jsx("div",{className:`w-2 h-2 rounded-full ${C?"bg-[#1FC5A8]":"bg-[#C45B5B]"}`}),C?"Connected to Purple Lab backend":"Waiting for backend connection..."]})]})})]})}export{Xe as default};