dryymatt commited on
Commit
cb8e44d
Β·
verified Β·
1 Parent(s): 9c322c2

Upload server.py

Browse files
Files changed (1) hide show
  1. server.py +74 -102
server.py CHANGED
@@ -1,14 +1,13 @@
1
  """
2
  ╔══════════════════════════════════════════════════════╗
3
- β•‘ OMNI-VIBE STUDIO β€” INSTANT WAKE Server β•‘
4
  β•‘ β•‘
5
  β•‘ PHASE 1 (<1ms): Bind 0.0.0.0:7860, serve 200 OK β•‘
6
- β•‘ health + loading HTML immediately. β•‘
7
  β•‘ PHASE 2 (bg): Lazy-import OmniVibeEngine, β•‘
8
  β•‘ PoseArchitect, PosePainter, β•‘
9
  β•‘ PoseAuditor, ReflectSelect. β•‘
10
  β•‘ β•‘
11
- β•‘ v3.2: E2E Handshake endpoint for litheat.app β•‘
12
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
13
  """
14
 
@@ -20,7 +19,6 @@ from aiohttp import web
20
  PORT = int(os.environ.get("WIZARD_PORT", 7860))
21
  STATIC = Path(__file__).parent / "static"
22
  CANONICAL_REPO = "dryymatt/Wizard-Vibe-Studio"
23
- WIZARD_HAT_COLOR = "steady-gold"
24
 
25
  # ─── Engine refs β€” lazy-loaded in Phase 2 ───
26
  _engine = None
@@ -29,7 +27,7 @@ _reflect = None
29
  _engine_loaded = False
30
 
31
  # ──────────────────────────────────────────────────────
32
- # PHASE 1: Instant HTML β€” served before any imports
33
  # ──────────────────────────────────────────────────────
34
 
35
  LOADING_HTML = """<!DOCTYPE html>
@@ -37,106 +35,87 @@ LOADING_HTML = """<!DOCTYPE html>
37
  <head>
38
  <meta charset="UTF-8">
39
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
40
- <title>Omni-Vibe Studio</title>
41
  <style>
42
  :root{
43
- --glass-bg:rgba(255,255,255,.03);--glass-border:rgba(255,255,255,.06);
44
- --purple:#8B5CF6;--cyan:#06B6D4;--green:#10B981;--gold:#F59E0B;
45
- --text:#e0e0ff;--text2:#9090b0;--text3:#606080;
46
- --bg1:#0a0a1a;--bg2:#1a0a2e;--radius:24px;
47
  --font:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
48
  }
49
  *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
50
  body{
51
- font-family:var(--font);
52
- background:linear-gradient(135deg,var(--bg1),var(--bg2),#0a1a2e);
53
- color:var(--text);min-height:100vh;display:flex;
54
- align-items:center;justify-content:center;
55
  -webkit-font-smoothing:antialiased;
56
  }
57
- ::selection{background:rgba(139,92,246,.5);color:#fff}
58
- .glass{
59
- background:var(--glass-bg);backdrop-filter:blur(20px);
60
- -webkit-backdrop-filter:blur(20px);
61
- border:1px solid var(--glass-border);border-radius:var(--radius);
62
- padding:3rem 4rem;text-align:center;
63
- animation:fadeIn .6s ease-out;
64
  }
65
- @keyframes fadeIn{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
66
  .gradient-text{
67
- background:linear-gradient(135deg,var(--purple),var(--cyan),var(--green));
68
  -webkit-background-clip:text;-webkit-text-fill-color:transparent;
69
  background-clip:text;
70
  }
71
- h1{font-size:clamp(1.8rem,6vw,2.8rem);font-weight:800;line-height:1.15}
72
- .hero-sub{color:var(--text2);font-size:1rem;font-weight:400;margin-top:.4rem}
73
- .loading-bar{
74
- width:240px;height:3px;background:var(--glass-bg);
75
- border-radius:2px;margin:1.5rem auto 0;overflow:hidden;
76
  }
77
- .loading-bar::after{
78
- content:'';display:block;width:40%;height:100%;
79
  background:linear-gradient(90deg,var(--purple),var(--cyan),var(--green));
80
- border-radius:2px;
81
- animation:slide 1.2s ease-in-out infinite;
82
  }
83
- @keyframes slide{0%{transform:translateX(-100%)}100%{transform:translateX(350%)}}
84
- .status-dot{display:inline-block;width:6px;height:6px;border-radius:50%;margin-right:6px}
85
- .status-dot.gold{background:var(--gold);box-shadow:0 0 6px var(--gold)}
86
- .pulse{animation:pulse 2s ease-in-out infinite}
87
- @keyframes pulse{0%,100%{opacity:1}50%{opacity:.3}}
88
- .wizard-svg{filter:drop-shadow(0 0 16px rgba(139,92,246,.5));margin-bottom:1.5rem}
89
  </style>
90
  <script>
91
  let pollTimer;
92
  function checkReady(){
93
  fetch('/api/health').then(r=>r.json()).then(d=>{
94
- if(d.engine_loaded){
95
- clearInterval(pollTimer);
96
- location.reload();
97
- }
98
  }).catch(()=>{});
99
  }
100
  pollTimer=setInterval(checkReady,500);
101
- document.addEventListener('DOMContentLoaded',()=>{
102
- document.getElementById('status-text').textContent='Waking the Athanor\u2026';
103
- });
104
  </script>
105
  </head>
106
  <body>
107
- <div class="glass">
108
- <svg class="wizard-svg" width="48" height="48" viewBox="0 0 64 64">
109
  <defs><linearGradient id="hg" x1="0%" y1="0%" x2="100%" y2="100%">
110
- <stop offset="0%" style="stop-color:#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#06B6D4;#10B981;#8B5CF6" dur="6s" repeatCount="indefinite"/></stop>
111
- <stop offset="50%" style="stop-color:#06B6D4"><animate attributeName="stop-color" values="#06B6D4;#10B981;#8B5CF6;#06B6D4" dur="6s" repeatCount="indefinite"/></stop>
112
- <stop offset="100%" style="stop-color:#10B981"><animate attributeName="stop-color" values="#10B981;#8B5CF6;#06B6D4;#10B981" dur="6s" repeatCount="indefinite"/></stop>
113
  </linearGradient></defs>
114
- <path d="M32 8 L8 48 L32 40 L56 48 Z" fill="url(#hg)" stroke="rgba(255,255,255,.3)" stroke-width="1.2">
115
- <animateTransform attributeName="transform" type="rotate" values="0 32 28;2 32 28;-1 32 28;0 32 28" dur="6s" repeatCount="indefinite"/>
116
- </path>
117
- <ellipse cx="32" cy="48" rx="26" ry="7" fill="none" stroke="url(#hg)" stroke-width="2" opacity=".6">
118
- <animate attributeName="rx" values="26;28;26" dur="3s" repeatCount="indefinite"/>
119
- </ellipse>
120
  </svg>
121
  <h1 class="gradient-text">Build anything.</h1>
122
- <p class="hero-sub">Simple. Beautiful. Easy to use.</p>
123
- <div class="loading-bar"></div>
124
- <p style="font-size:.85rem;color:var(--text3);margin-top:1rem">
125
  <span class="status-dot gold pulse"></span>
126
- <span id="status-text">Initializing LiteRT engine\u2026</span>
127
  </p>
128
- <p style="font-size:.7rem;color:var(--text3);margin-top:1.5rem">0.0.0.0:7860 \u00b7 Steady Gold</p>
129
  </div>
130
  </body>
131
  </html>"""
132
 
133
 
134
  # ──────────────────────────────────────────────────────
135
- # PHASE 1 HANDLERS β€” respond immediately, no imports
136
  # ──────────────────────────────────────────────────────
137
 
138
  async def handle_root_get(req):
139
- """GET / β†’ loading HTML if engine not ready, else full Liquid Glass."""
140
  if _engine_loaded:
141
  fp = STATIC / "index.html"
142
  if fp.exists():
@@ -145,40 +124,38 @@ async def handle_root_get(req):
145
 
146
 
147
  async def handle_health(req):
148
- """GET /api/health β†’ 200 OK pulse. First byte on wire in <1ms."""
149
  return web.json_response({
150
  "status": "alive",
151
- "engine": "Omni-Vibe Studio β€” Specialized Swarm",
152
  "engine_loaded": _engine_loaded,
153
  "binding": "0.0.0.0:7860",
154
  "port": PORT,
155
- "hat": WIZARD_HAT_COLOR,
156
  "hf_token": bool(os.environ.get("HF_TOKEN")),
157
  })
158
 
159
 
160
  async def handle_agent(req):
161
- """A2A agent card β€” static, no imports needed."""
162
  return web.json_response({
163
- "name": "omni-vibe-studio",
164
- "description": "Omni-Vibe Studio β€” Specialized AI Swarm. 0.0.0.0:7860. LiteRT engine. Build anything. Simple. Beautiful. Easy to use.",
165
- "url": "https://dryymatt-wizard-vibe-studio-v2.hf.space",
166
- "provider": {"organization": "Omni-Vibe Studio β€” Litehat System",
167
  "url": "https://huggingface.co/dryymatt"},
168
- "version": "3.2.0",
169
- "capabilities": {"streaming": True, "ghostDeploy": True, "liquidGlass": True, "tabbedInterface": True, "e2eHandshake": True},
170
  })
171
 
172
 
173
  # ──────────────────────────────────────────────────────
174
- # E2E HANDSHAKE VERIFICATION
175
  # ──────────────────────────────────────────────────────
176
 
177
  async def handle_verify_handshake(req):
178
  """
179
  POST /api/verify-handshake
180
- Verifies that the target server (litheat.app / deployed Space) is reachable.
181
  Body: {"url": "litheat.app" or "https://deployed-space.hf.space"}
 
182
  """
183
  try:
184
  data = await req.json()
@@ -189,7 +166,6 @@ async def handle_verify_handshake(req):
189
  if not target:
190
  return web.json_response({"verified": False, "error": "No URL provided"}, status=400)
191
 
192
- # Normalize URL
193
  if not target.startswith("http"):
194
  target = f"https://{target}"
195
 
@@ -198,31 +174,32 @@ async def handle_verify_handshake(req):
198
  # Check 1: DNS resolution
199
  import socket
200
  t0 = time.time()
 
201
  try:
202
- host = target.replace("https://", "").replace("http://", "").split("/")[0]
203
  socket.getaddrinfo(host, 443 if target.startswith("https") else 80)
204
  results["checks"]["dns"] = True
205
  except Exception as e:
206
  results["checks"]["dns"] = False
207
- results["error"] = f"DNS resolution failed: {str(e)}"
208
  return web.json_response(results, status=200)
209
 
210
  # Check 2: HTTP reachability
 
211
  try:
212
- import urllib.request
213
- req = urllib.request.Request(target, headers={"User-Agent": "Omni-Vibe-Handshake/3.2"})
214
- resp = urllib.request.urlopen(req, timeout=10)
215
  latency = round((time.time() - t0) * 1000)
216
  results["latency_ms"] = latency
217
  results["checks"]["http"] = True
218
  results["checks"]["status_code"] = resp.getcode()
 
219
  if 200 <= resp.getcode() < 500:
220
  results["verified"] = True
221
  else:
222
  results["error"] = f"HTTP {resp.getcode()}"
223
  except Exception as e:
224
  results["checks"]["http"] = False
225
- results["error"] = f"HTTP check failed: {str(e)[:120]}"
226
 
227
  return web.json_response(results)
228
 
@@ -249,7 +226,7 @@ def _get_engine():
249
  _ghost = g
250
  _reflect = st.reflect
251
  _engine_loaded = True
252
- print("⚑ Omni-Vibe Engine: LAZY-LOADED")
253
  from core import state as st
254
  return st, _ghost
255
 
@@ -353,7 +330,7 @@ async def handle_publish(req):
353
  code = st.codes.get(sid,"")
354
  if not code: return web.json_response({"success":False,"error":"No code"}, status=400)
355
  description = d.get("description", st.sessions.get(sid,{}).get("prompt",""))
356
- result = await ghost.publish(code, d.get("vibe_name",f"omni-vibe-{sid}"),
357
  description[:200] if description else "", port=PORT)
358
  if result.get("success"):
359
  st.sessions[sid]["published"] = True
@@ -368,7 +345,7 @@ async def handle_status(req):
368
  s = st.sessions[sid]
369
  return web.json_response({"status":s["status"],"sandbox":st.sandbox.get(sid),
370
  "ready":st.publish_ready.get(sid),"deploy_url":s.get("deploy_url")})
371
- return web.json_response({"sessions":len(st.sessions),"engine":"omni-vibe","hat":WIZARD_HAT_COLOR})
372
 
373
 
374
  async def handle_vibes(req):
@@ -395,7 +372,7 @@ async def handle_schema(req):
395
  async def handle_preview(req):
396
  st, _ = _get_engine()
397
  sid = req.query.get("session_id", "")
398
- return web.Response(text=st.codes.get(sid,"<!-- Omni-Vibe -->"), content_type="text/html")
399
 
400
 
401
  # ──────────────────────────────────────────────────────
@@ -405,13 +382,13 @@ async def handle_preview(req):
405
  def create_app():
406
  app = web.Application()
407
 
408
- # Phase 1 routes (available immediately, no engine needed)
409
  app.router.add_get("/", handle_root_get)
410
  app.router.add_get("/api/health", handle_health)
411
  app.router.add_get("/.well-known/agent.json", handle_agent)
412
  app.router.add_post("/api/verify-handshake", handle_verify_handshake)
413
 
414
- # Phase 2 routes (lazy-load engine on first call)
415
  app.router.add_post("/api/stream", handle_stream)
416
  app.router.add_post("/api/publish", handle_publish)
417
  app.router.add_get("/api/status", handle_status)
@@ -420,15 +397,10 @@ def create_app():
420
  app.router.add_get("/api/tunnel", handle_tunnel)
421
  app.router.add_get("/api/schema", handle_schema)
422
 
423
- # Static catch-all
424
  app.router.add_get("/{path:.*}", handle_static)
425
  return app
426
 
427
 
428
- # ──────────────────────────────────────────────────────
429
- # MAIN β€” bind IMMEDIATELY, then lazy-load engine
430
- # ──────────────────────────────────────────────────────
431
-
432
  def main():
433
  import subprocess
434
  try:
@@ -437,30 +409,30 @@ def main():
437
  capture_output=True, timeout=5
438
  )
439
  if result.returncode == 0:
440
- print(f"πŸ”ͺ Killed ghost process on port {PORT}")
441
  except Exception:
442
  pass
443
 
444
- print(f"πŸ§™β€β™‚οΈ Omni-Vibe Studio v3.2 β€” INSTANT WAKE + E2E Handshake")
445
  print(f" Binding : 0.0.0.0:{PORT}")
446
  print(f" Health pulse : 200 OK in <1ms")
447
- print(f" Loading HTML : served before engine import")
448
  print(f" Registry : {CANONICAL_REPO}")
449
- print(f" Hat : {WIZARD_HAT_COLOR}")
450
- print(f" Handshake : /api/verify-handshake")
451
 
452
  loop = asyncio.new_event_loop()
453
  asyncio.set_event_loop(loop)
454
 
455
  async def warm_start():
456
  await asyncio.sleep(0.5)
457
- print("⚑ Warm Start: loading OmniVibeEngine…")
458
  try:
459
  st, ghost = _get_engine()
460
- print(f"⚑ Engine loaded: {_engine_loaded}")
461
- print(f" Poses: Architect, Painter, Auditor β€” all active")
462
  except Exception as e:
463
- print(f"⚠ Engine load warning (non-fatal): {e}")
464
 
465
  loop.create_task(warm_start())
466
 
 
1
  """
2
  ╔══════════════════════════════════════════════════════╗
3
+ β•‘ OBSIDIAN FORGE β€” Kinetic RLM Server β•‘
4
  β•‘ β•‘
5
  β•‘ PHASE 1 (<1ms): Bind 0.0.0.0:7860, serve 200 OK β•‘
 
6
  β•‘ PHASE 2 (bg): Lazy-import OmniVibeEngine, β•‘
7
  β•‘ PoseArchitect, PosePainter, β•‘
8
  β•‘ PoseAuditor, ReflectSelect. β•‘
9
  β•‘ β•‘
10
+ β•‘ v4.0: Obsidian Forge β€” Absolute Black Β· RLM Core β•‘
11
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
12
  """
13
 
 
19
  PORT = int(os.environ.get("WIZARD_PORT", 7860))
20
  STATIC = Path(__file__).parent / "static"
21
  CANONICAL_REPO = "dryymatt/Wizard-Vibe-Studio"
 
22
 
23
  # ─── Engine refs β€” lazy-loaded in Phase 2 ───
24
  _engine = None
 
27
  _engine_loaded = False
28
 
29
  # ──────────────────────────────────────────────────────
30
+ # PHASE 1: Instant HTML β€” absolute black loading page
31
  # ──────────────────────────────────────────────────────
32
 
33
  LOADING_HTML = """<!DOCTYPE html>
 
35
  <head>
36
  <meta charset="UTF-8">
37
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
38
+ <title>Obsidian Forge</title>
39
  <style>
40
  :root{
41
+ --void:#000;--purple:#8B5CF6;--cyan:#06B6D4;--green:#10B981;--gold:#F59E0B;
42
+ --text:#e0e0e0;--text2:#8888a0;--text3:#555570;
 
 
43
  --font:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;
44
  }
45
  *,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
46
  body{
47
+ font-family:var(--font);background:var(--void);color:var(--text);
48
+ min-height:100vh;display:flex;align-items:center;justify-content:center;
 
 
49
  -webkit-font-smoothing:antialiased;
50
  }
51
+ ::selection{background:rgba(139,92,246,.4);color:#fff}
52
+ .forge-glass{
53
+ background:rgba(255,255,255,.015);border:1px solid rgba(255,255,255,.06);
54
+ border-radius:16px;padding:3rem 4rem;text-align:center;
55
+ animation:fadeIn .5s ease-out;
 
 
56
  }
57
+ @keyframes fadeIn{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:translateY(0)}}
58
  .gradient-text{
59
+ background:linear-gradient(135deg,#A78BFA,#22D3EE,#34D399);
60
  -webkit-background-clip:text;-webkit-text-fill-color:transparent;
61
  background-clip:text;
62
  }
63
+ h1{font-size:clamp(1.6rem,5vw,2.2rem);font-weight:800;line-height:1.1}
64
+ .loading-pulse{
65
+ width:180px;height:1.5px;background:rgba(255,255,255,.04);
66
+ border-radius:1px;margin:1.5rem auto 0;overflow:hidden;
 
67
  }
68
+ .loading-pulse::after{
69
+ content:'';display:block;width:35%;height:100%;
70
  background:linear-gradient(90deg,var(--purple),var(--cyan),var(--green));
71
+ border-radius:1px;
72
+ animation:slide .9s ease-in-out infinite;
73
  }
74
+ @keyframes slide{0%{transform:translateX(-100%)}100%{transform:translateX(380%)}}
75
+ .status-dot{display:inline-block;width:4px;height:4px;border-radius:50%;margin-right:5px}
76
+ .status-dot.gold{background:var(--gold);box-shadow:0 0 4px var(--gold)}
77
+ .pulse{animation:pulse 1.5s ease-in-out infinite}
78
+ @keyframes pulse{0%,100%{opacity:1}50%{opacity:.25}}
79
+ .wiz-svg{filter:drop-shadow(0 0 10px rgba(139,92,246,.3));margin-bottom:1.5rem}
80
  </style>
81
  <script>
82
  let pollTimer;
83
  function checkReady(){
84
  fetch('/api/health').then(r=>r.json()).then(d=>{
85
+ if(d.engine_loaded){clearInterval(pollTimer);location.reload();}
 
 
 
86
  }).catch(()=>{});
87
  }
88
  pollTimer=setInterval(checkReady,500);
 
 
 
89
  </script>
90
  </head>
91
  <body>
92
+ <div class="forge-glass">
93
+ <svg class="wiz-svg" width="44" height="44" viewBox="0 0 64 64">
94
  <defs><linearGradient id="hg" x1="0%" y1="0%" x2="100%" y2="100%">
95
+ <stop offset="0%" stop-color="#8B5CF6"><animate attributeName="stop-color" values="#8B5CF6;#06B6D4;#10B981;#8B5CF6" dur="6s" repeatCount="indefinite"/></stop>
96
+ <stop offset="50%" stop-color="#06B6D4"><animate attributeName="stop-color" values="#06B6D4;#10B981;#8B5CF6;#06B6D4" dur="6s" repeatCount="indefinite"/></stop>
97
+ <stop offset="100%" stop-color="#10B981"><animate attributeName="stop-color" values="#10B981;#8B5CF6;#06B6D4;#10B981" dur="6s" repeatCount="indefinite"/></stop>
98
  </linearGradient></defs>
99
+ <path d="M32 8 L8 48 L32 40 L56 48 Z" fill="url(#hg)" stroke="rgba(255,255,255,.15)" stroke-width="1"/>
100
+ <ellipse cx="32" cy="48" rx="26" ry="7" fill="none" stroke="url(#hg)" stroke-width="1.5" opacity=".4"/>
 
 
 
 
101
  </svg>
102
  <h1 class="gradient-text">Build anything.</h1>
103
+ <div class="loading-pulse"></div>
104
+ <p style="font-size:.8rem;color:var(--text3);margin-top:1rem">
 
105
  <span class="status-dot gold pulse"></span>
106
+ <span id="status-text">Obsidian Forge initializing…</span>
107
  </p>
108
+ <p style="font-size:.65rem;color:var(--text3);margin-top:1.5rem">0.0.0.0:7860 Β· RLM Core</p>
109
  </div>
110
  </body>
111
  </html>"""
112
 
113
 
114
  # ──────────────────────────────────────────────────────
115
+ # PHASE 1 HANDLERS
116
  # ──────────────────────────────────────────────────────
117
 
118
  async def handle_root_get(req):
 
119
  if _engine_loaded:
120
  fp = STATIC / "index.html"
121
  if fp.exists():
 
124
 
125
 
126
  async def handle_health(req):
 
127
  return web.json_response({
128
  "status": "alive",
129
+ "engine": "Obsidian Forge β€” Kinetic RLM Environment",
130
  "engine_loaded": _engine_loaded,
131
  "binding": "0.0.0.0:7860",
132
  "port": PORT,
 
133
  "hf_token": bool(os.environ.get("HF_TOKEN")),
134
  })
135
 
136
 
137
  async def handle_agent(req):
 
138
  return web.json_response({
139
+ "name": "obsidian-forge",
140
+ "description": "Obsidian Forge β€” Kinetic RLM Environment. Build anything. Recursive Language Modeling core with Context Folding and Quantum Sandbox.",
141
+ "url": "https://dryymatt-obsidian-forge.hf.space",
142
+ "provider": {"organization": "Obsidian Forge β€” Litehat System",
143
  "url": "https://huggingface.co/dryymatt"},
144
+ "version": "4.0.0",
145
+ "capabilities": {"streaming": True, "ghostDeploy": True, "rlm": True, "contextFolding": True, "quantumSandbox": True, "silentHandshake": True},
146
  })
147
 
148
 
149
  # ──────────────────────────────────────────────────────
150
+ # E2E HANDSHAKE β€” enhanced for Obsidian Forge
151
  # ──────────────────────────────────────────────────────
152
 
153
  async def handle_verify_handshake(req):
154
  """
155
  POST /api/verify-handshake
156
+ Silent DNS + HTTP verification for litheat.app and deployed Spaces.
157
  Body: {"url": "litheat.app" or "https://deployed-space.hf.space"}
158
+ Returns verification status, latency, and detailed checks.
159
  """
160
  try:
161
  data = await req.json()
 
166
  if not target:
167
  return web.json_response({"verified": False, "error": "No URL provided"}, status=400)
168
 
 
169
  if not target.startswith("http"):
170
  target = f"https://{target}"
171
 
 
174
  # Check 1: DNS resolution
175
  import socket
176
  t0 = time.time()
177
+ host = target.replace("https://", "").replace("http://", "").split("/")[0]
178
  try:
 
179
  socket.getaddrinfo(host, 443 if target.startswith("https") else 80)
180
  results["checks"]["dns"] = True
181
  except Exception as e:
182
  results["checks"]["dns"] = False
183
+ results["error"] = f"DNS: {str(e)[:80]}"
184
  return web.json_response(results, status=200)
185
 
186
  # Check 2: HTTP reachability
187
+ import urllib.request
188
  try:
189
+ req = urllib.request.Request(target, headers={"User-Agent": "Obsidian-Forge-Handshake/4.0"})
190
+ resp = urllib.request.urlopen(req, timeout=8)
 
191
  latency = round((time.time() - t0) * 1000)
192
  results["latency_ms"] = latency
193
  results["checks"]["http"] = True
194
  results["checks"]["status_code"] = resp.getcode()
195
+ # Accept 200-499 (some sites return 301/302/401 β€” still reachable)
196
  if 200 <= resp.getcode() < 500:
197
  results["verified"] = True
198
  else:
199
  results["error"] = f"HTTP {resp.getcode()}"
200
  except Exception as e:
201
  results["checks"]["http"] = False
202
+ results["error"] = f"HTTP: {str(e)[:120]}"
203
 
204
  return web.json_response(results)
205
 
 
226
  _ghost = g
227
  _reflect = st.reflect
228
  _engine_loaded = True
229
+ print("β—ˆ Obsidian Forge: RLM Engine LAZY-LOADED")
230
  from core import state as st
231
  return st, _ghost
232
 
 
330
  code = st.codes.get(sid,"")
331
  if not code: return web.json_response({"success":False,"error":"No code"}, status=400)
332
  description = d.get("description", st.sessions.get(sid,{}).get("prompt",""))
333
+ result = await ghost.publish(code, d.get("vibe_name",f"obsidian-{sid}"),
334
  description[:200] if description else "", port=PORT)
335
  if result.get("success"):
336
  st.sessions[sid]["published"] = True
 
345
  s = st.sessions[sid]
346
  return web.json_response({"status":s["status"],"sandbox":st.sandbox.get(sid),
347
  "ready":st.publish_ready.get(sid),"deploy_url":s.get("deploy_url")})
348
+ return web.json_response({"sessions":len(st.sessions),"engine":"obsidian-forge-rlm"})
349
 
350
 
351
  async def handle_vibes(req):
 
372
  async def handle_preview(req):
373
  st, _ = _get_engine()
374
  sid = req.query.get("session_id", "")
375
+ return web.Response(text=st.codes.get(sid,"<!-- Obsidian Forge -->"), content_type="text/html")
376
 
377
 
378
  # ──────────────────────────────────────────────────────
 
382
  def create_app():
383
  app = web.Application()
384
 
385
+ # Phase 1 routes
386
  app.router.add_get("/", handle_root_get)
387
  app.router.add_get("/api/health", handle_health)
388
  app.router.add_get("/.well-known/agent.json", handle_agent)
389
  app.router.add_post("/api/verify-handshake", handle_verify_handshake)
390
 
391
+ # Phase 2 routes
392
  app.router.add_post("/api/stream", handle_stream)
393
  app.router.add_post("/api/publish", handle_publish)
394
  app.router.add_get("/api/status", handle_status)
 
397
  app.router.add_get("/api/tunnel", handle_tunnel)
398
  app.router.add_get("/api/schema", handle_schema)
399
 
 
400
  app.router.add_get("/{path:.*}", handle_static)
401
  return app
402
 
403
 
 
 
 
 
404
  def main():
405
  import subprocess
406
  try:
 
409
  capture_output=True, timeout=5
410
  )
411
  if result.returncode == 0:
412
+ print(f"β—ˆ Killed ghost on port {PORT}")
413
  except Exception:
414
  pass
415
 
416
+ print(f"β—ˆ Obsidian Forge v4.0 β€” Kinetic RLM Environment")
417
  print(f" Binding : 0.0.0.0:{PORT}")
418
  print(f" Health pulse : 200 OK in <1ms")
419
+ print(f" Loading HTML : absolute black Β· 1px glass")
420
  print(f" Registry : {CANONICAL_REPO}")
421
+ print(f" RLM Core : Recursive Language Modeling")
422
+ print(f" Handshake : silent DNS + poll-until-live")
423
 
424
  loop = asyncio.new_event_loop()
425
  asyncio.set_event_loop(loop)
426
 
427
  async def warm_start():
428
  await asyncio.sleep(0.5)
429
+ print("β—ˆ Warm Start: loading RLM engine…")
430
  try:
431
  st, ghost = _get_engine()
432
+ print(f"β—ˆ RLM Engine: loaded ({_engine_loaded})")
433
+ print(f" Poses: Architect, Painter, Auditor β€” synchronized")
434
  except Exception as e:
435
+ print(f"β—ˆ Engine warning (non-fatal): {e}")
436
 
437
  loop.create_task(warm_start())
438