dryymatt commited on
Commit
aae3922
·
verified ·
1 Parent(s): bfaf402

STABLE VIBE: core.py — port 7860, root HEAD/GET, simplicity audit

Browse files
Files changed (1) hide show
  1. core.py +825 -18
core.py CHANGED
@@ -1,19 +1,826 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
- "╔══════════════════════════════════════════════════════╗
3
- ║ OMNI-VIBE CORE Specialized Swarm Architecture ║
4
- ║ ║
5
- ║ The Athanor: LiteRT engine, sub-second latency ║
6
- ║ ║
7
- ║ POSE ARCHITECT: full-stack schema + zero-config DB║
8
- ║ + Google OAuth out-of-the-box ║
9
- POSE PAINTER: Liquid Glass design system forced ║
10
- ║ across every generated app ║
11
- ║ POSE AUDITOR: step-by-step reasoning, verify ║
12
- ║ code before every hot-reload ║
13
- ║ ║
14
- ║ All Poses run locally — zero external API calls. ║
15
- Sub-second Reflect-Select loop with regex engine. ║
16
- ╚══════════════════════════════════════════════════════╝
17
- "
18
-
19
- ... (full content from write above)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ╔══════════════════════════════════════════════════════════╗
3
+ ║ OMNI-VIBE CORE — Specialized Swarm Architecture ║
4
+ ║ ║
5
+ ║ The Athanor: LiteRT engine, sub-second latency ║
6
+ ║ ║
7
+ ║ POSE ARCHITECT: full-stack schema + zero-config DB ║
8
+ ║ + Google OAuth out-of-the-box ║
9
+ ║ POSE PAINTER: Liquid Glass design system enforced ║
10
+ ║ across every generated app ║
11
+ ║ POSE AUDITOR: step-by-step reasoning, verify code ║
12
+ ║ before every hot-reload ║
13
+ ║ ║
14
+ ║ All Poses run locally — zero external API calls. ║
15
+ ║ Sub-second Reflect-Select loop with regex engine. ║
16
+ ╚══════════════════════════════════════════════════════════╝
17
+ """
18
 
19
+ import asyncio, json, os, re, time, uuid, textwrap, hashlib
20
+ from pathlib import Path
21
+ from typing import Dict, List, Optional, Tuple
22
+ from dataclasses import dataclass, field
23
+
24
+
25
+ # ═══════════════════════════════════════════════════════
26
+ # POSES The Specialized Swarm
27
+ # ═══════════════════════════════════════════════════════
28
+
29
+ @dataclass
30
+ class AuditFinding:
31
+ line: int
32
+ severity: str # ERROR | WARN | INFO
33
+ message: str
34
+ fix: Optional[str] = None
35
+
36
+
37
+ # ─── LIQUID GLASS DESIGN SYSTEM ────────────────────────
38
+ # Canonical CSS variables injected into every output
39
+
40
+ LIQUID_GLASS_CSS = """
41
+ :root {
42
+ --glass-bg: rgba(255,255,255,.03);
43
+ --glass-border: rgba(255,255,255,.06);
44
+ --glass-hover: rgba(255,255,255,.08);
45
+ --purple: #8B5CF6; --cyan: #06B6D4; --green: #10B981; --gold: #F59E0B;
46
+ --text: #e0e0ff; --text2: #9090b0; --text3: #606080;
47
+ --bg1: #0a0a1a; --bg2: #1a0a2e;
48
+ --radius: 20px; --radius-sm: 12px;
49
+ --font: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
50
+ --mono: 'SF Mono','Fira Code',monospace;
51
+ }
52
+ *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
53
+ body{font-family:var(--font);background:linear-gradient(135deg,var(--bg1),var(--bg2),#0a1a2e);color:var(--text);min-height:100vh;-webkit-font-smoothing:antialiased}
54
+ ::selection{background:rgba(139,92,246,.5);color:#fff}
55
+ .glass{background:var(--glass-bg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius)}
56
+ .glass-hover:hover{background:var(--glass-hover);border-color:rgba(139,92,246,.2)}
57
+ .btn{display:inline-flex;align-items:center;gap:.5rem;padding:.75rem 1.75rem;background:linear-gradient(135deg,var(--purple),var(--cyan));border:none;border-radius:var(--radius-sm);color:#fff;font-weight:600;cursor:pointer;transition:transform .15s,box-shadow .15s}
58
+ .btn:hover{transform:translateY(-1px);box-shadow:0 4px 20px rgba(139,92,246,.4)}
59
+ .btn-outline{background:var(--glass-bg);border:1px solid var(--glass-border);color:var(--text2)}
60
+ .input-glass{width:100%;padding:.75rem 1rem;background:var(--glass-bg);border:1px solid var(--glass-border);border-radius:var(--radius-sm);color:var(--text);font-size:.95rem;outline:none;transition:border-color .15s,box-shadow .15s}
61
+ .input-glass:focus{border-color:rgba(139,92,246,.4);box-shadow:0 0 20px rgba(139,92,246,.1)}
62
+ .card{background:var(--glass-bg);backdrop-filter:blur(20px);border:1px solid var(--glass-border);border-radius:var(--radius);padding:1.5rem}
63
+ .gradient-text{background:linear-gradient(135deg,var(--purple),var(--cyan),var(--green));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
64
+ """
65
+
66
+ LIQUID_GLASS_LOGO = """
67
+ <svg width="48" height="48" viewBox="0 0 64 64" id="wizard-hat" style="filter:drop-shadow(0 0 20px rgba(139,92,246,.6))">
68
+ <defs><linearGradient id="hg" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="0%" style="stop-color:#8B5CF6"/><stop offset="50%" style="stop-color:#06B6D4"/><stop offset="100%" style="stop-color:#10B981"/></linearGradient></defs>
69
+ <path d="M32 8 L8 48 L32 40 L56 48 Z" fill="url(#hg)" stroke="rgba(255,255,255,.3)" stroke-width="1.5"/>
70
+ <ellipse cx="32" cy="48" rx="26" ry="7" fill="none" stroke="url(#hg)" stroke-width="2" opacity=".6"/>
71
+ </svg>
72
+ """
73
+
74
+ # ─── ZERO-CONFIG DATABASE SCHEMA ───────────────────────
75
+
76
+ ZERO_DB_SCHEMA = """
77
+ -- Omni-Vibe Zero-Config Database
78
+ -- Uses SQLite (built-in, zero setup) with WAL mode
79
+
80
+ CREATE TABLE IF NOT EXISTS users (
81
+ id TEXT PRIMARY KEY,
82
+ email TEXT UNIQUE NOT NULL,
83
+ name TEXT,
84
+ avatar_url TEXT,
85
+ google_id TEXT UNIQUE,
86
+ created_at TEXT DEFAULT (datetime('now')),
87
+ updated_at TEXT DEFAULT (datetime('now'))
88
+ );
89
+
90
+ CREATE TABLE IF NOT EXISTS sessions (
91
+ id TEXT PRIMARY KEY,
92
+ user_id TEXT NOT NULL REFERENCES users(id),
93
+ token TEXT UNIQUE NOT NULL,
94
+ expires_at TEXT NOT NULL,
95
+ created_at TEXT DEFAULT (datetime('now'))
96
+ );
97
+
98
+ CREATE TABLE IF NOT EXISTS items (
99
+ id TEXT PRIMARY KEY,
100
+ user_id TEXT NOT NULL REFERENCES users(id),
101
+ title TEXT NOT NULL,
102
+ content TEXT,
103
+ status TEXT DEFAULT 'active',
104
+ created_at TEXT DEFAULT (datetime('now')),
105
+ updated_at TEXT DEFAULT (datetime('now'))
106
+ );
107
+
108
+ CREATE INDEX IF NOT EXISTS idx_items_user ON items(user_id);
109
+ CREATE INDEX IF NOT EXISTS idx_sessions_token ON sessions(token);
110
+ """
111
+
112
+ # ─── GOOGLE OAUTH SERVER-SIDE ──────────────────────────
113
+
114
+ GOOGLE_OAUTH_PY = """
115
+ import os, json, httpx
116
+ from urllib.parse import urlencode
117
+
118
+ GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", "")
119
+ GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", "")
120
+ GOOGLE_REDIRECT = os.environ.get("GOOGLE_REDIRECT_URI", "http://localhost:8080/auth/callback")
121
+
122
+ def get_auth_url(state: str = "") -> str:
123
+ params = {
124
+ "client_id": GOOGLE_CLIENT_ID,
125
+ "redirect_uri": GOOGLE_REDIRECT,
126
+ "response_type": "code",
127
+ "scope": "openid email profile",
128
+ "state": state,
129
+ }
130
+ return f"https://accounts.google.com/o/oauth2/v2/auth?{urlencode(params)}"
131
+
132
+ async def exchange_code(code: str) -> dict:
133
+ async with httpx.AsyncClient() as c:
134
+ resp = await c.post("https://oauth2.googleapis.com/token", data={
135
+ "code": code, "client_id": GOOGLE_CLIENT_ID,
136
+ "client_secret": GOOGLE_CLIENT_SECRET,
137
+ "redirect_uri": GOOGLE_REDIRECT, "grant_type": "authorization_code",
138
+ })
139
+ tokens = resp.json()
140
+ user = await c.get("https://www.googleapis.com/oauth2/v2/userinfo",
141
+ headers={"Authorization": f"Bearer {tokens['access_token']}"})
142
+ return {**tokens, "user": user.json()}
143
+ """
144
+
145
+ GOOGLE_OAUTH_JS = """
146
+ // Google OAuth client-side — Liquid Glass styled
147
+ async function initGoogleAuth() {
148
+ const btn = document.getElementById('google-auth-btn');
149
+ if (!btn) return;
150
+
151
+ btn.addEventListener('click', () => {
152
+ const state = crypto.randomUUID();
153
+ localStorage.setItem('oauth_state', state);
154
+ window.location.href = `/auth/google?state=${state}`;
155
+ });
156
+
157
+ // Check for callback
158
+ const params = new URLSearchParams(window.location.search);
159
+ if (params.get('code')) {
160
+ const resp = await fetch('/auth/callback?' + params.toString());
161
+ const data = await resp.json();
162
+ if (data.user) {
163
+ localStorage.setItem('user', JSON.stringify(data.user));
164
+ window.location.href = '/';
165
+ }
166
+ }
167
+ }
168
+ document.addEventListener('DOMContentLoaded', initGoogleAuth);
169
+ """
170
+
171
+
172
+ # ═══════════════════════════════════════════════════════
173
+ # POSE ARCHITECT — Full-Stack Schema Generator
174
+ # ═══════════════════════════════════════════════════════
175
+
176
+ class PoseArchitect:
177
+ """
178
+ Generates full-stack application architectures.
179
+ Every output includes: zero-config SQLite DB + Google OAuth.
180
+ """
181
+
182
+ STACKS = {
183
+ "html": {"backend": None, "frontend": "Vanilla HTML/CSS/JS + Liquid Glass"},
184
+ "flask": {"backend": "Flask+SQLite","frontend": "Jinja2 + Liquid Glass"},
185
+ "fastapi": {"backend": "FastAPI+SQLite","frontend": "HTMX + Liquid Glass"},
186
+ "node": {"backend": "Express+better-sqlite3","frontend": "Vanilla + Liquid Glass"},
187
+ }
188
+
189
+ def design(self, prompt: str) -> Dict:
190
+ """Analyze prompt and design the full-stack schema."""
191
+ p = prompt.lower()
192
+
193
+ # Detect stack
194
+ stack = "html"
195
+ if any(w in p for w in ["api","backend","server","flask","fastapi"]):
196
+ stack = "fastapi" if "fastapi" in p else "flask"
197
+ elif any(w in p for w in ["node","express","javascript backend"]):
198
+ stack = "node"
199
+ elif any(w in p for w in ["app","saas","platform","dashboard","database"]):
200
+ stack = "fastapi"
201
+
202
+ # Detect features
203
+ features = []
204
+ if any(w in p for w in ["auth","login","signup","oauth","google"]):
205
+ features.append("google-oauth")
206
+ if any(w in p for w in ["database","db","storage","data","crud"]):
207
+ features.append("zero-db")
208
+ if any(w in p for w in ["dashboard","admin","panel"]):
209
+ features.append("dashboard")
210
+ if any(w in p for w in ["landing","page","homepage","marketing"]):
211
+ features.append("landing-page")
212
+ if any(w in p for w in ["dark","theme","purple","glass","gradient"]):
213
+ features.append("liquid-glass-theme")
214
+
215
+ schema = {
216
+ "stack": self.STACKS[stack],
217
+ "features": features,
218
+ "has_db": "zero-db" in features,
219
+ "has_auth": "google-oauth" in features,
220
+ "has_dashboard": "dashboard" in features,
221
+ "files_needed": self._compute_files(stack, features),
222
+ "landing_title": self._extract_title(prompt),
223
+ }
224
+ return schema
225
+
226
+ def _compute_files(self, stack: str, features: List[str]) -> List[str]:
227
+ files = ["index.html"]
228
+ if "google-oauth" in features:
229
+ files.extend(["auth.py", "static/auth.js"])
230
+ if "zero-db" in features:
231
+ files.append("database.py")
232
+ if stack in ("flask", "fastapi"):
233
+ files.extend(["app.py", "requirements.txt"])
234
+ if stack == "fastapi":
235
+ files.append("Dockerfile")
236
+ if "dashboard" in features:
237
+ files.append("templates/dashboard.html")
238
+ return files
239
+
240
+ def _extract_title(self, prompt: str) -> str:
241
+ """Extract a meaningful title from the prompt."""
242
+ for phrase in ["called ", "named ", "titled "]:
243
+ if phrase in prompt.lower():
244
+ idx = prompt.lower().find(phrase) + len(phrase)
245
+ end = min(prompt.find(" ", idx + 1) if " " in prompt[idx:] else len(prompt), idx + 30)
246
+ name = prompt[idx:end].strip().rstrip(".,;!?")
247
+ if name: return name
248
+ for w in ["startup", "saas", "app", "platform", "labs", "studio"]:
249
+ if w in prompt.lower():
250
+ return f"{w.title()} — Omni-Vibe"
251
+ return "Omni-Vibe App"
252
+
253
+ def generate_backend(self, schema: Dict) -> str:
254
+ """Generate zero-config backend code."""
255
+ if not schema["has_db"] and not schema["has_auth"]:
256
+ return ""
257
+
258
+ code = []
259
+ if schema["stack"]["backend"] and "Flask" in schema["stack"]["backend"]:
260
+ code.append("from flask import Flask, request, jsonify, redirect, session\n")
261
+ code.append("import sqlite3, os, uuid, hashlib\n\n")
262
+ code.append("app = Flask(__name__)\napp.secret_key = os.environ.get('SECRET_KEY', 'omni-vibe-dev')\n\n")
263
+ code.append("# ─── Zero-Config Database ───\n")
264
+ code.append("DB = os.environ.get('DATABASE_URL', 'app.db')\n\n")
265
+ code.append("def get_db():\n conn = sqlite3.connect(DB)\n conn.row_factory = sqlite3.Row\n conn.execute('PRAGMA journal_mode=WAL')\n return conn\n\n")
266
+ code.append("# ─── Init Schema ───\n")
267
+ code.append("def init_db():\n with get_db() as db:\n")
268
+ for line in ZERO_DB_SCHEMA.strip().split("\n"):
269
+ if line.strip() and not line.startswith("--"):
270
+ code.append(f" db.execute('''{line.strip()}''')\n")
271
+ code.append(" print('✅ Omni-Vibe DB initialized')\n\ninit_db()\n\n")
272
+
273
+ if schema["has_auth"]:
274
+ code.append("# ─── Google OAuth ───\n")
275
+ code.append(GOOGLE_OAUTH_PY.strip() + "\n\n")
276
+
277
+ elif schema["stack"]["backend"] and "FastAPI" in schema["stack"]["backend"]:
278
+ code.append("from fastapi import FastAPI, Request, HTTPException\n")
279
+ code.append("from fastapi.responses import JSONResponse, RedirectResponse\n")
280
+ code.append("import sqlite3, os, uuid\n\n")
281
+ code.append("app = FastAPI(title='Omni-Vibe')\n\n")
282
+
283
+ return "".join(code)
284
+
285
+
286
+ # ═══════════════════════════════════════════════════════
287
+ # POSE PAINTER — Liquid Glass Design Enforcer
288
+ # ═════════════════════════════════════════��═════════════
289
+
290
+ class PosePainter:
291
+ """
292
+ Enforces the Liquid Glass design system on every generated app.
293
+ Injects canonical CSS, logo SVG, and ensures consistent theming.
294
+ """
295
+
296
+ LG_COMPONENTS = {
297
+ "navbar": """
298
+ <nav class="glass" style="padding:1rem 2rem;display:flex;align-items:center;justify-content:space-between">
299
+ <div style="display:flex;align-items:center;gap:.75rem">
300
+ {LOGO}
301
+ <span class="gradient-text" style="font-weight:700;font-size:1.1rem">{TITLE}</span>
302
+ </div>
303
+ <div style="display:flex;gap:1rem">
304
+ <a href="/" class="btn-outline btn" style="padding:.5rem 1rem;font-size:.85rem">Home</a>
305
+ <a href="/dashboard" class="btn-outline btn" style="padding:.5rem 1rem;font-size:.85rem">Dashboard</a>
306
+ <button id="google-auth-btn" class="btn" style="padding:.5rem 1rem;font-size:.85rem">Sign In</button>
307
+ </div>
308
+ </nav>
309
+ """,
310
+ "hero": """
311
+ <section style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:80vh;padding:2rem;text-align:center">
312
+ <h1 class="gradient-text" style="font-size:clamp(2.5rem,8vw,5rem);font-weight:800;line-height:1.1">{TITLE}</h1>
313
+ <p style="font-size:1.25rem;color:var(--text2);margin-top:1.5rem;max-width:600px">{SUBTITLE}</p>
314
+ <div style="display:flex;gap:1rem;margin-top:2.5rem">
315
+ <button class="btn" onclick="document.getElementById('cta-section').scrollIntoView({behavior:'smooth'})">Get Started</button>
316
+ <button class="btn btn-outline">Learn More</button>
317
+ </div>
318
+ </section>
319
+ """,
320
+ "features": """
321
+ <section style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;padding:3rem 2rem;max-width:1200px;margin:0 auto">
322
+ {FEATURE_CARDS}
323
+ </section>
324
+ """,
325
+ "feature_card": """
326
+ <div class="card glass-hover">
327
+ <div style="font-size:2rem;margin-bottom:.75rem">{ICON}</div>
328
+ <h3 style="color:var(--{COLOR});font-size:1.15rem;margin-bottom:.5rem">{TITLE}</h3>
329
+ <p style="color:var(--text2);font-size:.9rem;line-height:1.5">{DESCRIPTION}</p>
330
+ </div>
331
+ """,
332
+ "footer": """
333
+ <footer class="glass" style="margin-top:3rem;padding:2rem;text-align:center;color:var(--text3);font-size:.85rem">
334
+ <p>Built with <span class="gradient-text" style="font-weight:600">Omni-Vibe Studio</span> — Liquid Glass Design System</p>
335
+ <p style="margin-top:.5rem">Zero-config · Google OAuth · SQLite · Pinggy Deploy</p>
336
+ </footer>
337
+ """,
338
+ }
339
+
340
+ def paint(self, code: str, schema: Dict) -> str:
341
+ """Inject Liquid Glass design system into generated code."""
342
+ title = schema.get("landing_title", "Omni-Vibe App")
343
+
344
+ # 1. Inject canonical CSS if not present
345
+ if "liquid-glass" not in code.lower() and "--glass-bg" not in code:
346
+ code = code.replace("</head>",
347
+ f"<style>\n/* Liquid Glass Design System — Omni-Vibe */\n{LIQUID_GLASS_CSS.strip()}\n</style>\n</head>")
348
+
349
+ # 2. Replace <!-- WIZARD-LOGO --> with actual SVG
350
+ code = code.replace("<!-- WIZARD-LOGO -->", LIQUID_GLASS_LOGO)
351
+
352
+ # 3. Inject navbar if missing
353
+ if "<nav" not in code.lower() and "navbar" not in code.lower() and schema.get("has_auth"):
354
+ navbar = self.LG_COMPONENTS["navbar"].replace("{LOGO}", LIQUID_GLASS_LOGO).replace("{TITLE}", title)
355
+ code = code.replace("<body>", f"<body>\n{navbar}")
356
+
357
+ # 4. Ensure gradient-text class exists
358
+ if "gradient-text" not in code and ".gradient-text" not in code:
359
+ if "</style>" in code:
360
+ code = code.replace("</style>",
361
+ ".gradient-text{background:linear-gradient(135deg,var(--purple),var(--cyan),var(--green));-webkit-background-clip:text;-webkit-text-fill-color:transparent}\n</style>")
362
+
363
+ # 5. Inject Google OAuth JS if auth is needed
364
+ if schema.get("has_auth") and "google-auth" not in code:
365
+ code = code.replace("</body>",
366
+ f"<script>\n{GOOGLE_OAUTH_JS.strip()}\n</script>\n</body>")
367
+
368
+ return code
369
+
370
+
371
+ # ═══════════════════════════════════════════════════════
372
+ # POSE AUDITOR — Step-by-Step Code Verification
373
+ # ═══════════════════════════════════════════════════════
374
+
375
+ class PoseAuditor:
376
+ """
377
+ Step-by-step reasoning: verifies code correctness before hot-reload.
378
+ Returns structured findings with severity and suggested fixes.
379
+ """
380
+
381
+ VOID = {'br','hr','img','input','meta','link','area','base','col','embed','source','track','wbr'}
382
+ SVG_VOID = VOID | {'lineargradient','defs','stop','animate','animatetransform','fegaussianblur','femerge','femergenode','ellipse','path','circle','rect','polygon','polyline','g','use','svg'}
383
+
384
+ def audit(self, code: str, schema: Dict = None) -> List[AuditFinding]:
385
+ """Full audit: HTML validity, JS correctness, accessibility, security, simplicity."""
386
+ findings = []
387
+
388
+ # STEP 1: HTML validity
389
+ findings.extend(self._audit_html(code))
390
+
391
+ # STEP 2: JS correctness
392
+ findings.extend(self._audit_js(code))
393
+
394
+ # STEP 3: Liquid Glass compliance
395
+ if schema and schema.get("features"):
396
+ findings.extend(self._audit_liquid_glass(code))
397
+
398
+ # STEP 4: STABLE VIBE — simplicity verification (Painter must strip SaaS)
399
+ findings.extend(self._audit_simplicity(code, schema))
400
+
401
+ # STEP 5: Security & best practices
402
+ findings.extend(self._audit_security(code, schema))
403
+
404
+ return findings
405
+
406
+ def _audit_html(self, code: str) -> List[AuditFinding]:
407
+ findings = []
408
+ stack = []
409
+
410
+ for m in re.finditer(r'<(?P<closing>/)?(?P<tag>\w+)(?:\s[^>]*?)?(?P<self>/)?>', code, re.IGNORECASE):
411
+ t = m.group('tag').lower()
412
+ if t in self.SVG_VOID: continue
413
+ if m.group('self'): continue
414
+ if m.group('closing'):
415
+ if stack and stack[-1] == t: stack.pop()
416
+ else: findings.append(AuditFinding(
417
+ line=code[:m.start()].count('\n')+1, severity="ERROR",
418
+ message=f"Unmatched closing tag </{t}>",
419
+ fix=f"Remove or match with opening <{t}>"))
420
+ else: stack.append(t)
421
+
422
+ for t in stack:
423
+ findings.append(AuditFinding(
424
+ line=1, severity="ERROR",
425
+ message=f"Unclosed tag <{t}>",
426
+ fix=f"Add </{t}> before parent closes"))
427
+
428
+ # Check DOCTYPE
429
+ if '<html' in code.lower() and not code.strip().startswith('<!'):
430
+ findings.append(AuditFinding(line=1, severity="WARN",
431
+ message="Missing DOCTYPE declaration",
432
+ fix="Add <!DOCTYPE html> at line 1"))
433
+
434
+ return findings
435
+
436
+ def _audit_js(self, code: str) -> List[AuditFinding]:
437
+ findings = []
438
+ scripts = re.findall(r'<script[^>]*>(.*?)</script>', code, re.DOTALL | re.IGNORECASE)
439
+
440
+ for i, script in enumerate(scripts):
441
+ lines = script.split('\n')
442
+ for ln, line in enumerate(lines, 1):
443
+ # Common typos
444
+ typos = {
445
+ "console.loge(": "console.log(",
446
+ "docment.": "document.",
447
+ "getElementbyId": "getElementById",
448
+ "innerHtml": "innerHTML",
449
+ "functon ": "function ",
450
+ "retrun": "return",
451
+ "alet(": "alert(",
452
+ "consts ": "const ",
453
+ }
454
+ for typo, fix in typos.items():
455
+ if typo in line:
456
+ findings.append(AuditFinding(
457
+ line=ln, severity="ERROR",
458
+ message=f"Typo: {typo.strip('(')} → {fix.strip('(')}",
459
+ fix=f"Replace '{typo}' with '{fix}'"))
460
+
461
+ return findings
462
+
463
+ def _audit_liquid_glass(self, code: str) -> List[AuditFinding]:
464
+ findings = []
465
+ if "--glass-bg" not in code and "var(--glass" not in code:
466
+ findings.append(AuditFinding(line=1, severity="WARN",
467
+ message="Liquid Glass CSS variables not detected",
468
+ fix="Inject Liquid Glass design system CSS"))
469
+ return findings
470
+
471
+ def _audit_security(self, code: str, schema: Dict) -> List[AuditFinding]:
472
+ findings = []
473
+ # Check for innerHTML usage (XSS risk)
474
+ if re.search(r'\.innerHTML\s*=', code) and "sanitize" not in code.lower():
475
+ findings.append(AuditFinding(line=1, severity="WARN",
476
+ message="innerHTML assignment detected without sanitization — XSS risk",
477
+ fix="Use textContent or DOMPurify.sanitize()"))
478
+ return findings
479
+
480
+ def _audit_simplicity(self, code: str, schema: Dict) -> List[AuditFinding]:
481
+ """
482
+ STABLE VIBE: Verify Painter produced a single, elegant Liquid Glass
483
+ landing page — no SaaS complexity, no broken asset paths.
484
+ """
485
+ findings = []
486
+
487
+ # 1. No dashboard/multi-page routing — must be single-page
488
+ saas_routes = ['/dashboard', '/admin', '/settings', '/login', '/register', '/signup',
489
+ '/api/', '/app/', '/profile', '/billing', '/tasks', '/items']
490
+ for route in saas_routes:
491
+ if route in code and f'href="{route}"' in code:
492
+ findings.append(AuditFinding(line=1, severity="ERROR",
493
+ message=f"SaaS route detected: {route} — STABLE VIBE requires single landing page",
494
+ fix=f"Remove navigation link to {route}"))
495
+
496
+ # 2. No database initialization scripts in the HTML
497
+ db_patterns = ['CREATE TABLE', 'INSERT INTO', 'sqlite3', 'better-sqlite3',
498
+ 'mongoose', 'prisma', 'supabase', 'firebase', 'mongodb']
499
+ for pat in db_patterns:
500
+ if pat.lower() in code.lower():
501
+ findings.append(AuditFinding(line=1, severity="ERROR",
502
+ message=f"Database reference '{pat}' found in HTML — strip backend complexity",
503
+ fix="Remove database initialization from frontend code"))
504
+
505
+ # 3. No external asset paths — must use relative paths or inline everything
506
+ external_assets = re.findall(r'(?:src|href)=["\'](https?://[^"\']+)["\']', code)
507
+ # Allow: HF Spaces URLs, Google Fonts, Google OAuth endpoints
508
+ allowed_prefixes = ('https://huggingface.co', 'https://accounts.google.com',
509
+ 'https://oauth2.googleapis.com', 'https://fonts.googleapis.com',
510
+ 'https://cdnjs.cloudflare.com', 'https://fonts.gstatic.com')
511
+ for asset in external_assets:
512
+ if not any(asset.startswith(p) for p in allowed_prefixes):
513
+ findings.append(AuditFinding(line=1, severity="WARN",
514
+ message=f"External asset: {asset[:80]} — prefer inline or relative paths",
515
+ fix="Inline the resource or use a relative path"))
516
+
517
+ # 4. Must have exactly one <html> document (no iframes with separate apps)
518
+ html_count = len(re.findall(r'<html', code, re.IGNORECASE))
519
+ if html_count > 1:
520
+ findings.append(AuditFinding(line=1, severity="ERROR",
521
+ message=f"Multiple <html> documents ({html_count}) — must be single page",
522
+ fix="Merge into one HTML document"))
523
+
524
+ # 5. Must have Liquid Glass CSS variables
525
+ if "--glass-bg" not in code and "var(--glass" not in code:
526
+ findings.append(AuditFinding(line=1, severity="ERROR",
527
+ message="Liquid Glass CSS variables missing — Painter must enforce",
528
+ fix="Inject the Liquid Glass design system CSS"))
529
+
530
+ # 6. Must have wizard-hat SVG (brand identity)
531
+ if 'wizard-hat' not in code.lower() and 'wizard_hat' not in code.lower():
532
+ findings.append(AuditFinding(line=1, severity="WARN",
533
+ message="Wizard hat SVG missing — brand element required",
534
+ fix="Add the wizard hat SVG logo"))
535
+
536
+ return findings
537
+
538
+ def heal_findings(self, code: str, findings: List[AuditFinding]) -> Tuple[str, int]:
539
+ """Apply all ERROR-level fixes."""
540
+ fixed = code
541
+ count = 0
542
+ for f in findings:
543
+ if f.severity == "ERROR" and f.fix:
544
+ # Apply typo fixes
545
+ for typo, fix in [
546
+ ("console.loge(", "console.log("),
547
+ ("docment.", "document."),
548
+ ("getElementbyId", "getElementById"),
549
+ ("innerHtml", "innerHTML"),
550
+ ("functon ", "function "),
551
+ ("retrun", "return"),
552
+ ("alet(", "alert("),
553
+ ]:
554
+ if typo in fixed:
555
+ fixed = fixed.replace(typo, fix)
556
+ count += 1
557
+ return fixed, count
558
+
559
+
560
+ # ═══════════════════════════════════════════════════════
561
+ # OMNI-VIBE ENGINE — Swarm Orchestrator
562
+ # ═══════════════════════════════════════════════════════
563
+
564
+ class OmniVibeEngine:
565
+ """The Athanor: all three Poses running as a synchronized swarm."""
566
+
567
+ def __init__(self):
568
+ self.architect = PoseArchitect()
569
+ self.painter = PosePainter()
570
+ self.auditor = PoseAuditor()
571
+
572
+ def pose(self, prompt: str) -> Dict:
573
+ """All three Poses analyze the prompt in parallel."""
574
+ return {
575
+ "architect": self.architect.design(prompt),
576
+ "painter": {"design_system": "Liquid Glass", "components": sorted(self.painter.LG_COMPONENTS.keys())},
577
+ "auditor": {"strategy": "step-by-step reasoning", "checks": ["HTML validity", "JS correctness", "Liquid Glass compliance", "Simplicity (no SaaS)", "Security"]},
578
+ }
579
+
580
+ def generate(self, prompt: str) -> Tuple[str, Dict]:
581
+ """
582
+ Full Omni-Vibe generation:
583
+ 1. Architect designs the full-stack schema
584
+ 2. Painter enforces Liquid Glass design
585
+ 3. Auditor verifies every line
586
+ Returns (code, schema)
587
+ """
588
+ schema = self.architect.design(prompt)
589
+
590
+ # Determine what to generate
591
+ if schema["features"] and any(f in schema["features"] for f in ["landing-page", "dashboard"]):
592
+ code = self._generate_frontend(prompt, schema)
593
+ elif schema["stack"]["backend"]:
594
+ code = self.architect.generate_backend(schema)
595
+ else:
596
+ code = self._generate_frontend(prompt, schema)
597
+
598
+ # Painter: enforce Liquid Glass
599
+ code = self.painter.paint(code, schema)
600
+
601
+ # Auditor: verify and fix
602
+ findings = self.auditor.audit(code, schema)
603
+ code, fixes = self.auditor.heal_findings(code, findings)
604
+
605
+ return code, schema
606
+
607
+ def _generate_frontend(self, prompt: str, schema: Dict) -> str:
608
+ """Generate a Liquid Glass frontend."""
609
+ title = schema["landing_title"]
610
+ has_auth = schema.get("has_auth", False)
611
+
612
+ features_html = ""
613
+ default_features = [
614
+ ("⚡", "purple", "Zero-Delay", "Real-time streaming with sub-second hot reload in sandboxed iframe."),
615
+ ("🔄", "cyan", "Reflect-Select", "Autonomous code healing — errors fixed before you see them."),
616
+ ("🚀", "green", "Ghost Deploy", "One-click publish to HF Spaces with instant live URL."),
617
+ ]
618
+ for icon, color, ftitle, desc in default_features:
619
+ features_html += self.painter.LG_COMPONENTS["feature_card"].format(
620
+ ICON=icon, COLOR=color, TITLE=ftitle, DESCRIPTION=desc)
621
+
622
+ hero_subtitle = "Built with Omni-Vibe Studio — specialized AI swarm with zero-config database, Google OAuth, and Liquid Glass design."
623
+
624
+ auth_section = ""
625
+ if has_auth:
626
+ auth_section = """
627
+ <section id="cta-section" class="glass" style="max-width:500px;margin:3rem auto;padding:2.5rem;text-align:center">
628
+ <h3 class="gradient-text" style="font-size:1.5rem;margin-bottom:1rem">Get Started</h3>
629
+ <p style="color:var(--text2);margin-bottom:1.5rem">Sign in with Google — no password required.</p>
630
+ <button id="google-auth-btn" class="btn" style="width:100%;justify-content:center">
631
+ <svg width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" 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"/><path fill="currentColor" 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"/><path fill="currentColor" 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"/><path fill="currentColor" 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"/></svg>
632
+ Sign in with Google
633
+ </button>
634
+ </section>"""
635
+
636
+ return f"""<!DOCTYPE html>
637
+ <html lang="en">
638
+ <head>
639
+ <meta charset="UTF-8">
640
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
641
+ <title>{title}</title>
642
+ <style>
643
+ /* Omni-Vibe Liquid Glass Design System */
644
+ {LIQUID_GLASS_CSS.strip()}
645
+ </style>
646
+ </head>
647
+ <body>
648
+
649
+ <!-- Liquid Glass Wizard Logo -->
650
+ <div style="position:fixed;top:20px;left:50%;transform:translateX(-50%);z-index:100">
651
+ {LIQUID_GLASS_LOGO}
652
+ </div>
653
+
654
+ <!-- Navbar -->
655
+ <nav class="glass" style="padding:1rem 2rem;display:flex;align-items:center;justify-content:space-between;margin:0 1rem">
656
+ <div style="display:flex;align-items:center;gap:.75rem">
657
+ {LIQUID_GLASS_LOGO.replace('width="48"','width="32"').replace('height="48"','height="32"')}
658
+ <span class="gradient-text" style="font-weight:700;font-size:1.1rem">{title}</span>
659
+ </div>
660
+ <div style="display:flex;gap:1rem">
661
+ {'''<button id="google-auth-btn" class="btn" style="padding:.5rem 1.25rem;font-size:.85rem">Sign In</button>''' if has_auth else '<button class="btn btn-outline" style="padding:.5rem 1.25rem;font-size:.85rem">Documentation</button>'}
662
+ </div>
663
+ </nav>
664
+
665
+ <!-- Hero -->
666
+ <section style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:80vh;padding:2rem;text-align:center;margin-top:-60px">
667
+ <h1 class="gradient-text" style="font-size:clamp(2.5rem,8vw,5rem);font-weight:800;line-height:1.1">{title}</h1>
668
+ <p style="font-size:1.25rem;color:var(--text2);margin-top:1.5rem;max-width:600px">{hero_subtitle}</p>
669
+ <div style="display:flex;gap:1rem;margin-top:2.5rem">
670
+ <button class="btn">Get Started</button>
671
+ <button class="btn btn-outline">Learn More</button>
672
+ </div>
673
+ </section>
674
+
675
+ <!-- Features -->
676
+ <section style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1.5rem;padding:3rem 2rem;max-width:1200px;margin:0 auto">
677
+ {features_html}
678
+ </section>
679
+
680
+ {auth_section}
681
+
682
+ <!-- Footer -->
683
+ <footer class="glass" style="margin-top:3rem;padding:2rem;text-align:center;color:var(--text3);font-size:.85rem">
684
+ <p>Built with <span class="gradient-text" style="font-weight:600">Omni-Vibe Studio</span> — Liquid Glass Design System</p>
685
+ <p style="margin-top:.5rem">Zero-config · Google OAuth · SQLite · Ghost Deploy · Pinggy</p>
686
+ </footer>
687
+
688
+ {f'''<script>
689
+ {GOOGLE_OAUTH_JS.strip()}
690
+ </script>''' if has_auth else ''}
691
+
692
+ <script>
693
+ // Wizard hat pulse animation
694
+ const hat = document.querySelector('#wizard-hat');
695
+ if (hat) {{
696
+ let p = 0;
697
+ function animate() {{
698
+ p += 0.02;
699
+ hat.style.transform = `scale(${{1 + Math.sin(p) * 0.06}})`;
700
+ hat.style.filter = `drop-shadow(0 0 ${{18 + Math.sin(p * 1.5) * 8}}px rgba(139,92,246,.6))`;
701
+ requestAnimationFrame(animate);
702
+ }}
703
+ animate();
704
+ }}
705
+ </script>
706
+
707
+ </body>
708
+ </html>"""
709
+
710
+
711
+ # ═══════════════════════════════════════════════════════
712
+ # REFLECT-SELECT — Sub-Second Loop
713
+ # ═══════════════════════════════════════════════════════
714
+
715
+ class ReflectSelect:
716
+ """Sub-second Reflect-Select using compiled regex patterns."""
717
+ VOID = PoseAuditor.SVG_VOID
718
+ PATTERNS = [
719
+ (re.compile(r"console\.loge\("), "console.log("),
720
+ (re.compile(r"docment\."), "document."),
721
+ (re.compile(r"getElementbyId"), "getElementById"),
722
+ (re.compile(r"innerHtml"), "innerHTML"),
723
+ (re.compile(r"functon\s"), "function "),
724
+ (re.compile(r"retrun"), "return"),
725
+ ]
726
+
727
+ def heal(self, code: str, errors: List[str] = None) -> Tuple[str, int, int]:
728
+ errors_list = self._detect(code)
729
+ if errors: errors_list.extend(errors)
730
+ errors_list = list(set(errors_list))
731
+ found = len(errors_list)
732
+ if not found: return code, 0, 0
733
+ fixed = 0
734
+ for i in range(15):
735
+ if not errors_list: break
736
+ code = self._apply_fixes(code, errors_list)
737
+ fixed += 1
738
+ errors_list = self._detect(code)
739
+ return code, found, fixed
740
+
741
+ def _detect(self, code: str) -> List[str]:
742
+ e = []
743
+ # HTML
744
+ if "<html" in code.lower() or code.startswith("<!"):
745
+ stack = []
746
+ for m in re.finditer(r'<(?P<closing>/)?(?P<tag>\w+)(?:\s[^>]*?)?(?P<self>/)?>', code, re.IGNORECASE):
747
+ t = m.group('tag').lower()
748
+ if t in self.VOID: continue
749
+ if m.group('self'): continue
750
+ if m.group('closing'):
751
+ if stack and stack[-1]==t: stack.pop()
752
+ else: e.append(f"Unmatched </{t}>")
753
+ else: stack.append(t)
754
+ for t in stack: e.append(f"Unclosed <{t}>")
755
+ # Python
756
+ elif code.startswith("import") or "def " in code:
757
+ try: compile(code,'<s>','exec')
758
+ except SyntaxError as se: e.append(f"Syntax: {se}")
759
+ # Generic bracket check
760
+ if code.count('(')!=code.count(')'): e.append("Parenthesis mismatch")
761
+ if code.count('{')!=code.count('}'): e.append("Brace mismatch")
762
+ return e
763
+
764
+ def _apply_fixes(self, code: str, errors: List[str]) -> str:
765
+ for pat, rep in self.PATTERNS:
766
+ code = pat.sub(rep, code)
767
+ # Close unclosed HTML tags
768
+ for tag in re.findall(r'Unclosed <(\w+)>', '\n'.join(errors)):
769
+ if tag.lower() not in self.VOID:
770
+ close = code.lower().rfind('</body>') or code.lower().rfind('</html>')
771
+ if close >= 0:
772
+ code = code[:close] + f'</{tag}>\n' + code[close:]
773
+ return code
774
+
775
+ def validate(self, code: str) -> Dict:
776
+ e = self._detect(code)
777
+ return {"success": len(e)==0, "errors": e}
778
+
779
+
780
+ # ═══════════════════════════════════════════════════════
781
+ # STATE
782
+ # ═══════════════════════════════════════════════════════
783
+
784
+ @dataclass
785
+ class State:
786
+ engine: OmniVibeEngine = field(default_factory=OmniVibeEngine)
787
+ reflect: ReflectSelect = field(default_factory=ReflectSelect)
788
+ sessions: Dict = field(default_factory=dict)
789
+ codes: Dict = field(default_factory=dict)
790
+ sandbox: Dict = field(default_factory=dict)
791
+ publish_ready: Dict = field(default_factory=dict)
792
+
793
+ state = State()
794
+
795
+
796
+ # ═══════════════════════════════════════════════════════
797
+ # COMPATIBILITY EXPORTS
798
+ # ═══════════════════════════════════════════════════════
799
+
800
+ # Expose the old API for server.py compatibility
801
+ class Orchestrator:
802
+ """Backward-compatible wrapper around OmniVibeEngine."""
803
+ def pose(self, prompt: str) -> Dict:
804
+ plan = state.engine.pose(prompt)
805
+ return {
806
+ "model": "omni-vibe-swarm",
807
+ "domain": plan["architect"]["stack"]["backend"] and "fullstack" or "frontend",
808
+ "plan": plan,
809
+ }
810
+ def generate(self, prompt: str):
811
+ code, schema = state.engine.generate(prompt)
812
+ # Yield chunks for SSE streaming
813
+ chunk_size = max(1, len(code) // 20)
814
+ for i in range(0, len(code), chunk_size):
815
+ yield code[i:i+chunk_size]
816
+ time.sleep(0.02)
817
+ state.codes["_last_schema"] = schema
818
+
819
+ def sandbox_validate(code: str) -> Dict:
820
+ return state.reflect.validate(code)
821
+
822
+ print("🧙‍♂️ Omni-Vibe Core — Swarm Synchronized")
823
+ print(" Pose Architect: full-stack + zero-DB + Google OAuth")
824
+ print(" Pose Painter: Liquid Glass design system")
825
+ print(" Pose Auditor: step-by-step verification")
826
+ print(" Athanor ready — Steady Gold")