loki-mode 6.53.0 → 6.55.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 (46) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/bin/postinstall.js +29 -0
  4. package/dashboard/__init__.py +1 -1
  5. package/docs/INSTALLATION.md +1 -1
  6. package/mcp/__init__.py +1 -1
  7. package/package.json +11 -2
  8. package/web-app/Dockerfile +59 -0
  9. package/web-app/alembic.ini +43 -0
  10. package/web-app/auth.py +249 -0
  11. package/web-app/crypto.py +83 -0
  12. package/web-app/deploy/k8s/purple-lab/configmap.yaml +8 -0
  13. package/web-app/deploy/k8s/purple-lab/deployment.yaml +69 -0
  14. package/web-app/deploy/k8s/purple-lab/hpa.yaml +24 -0
  15. package/web-app/deploy/k8s/purple-lab/ingress.yaml +30 -0
  16. package/web-app/deploy/k8s/purple-lab/networkpolicy.yaml +82 -0
  17. package/web-app/deploy/k8s/purple-lab/pdb.yaml +11 -0
  18. package/web-app/deploy/k8s/purple-lab/postgres.yaml +84 -0
  19. package/web-app/deploy/k8s/purple-lab/pvc.yaml +10 -0
  20. package/web-app/deploy/k8s/purple-lab/secret.yaml +13 -0
  21. package/web-app/deploy/k8s/purple-lab/service.yaml +13 -0
  22. package/web-app/deploy/k8s/purple-lab/serviceaccount.yaml +7 -0
  23. package/web-app/dist/assets/{Badge-CnWBUi7C.js → Badge-BDr4DPCT.js} +1 -1
  24. package/web-app/dist/assets/{Button-5ThWFbkO.js → Button-WBFGRnUr.js} +1 -1
  25. package/web-app/dist/assets/{Card-CcTmaOCN.js → Card-DzOT34Rr.js} +1 -1
  26. package/web-app/dist/assets/{HomePage-Dx4Ae0hu.js → HomePage-B8kMCXMB.js} +1 -1
  27. package/web-app/dist/assets/{LoginPage-CRffqZNo.js → LoginPage-D9lCyiqM.js} +1 -1
  28. package/web-app/dist/assets/{NotFoundPage-B1QZ92yR.js → NotFoundPage-DzeZ0uQ6.js} +1 -1
  29. package/web-app/dist/assets/{ProjectPage-BVnDGxXk.js → ProjectPage-C-k0iy0i.js} +14 -14
  30. package/web-app/dist/assets/{ProjectsPage-2Fi6cKB-.js → ProjectsPage-jys_pHzp.js} +1 -1
  31. package/web-app/dist/assets/{SettingsPage-DOzGoyLv.js → SettingsPage-Cz_RXr82.js} +1 -1
  32. package/web-app/dist/assets/{TemplatesPage-B-f1Gfbg.js → TemplatesPage-COnhb_Wq.js} +1 -1
  33. package/web-app/dist/assets/{TerminalOutput-DrKIbiB8.js → TerminalOutput-CmdEXHHd.js} +1 -1
  34. package/web-app/dist/assets/{arrow-left-CFG0TEkb.js → arrow-left-DAZzI0L-.js} +1 -1
  35. package/web-app/dist/assets/{clock-C-GPrW5k.js → clock-BHGf6zSk.js} +1 -1
  36. package/web-app/dist/assets/{external-link-ujbkNBY4.js → external-link-DLYjfP9j.js} +1 -1
  37. package/web-app/dist/assets/{index-B8gGcUMo.js → index-B8Eg1YHL.js} +2 -2
  38. package/web-app/dist/index.html +1 -1
  39. package/web-app/docker-compose.purple-lab.yml +76 -0
  40. package/web-app/migrations/env.py +103 -0
  41. package/web-app/migrations/script.py.mako +25 -0
  42. package/web-app/migrations/versions/.gitkeep +0 -0
  43. package/web-app/migrations/versions/001_initial_schema.py +118 -0
  44. package/web-app/models.py +140 -0
  45. package/web-app/requirements.txt +27 -0
  46. package/web-app/server.py +158 -22
@@ -0,0 +1,82 @@
1
+ apiVersion: networking.k8s.io/v1
2
+ kind: NetworkPolicy
3
+ metadata:
4
+ name: purple-lab
5
+ labels:
6
+ app: purple-lab
7
+ spec:
8
+ podSelector:
9
+ matchLabels:
10
+ app: purple-lab
11
+ policyTypes:
12
+ - Ingress
13
+ - Egress
14
+ ingress:
15
+ # Allow traffic from ingress controller
16
+ - from:
17
+ - namespaceSelector:
18
+ matchLabels:
19
+ kubernetes.io/metadata.name: ingress-nginx
20
+ ports:
21
+ - port: 57375
22
+ protocol: TCP
23
+ egress:
24
+ # Allow DNS resolution
25
+ - to:
26
+ - namespaceSelector: {}
27
+ ports:
28
+ - port: 53
29
+ protocol: UDP
30
+ - port: 53
31
+ protocol: TCP
32
+ # Allow connections to PostgreSQL
33
+ - to:
34
+ - podSelector:
35
+ matchLabels:
36
+ app: postgres-purple-lab
37
+ ports:
38
+ - port: 5432
39
+ protocol: TCP
40
+ # Allow outbound HTTPS (GitHub OAuth, external APIs)
41
+ - to:
42
+ - ipBlock:
43
+ cidr: 0.0.0.0/0
44
+ except:
45
+ - 10.0.0.0/8
46
+ - 172.16.0.0/12
47
+ - 192.168.0.0/16
48
+ ports:
49
+ - port: 443
50
+ protocol: TCP
51
+ ---
52
+ apiVersion: networking.k8s.io/v1
53
+ kind: NetworkPolicy
54
+ metadata:
55
+ name: postgres-purple-lab
56
+ labels:
57
+ app: postgres-purple-lab
58
+ spec:
59
+ podSelector:
60
+ matchLabels:
61
+ app: postgres-purple-lab
62
+ policyTypes:
63
+ - Ingress
64
+ - Egress
65
+ ingress:
66
+ # Only allow connections from purple-lab pods
67
+ - from:
68
+ - podSelector:
69
+ matchLabels:
70
+ app: purple-lab
71
+ ports:
72
+ - port: 5432
73
+ protocol: TCP
74
+ egress:
75
+ # Allow DNS resolution only
76
+ - to:
77
+ - namespaceSelector: {}
78
+ ports:
79
+ - port: 53
80
+ protocol: UDP
81
+ - port: 53
82
+ protocol: TCP
@@ -0,0 +1,11 @@
1
+ apiVersion: policy/v1
2
+ kind: PodDisruptionBudget
3
+ metadata:
4
+ name: purple-lab
5
+ labels:
6
+ app: purple-lab
7
+ spec:
8
+ minAvailable: 1
9
+ selector:
10
+ matchLabels:
11
+ app: purple-lab
@@ -0,0 +1,84 @@
1
+ apiVersion: v1
2
+ kind: Service
3
+ metadata:
4
+ name: postgres-purple-lab
5
+ spec:
6
+ selector:
7
+ app: postgres-purple-lab
8
+ ports:
9
+ - name: postgres
10
+ port: 5432
11
+ targetPort: 5432
12
+ protocol: TCP
13
+ clusterIP: None
14
+ ---
15
+ apiVersion: apps/v1
16
+ kind: StatefulSet
17
+ metadata:
18
+ name: postgres-purple-lab
19
+ spec:
20
+ serviceName: postgres-purple-lab
21
+ replicas: 1
22
+ selector:
23
+ matchLabels:
24
+ app: postgres-purple-lab
25
+ template:
26
+ metadata:
27
+ labels:
28
+ app: postgres-purple-lab
29
+ spec:
30
+ securityContext:
31
+ runAsUser: 999
32
+ runAsGroup: 999
33
+ fsGroup: 999
34
+ containers:
35
+ - name: postgres
36
+ image: postgres:16-alpine
37
+ ports:
38
+ - name: postgres
39
+ containerPort: 5432
40
+ protocol: TCP
41
+ env:
42
+ - name: POSTGRES_USER
43
+ value: purplelab
44
+ - name: POSTGRES_PASSWORD
45
+ valueFrom:
46
+ secretKeyRef:
47
+ name: purple-lab-secrets
48
+ key: POSTGRES_PASSWORD
49
+ - name: POSTGRES_DB
50
+ value: purplelab
51
+ - name: PGDATA
52
+ value: /var/lib/postgresql/data/pgdata
53
+ volumeMounts:
54
+ - name: postgres-data
55
+ mountPath: /var/lib/postgresql/data
56
+ resources:
57
+ requests:
58
+ memory: "256Mi"
59
+ cpu: "250m"
60
+ limits:
61
+ memory: "512Mi"
62
+ cpu: "500m"
63
+ livenessProbe:
64
+ exec:
65
+ command: ["pg_isready", "-U", "purplelab"]
66
+ initialDelaySeconds: 15
67
+ periodSeconds: 10
68
+ timeoutSeconds: 5
69
+ failureThreshold: 3
70
+ readinessProbe:
71
+ exec:
72
+ command: ["pg_isready", "-U", "purplelab"]
73
+ initialDelaySeconds: 5
74
+ periodSeconds: 5
75
+ timeoutSeconds: 3
76
+ failureThreshold: 3
77
+ volumeClaimTemplates:
78
+ - metadata:
79
+ name: postgres-data
80
+ spec:
81
+ accessModes: ["ReadWriteOnce"]
82
+ resources:
83
+ requests:
84
+ storage: 10Gi
@@ -0,0 +1,10 @@
1
+ apiVersion: v1
2
+ kind: PersistentVolumeClaim
3
+ metadata:
4
+ name: purple-lab-projects
5
+ spec:
6
+ accessModes:
7
+ - ReadWriteMany
8
+ resources:
9
+ requests:
10
+ storage: 50Gi
@@ -0,0 +1,13 @@
1
+ apiVersion: v1
2
+ kind: Secret
3
+ metadata:
4
+ name: purple-lab-secrets
5
+ type: Opaque
6
+ stringData:
7
+ DATABASE_URL: "postgresql+asyncpg://purplelab:CHANGE_ME@postgres-purple-lab:5432/purplelab"
8
+ PURPLE_LAB_SECRET_KEY: "CHANGE_ME_TO_RANDOM_64_CHAR_HEX"
9
+ POSTGRES_PASSWORD: "CHANGE_ME"
10
+ GITHUB_CLIENT_ID: ""
11
+ GITHUB_CLIENT_SECRET: ""
12
+ GOOGLE_CLIENT_ID: ""
13
+ GOOGLE_CLIENT_SECRET: ""
@@ -0,0 +1,13 @@
1
+ apiVersion: v1
2
+ kind: Service
3
+ metadata:
4
+ name: purple-lab
5
+ spec:
6
+ selector:
7
+ app: purple-lab
8
+ ports:
9
+ - name: http
10
+ port: 80
11
+ targetPort: 57375
12
+ protocol: TCP
13
+ type: ClusterIP
@@ -0,0 +1,7 @@
1
+ apiVersion: v1
2
+ kind: ServiceAccount
3
+ metadata:
4
+ name: purple-lab
5
+ labels:
6
+ app: purple-lab
7
+ automountServiceAccountToken: false
@@ -1,4 +1,4 @@
1
- import{c as m,r,j as e}from"./index-B8gGcUMo.js";import{C as g,a as p}from"./clock-C-GPrW5k.js";/**
1
+ import{c as m,r,j as e}from"./index-B8Eg1YHL.js";import{C as g,a as p}from"./clock-BHGf6zSk.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 p,r as u,j as e}from"./index-B8gGcUMo.js";/**
1
+ import{c as p,r as u,j as e}from"./index-B8Eg1YHL.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{j as s}from"./index-B8gGcUMo.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};
1
+ import{j as s}from"./index-B8Eg1YHL.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};
@@ -1,4 +1,4 @@
1
- import{j as e,r as n,a as h,u as be,b as ge}from"./index-B8gGcUMo.js";import{u as I,B as je}from"./Badge-CnWBUi7C.js";import{P as ve,a as Ne,S as ye,E,T as we}from"./TerminalOutput-DrKIbiB8.js";import"./clock-C-GPrW5k.js";function ke(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),l=Math.floor(t%3600/60);return`${s}h ${l}m`}function Se(t,s){if(!t||t<=0)return"--";const l={simple:{opus:1,haiku:1,total:3},standard:{opus:2,haiku:2,total:5},complex:{opus:3,haiku:3,total:8}},r=l[s]||l.standard;return t<=r.opus?"Opus":t>r.total-r.haiku?"Haiku":"Sonnet"}function Ce({status:t,prdSummary:s,onStop:l,onPause:r,onResume:a,isPaused:c}){const i=t?Se(t.iteration??0,t.complexity||"standard"):"--",o=c??(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 ${i==="Opus"?"bg-primary/10 text-primary":i==="Haiku"?"bg-success/10 text-success":"bg-primary/10 text-primary"}`,children:i})]}),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:ke((t==null?void 0:t.uptime)??0)}),(r||a)&&e.jsxs("button",{onClick:o?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:[o?e.jsx(ve,{size:14}):e.jsx(Ne,{size:14}),o?"Resume":"Pause"]}),l&&e.jsxs("button",{onClick:l,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(ye,{size:14}),"Stop"]})]})}function Ee({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(l=>e.jsxs("div",{className:"card p-4 text-center",children:[e.jsx("div",{className:`text-2xl font-bold font-mono ${l.color}`,children:l.value}),e.jsx("div",{className:"text-xs text-muted font-medium mt-1 uppercase tracking-wider",children:l.label})]},l.label))})}function Pe({plan:t,loading:s,onConfirm:l,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..."}),e.jsxs("div",{className:"flex gap-3 mt-4",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:l,className:"px-4 py-2 text-sm font-medium text-primary hover:text-primary/80 transition-colors underline",children:"Skip analysis, build now"})]})]}):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-xs 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-xs 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-xs 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-xs 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-xs 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:l,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 _e({onSubmit:t,running:s,error:l,provider:r,onProviderChange:a,initialPrd:c}){const[i,o]=n.useState(""),[m,b]=n.useState(""),[f,y]=n.useState("claude"),[d,g]=n.useState(""),j=r??f,[v,w]=n.useState(!1),[k,T]=n.useState([]),[x,P]=n.useState(!1),[N,M]=n.useState(!1),[_,A]=n.useState(!1),[z,F]=n.useState(null),[L,$]=n.useState(!1),[O,D]=n.useState(!1);n.useEffect(()=>{h.getTemplates().then(u=>{T(u),P(!1)}).catch(()=>{T([]),P(!0)})},[]),n.useEffect(()=>{c&&o(c)},[c]),n.useEffect(()=>{if(c)return;const u=localStorage.getItem("loki-prd-draft");u&&o(u),h.getPrdPrefill().then(({content:S})=>{S&&o(S)}).catch(()=>{})},[c]),n.useEffect(()=>{i.trim()?localStorage.setItem("loki-prd-draft",i):localStorage.removeItem("loki-prd-draft")},[i]),n.useEffect(()=>{const u=S=>{i.trim()&&S.preventDefault()};return window.addEventListener("beforeunload",u),()=>window.removeEventListener("beforeunload",u)},[i]);const R=n.useCallback(async(u,S)=>{b(S),w(!1);try{const G=await h.getTemplateContent(u);o(G.content)}catch{o(`# ${S}
1
+ import{j as e,r as n,a as h,u as be,b as ge}from"./index-B8Eg1YHL.js";import{u as I,B as je}from"./Badge-BDr4DPCT.js";import{P as ve,a as Ne,S as ye,E,T as we}from"./TerminalOutput-CmdEXHHd.js";import"./clock-BHGf6zSk.js";function ke(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),l=Math.floor(t%3600/60);return`${s}h ${l}m`}function Se(t,s){if(!t||t<=0)return"--";const l={simple:{opus:1,haiku:1,total:3},standard:{opus:2,haiku:2,total:5},complex:{opus:3,haiku:3,total:8}},r=l[s]||l.standard;return t<=r.opus?"Opus":t>r.total-r.haiku?"Haiku":"Sonnet"}function Ce({status:t,prdSummary:s,onStop:l,onPause:r,onResume:a,isPaused:c}){const i=t?Se(t.iteration??0,t.complexity||"standard"):"--",o=c??(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 ${i==="Opus"?"bg-primary/10 text-primary":i==="Haiku"?"bg-success/10 text-success":"bg-primary/10 text-primary"}`,children:i})]}),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:ke((t==null?void 0:t.uptime)??0)}),(r||a)&&e.jsxs("button",{onClick:o?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:[o?e.jsx(ve,{size:14}):e.jsx(Ne,{size:14}),o?"Resume":"Pause"]}),l&&e.jsxs("button",{onClick:l,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(ye,{size:14}),"Stop"]})]})}function Ee({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(l=>e.jsxs("div",{className:"card p-4 text-center",children:[e.jsx("div",{className:`text-2xl font-bold font-mono ${l.color}`,children:l.value}),e.jsx("div",{className:"text-xs text-muted font-medium mt-1 uppercase tracking-wider",children:l.label})]},l.label))})}function Pe({plan:t,loading:s,onConfirm:l,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..."}),e.jsxs("div",{className:"flex gap-3 mt-4",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:l,className:"px-4 py-2 text-sm font-medium text-primary hover:text-primary/80 transition-colors underline",children:"Skip analysis, build now"})]})]}):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-xs 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-xs 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-xs 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-xs 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-xs 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:l,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 _e({onSubmit:t,running:s,error:l,provider:r,onProviderChange:a,initialPrd:c}){const[i,o]=n.useState(""),[m,b]=n.useState(""),[f,y]=n.useState("claude"),[d,g]=n.useState(""),j=r??f,[v,w]=n.useState(!1),[k,T]=n.useState([]),[x,P]=n.useState(!1),[N,M]=n.useState(!1),[_,A]=n.useState(!1),[z,F]=n.useState(null),[L,$]=n.useState(!1),[O,D]=n.useState(!1);n.useEffect(()=>{h.getTemplates().then(u=>{T(u),P(!1)}).catch(()=>{T([]),P(!0)})},[]),n.useEffect(()=>{c&&o(c)},[c]),n.useEffect(()=>{if(c)return;const u=localStorage.getItem("loki-prd-draft");u&&o(u),h.getPrdPrefill().then(({content:S})=>{S&&o(S)}).catch(()=>{})},[c]),n.useEffect(()=>{i.trim()?localStorage.setItem("loki-prd-draft",i):localStorage.removeItem("loki-prd-draft")},[i]),n.useEffect(()=>{const u=S=>{i.trim()&&S.preventDefault()};return window.addEventListener("beforeunload",u),()=>window.removeEventListener("beforeunload",u)},[i]);const R=n.useCallback(async(u,S)=>{b(S),w(!1);try{const G=await h.getTemplateContent(u);o(G.content)}catch{o(`# ${S}
2
2
 
3
3
  ## Overview
4
4
 
@@ -1 +1 @@
1
- import{g as r,u as o,r as c,j as e}from"./index-B8gGcUMo.js";function x(){const{user:l,loading:t,login:i,isLocalMode:n}=r(),s=o();return c.useEffect(()=>{!t&&(l||n)&&s("/",{replace:!0})},[l,t,n,s]),t?e.jsx("div",{className:"h-screen bg-[#FAF9F6] flex items-center justify-center text-[#6B6960] text-sm",children:"Loading..."}):e.jsx("div",{className:"h-screen bg-[#FAF9F6] flex items-center justify-center",children:e.jsxs("div",{className:"w-full max-w-sm mx-auto px-6",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx("h1",{className:"font-heading text-3xl font-bold text-[#36342E] mb-1",children:"Purple Lab"}),e.jsx("p",{className:"text-sm text-[#6B6960]",children:"Autonomous agent workspace powered by Loki"})]}),e.jsxs("div",{className:"bg-white rounded-lg border border-[#ECEAE3] shadow-sm p-6 space-y-4",children:[e.jsx("h2",{className:"text-base font-medium text-[#36342E] text-center",children:"Sign in to continue"}),e.jsxs("button",{type:"button",onClick:()=>i("github"),className:"w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-[5px] border border-[#ECEAE3] bg-[#24292f] text-white text-sm font-medium hover:bg-[#1b1f23] transition-colors",children:[e.jsx("svg",{className:"w-5 h-5",fill:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"})}),"Sign in with GitHub"]}),e.jsxs("button",{type:"button",onClick:()=>i("google"),className:"w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-[5px] border border-[#ECEAE3] bg-white text-[#36342E] text-sm font-medium hover:bg-[#F8F4F0] transition-colors",children:[e.jsxs("svg",{className:"w-5 h-5",viewBox:"0 0 24 24",children:[e.jsx("path",{fill:"#4285F4",d:"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"}),e.jsx("path",{fill:"#34A853",d:"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"}),e.jsx("path",{fill:"#FBBC05",d:"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"}),e.jsx("path",{fill:"#EA4335",d:"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"})]}),"Sign in with Google"]}),e.jsxs("div",{className:"relative",children:[e.jsx("div",{className:"absolute inset-0 flex items-center",children:e.jsx("div",{className:"w-full border-t border-[#ECEAE3]"})}),e.jsx("div",{className:"relative flex justify-center text-xs",children:e.jsx("span",{className:"bg-white px-2 text-[#939084]",children:"or"})})]}),e.jsx("button",{type:"button",onClick:()=>s("/"),className:"w-full text-center text-sm text-[#6B6960] hover:text-[#553DE9] transition-colors py-1",children:"Continue without account (local mode)"})]}),e.jsx("p",{className:"text-xs text-[#939084] text-center mt-4",children:"Local mode stores everything on your machine. Sign in for cloud sync and collaboration."})]})})}export{x as default};
1
+ import{g as r,u as o,r as c,j as e}from"./index-B8Eg1YHL.js";function x(){const{user:l,loading:t,login:i,isLocalMode:n}=r(),s=o();return c.useEffect(()=>{!t&&(l||n)&&s("/",{replace:!0})},[l,t,n,s]),t?e.jsx("div",{className:"h-screen bg-[#FAF9F6] flex items-center justify-center text-[#6B6960] text-sm",children:"Loading..."}):e.jsx("div",{className:"h-screen bg-[#FAF9F6] flex items-center justify-center",children:e.jsxs("div",{className:"w-full max-w-sm mx-auto px-6",children:[e.jsxs("div",{className:"text-center mb-8",children:[e.jsx("h1",{className:"font-heading text-3xl font-bold text-[#36342E] mb-1",children:"Purple Lab"}),e.jsx("p",{className:"text-sm text-[#6B6960]",children:"Autonomous agent workspace powered by Loki"})]}),e.jsxs("div",{className:"bg-white rounded-lg border border-[#ECEAE3] shadow-sm p-6 space-y-4",children:[e.jsx("h2",{className:"text-base font-medium text-[#36342E] text-center",children:"Sign in to continue"}),e.jsxs("button",{type:"button",onClick:()=>i("github"),className:"w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-[5px] border border-[#ECEAE3] bg-[#24292f] text-white text-sm font-medium hover:bg-[#1b1f23] transition-colors",children:[e.jsx("svg",{className:"w-5 h-5",fill:"currentColor",viewBox:"0 0 24 24",children:e.jsx("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"})}),"Sign in with GitHub"]}),e.jsxs("button",{type:"button",onClick:()=>i("google"),className:"w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-[5px] border border-[#ECEAE3] bg-white text-[#36342E] text-sm font-medium hover:bg-[#F8F4F0] transition-colors",children:[e.jsxs("svg",{className:"w-5 h-5",viewBox:"0 0 24 24",children:[e.jsx("path",{fill:"#4285F4",d:"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"}),e.jsx("path",{fill:"#34A853",d:"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"}),e.jsx("path",{fill:"#FBBC05",d:"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"}),e.jsx("path",{fill:"#EA4335",d:"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"})]}),"Sign in with Google"]}),e.jsxs("div",{className:"relative",children:[e.jsx("div",{className:"absolute inset-0 flex items-center",children:e.jsx("div",{className:"w-full border-t border-[#ECEAE3]"})}),e.jsx("div",{className:"relative flex justify-center text-xs",children:e.jsx("span",{className:"bg-white px-2 text-[#939084]",children:"or"})})]}),e.jsx("button",{type:"button",onClick:()=>s("/"),className:"w-full text-center text-sm text-[#6B6960] hover:text-[#553DE9] transition-colors py-1",children:"Continue without account (local mode)"})]}),e.jsx("p",{className:"text-xs text-[#939084] text-center mt-4",children:"Local mode stores everything on your machine. Sign in for cloud sync and collaboration."})]})})}export{x as default};
@@ -1 +1 @@
1
- import{j as e,L as t,H as s}from"./index-B8gGcUMo.js";import{A as o}from"./arrow-left-CFG0TEkb.js";function i(){return e.jsxs("div",{className:"flex flex-col items-center justify-center h-full min-h-[60vh] p-8 text-center",children:[e.jsx("div",{className:"text-6xl font-heading font-bold text-primary/20 mb-4",children:"404"}),e.jsx("h1",{className:"text-h3 font-heading font-bold text-ink mb-2",children:"Page not found"}),e.jsx("p",{className:"text-sm text-muted-accessible mb-6 max-w-xs",children:"The page you are looking for does not exist or has been moved."}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("button",{onClick:()=>window.history.back(),className:"inline-flex items-center gap-1.5 px-4 py-2 text-xs font-medium rounded-btn border border-border text-secondary hover:bg-hover transition-colors",children:[e.jsx(o,{size:14}),"Go Back"]}),e.jsxs(t,{to:"/",className:"inline-flex items-center gap-1.5 px-4 py-2 text-xs font-medium rounded-btn bg-primary text-white hover:bg-[#4432c4] transition-colors shadow-button",children:[e.jsx(s,{size:14}),"Home"]})]})]})}export{i as default};
1
+ import{j as e,L as t,H as s}from"./index-B8Eg1YHL.js";import{A as o}from"./arrow-left-DAZzI0L-.js";function i(){return e.jsxs("div",{className:"flex flex-col items-center justify-center h-full min-h-[60vh] p-8 text-center",children:[e.jsx("div",{className:"text-6xl font-heading font-bold text-primary/20 mb-4",children:"404"}),e.jsx("h1",{className:"text-h3 font-heading font-bold text-ink mb-2",children:"Page not found"}),e.jsx("p",{className:"text-sm text-muted-accessible mb-6 max-w-xs",children:"The page you are looking for does not exist or has been moved."}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("button",{onClick:()=>window.history.back(),className:"inline-flex items-center gap-1.5 px-4 py-2 text-xs font-medium rounded-btn border border-border text-secondary hover:bg-hover transition-colors",children:[e.jsx(o,{size:14}),"Go Back"]}),e.jsxs(t,{to:"/",className:"inline-flex items-center gap-1.5 px-4 py-2 text-xs font-medium rounded-btn bg-primary text-white hover:bg-[#4432c4] transition-colors shadow-button",children:[e.jsx(s,{size:14}),"Home"]})]})]})}export{i as default};