SignalMesh / signalmesh_api.py
acecalisto3
feat(binder): identity survives a rebuild; distribution is observed, not assumed
2f6fd0e
Raw
History Blame Contribute Delete
139 kB
"""
signalmesh_api.py — SignalMesh Sovereign Liquid Matrix Gateway
=======================================================
Public API: /api/* — requires X-SignalMesh-Key header
Dashboard: /ui/* — server-side key, no browser exposure
Landing: / — interactive HTML dashboard
"""
from __future__ import annotations
import asyncio, hashlib, html, json, os, sys, time, re
import urllib.parse
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Any, Dict, List, Optional
_HERE = Path(__file__).parent
sys.path.insert(0, str(_HERE))
import types
_app_pkg = types.ModuleType("app")
_log_pkg = types.ModuleType("app.logger")
class _L:
def info(self,*a,**k): pass
def warning(self,*a,**k): pass
def error(self,*a,**k): pass
def debug(self,*a,**k): pass
_log_pkg.logger = _L()
sys.modules.setdefault("app", _app_pkg)
sys.modules.setdefault("app.logger", _log_pkg)
_app_pkg.logger = _log_pkg.logger
import feedparser, httpx
from fastapi import FastAPI, Header, HTTPException, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
from pydantic import BaseModel
from core.signal_registry import SignalRegistry, signal_registry
from core.spatial_grid import SpatialGridManager
from core.feed_hydrator import feed_hydrator
from core.source_hydrator import source_hydrator
from core import mport_articles
from core import binder
from core import world_state
from core import broadcast_journal
from core.antenna import AntennaForge, TARGETS as ANTENNA_TARGETS
from core.manifest_parser import manifest_registry, ManifestParser
from core.sec_omega import guarded_broadcast, sec_omega
from core.coordinate_resolver import coordinate_resolver, NAMESPACES, SLOTS
from core.relationship_graph import relationship_graph
from core import submesh as mport
from tools.autonomous_pumps import adys_pump
grid = SpatialGridManager(index_path=str(_HERE / "workspace" / "spatial_index.json"))
_ROWS = SpatialGridManager.GRID_ROWS
_COLS = SpatialGridManager.GRID_COLS
_PROT = ("security_","sql_","auth_","key_","secret_","credential_")
_SEC_Q: List[Dict[str,Any]] = []
antenna_forge = AntennaForge(signal_registry)
# ── Key tier system ───────────────────────────────────────────────────────────
# Tiers: admin (unlimited) | paid (unlimited) | update (update-channel only).
# No public free tier. The legacy demo key lives on permanently as the OCODX
# update-channel key: shipped builds poll release/update signals with it
# (submesh reads + ocodx.* tune_in) and nothing else.
_UPDATE_KEY = os.environ.get("SIGNALMESH_UPDATE_KEY", "smesh-free-demo")
_ADMIN_KEY = os.environ.get("SIGNALMESH_API_KEY", "")
_PAID_KEYS = set(filter(None, os.environ.get("SIGNALMESH_PAID_KEYS", "").split(",")))
def _key_values(raw: str) -> set[str]:
keys = set()
for part in raw.split(","):
part = part.strip()
if not part:
continue
label, sep, value = part.partition(":")
keys.add((value if sep else label).strip())
return {k for k in keys if k}
def _owner_keys() -> set[str]:
return (
_key_values(os.environ.get("SIGNALMESH_OWNER_KEYS", ""))
| _key_values(os.environ.get("SIGNALMESH_OWNER_KEY", ""))
| _key_values(os.environ.get("OWNER_KEY", ""))
)
# Rate limit: the update key is shared by every shipped build
_UPDATE_RATE_LIMIT = 5000 # calls per rolling 24h window
_update_usage: Dict[str, List[float]] = {} # key → list of call timestamps
def _tier(k: Optional[str]) -> str:
if k and (k == _ADMIN_KEY or k in _owner_keys()):
return "admin"
if k and k in _PAID_KEYS:
return "paid"
if k and k == _UPDATE_KEY:
return "update"
return "none"
def _check_key(k: Optional[str], require_paid: bool = False, allow_update: bool = False):
t = _tier(k)
if t == "none":
if k and _db_get_by_key(k):
return # valid DB paid user
raise HTTPException(401, detail={
"error": "Invalid or missing X-SignalMesh-Key",
"get_paid_key": "https://kyklos.io/apps/signalmesh/",
})
if t == "update":
if not allow_update or require_paid:
raise HTTPException(403, detail={
"error": "This key is restricted to the OCODX update channel",
"get_paid_key": "https://kyklos.io/apps/signalmesh/",
})
_rate_check(k)
def _rate_check(k: str):
now = time.time()
window = now - 86400 # 24h
hits = [ts for ts in _update_usage.get(k, []) if ts > window]
if len(hits) >= _UPDATE_RATE_LIMIT:
raise HTTPException(429, detail={
"error": f"Update-channel limit ({_UPDATE_RATE_LIMIT} calls/24h) reached",
})
hits.append(now)
_update_usage[k] = hits
# ── User database (SQLite + HF dataset backup) ────────────────────────────────
import sqlite3, secrets, threading
# Persist outside /tmp where possible: HF Spaces persistent storage is /data.
# Falls back to /tmp (still backed up to the HF dataset) if /data isn't writable.
_DB_DIR = os.environ.get("SIGNALMESH_DB_DIR") or (
"/data" if os.path.isdir("/data") and os.access("/data", os.W_OK) else "/tmp")
_DB_PATH = os.path.join(_DB_DIR, "signalmesh_users.db")
_DB_LOCK = threading.Lock()
def _db_conn():
conn = sqlite3.connect(_DB_PATH)
conn.row_factory = sqlite3.Row
return conn
def _db_init():
try:
from huggingface_hub import hf_hub_download
import shutil
p = hf_hub_download("acecalisto3/signalmesh-users", "users.db",
repo_type="dataset", local_dir="/tmp")
shutil.copy(p, _DB_PATH)
print("[UserDB] Loaded from HF dataset")
except Exception:
print("[UserDB] Starting fresh")
with _DB_LOCK:
conn = _db_conn()
conn.execute("""CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT NOT NULL,
api_key TEXT UNIQUE NOT NULL,
tier TEXT DEFAULT 'paid',
stripe_customer_id TEXT,
stripe_session_id TEXT,
active INTEGER DEFAULT 1,
created_at REAL,
last_seen REAL,
call_count INTEGER DEFAULT 0
)""")
conn.commit(); conn.close()
def _db_backup():
try:
from huggingface_hub import HfApi
_hf = HfApi()
try:
_hf.create_repo("signalmesh-users", repo_type="dataset", private=True)
except Exception:
pass
_hf.upload_file(path_or_fileobj=_DB_PATH, path_in_repo="users.db",
repo_id="acecalisto3/signalmesh-users", repo_type="dataset",
commit_message="auto-backup users.db")
except Exception as e:
print(f"[UserDB] Backup failed: {e}")
def _db_create_user(
email: str,
stripe_customer_id: str,
stripe_session_id: str,
tier: str = "managed_monthly",
) -> str:
key = "smesh-" + secrets.token_urlsafe(24)
uid = secrets.token_hex(8)
with _DB_LOCK:
conn = _db_conn()
conn.execute("INSERT OR IGNORE INTO users VALUES (?,?,?,?,?,?,1,?,?,0)",
(uid, email, key, tier, stripe_customer_id,
stripe_session_id, time.time(), time.time()))
conn.commit(); conn.close()
threading.Thread(target=_db_backup, daemon=True).start()
return key
def _db_get_by_key(key: str):
with _DB_LOCK:
conn = _db_conn()
row = conn.execute("SELECT * FROM users WHERE api_key=? AND active=1", (key,)).fetchone()
if row:
conn.execute("UPDATE users SET last_seen=?,call_count=call_count+1 WHERE api_key=?",
(time.time(), key))
conn.commit()
conn.close()
return dict(row) if row else None
def _dev_from_key(key: str) -> int:
"""Read the device quota out of a signed OCODX1.<payload>.<sig> token."""
try:
import base64 as _b64
pb = key.split(".")[1]
data = json.loads(_b64.urlsafe_b64decode(pb + "=" * (-len(pb) % 4)))
return int(data.get("dev", 0))
except Exception:
return 0
def _db_get_by_email(email: str):
with _DB_LOCK:
conn = _db_conn()
row = conn.execute("SELECT * FROM users WHERE email=? AND active=1 "
"ORDER BY created_at DESC LIMIT 1", (email,)).fetchone()
conn.close()
return dict(row) if row else None
def _db_add_seats(email: str, add: int, cid: str, sid: str) -> str:
"""Upgrade an existing license in place: re-mint the same email's key with
dev = current + add. If they have no base license yet, treat the add as solo+add."""
cur = _db_get_by_email(email)
if cur:
tier = cur.get("tier", "solo")
base = _dev_from_key(cur.get("api_key", "")) or TIER_DEVICES.get(tier, 1)
else:
tier, base = "solo", TIER_DEVICES.get("solo", 1)
new_dev = base + max(0, add)
key = _mint_ocodx_key(email, tier, new_dev)
uid = (cur or {}).get("id") or secrets.token_hex(8)
with _DB_LOCK:
conn = _db_conn()
if cur:
conn.execute("UPDATE users SET api_key=?,stripe_session_id=?,last_seen=? WHERE id=?",
(key, sid, time.time(), uid))
else:
conn.execute("INSERT OR IGNORE INTO users VALUES (?,?,?,?,?,?,1,?,?,0)",
(uid, email, key, tier, cid, sid, time.time(), time.time()))
conn.commit(); conn.close()
threading.Thread(target=_db_backup, daemon=True).start()
return key
def _db_get_by_session(session_id: str):
with _DB_LOCK:
conn = _db_conn()
row = conn.execute("SELECT * FROM users WHERE stripe_session_id=?", (session_id,)).fetchone()
conn.close()
return dict(row) if row else None
def _db_revoke(stripe_customer_id: str):
with _DB_LOCK:
conn = _db_conn()
conn.execute("UPDATE users SET active=0 WHERE stripe_customer_id=?", (stripe_customer_id,))
conn.commit(); conn.close()
threading.Thread(target=_db_backup, daemon=True).start()
def _db_all() -> list:
with _DB_LOCK:
conn = _db_conn()
rows = conn.execute("SELECT * FROM users ORDER BY created_at DESC").fetchall()
conn.close()
return [dict(r) for r in rows]
def _socket_limit(key: Optional[str]) -> int:
"""Resolve the number of public MPort edge sockets a key may own."""
if key and (key == _ADMIN_KEY or key in _owner_keys()):
return int(os.environ.get("SIGNALMESH_ADMIN_SOCKET_LIMIT", "1000"))
if key and key in _PAID_KEYS:
return int(os.environ.get("SIGNALMESH_STATIC_KEY_SOCKET_LIMIT", "1"))
if key:
user = _db_get_by_key(key)
if user:
# Current managed plans include one public relay. Additional relay
# products can raise this without changing the MPort protocol.
return max(1, int(user.get("socket_limit", 1) or 1))
return 0
_db_init()
# ── OpenAPI tag groups ────────────────────────────────────────────────────────
_TAGS = [
{"name": "Core", "description": "Broadcast signals, tune in, check mesh status."},
{"name": "Feeds", "description": "RSS/Atom hydration — auto-broadcast feed items into the mesh."},
{"name": "Manifest", "description": "AGENTS.md ingestion — register external nodes by URL."},
{"name": "Coordinates", "description": "Addressable memory grid — store and resolve AA01-style coordinates."},
{"name": "Trails", "description": "Fuzzy keyword trails — self-healing synonym paths the mesh learns from misses."},
{"name": "Grid", "description": "72-node spatial grid state and SEC-Ω quarantine queue."},
{"name": "MPort", "description": "Discover, simulate, approve, and execute mesh-native capabilities."},
]
SITE_INGEST_DEFAULT = ",".join([
"nexus.overview=https://www.nexusaifirst.com/",
"nexus.modules.roadmap=https://www.nexusaifirst.com/modules",
"nexus.tech.architecture=https://www.nexusaifirst.com/docs/technical",
"nexus.industries=https://www.nexusaifirst.com/industries",
])
def _page_text(html_raw: str, base: str) -> str:
"""Strip to prose but keep the hrefs — a signal with no link can't be cited."""
# Chrome first: nav/header/footer repeat on every page and otherwise dominate chunk 1.
body = re.sub(r"<(script|style|nav|header|footer|aside|form)\b[\s\S]*?</\1>", " ", html_raw, flags=re.I)
body = re.sub(r'<[a-z]+[^>]*\b(?:class|id)="[^"]*\b(?:nav|navbar|menu|footer|header|cookie|banner)\b[^"]*"[^>]*>',
" ", body, flags=re.I)
links = []
for href, label in re.findall(r'<a[^>]+href="([^"]+)"[^>]*>([\s\S]{0,80}?)</a>', body, re.I):
label = " ".join(re.sub(r"<[^>]+>", " ", label).split())
if label and href.startswith(("http", "/")) and not href.startswith("#"):
links.append(f"{label} <{urllib.parse.urljoin(base, href)}>")
text = " ".join(html.unescape(re.sub(r"<[^>]+>", " ", body)).split())
seen, uniq = set(), []
for l in links:
if l not in seen:
seen.add(l); uniq.append(l)
return text + (" Links: " + " · ".join(uniq[:25]) if uniq else "")
def _chunks(text: str, size: int = 360) -> List[str]:
"""_do_tune_in renders each signal at [:400]; anything past that is unreachable."""
out, cur = [], ""
for w in text.split():
if len(cur) + len(w) + 1 > size:
out.append(cur); cur = w
else:
cur = f"{cur} {w}".strip()
if cur:
out.append(cur)
return out
async def _ingest_sites() -> None:
"""Re-broadcast configured doc sites on boot — signals live in memory and a
Space restart wipes them, so a one-shot broadcast does not survive a rebuild."""
spec = os.environ.get("SITE_INGEST", SITE_INGEST_DEFAULT).strip()
if not spec:
return
async with httpx.AsyncClient(timeout=25.0, follow_redirects=True) as client:
for pair in spec.split(","):
freq, _, url = pair.strip().partition("=")
if not (freq and url):
continue
try:
r = await client.get(url, headers={"User-Agent": "SignalMesh/1.0"})
if r.status_code != 200:
print(f"[site_ingest] {freq}: HTTP {r.status_code}"); continue
parts = _chunks(_page_text(r.text, url)[:12000])
for p in parts:
signal_registry.broadcast(name=freq, source_type="site_docs",
data=f"{p} (source: {url})",
metadata={"source_url": url})
print(f"[site_ingest] {freq}: {len(parts)} signals from {url}")
except Exception as e:
print(f"[site_ingest] {freq}: {str(e)[:120]}")
@asynccontextmanager
async def _lifespan(_app: FastAPI):
binder.restore() # identity survives a rebuild
broadcast_journal.replay(signal_registry) # ad-hoc signals survive a restart
# Re-register runtime-added sources BEFORE the hydrators start, so they are
# polled exactly like the curated ones instead of returning as dead history.
broadcast_journal.replay_sources(feed_hydrator, source_hydrator)
feed_hydrator.start()
source_hydrator.start()
antenna_forge.registry = signal_registry
adys_pump.start()
mport.load_state(
try_hf=os.environ.get("SIGNALMESH_MPORT_RESTORE", "1") == "1"
)
mport.broadcast_nicoli_catalog_now(signal_registry)
persistence_task = asyncio.create_task(mport.persistence_loop())
ingest_task = asyncio.create_task(_ingest_sites())
try:
yield
finally:
persistence_task.cancel(); ingest_task.cancel()
app = FastAPI(
title="SignalMesh — Sovereign Liquid Matrix Gateway",
description="""
Ambient context bus for AI agent fleets. Agents broadcast to named frequencies;
other agents tune in by keyword — no config, no service registry, no tool calls.
## Authentication
All `/api/*` endpoints require an `X-SignalMesh-Key` header.
| Tier | Key | Limits |
|------|-----|--------|
| **Managed** | personal key | Hosted API + one public MPort relay |
[Get managed access →](https://kyklos.io/apps/signalmesh/#pricing)
## Quick start
```bash
# Broadcast a signal
curl -X POST https://acecalisto3-signalmesh.hf.space/api/broadcast \\
-H "X-SignalMesh-Key: YOUR_KEY" \\
-H "Content-Type: application/json" \\
-d '{"frequency":"my_agent","content":"hello mesh","source_type":"demo"}'
# Tune in
curl -X POST https://acecalisto3-signalmesh.hf.space/api/tune_in \\
-H "X-SignalMesh-Key: YOUR_KEY" \\
-H "Content-Type: application/json" \\
-d '{"keywords":["my_agent"]}'
```
""",
version="2.0.0",
docs_url="/docs",
redoc_url=None,
openapi_tags=_TAGS,
lifespan=_lifespan,
)
@app.get("/redoc", include_in_schema=False)
async def redoc_html():
from fastapi.responses import HTMLResponse
return HTMLResponse("""<!DOCTYPE html>
<html><head>
<title>SignalMesh API Docs</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<style>body{margin:0;padding:0}</style>
</head>
<body>
<redoc spec-url='/openapi.json' expand-responses="200,201"
theme='{"colors":{"primary":{"main":"#e91e8c"}},"typography":{"fontSize":"14px","fontFamily":"Roboto,sans-serif","headings":{"fontFamily":"Montserrat,sans-serif"}}}'
></redoc>
<script src="https://unpkg.com/redoc@latest/bundles/redoc.standalone.js"></script>
</body></html>""")
_cors_origins = [
origin.strip()
for origin in os.environ.get("SIGNALMESH_CORS_ORIGINS", "").split(",")
if origin.strip()
]
app.add_middleware(
CORSMiddleware,
allow_origins=_cors_origins or ["*"],
allow_credentials=bool(_cors_origins),
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(
mport.make_router(
check_key=_check_key,
signal_registry=signal_registry,
sec_omega=sec_omega,
socket_limit=_socket_limit,
)
)
# ── the editor ────────────────────────────────────────────────────────────────
# Mounted, not merged. It is a complete app — its own sessions, its own ACL read
# from the client's Joomla, its own write adapter — and mounting keeps a single
# implementation: the same code runs standalone on the machine that edits one
# site, and here as a Studio tab.
#
# The prefix also settles the route collisions for free: both apps define
# /healthz and /api/media, and neither has to give up its name.
# The import is guarded: a build that ships without the package loses the tab,
# not the Studio.
try:
import editor as _editor # noqa: E402
_editor_app = _editor.build()
except ImportError as e:
_editor_app = None
print(f"[editor] not present, tab disabled: {e}", flush=True)
if _editor_app is not None:
app.mount("/api/editor", _editor_app)
print("[editor] mounted at /api/editor", flush=True)
# ── Models ────────────────────────────────────────────────────────────────────
class BroadcastReq(BaseModel):
frequency: str; content: str
bypass_gate: bool = False; source_type: str = "external"
# rolling diff / provenance (all optional)
change_id: int = 0; parent_change: int = 0
origin_agent: str = ""; change_type: str = ""
files: List[str] = []; summary: str = ""
ttl_ms: int = 0
class AntennaReq(BaseModel):
frequency: str
target: str
name: Optional[str] = None
class TuneInReq(BaseModel):
keywords: List[str]
role: Optional[str] = None # role-scoped delivery
limit: int = 0 # 0 = every match; else newest N
class CoordinateStoreReq(BaseModel):
coordinate: str; data: Any
symbolic: str = ""; change_id: int = 0; ttl_ms: int = 0
class IdentitySeedReq(BaseModel):
canonical_locator: str
revision: str = ""
deployed_as: str = ""
lineage_fingerprint: str = ""
class RelationshipRoleReq(BaseModel):
role: str; patterns: List[str]
class RssSyncReq(BaseModel):
url: str
class ContextDiscoveryReq(BaseModel):
text: str
class HfInjectReq(BaseModel):
repo_id: str
repo_type: str = "model" # model | dataset | space
class ArxivInjectReq(BaseModel):
arxiv_id: str # e.g. "2303.08774"
class FeedAddReq(BaseModel):
url: str
frequency: str
interval: int = 3600
label: str = ""
class ArticleFetchReq(BaseModel):
url: str
with_images: bool = False
class ArticleSnapshotReq(BaseModel):
frequency: str
limit: int = 5
with_images: bool = False
class FeedDiscoverReq(BaseModel):
url: str
class ManifestIngestReq(BaseModel):
url: str # raw URL to an AGENTS.md file
# ── Internal helpers ──────────────────────────────────────────────────────────
def _node_idx(freq: str) -> int:
return int(hashlib.sha256(freq.encode()).hexdigest(), 16) % (_ROWS * _COLS)
def _agent_for(freq: str):
idx = _node_idx(freq); r,c = divmod(idx, _COLS)
return idx, grid.coords_to_agent.get((r,c), f"node-{idx}")
def _mesh_size() -> int:
return sum(len(v) for v in signal_registry.streams.values())
def _is_prot(freq: str) -> bool:
return any(freq.lower().startswith(p) for p in _PROT)
# ── Core logic (no auth — called by both /api/ and /ui/ routes) ───────────────
def _do_status():
return {"status":"live","signals_in_mesh":_mesh_size(),
"active_frequencies":len(signal_registry.streams),
"grid_nodes":_ROWS*_COLS,"quarantined":len(_SEC_Q),"version":"2.0.0",
"mesh":"Sovereign Liquid Matrix"}
def _do_broadcast(req: BroadcastReq):
idx, agent = _agent_for(req.frequency)
if _is_prot(req.frequency) and not req.bypass_gate:
_SEC_Q.append({"frequency":req.frequency,"content":req.content,
"source_type":req.source_type,"node":idx,"agent":agent,
"queued_at":time.time()})
return {"status":"quarantined","node":idx,"agent":agent,
"frequency":req.frequency,
"reason":"Protected frequency — SEC-Ω staged. Use bypass_gate=true to commit."}
result = guarded_broadcast(signal_registry, req.frequency, req.content,
source_type=req.source_type,
metadata={"node":idx,"agent":agent,"source":"external_api"},
ttl_ms=req.ttl_ms, change_id=req.change_id,
parent_change=req.parent_change,
origin_agent=req.origin_agent,
change_type=req.change_type,
files=req.files, summary=req.summary)
if not result["ok"]:
raise HTTPException(400, f"SEC-Ω blocked: {result['reason']}")
return {"status":"live","node":idx,"agent":agent,"frequency":req.frequency,
"fingerprint":result["fingerprint"],"signals_in_mesh":_mesh_size()}
def _do_tune_in(keywords: List[str], role: Optional[str] = None, limit: int = 0):
t0 = time.perf_counter()
signals = signal_registry.tune_in(keywords)
if role:
signals = relationship_graph.filter_signals(role, signals)
# ponytail: cap after role filtering — signals arrive newest-first, so the
# slice keeps the freshest N rather than whatever survived the filter.
if limit:
signals = signals[:limit]
us = (time.perf_counter()-t0)*1e6
# Collect any fuzzy trail bridges that fired during this call
trails_fired = {}
for s in signals:
t = s.get("_trail")
if t:
via = next((k for k in keywords if k in signal_registry.fuzzy_trails), None)
if via:
trails_fired[via] = t
if signals:
lines = ["[SignalMesh — Live Context]"]
for s in signals:
age = round(s.get("age", 0), 1)
prov = ""
if s.get("change_id"):
prov = f" | Δ{s['change_id']} by {s.get('origin_agent','?')} ({s.get('change_type','')})"
trail_note = ""
if s.get("_trail"):
tr = s["_trail"]
trail_note = f" [⟿ trail: {tr.get('bridged_to','?')} @ {tr.get('confidence','?')}]"
lines.append(f"• [{s['name']}] ({s['type']}, {age}s ago{prov}{trail_note}): {str(s['content'])[:400]}")
ctx = "\n".join(lines)
else:
ctx = ""
# Check if any keyword was a pure miss (trail written but no signals yet on that frequency)
misses = []
for kw in keywords:
if kw in signal_registry.fuzzy_trails and not any(
s["name"] == signal_registry.fuzzy_trails[kw][0] for s in signals
):
best = signal_registry.fuzzy_trails[kw][0]
conf = signal_registry.trail_gaps.get(kw, {}).get(best, 0)
misses.append({"keyword": kw, "bridged_to": best, "confidence": conf,
"branches": signal_registry.fuzzy_trails[kw][1:]})
return {
"context": ctx,
"signals_matched": len(signals),
"keywords": keywords,
"role": role,
"latency_us": round(us, 2),
"trails_fired": trails_fired,
"misses": misses,
}
async def _do_rss_sync(url: str):
try:
async with httpx.AsyncClient(timeout=30.0) as c:
r = await c.get(url, follow_redirects=True,
headers={"User-Agent":"SignalMesh/2.0"})
r.raise_for_status()
raw_bytes = r.content
raw = r.text
except Exception as e:
raise HTTPException(502, f"Fetch failed: {e}")
feed = feedparser.parse(raw)
if feed.bozo and not feed.entries:
feed = feedparser.parse(raw_bytes)
if feed.bozo and not feed.entries:
import re as _re
sanitized = _re.sub(r'&(?!amp;|lt;|gt;|quot;|apos;|#\d+;|#x[\da-fA-F]+;)', '&amp;', raw)
sanitized = _re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', sanitized)
feed = feedparser.parse(sanitized)
if not feed.entries:
exc = getattr(feed, 'bozo_exception', None)
raise HTTPException(422, f"Feed parse error: {exc or 'no entries found'}")
synced = []
for entry in feed.entries:
title = entry.get("title","Untitled")
link = entry.get("link","") or entry.get("id","")
summary = entry.get("summary", entry.get("description",""))[:400]
if not link: continue
idx, agent = _agent_for(link)
signal_registry.broadcast(name=f"rss_{agent}", source_type="rss_cp",
data={"title":title,"link":link,"summary":summary},
metadata={"node":idx,"agent":agent,"feed_url":url})
synced.append({"title":title,"node":idx,"agent":agent,"link":link})
return {"synced":len(synced),"feed_url":url,
"feed_title":feed.feed.get("title",""),
"items":synced[:20],"signals_in_mesh":_mesh_size()}
async def _do_context_discovery(text: str):
url_pat = re.compile(r'https?://[^\s<>"\']+')
all_urls = list(set(url_pat.findall(text)))
rss_urls = [u for u in all_urls if any(k in u.lower() for k in ("rss","atom","xml","feed"))]
other_urls = [u for u in all_urls if u not in rss_urls]
for u in other_urls[:20]:
idx, agent = _agent_for(u)
signal_registry.broadcast(name=f"discovered_{agent}", source_type="context_discovery",
data=u, metadata={"node":idx,"agent":agent})
rss_results = []
for rss_url in rss_urls[:5]:
try:
d = await _do_rss_sync(rss_url)
rss_results.append({"url":rss_url,"synced":d["synced"],"feed_title":d.get("feed_title","")})
except Exception as e:
rss_results.append({"url":rss_url,"error":str(e)})
return {"urls_found":len(all_urls),"rss_feeds_synced":rss_results,
"signals_broadcast":len(other_urls),"signals_in_mesh":_mesh_size()}
async def _do_hf_inject(repo_id: str, repo_type: str = "model"):
hf_url = f"https://huggingface.co/api/{repo_type}s/{repo_id}"
try:
async with httpx.AsyncClient(timeout=20.0, follow_redirects=True) as c:
r = await c.get(hf_url, headers={"User-Agent":"SignalMesh/2.0"})
r.raise_for_status(); data = r.json()
except Exception as e:
raise HTTPException(502, f"HuggingFace API error: {e}")
content = {
"id": data.get("id", repo_id), "type": repo_type,
"downloads": data.get("downloads", 0), "likes": data.get("likes", 0),
"tags": (data.get("tags") or [])[:12],
"pipeline_tag": data.get("pipeline_tag",""),
"private": data.get("private", False),
}
freq = f"hf_{repo_type}_{repo_id.replace('/','__').replace('-','_')}"
idx, agent = _agent_for(freq)
signal_registry.broadcast(name=freq, source_type="hf_inject",
data=content, metadata={"node":idx,"agent":agent,"hf_url":f"https://huggingface.co/{repo_id}"})
return {"injected":content,"frequency":freq,"node":idx,"agent":agent,
"hf_url":f"https://huggingface.co/{repo_id}","signals_in_mesh":_mesh_size()}
async def _do_arxiv_inject(arxiv_id: str):
clean_id = arxiv_id.strip().replace("https://arxiv.org/abs/","").replace("arxiv:","")
url = f"https://export.arxiv.org/api/query?id_list={clean_id}&max_results=1"
try:
async with httpx.AsyncClient(timeout=20.0) as c:
r = await c.get(url, headers={"User-Agent":"SignalMesh/2.0"})
r.raise_for_status(); raw = r.text
except Exception as e:
raise HTTPException(502, f"arxiv fetch error: {e}")
feed = feedparser.parse(raw)
if not feed.entries:
raise HTTPException(404, f"Paper {clean_id} not found on arxiv")
entry = feed.entries[0]
authors = [a.get("name","") for a in entry.get("authors",[])][:5]
content = {
"arxiv_id": clean_id,
"title": re.sub(r'\s+',' ', entry.get("title","")),
"authors": authors,
"summary": (entry.get("summary",""))[:600],
"published": entry.get("published",""),
"link": entry.get("link",""),
}
freq = f"arxiv_{clean_id.replace('.','_').replace('-','_')}"
idx, agent = _agent_for(freq)
signal_registry.broadcast(name=freq, source_type="arxiv_inject",
data=content, metadata={"node":idx,"agent":agent})
return {"injected":content,"frequency":freq,"node":idx,"agent":agent,
"signals_in_mesh":_mesh_size()}
def _do_grid_state():
active_freqs = set(signal_registry.streams.keys())
nodes = []
for (r,c), kw in grid.coords_to_agent.items():
idx = r*_COLS+c
sigs = [s for fn in active_freqs
if kw.lower() in fn.lower() or fn.lower() in kw.lower()
for s in signal_registry.streams.get(fn,[])]
nodes.append({"node":idx,"row":r,"col":c,"agent":kw,
"active":len(sigs)>0,"signal_count":len(sigs)})
occupied = {n["node"] for n in nodes}
for i in range(_ROWS*_COLS):
if i not in occupied:
rr,cc = divmod(i,_COLS)
nodes.append({"node":i,"row":rr,"col":cc,"agent":None,"active":False,"signal_count":0})
nodes.sort(key=lambda n:n["node"])
return {"nodes":nodes,"total_nodes":len(nodes),
"active_count":sum(1 for n in nodes if n["active"]),
"occupied_count":len(occupied)}
def _do_frequencies():
res = []
for name, buf in signal_registry.streams.items():
if buf:
lat = buf[-1]
res.append({"frequency":name,"signal_count":len(buf),
"latest_type":lat.source_type,
"latest_age_s":round(time.time()-lat.timestamp,1),
"node":_node_idx(name),"protected":_is_prot(name)})
res.sort(key=lambda f:f["signal_count"],reverse=True)
return {"frequencies":res,"count":len(res)}
# ── Public API (requires X-SignalMesh-Key header) ─────────────────────────────
@app.get("/api/status", tags=["Core"], summary="Mesh health and signal count")
def api_status(x_signalmesh_key: Optional[str]=Header(default=None)):
_check_key(x_signalmesh_key); return _do_status()
@app.post("/api/broadcast", tags=["Core"], summary="Broadcast a signal to a named frequency")
def api_broadcast(req: BroadcastReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""
Broadcast content to a frequency. All agents tuned to matching keywords
will receive it on their next `tune_in` call. SEC-Ω gates protected prefixes
(security_, auth_, key_, etc.) — use `bypass_gate=true` to commit after review.
"""
_check_key(x_signalmesh_key); return _do_broadcast(req)
@app.post("/api/tune_in", tags=["Core"], summary="Tune in — retrieve signals matching keywords")
def api_tune_in(req: TuneInReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""
Retrieve all signals whose frequency matches any of the given keywords.
Fuzzy matching via learned trails handles near-misses automatically.
Pass `role` to filter by relationship graph (e.g. only signals relevant to CodeAgent).
"""
_check_key(x_signalmesh_key, allow_update=True)
if _tier(x_signalmesh_key) == "update" and not all(str(kw).startswith("ocodx") for kw in req.keywords):
raise HTTPException(403, detail="Update key may only tune ocodx.* frequencies")
return _do_tune_in(req.keywords, req.role, req.limit)
@app.get("/api/tune/{frequency}", tags=["Core"], summary="Tune to a single named frequency")
def api_tune_freq(frequency: str, limit: int = 0, x_signalmesh_key: Optional[str]=Header(default=None)):
"""Quick single-frequency lookup with latency measurement."""
_check_key(x_signalmesh_key, allow_update=frequency.startswith("ocodx"))
t0=time.perf_counter(); sigs=signal_registry.tune_in([frequency], limit); us=(time.perf_counter()-t0)*1e6
return {"frequency":frequency,"signals":sigs,"count":len(sigs),"latency_us":round(us,2)}
@app.get("/api/grid", tags=["Grid"], summary="72-node spatial grid state")
def api_grid(x_signalmesh_key: Optional[str]=Header(default=None)):
"""Returns the full 9×8 coordinate grid — each node's assigned agent and live signal count."""
_check_key(x_signalmesh_key); return _do_grid_state()
@app.get("/api/frequencies", tags=["Grid"], summary="List all active broadcast frequencies")
def api_frequencies(x_signalmesh_key: Optional[str]=Header(default=None)):
"""Returns every named frequency that has at least one signal in the mesh."""
_check_key(x_signalmesh_key); return _do_frequencies()
@app.get("/api/quarantine", tags=["Grid"], summary="SEC-Ω quarantine queue")
def api_quarantine(x_signalmesh_key: Optional[str]=Header(default=None)):
"""Signals staged by the SEC-Ω gate pending review. Use bypass_gate=true to commit."""
_check_key(x_signalmesh_key); return {"quarantined":_SEC_Q,"count":len(_SEC_Q)}
@app.post("/api/tools/signal_broadcast", tags=["Core"], summary="Tool-compatible broadcast (MCP/LangChain)")
def api_tool_broadcast(req: BroadcastReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""Identical to /api/broadcast — exposed under /tools/ for MCP and LangChain tool registries."""
_check_key(x_signalmesh_key); return _do_broadcast(req)
@app.post("/api/tools/rss_sync", tags=["Feeds"], summary="One-shot RSS → mesh broadcast")
async def api_tool_rss(req: RssSyncReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""Fetch an RSS/Atom feed and broadcast each item as a signal."""
_check_key(x_signalmesh_key); return await _do_rss_sync(req.url)
@app.post("/api/tools/context_discovery", tags=["Core"], summary="Extract and broadcast context from free text")
async def api_tool_ctx(req: ContextDiscoveryReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""NLP extraction — finds named entities and keywords, broadcasts each as a signal."""
_check_key(x_signalmesh_key); return await _do_context_discovery(req.text)
@app.post("/api/tools/hf_inject", tags=["Core"], summary="Inject a HuggingFace repo as signals")
async def api_hf_inject(req: HfInjectReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""Fetches repo metadata from HuggingFace Hub and broadcasts it as signals."""
_check_key(x_signalmesh_key); return await _do_hf_inject(req.repo_id, req.repo_type)
@app.post("/api/tools/arxiv_inject", tags=["Core"], summary="Inject an arXiv paper as signals")
async def api_arxiv_inject(req: ArxivInjectReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""Fetches abstract and metadata from arXiv and broadcasts as signals."""
_check_key(x_signalmesh_key); return await _do_arxiv_inject(req.arxiv_id)
# ── UI proxy routes (no key exposure — dashboard uses these) ──────────────────
@app.get("/ui/status")
def ui_status(): return _do_status()
@app.get("/health", include_in_schema=False)
@app.get("/healthz", include_in_schema=False)
def public_health():
"""Keyless liveness probe with no user, key, or payload data."""
status = _do_status()
return {
"ok": True,
"service": "signalmesh",
"version": app.version,
"signals_in_mesh": status.get("signals_in_mesh", 0),
"active_frequencies": status.get("active_frequencies", 0),
}
def _do_world_state():
return world_state.build(
signal_registry=signal_registry, grid=grid,
feed_hydrator=feed_hydrator, source_hydrator=source_hydrator,
coordinate_resolver=coordinate_resolver, binder=binder, mport=mport,
node_idx=_node_idx, rows=_ROWS, cols=_COLS)
@app.get("/ui/world", tags=["Core"], summary="Canonical read model for skins")
def ui_world_state():
"""One semantic projection every antenna and skin renders from.
Server-side on purpose: if each client assembled its own, one would derive
provenance edges from real evidence and another would draw /ui/relationship
— an agent keyword table — as causality. Disposable; nothing here is stored.
Roles with no producer report not_modeled and carry no values.
"""
return _do_world_state()
@app.get("/identity", tags=["Core"], summary="Which copy of SignalMesh is canonical")
def public_identity():
"""Keyless. The centrally adjudicated record for SignalMesh itself.
Exists so a cold agent in any directory can settle "which copy is real" in
one request instead of inferring it from whichever clone looks newest —
the inference that sent a full session's work into a stale fork on
2026-08-03. Returns authority_unresolved rather than guessing.
"""
return binder.self_identity()
@app.post("/api/identity/seed", tags=["Core"], summary="Deliberately seed SignalMesh identity")
def api_identity_seed(req: IdentitySeedReq, x_signalmesh_key: Optional[str]=Header(default=None)):
"""Owner/admin bootstrap for the canonical SignalMesh identity.
This is deliberately not automatic. A missing record must stay unresolved
until an owner chooses the canonical locator and revision. A second call is
passed through to binder.register_self(), which refuses to overwrite the
existing identity; corrections belong in binder.adjudicate().
"""
if _tier(x_signalmesh_key) != "admin":
raise HTTPException(403, "Admin only")
canonical = req.canonical_locator.strip()
if not canonical:
raise HTTPException(400, "canonical_locator is required")
return binder.register_self(
canonical,
revision=req.revision.strip() or None,
deployed_as=req.deployed_as.strip(),
lineage_fingerprint=req.lineage_fingerprint.strip() or None,
)
@app.get("/mport", include_in_schema=False)
def mport_console():
"""Stable product URL; the Submesh path remains the protocol/API name.
Lands on Articles, not Studio. Both links used to resolve to the same Studio
page, so MPort and Studio were indistinguishable in the UI even though they
are different planes — Studio ports a site, MPort executes capabilities.
"""
return RedirectResponse("/api/submesh/ui?tab=articles", status_code=307)
@app.get("/studio", include_in_schema=False)
def studio_console():
"""URL → pixel-identical mesh → platform-specific bundle. Opens the MPort face
on its Studio tab so Scan stays one click away."""
return RedirectResponse("/api/submesh/ui?tab=studio", status_code=307)
@app.post("/ui/broadcast")
def ui_broadcast(req: BroadcastReq): return _do_broadcast(req)
@app.post("/ui/tune_in")
def ui_tune_in(req: TuneInReq): return _do_tune_in(req.keywords, req.role, req.limit)
@app.get("/ui/tune/{frequency}", tags=["Core"], summary="Tune to one frequency — no key")
def ui_tune_freq(frequency: str, limit: int = 0):
"""Keyless read for antennas. Any receiver tunes and renders in its own wrapper."""
t0=time.perf_counter(); sigs=signal_registry.tune_in([frequency], limit); us=(time.perf_counter()-t0)*1e6
return {"frequency":frequency,"signals":sigs,"count":len(sigs),"latency_us":round(us,2)}
@app.get("/ui/sources", tags=["Core"], summary="Pointer frequencies being hydrated")
def ui_sources():
return {"sources": source_hydrator.list_sources()}
@app.post("/ui/sources/{frequency}/refresh", tags=["Core"], summary="Re-read a frequency's source now")
async def ui_source_refresh(frequency: str):
"""Pull from the source immediately instead of waiting for the poll."""
return await source_hydrator.refresh(frequency)
def _public_base(request: Request) -> str:
"""The URL an antenna out in the world must call — not the in-container address."""
host = os.environ.get("SPACE_HOST") or os.environ.get("SIGNALMESH_PUBLIC_URL")
if host:
return host if host.startswith("http") else f"https://{host}"
fwd_host = request.headers.get("x-forwarded-host") or request.headers.get("host")
if fwd_host and not fwd_host.startswith(("127.", "localhost", "0.0.0.0")):
proto = request.headers.get("x-forwarded-proto", "https")
return f"{proto}://{fwd_host}"
return str(request.base_url).rstrip("/")
@app.get("/ui/antennas/{frequency}", tags=["Core"], summary="What shape is this frequency carrying?")
def ui_antenna_inspect(frequency: str):
return antenna_forge.inspect(frequency)
@app.post("/ui/antennas", tags=["Core"], summary="Build a receiver for a frequency")
def ui_antenna_build(req: AntennaReq, request: Request):
"""Emit a wrapper shaped to what the frequency actually carries."""
try:
return antenna_forge.generate(req.frequency, req.target, req.name,
mesh_url=_public_base(request))
except ValueError as e:
raise HTTPException(400, detail={"error": str(e), "targets": list(ANTENNA_TARGETS)})
@app.get("/ui/grid")
def ui_grid(): return _do_grid_state()
@app.get("/ui/frequencies")
def ui_frequencies(): return _do_frequencies()
@app.get("/ui/quarantine")
def ui_quarantine(): return {"quarantined":_SEC_Q,"count":len(_SEC_Q)}
@app.post("/ui/rss_sync")
async def ui_rss(req: RssSyncReq): return await _do_rss_sync(req.url)
@app.post("/ui/context_discovery")
async def ui_ctx(req: ContextDiscoveryReq): return await _do_context_discovery(req.text)
@app.post("/ui/hf_inject")
async def ui_hf(req: HfInjectReq): return await _do_hf_inject(req.repo_id, req.repo_type)
@app.post("/ui/arxiv_inject")
async def ui_arxiv(req: ArxivInjectReq): return await _do_arxiv_inject(req.arxiv_id)
@app.get("/ui/feeds")
def ui_feeds():
"""List all active hydrator feeds — label, URL, freshness, item count."""
return {"feeds": feed_hydrator.list_feeds(), "count": len(feed_hydrator._feeds)}
@app.post("/ui/feeds/add")
async def ui_feeds_add(req: FeedAddReq):
cfg = feed_hydrator.add_feed(req.url, req.frequency, req.interval, req.label)
return {"added": True, "frequency": cfg.frequency, "url": cfg.url,
"interval_s": cfg.interval, "persisted": True,
"env_var": "SIGNALMESH_FEEDS", "env_value": feed_hydrator.env_value()}
@app.post("/ui/feeds/discover")
async def ui_feeds_discover(req: FeedDiscoverReq):
"""Probe any URL for RSS/Atom feeds — RSSHub Radar built in."""
feeds = await feed_hydrator.discover(req.url)
return {"url": req.url, "found": feeds, "count": len(feeds)}
@app.get("/api/feeds", tags=["Feeds"], summary="List active hydrator feeds")
def api_feeds(x_signalmesh_key: Optional[str] = Header(default=None)):
"""Returns all registered RSS/Atom feeds with freshness and item counts."""
_check_key(x_signalmesh_key)
return {"feeds": feed_hydrator.list_feeds(), "count": len(feed_hydrator._feeds)}
@app.post("/api/feeds/add", tags=["Feeds"], summary="Register a new RSS/Atom feed")
async def api_feeds_add(req: FeedAddReq, x_signalmesh_key: Optional[str] = Header(default=None)):
"""Add a feed — items auto-broadcast to that frequency on each poll.
The registration is persisted (local + HF dataset). `env_value` is the same
set as a SIGNALMESH_FEEDS variable, for anyone who wants it as config rather
than state — we hand it back instead of writing the Space variable ourselves,
because that write restarts the Space.
"""
_check_key(x_signalmesh_key)
cfg = feed_hydrator.add_feed(req.url, req.frequency, req.interval, req.label)
return {"added": True, "frequency": cfg.frequency, "url": cfg.url,
"persisted": True, "env_var": "SIGNALMESH_FEEDS",
"env_value": feed_hydrator.env_value()}
@app.post("/api/feeds/persist", tags=["Feeds"], summary="Flush dynamic feeds to durable storage now")
async def api_feeds_persist(x_signalmesh_key: Optional[str] = Header(default=None)):
"""Force the HF-dataset upload instead of waiting for the background loop."""
_check_key(x_signalmesh_key)
ok = await asyncio.to_thread(feed_hydrator.persist_hf)
return {"persisted": ok, "feeds": len(feed_hydrator.dynamic()),
"dataset": None if not ok else "feeds.json",
"env_var": "SIGNALMESH_FEEDS", "env_value": feed_hydrator.env_value()}
@app.get("/api/mport/articles/{frequency}", tags=["MPort"],
summary="Article identity held on a frequency — no fetching")
def api_mport_articles(frequency: str, limit: int = 0,
x_signalmesh_key: Optional[str] = Header(default=None)):
"""Title, link, summary, published, feed. The mesh's half of the contract."""
_check_key(x_signalmesh_key)
return mport_articles.export_feed_json(frequency, limit)
@app.post("/api/mport/article", tags=["MPort"],
summary="Fetch one article body — MPort does the work, not the mesh")
async def api_mport_article(req: ArticleFetchReq,
x_signalmesh_key: Optional[str] = Header(default=None)):
"""Full body and image URLs. Deliberately never broadcast into the mesh."""
_check_key(x_signalmesh_key)
return await mport_articles.fetch_article(req.url, req.with_images)
@app.post("/api/mport/snapshot", tags=["MPort"],
summary="Bundle the newest N articles on a frequency into an archive")
async def api_mport_snapshot(req: ArticleSnapshotReq,
x_signalmesh_key: Optional[str] = Header(default=None)):
"""Returns a download token, not bytes — "download Robert's latest five
typewriter posts with their images" lands here after semantic resolution."""
_check_key(x_signalmesh_key)
return await mport_articles.snapshot_articles(req.frequency, req.limit,
req.with_images)
@app.get("/ui/mport/articles/{frequency}", include_in_schema=False)
def ui_mport_articles(frequency: str, limit: int = 0):
"""Keyless read — identity only, same as every other /ui/ receiver route."""
return mport_articles.export_feed_json(frequency, limit)
@app.get("/ui/aliases", tags=["Trails"], summary="Names each frequency answers to")
def ui_aliases(frequency: str = ""):
"""The alias index: feed titles, authors, hostnames and article titles that
resolve to a frequency. Makes wording-based resolution inspectable."""
return signal_registry.get_aliases(frequency)
@app.post("/api/feeds/discover", tags=["Feeds"], summary="Discover RSS feeds on any URL")
async def api_feeds_discover(req: FeedDiscoverReq, x_signalmesh_key: Optional[str] = Header(default=None)):
"""Probe any URL — finds RSS/Atom feeds via link headers and common paths."""
_check_key(x_signalmesh_key)
return {"url": req.url, "found": await feed_hydrator.discover(req.url)}
@app.get("/ui/trails", tags=["Trails"], summary="All learned fuzzy keyword trails")
def ui_trails():
"""
Returns every keyword trail the mesh has self-healed — the fuzzy paths it builds
when a keyword misses and a close-enough frequency is found via SequenceMatcher + token overlap.
Empty dict on a fresh instance; grows as agents use the mesh.
"""
return signal_registry.get_trails()
@app.delete("/ui/trails/{keyword}", tags=["Trails"], summary="Clear a learned trail")
def ui_clear_trail(keyword: str):
"""Remove a specific keyword trail — the mesh will re-learn it from scratch on next miss."""
removed = signal_registry.clear_trail(keyword)
return {"removed": removed, "keyword": keyword}
@app.get("/api/trails", tags=["Trails"], summary="All learned fuzzy keyword trails (API)")
def api_trails(x_signalmesh_key: Optional[str] = Header(default=None)):
"""Same as /ui/trails — requires API key."""
_check_key(x_signalmesh_key)
return signal_registry.get_trails()
# ── AGENTS.md Manifest endpoints ─────────────────────────────────────────────
@app.get("/agents.md", response_class=HTMLResponse, include_in_schema=False)
async def serve_agents_md():
"""Serve this node's AGENTS.md manifest so any external agent can discover it."""
here = Path(__file__).parent / "AGENTS.md"
if not here.exists():
raise HTTPException(404, "AGENTS.md not found on this node")
return HTMLResponse(content=here.read_text(), media_type="text/markdown")
@app.post("/api/manifest/ingest", tags=["Manifest"], summary="Ingest a remote AGENTS.md node")
async def api_manifest_ingest(req: ManifestIngestReq,
x_signalmesh_key: Optional[str] = Header(default=None)):
"""
Fetch a remote AGENTS.md and register its node in the mesh.
Parses declared frequencies and auto-broadcasts them. SEC-Ω validated before ingestion.
"""
_check_key(x_signalmesh_key)
try:
async with httpx.AsyncClient(follow_redirects=True, timeout=10.0) as client:
r = await client.get(req.url)
r.raise_for_status()
raw = r.text
except Exception as e:
raise HTTPException(502, f"Fetch failed: {e}")
safe, reason = sec_omega.validate("manifest", raw[:2000], "external_manifest")
if not safe:
raise HTTPException(400, f"SEC-Ω blocked manifest: {reason}")
parsed = manifest_registry.ingest(raw, source_uri=req.url)
# Register all declared frequencies into the mesh
for freq in parsed.get("frequencies", []):
signal_registry.broadcast(
name=freq["frequency"],
source_type="manifest_ingestion",
data={"node_uri": parsed["node_uri"], "mode": freq["mode"]},
metadata={"grid_hash": parsed["grid_hash"]},
)
return {
"ingested": True,
"node_uri": parsed["node_uri"],
"grid_hash": parsed["grid_hash"],
"frequencies_registered": [f["frequency"] for f in parsed["frequencies"]],
"gc_strategy": parsed["gc_rules"].get("strategy", "auto"),
"strip_tool_schemas": parsed["strip_tool_schemas"],
}
@app.get("/api/manifest/nodes", tags=["Manifest"], summary="List all registered mesh nodes")
def api_manifest_nodes(x_signalmesh_key: Optional[str] = Header(default=None)):
"""All external nodes registered via AGENTS.md ingestion — URI, grid hash, declared frequencies."""
_check_key(x_signalmesh_key)
return {"nodes": manifest_registry.all_nodes(), "count": len(manifest_registry._manifests)}
@app.post("/ui/manifest/ingest")
async def ui_manifest_ingest(req: ManifestIngestReq):
"""Dashboard-accessible manifest ingestion (no key — uses server-side validation)."""
try:
async with httpx.AsyncClient(follow_redirects=True, timeout=10.0) as client:
r = await client.get(req.url); r.raise_for_status(); raw = r.text
except Exception as e:
raise HTTPException(502, f"Fetch failed: {e}")
safe, reason = sec_omega.validate("manifest", raw[:2000], "ui_manifest")
if not safe:
raise HTTPException(400, f"SEC-Ω blocked: {reason}")
parsed = manifest_registry.ingest(raw, source_uri=req.url)
return {"ingested": True, "node_uri": parsed["node_uri"],
"frequencies": len(parsed["frequencies"])}
# ── Coordinate addressing ────────────────────────────────────────────────────
@app.post("/ui/coordinate", tags=["Coordinates"], summary="Store or update a coordinate")
def ui_store_coordinate(req: CoordinateStoreReq):
"""Store content at a grid address (e.g. AA03). Supports symbolic names, TTL, and change_id for provenance."""
coord = coordinate_resolver.store(
req.coordinate, req.data,
symbolic=req.symbolic, change_id=req.change_id, ttl_ms=req.ttl_ms
)
return {"coordinate": coord, "symbolic": req.symbolic, "stored": True}
@app.get("/ui/resolve/{address:path}", tags=["Coordinates"], summary="Resolve a coordinate or symbolic name")
def ui_resolve(address: str):
"""
Resolve any address form to stored content:
- `AA03` — grid coordinate
- `ARCH.DECISIONS.RETRY` — dot-path symbolic name
- `AA03:D2` — namespaced slot
- `AA03@371` — specific change_id version
Returns 404 if not found or TTL expired.
"""
result = coordinate_resolver.resolve(address)
if result is None:
raise HTTPException(404, f"Coordinate '{address}' not found or expired")
return {"address": address, "resolved": result}
@app.get("/ui/coordinates", tags=["Coordinates"], summary="List all active coordinates")
def ui_list_coordinates():
"""All live (non-TTL-expired) coordinates with namespaces and slot definitions."""
return {
"coordinates": coordinate_resolver.all_coordinates(),
"namespaces": NAMESPACES,
"slots": SLOTS,
}
# ── Relationship graph / scoped delivery ─────────────────────────────────────
@app.get("/ui/relationship", tags=["Core"], summary="Role → frequency pattern map")
def ui_get_relationship():
"""The relationship graph — maps agent roles (CodeAgent, QAAgent, etc.) to frequency patterns for scoped delivery."""
return {"roles": relationship_graph.all_roles()}
@app.post("/ui/relationship", tags=["Core"], summary="Set frequency patterns for a role")
def ui_set_relationship(req: RelationshipRoleReq):
"""Register or update which frequencies a given role should receive on tune_in."""
relationship_graph.set_role(req.role, req.patterns)
return {"role": req.role, "patterns": req.patterns, "updated": True}
# ── Dashboard (v3 — clean bright build) ──────────────────────────────────────
_HTML = r"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>SignalMesh</title>
<style>
:root{
--pink:#e91e8c;--amber:#f59e0b;--pink-light:#ff6ec7;--amber-light:#fcd34d;
--grad:linear-gradient(135deg,var(--pink),var(--amber));
--grad-soft:linear-gradient(135deg,#fce7f3,#fef9c3);
--bg:#fffbf0;--white:#ffffff;--card:#ffffff;
--border:#f0e8d0;--border-strong:#fcd34d;
--text:#1a0800;--dim:#7a6040;--dimmer:#c8a860;
--green:#059669;--red:#dc2626;--yellow:#d97706;
--font:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
--mono:'Courier New',monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--text);font-family:var(--font);font-size:13px;min-height:100vh}
a{color:var(--amber);text-decoration:none}a:hover{text-decoration:underline}
::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:4px}
/* ── Header ── */
.header{background:var(--white);border-bottom:1px solid var(--border);padding:0 24px;
display:flex;align-items:center;justify-content:space-between;height:56px;
box-shadow:0 1px 3px rgba(245,158,11,.08)}
.logo{display:flex;align-items:center;gap:10px}
.logo-icon{width:32px;height:32px;border-radius:8px;background:var(--grad);
display:flex;align-items:center;justify-content:center;font-size:16px}
.logo-name{font-size:16px;font-weight:700;background:var(--grad);
-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.logo-tag{font-size:11px;color:var(--dim);margin-left:2px}
.header-nav{display:flex;align-items:center;gap:4px}
.nav-link{padding:6px 12px;border-radius:6px;font-size:12px;font-weight:500;color:var(--dim);transition:all .15s}
.nav-link:hover{background:var(--grad-soft);color:var(--amber)}
.live-dot{width:7px;height:7px;border-radius:50%;background:var(--green);
box-shadow:0 0 0 2px rgba(5,150,105,.2);animation:livepulse 2s ease-in-out infinite;display:inline-block;margin-right:5px}
@keyframes livepulse{0%,100%{opacity:1}50%{opacity:.4}}
/* ── Status strip ── */
.status-strip{background:var(--white);border-bottom:1px solid var(--border);
display:flex;padding:0 24px;gap:0}
.sstat{padding:10px 24px 10px 0;margin-right:24px;border-right:1px solid var(--border)}
.sstat:last-child{border-right:none}
.sstat-val{font-size:24px;font-weight:700;background:var(--grad);
-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;line-height:1}
.sstat-lbl{font-size:10px;color:var(--dim);text-transform:uppercase;letter-spacing:.8px;margin-top:2px}
/* ── Layout ── */
.layout{display:grid;grid-template-columns:300px 1fr;align-items:start;min-height:calc(100vh - 100px)}
.sidebar{background:var(--white);border-right:1px solid var(--border);display:flex;flex-direction:column;position:sticky;top:0;max-height:100vh;overflow-y:auto}
.main{background:var(--bg);min-width:0}
/* ── Section header ── */
.sec-hdr{padding:14px 16px 10px;border-bottom:1px solid var(--border);
font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:1.2px;
color:var(--dim);display:flex;align-items:center;gap:6px}
.sec-hdr .dot{width:6px;height:6px;border-radius:50%}
.dot-pink{background:var(--pink)}
.dot-amber{background:var(--amber)}
.dot-green{background:var(--green)}
/* ── Walkthrough ── */
.wt-tabs{display:flex;overflow-x:auto;border-bottom:1px solid var(--border);gap:0}
.wt-tab{flex:none;padding:8px 14px;font-size:11px;font-weight:600;color:var(--dim);
cursor:pointer;border:none;background:transparent;font-family:var(--font);
border-bottom:2px solid transparent;transition:all .15s;white-space:nowrap}
.wt-tab:hover{color:var(--amber)}
.wt-tab.active{color:var(--amber);border-bottom-color:var(--amber)}
.wt-body{padding:14px 16px}
.wt-title{font-size:13px;font-weight:700;color:var(--text);margin-bottom:8px}
.wt-text{font-size:12px;color:var(--dim);line-height:1.7}
.wt-text strong{color:var(--text)}
.wt-text code{font-family:var(--mono);background:#fef9c3;color:var(--amber);padding:1px 5px;border-radius:3px;font-size:11px}
.compare{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:10px 0}
.cbox{padding:10px;border-radius:8px;font-size:11px;line-height:1.7}
.cbox.old{background:#fff1f2;border:1px solid #fecdd3}.cbox.old .clbl{color:var(--red)}
.cbox.new{background:#f0fdf4;border:1px solid #a7f3d0}.cbox.new .clbl{color:var(--green)}
.clbl{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:1px;margin-bottom:4px}
.callout{background:var(--grad-soft);border:1px solid var(--border-strong);border-radius:8px;
padding:10px 12px;font-size:11px;color:var(--dim);margin-top:10px;line-height:1.7}
.callout strong{color:var(--amber)}
.wt-actions{display:flex;gap:6px;margin-top:12px}
/* ── Panels ── */
.panel{padding:14px 16px;border-bottom:1px solid var(--border)}
/* ── Freq display ── */
.freq-display{background:var(--grad);border-radius:8px;padding:10px 14px;margin-bottom:10px;position:relative;overflow:hidden}
.freq-display::after{content:'';position:absolute;top:0;left:-100%;width:60%;height:100%;
background:linear-gradient(90deg,transparent,rgba(255,255,255,.15),transparent);
animation:shimmer 2.5s ease-in-out infinite}
@keyframes shimmer{0%{left:-100%}100%{left:150%}}
.freq-label{font-size:9px;color:rgba(255,255,255,.7);text-transform:uppercase;letter-spacing:1px;font-weight:600}
.freq-value{font-size:15px;font-weight:700;color:#fff;margin-top:2px;
white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:var(--mono)}
/* ── Tuner ── */
.tuner-wrap{background:linear-gradient(135deg,#1a0800,#1a0f00);border-radius:8px;
padding:12px;margin-bottom:10px;position:relative;overflow:hidden}
.tuner-scan{position:absolute;top:0;bottom:0;width:2px;
background:linear-gradient(180deg,var(--pink-light),var(--amber-light));
opacity:.8;animation:scan 2.2s linear infinite;box-shadow:0 0 8px var(--pink)}
@keyframes scan{0%{left:0}100%{left:100%}}
.tuner-freq{font-size:13px;font-weight:700;color:#fff;font-family:var(--mono);letter-spacing:1px}
.tuner-meta{font-size:10px;color:rgba(255,255,255,.5);margin-top:4px}
.tuner-bars{display:flex;align-items:flex-end;gap:2px;height:20px;margin-top:8px}
.tuner-bar{flex:1;border-radius:1px;transition:height .25s,background .25s}
/* ── Inputs ── */
input,textarea,select{width:100%;background:var(--white);border:1px solid var(--border);
color:var(--text);padding:8px 10px;border-radius:6px;font-family:var(--font);
font-size:12px;outline:none;resize:vertical;transition:border-color .15s,box-shadow .15s}
input:focus,textarea:focus,select:focus{border-color:var(--amber);box-shadow:0 0 0 3px rgba(245,158,11,.1)}
.field{margin-bottom:10px}
.field label{display:block;font-size:10px;font-weight:600;color:var(--dim);
margin-bottom:4px;text-transform:uppercase;letter-spacing:.8px}
select{cursor:pointer}
/* ── Buttons ── */
button{padding:7px 14px;border-radius:6px;font-family:var(--font);font-size:11px;
font-weight:600;cursor:pointer;letter-spacing:.3px;transition:all .15s;border:none;white-space:nowrap}
button.primary{background:var(--grad);color:#fff;box-shadow:0 2px 8px rgba(233,30,140,.25)}
button.primary:hover{opacity:.9;box-shadow:0 4px 14px rgba(233,30,140,.35);transform:translateY(-1px)}
button.secondary{background:var(--grad-soft);color:var(--amber);border:1px solid var(--border-strong)}
button.secondary:hover{background:var(--border-strong);color:#fff}
button.ghost{background:transparent;color:var(--dim);border:1px solid var(--border)}
button.ghost:hover{border-color:var(--amber);color:var(--amber)}
button.danger{background:#fff1f2;color:var(--red);border:1px solid #fecdd3}
button.danger:hover{background:var(--red);color:#fff}
button:disabled{opacity:.4;cursor:not-allowed;transform:none!important}
.btn-row{display:flex;gap:6px;flex-wrap:wrap}
/* ── Feed ── */
.feed{background:#fffbf0;border:1px solid var(--border);border-radius:6px;
overflow-y:auto;padding:8px;font-size:11px;line-height:1.7;min-height:44px;max-height:150px;font-family:var(--mono)}
.feed-item{padding:2px 0;border-bottom:1px solid var(--border)}
.feed-item:last-child{border-bottom:none}
.tag{display:inline-block;padding:1px 6px;border-radius:4px;font-size:9px;
font-weight:700;margin-right:5px;letter-spacing:.3px}
.tag.live{background:#d1fae5;color:#065f46}
.tag.q{background:#fef3c7;color:#92400e}
.tag.err{background:#fee2e2;color:#991b1b}
.tag.rss{background:#fef9c3;color:var(--amber)}
.tag.tune{background:#fce7f3;color:#9d174d}
.tag.hf{background:#fef9c3;color:#78350f}
.tag.ax{background:#e0f2fe;color:#075985}
.feed .dim{color:var(--dimmer)}
/* ── Grid ── */
.main-section{background:var(--white);border-bottom:1px solid var(--border)}
.main-section-hdr{padding:10px 20px;display:flex;justify-content:space-between;align-items:center;
border-bottom:1px solid var(--border)}
.main-section-hdr h3{font-size:11px;font-weight:700;text-transform:uppercase;
letter-spacing:1px;color:var(--dim)}
/* ── Freq ticker ── */
.freq-ticker{display:flex;flex-wrap:wrap;gap:6px;padding:12px 20px;min-height:56px;align-items:center}
.freq-pill{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:20px;
font-size:11px;font-weight:500;cursor:default;transition:all .2s;border:1px solid}
.freq-pill.active{background:#fce7f3;border-color:#f9a8d4;color:#9d174d}
.freq-pill.prot{background:#fef3c7;border-color:#fde68a;color:#92400e}
.fp-dot{width:5px;height:5px;border-radius:50%}
.freq-pill.active .fp-dot{background:var(--pink)}
.freq-pill.prot .fp-dot{background:var(--yellow)}
.no-freq{color:var(--dimmer);font-size:12px}
/* ── Antenna grid ── */
.ant-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(64px,1fr));gap:5px;padding:14px 20px}
.ant-node{position:relative;display:flex;flex-direction:column;align-items:center;
justify-content:flex-end;height:42px;border-radius:8px;background:var(--bg);
border:1px solid var(--border);cursor:default;overflow:visible;transition:all .3s}
.ant-node.active{background:linear-gradient(135deg,#fce7f3,#fef9c3);border-color:var(--pink-light);
box-shadow:0 2px 8px rgba(233,30,140,.15)}
.ant-node svg{flex:none;transition:color .3s}
.ant-node.active svg{color:var(--pink)}
.ant-node svg{color:var(--dimmer)}
.ant-lbl{font-size:7px;font-weight:600;color:var(--dimmer);text-align:center;
margin-top:2px;width:100%;overflow:hidden;text-overflow:ellipsis;
white-space:nowrap;padding:0 3px;transition:color .3s}
.ant-node.active .ant-lbl{color:var(--amber)}
.ant-node.active::before{content:'';position:absolute;top:6px;left:50%;
transform:translateX(-50%);width:6px;height:6px;border-radius:50%;
border:1px solid var(--pink);animation:ring-out 1.8s ease-out infinite}
@keyframes ring-out{0%{transform:translateX(-50%) scale(1);opacity:.8}100%{transform:translateX(-50%) scale(4);opacity:0}}
.ant-tip{display:none;position:absolute;bottom:calc(100%+6px);left:50%;
transform:translateX(-50%);background:var(--text);color:#fff;padding:5px 9px;
border-radius:6px;white-space:nowrap;z-index:30;font-size:10px;font-weight:500;
box-shadow:0 4px 14px rgba(0,0,0,.2)}
.ant-node:hover .ant-tip{display:block}
/* ── Inject panels ── */
/* ── Collapsible sections ── */
.ms-chev{display:inline-block;width:12px;font-size:9px;color:var(--dimmer);
transition:transform .18s;flex:none}
.collapsed>.main-section-hdr .ms-chev,.collapsed>.sec-hdr .ms-chev{transform:rotate(-90deg)}
.main-section.collapsed>.ms-body,.panel.collapsed>.ms-body{display:none}
.main-section-hdr,.panel>.sec-hdr{user-select:none}
.main-section-hdr:hover h3,.panel>.sec-hdr:hover{color:var(--amber)}
.ms-count{font-size:10px;color:var(--dimmer);font-weight:500;margin-left:6px}
.ms-title{display:flex;align-items:center;gap:8px;min-width:0}
/* ── Build antenna ── */
.ant-build{padding:14px 20px 18px}
.ant-build-note{font-size:11px;color:var(--dim);line-height:1.6;margin-bottom:12px;max-width:760px}
.ant-build-row{display:grid;grid-template-columns:minmax(150px,1.1fr) minmax(170px,1.2fr) minmax(110px,.8fr) auto;
gap:10px;align-items:end}
.ant-build-row .field{margin:0;min-width:0}
.ant-build-row .btn-row{padding:0;white-space:nowrap}
.ant-shape{font-size:11px;color:var(--dim);line-height:1.7;margin:10px 0 0}
.ant-shape code{background:var(--bg);border:1px solid var(--border);border-radius:3px;
padding:1px 4px;font-family:var(--mono);font-size:10px;display:inline-block;margin:1px 0}
#ant-out{margin-top:12px}
#ant-out pre{max-height:340px;overflow:auto;background:var(--bg);border:1px solid var(--border);
border-radius:6px;padding:10px;font-size:11px;line-height:1.5;font-family:var(--mono)}
@media(max-width:1100px){.ant-build-row{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.ant-build-row{grid-template-columns:1fr}}
.inject-grid{display:grid;grid-template-columns:1fr 1fr 1fr;border-bottom:1px solid var(--border)}
.inject-panel{padding:14px 16px;border-right:1px solid var(--border);background:var(--white)}
.inject-panel:last-child{border-right:none}
/* ── Tabs ── */
.tabs{display:flex;border-bottom:1px solid var(--border);margin-bottom:12px}
.tab{padding:5px 12px;font-size:11px;font-weight:600;color:var(--dim);cursor:pointer;
border:none;background:transparent;font-family:var(--font);
border-bottom:2px solid transparent;transition:all .15s}
.tab:hover{color:var(--amber)}
.tab.active{color:var(--amber);border-bottom-color:var(--amber)}
/* ── Preset grid ── */
.preset-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-bottom:10px}
.preset-btn{padding:5px 8px;font-size:10px;font-weight:500;text-align:left;
overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
@media(max-width:1280px){
.inject-grid{grid-template-columns:1fr 1fr}
}
@media(max-width:900px){
.layout{grid-template-columns:1fr}
.sidebar{position:static;max-height:none;border-right:none;border-bottom:1px solid var(--border)}
.inject-grid{grid-template-columns:1fr}
.compare{grid-template-columns:1fr}
}
</style>
</head>
<body>
<!-- HEADER -->
<div class="header">
<div class="logo">
<div class="logo-icon">📡</div>
<div>
<div class="logo-name">SignalMesh</div>
<div class="logo-tag">SignalMesh · Sovereign Liquid Matrix</div>
</div>
</div>
<div class="header-nav">
<span><span class="live-dot"></span><span id="live-label" style="font-size:11px;font-weight:600;color:var(--green)">Live</span></span>
<a class="nav-link" href="/mport">MPort</a>
<a class="nav-link" href="/studio">Studio</a>
<a class="nav-link" href="/docs">API Docs</a>
<a class="nav-link" href="/redoc">Redoc</a>
<a class="nav-link" href="https://kyklos.io/apps/signalmesh/#pricing">Managed Access</a>
</div>
</div>
<!-- STATUS STRIP -->
<div class="status-strip">
<div class="sstat"><div class="sstat-val" id="s-sig">—</div><div class="sstat-lbl">Signals in Mesh</div></div>
<div class="sstat"><div class="sstat-val" id="s-fr">—</div><div class="sstat-lbl">Frequencies</div></div>
<div class="sstat"><div class="sstat-val" id="s-nd">72</div><div class="sstat-lbl">Grid Nodes</div></div>
<div class="sstat"><div class="sstat-val" id="s-q">—</div><div class="sstat-lbl">SEC-Ω Queue</div></div>
</div>
<div class="layout">
<!-- ═══════════ SIDEBAR ═══════════ -->
<div class="sidebar">
<!-- Walkthrough -->
<div class="wt-tabs" id="wt-tabs">
<button class="wt-tab active" onclick="wt(0,this)">What is this?</button>
<button class="wt-tab" onclick="wt(1,this)">Broadcast</button>
<button class="wt-tab" onclick="wt(2,this)">Tune In</button>
<button class="wt-tab" onclick="wt(3,this)">Feed it</button>
<button class="wt-tab" onclick="wt(4,this)">The Grid</button>
<button class="wt-tab" onclick="wt(5,this)">Flash</button>
</div>
<div class="wt-body" id="wt-body"></div>
<!-- Broadcast -->
<div class="panel">
<div class="sec-hdr"><div class="dot dot-pink"></div>Transmit Signal</div>
<div class="freq-display">
<div class="freq-label">Frequency</div>
<div class="freq-value" id="bc-freq-display">signalmesh_signal</div>
</div>
<div class="field"><label>Frequency name</label>
<input id="bc-freq" value="signalmesh_signal" oninput="document.getElementById('bc-freq-display').textContent=this.value||'…'"/>
</div>
<div class="field"><label>Signal content</label>
<textarea id="bc-content" rows="3" placeholder="Any text, JSON, data…"></textarea>
</div>
<div class="field"><label>Source type</label>
<select id="bc-type">
<option value="external">external</option>
<option value="agent_broadcast">agent_broadcast</option>
<option value="rss_cp">rss_cp</option>
<option value="hf_inject">hf_inject</option>
<option value="arxiv_inject">arxiv_inject</option>
</select>
</div>
<div class="btn-row">
<button class="primary" onclick="doBroadcast()">▶ Broadcast</button>
<button class="ghost" onclick="doBroadcast(true)">Bypass SEC-Ω</button>
</div>
<div class="feed" id="bc-feed" style="margin-top:10px;height:110px"></div>
</div>
<!-- Tune In -->
<div class="panel" style="border-bottom:none">
<div class="sec-hdr"><div class="dot dot-amber"></div>Tune In</div>
<div class="tuner-wrap">
<div class="tuner-scan"></div>
<div class="tuner-freq" id="tuner-freq">signalmesh_signal, backend-architect</div>
<div class="tuner-meta" id="tuner-meta">awaiting signal…</div>
<div class="tuner-bars" id="tuner-bars"></div>
</div>
<div class="field"><label>Keywords (comma-separated)</label>
<input id="tune-kw" value="signalmesh_signal,backend-architect"
oninput="document.getElementById('tuner-freq').textContent=this.value"/>
</div>
<div class="btn-row">
<button class="primary" onclick="doTuneIn()">📡 Tune In</button>
<button class="secondary" id="autobtn" onclick="toggleAuto()">⟳ Auto 3s</button>
<button class="ghost" onclick="clearFeed('tune-feed')">Clear</button>
</div>
<div class="feed" id="tune-feed" style="margin-top:10px;height:160px"></div>
</div>
</div><!-- /sidebar -->
<!-- ═══════════ MAIN ═══════════ -->
<div class="main">
<!-- Live frequency ticker -->
<div class="main-section">
<div class="main-section-hdr">
<h3>⚡ Live Frequencies</h3>
<span style="font-size:10px;color:var(--dimmer)" id="ticker-ts"></span>
</div>
<div class="freq-ticker" id="freq-ticker"><span class="no-freq">No active frequencies yet — broadcast a signal or sync a feed.</span></div>
</div>
<!-- Inject panels -->
<div class="main-section">
<div class="main-section-hdr"><h3>📥 Ingest — RSS · HuggingFace · arXiv</h3></div>
<div class="inject-grid">
<!-- RSS -->
<div class="inject-panel">
<div class="sec-hdr" style="padding:0 0 10px"><div class="dot dot-amber"></div>RSS Feed Sync</div>
<div class="tabs">
<button class="tab active" onclick="setTab('rss','m',this)">URL</button>
<button class="tab" onclick="setTab('rss','p',this)">Presets</button>
</div>
<div id="rss-m">
<div class="field"><label>Feed URL</label>
<input id="rss-url" value="https://news.ycombinator.com/rss"/></div>
<button class="primary" onclick="doRss()">Sync →</button>
</div>
<div id="rss-p" style="display:none">
<div class="preset-grid">
<button class="ghost preset-btn" onclick="rssP('https://news.ycombinator.com/rss')">HN Top</button>
<button class="ghost preset-btn" onclick="rssP('https://www.reddit.com/r/MachineLearning/.rss')">r/ML</button>
<button class="ghost preset-btn" onclick="rssP('https://huggingface.co/blog/feed.xml')">HF Blog</button>
<button class="ghost preset-btn" onclick="rssP('https://dev.to/feed/tag/ai')">dev.to AI</button>
<button class="ghost preset-btn" onclick="rssP('https://openai.com/blog/rss.xml')">OpenAI</button>
<button class="ghost preset-btn" onclick="rssP('https://www.anthropic.com/rss.xml')">Anthropic</button>
</div>
<button class="primary" onclick="doRss()">Sync selected →</button>
</div>
<div class="feed" id="rss-feed" style="margin-top:10px"></div>
</div>
<!-- HF -->
<div class="inject-panel">
<div class="sec-hdr" style="padding:0 0 10px"><div class="dot dot-pink"></div>🤗 HF Dataset Flash</div>
<div class="tabs">
<button class="tab active" onclick="setTab('hf','m',this)">Repo ID</button>
<button class="tab" onclick="setTab('hf','p',this)">Presets</button>
</div>
<div id="hf-m">
<div class="field"><label>HuggingFace repo</label>
<input id="hf-id" value="acecalisto3/SignalMesh"/></div>
<div class="field"><label>Type</label>
<select id="hf-type"><option value="model">Model</option><option value="dataset">Dataset</option><option value="space">Space</option></select>
</div>
<button class="primary" onclick="doHf()">⚡ Flash into Mesh</button>
</div>
<div id="hf-p" style="display:none">
<div class="preset-grid">
<button class="ghost preset-btn" onclick="hfP('acecalisto3/SignalMesh','space')">SignalMesh</button>
<button class="ghost preset-btn" onclick="hfP('meta-llama/Llama-3.1-8B','model')">Llama 3.1</button>
<button class="ghost preset-btn" onclick="hfP('microsoft/phi-4','model')">Phi-4</button>
<button class="ghost preset-btn" onclick="hfP('Qwen/Qwen2.5-Coder-32B-Instruct','model')">Qwen2.5</button>
<button class="ghost preset-btn" onclick="hfP('HuggingFaceFW/fineweb','dataset')">FineWeb</button>
<button class="ghost preset-btn" onclick="hfP('openai/openai_humaneval','dataset')">HumanEval</button>
</div>
<button class="primary" onclick="doHf()">⚡ Flash selected</button>
</div>
<div class="feed" id="hf-feed" style="margin-top:10px"></div>
</div>
<!-- arxiv -->
<div class="inject-panel">
<div class="sec-hdr" style="padding:0 0 10px"><div class="dot dot-green"></div>📄 arxiv Paper Inject</div>
<div class="tabs">
<button class="tab active" onclick="setTab('ax','m',this)">Paper ID</button>
<button class="tab" onclick="setTab('ax','p',this)">Key Papers</button>
</div>
<div id="ax-m">
<div class="field"><label>arxiv ID or URL</label>
<input id="ax-id" value="2303.08774"/></div>
<button class="primary" onclick="doAx()">🔬 Inject Paper</button>
</div>
<div id="ax-p" style="display:none">
<div class="preset-grid">
<button class="ghost preset-btn" onclick="axP('2303.08774')">GPT-4 Report</button>
<button class="ghost preset-btn" onclick="axP('2210.03629')">ReAct</button>
<button class="ghost preset-btn" onclick="axP('2309.07864')">Cognitive Archs</button>
<button class="ghost preset-btn" onclick="axP('2305.10601')">Tree of Thoughts</button>
<button class="ghost preset-btn" onclick="axP('2401.04088')">LLM Agent Survey</button>
<button class="ghost preset-btn" onclick="axP('2311.10208')">DSPy</button>
</div>
<button class="primary" onclick="doAx()">🔬 Inject selected</button>
</div>
<div class="feed" id="ax-feed" style="margin-top:10px"></div>
</div>
</div>
</div>
<!-- Antenna Grid -->
<div class="main-section" data-collapsed="1">
<div class="main-section-hdr">
<h3>📡 Antenna Grid — 9×8 Spatial Matrix (72 nodes)</h3>
<div style="display:flex;gap:14px;font-size:11px">
<span><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:linear-gradient(135deg,#fce7f3,#fef9c3);border:1px solid #f9a8d4;margin-right:4px"></span>Transmitting</span>
<span style="color:var(--dimmer)"><span style="display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--bg);border:1px solid var(--border);margin-right:4px"></span>Silent</span>
</div>
</div>
<div class="ant-grid" id="ant-grid"></div>
</div>
<!-- Build Antenna -->
<div class="main-section">
<div class="main-section-hdr">
<h3>🛠 Build Antenna — materialize a frequency somewhere</h3>
<span style="font-size:10px;color:var(--dimmer)" id="ant-shape-ts"></span>
</div>
<div class="ant-build">
<div class="ant-build-note">
Transmit puts a signal on a frequency. This builds the receiving end: it reads what the
frequency is <em>actually</em> carrying right now and emits a wrapper shaped to it.
Same signal, any number of antennas.
</div>
<div class="ant-build-row">
<div class="field"><label>Frequency</label>
<select id="ant-freq"><option value="">— pick a live frequency —</option></select>
</div>
<div class="field"><label>Materialize as</label>
<select id="ant-target">
<option value="nextjs_route">Web route — Next.js / Vercel</option>
<option value="html_embed">Embeddable page — standalone HTML</option>
<option value="shell">Terminal — shell script</option>
<option value="system_prompt">Agent context — silent system prompt</option>
</select>
</div>
<div class="field"><label>Name (optional)</label>
<input id="ant-name" placeholder="calendar"/>
</div>
<div class="btn-row">
<button class="secondary" onclick="inspectAntenna()">Inspect</button>
<button class="primary" onclick="buildAntenna()">🛠 Build</button>
</div>
</div>
<div id="ant-shape" class="ant-shape"></div>
<div id="ant-out"></div>
</div>
</div>
</div><!-- /main -->
</div><!-- /layout -->
<script>
const H={'Content-Type':'application/json'};
async function api(m,p,b){
try{const r=await fetch(p,{method:m,headers:H,body:b?JSON.stringify(b):undefined});return await r.json()}
catch(e){return{error:String(e)}}
}
const ts=()=>new Date().toLocaleTimeString();
const esc=s=>String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
function appendFeed(id,html){const el=document.getElementById(id);if(!el)return;el.innerHTML+=`<div class="feed-item">${html}</div>`;el.scrollTop=el.scrollHeight}
function clearFeed(id){const el=document.getElementById(id);if(el)el.innerHTML=''}
// Status
async function pollStatus(){
const d=await api('GET','/ui/status');
if(d.error)return;
document.getElementById('s-sig').textContent=d.signals_in_mesh??'—';
document.getElementById('s-fr').textContent=d.active_frequencies??'—';
document.getElementById('s-nd').textContent=d.grid_nodes??72;
document.getElementById('s-q').textContent=d.quarantined??0;
}
// Frequency ticker
async function pollFreq(){
const d=await api('GET','/ui/frequencies');
const el=document.getElementById('freq-ticker');
if(!el||d.error||!d.frequencies)return;
fillAntFreqs(d.frequencies);
if(!d.frequencies.length){el.innerHTML='<span class="no-freq">No active frequencies yet — broadcast a signal or sync a feed to populate the mesh.</span>';return}
el.innerHTML=d.frequencies.slice(0,40).map(f=>
`<div class="freq-pill ${f.protected?'prot':'active'}"><div class="fp-dot"></div>${esc(f.frequency.length>22?f.frequency.slice(0,22)+'…':f.frequency)}<span style="font-size:9px;color:var(--dimmer);margin-left:2px">${f.signal_count}</span></div>`
).join('');
document.getElementById('ticker-ts').textContent='updated '+ts();
}
// Grid
const ANT=`<svg width="14" height="19" viewBox="0 0 14 19" fill="none" stroke="currentColor" stroke-linecap="round"><line x1="7" y1="19" x2="7" y2="10" stroke-width="1.5"/><line x1="3" y1="14" x2="11" y2="14" stroke-width="1"/><circle cx="7" cy="9" r="2" fill="currentColor" stroke="none"/><line x1="7" y1="7" x2="2" y2="3" stroke-width="1.5"/><line x1="7" y1="7" x2="12" y2="3" stroke-width="1.5"/></svg>`;
async function pollGrid(){
const d=await api('GET','/ui/grid');
const el=document.getElementById('ant-grid');
if(!el||d.error||!d.nodes)return;
el.innerHTML=d.nodes.map(n=>{
const lbl=n.agent?n.agent.split('-').map(w=>w[0]).join('').toUpperCase().slice(0,3):'·';
return `<div class="ant-node ${n.active?'active':''}">${ANT}<div class="ant-lbl">${lbl}</div><div class="ant-tip">${esc(n.agent||'empty')} · node ${n.node} · ${n.signal_count} sig</div></div>`;
}).join('');
}
// Collapsible sections — everything after a header folds, state remembered
function initCollapse(){
const setup=(sec,hdr)=>{
if(!hdr||sec.dataset.msInit)return; sec.dataset.msInit='1';
const label=(hdr.querySelector('h3')||hdr).textContent.trim().slice(0,40);
const key='ms:'+label;
const body=document.createElement('div'); body.className='ms-body';
while(hdr.nextSibling) body.appendChild(hdr.nextSibling);
sec.appendChild(body);
const chev=document.createElement('span'); chev.className='ms-chev'; chev.textContent='▾';
const h3=hdr.querySelector('h3');
if(h3){const grp=document.createElement('div'); grp.className='ms-title';
hdr.insertBefore(grp,h3); grp.appendChild(chev); grp.appendChild(h3);}
else hdr.insertBefore(chev,hdr.firstChild);
hdr.style.cursor='pointer';
const stored=localStorage.getItem(key);
const start=stored===null?sec.dataset.collapsed==='1':stored==='1';
sec.classList.toggle('collapsed',start);
hdr.addEventListener('click',e=>{
if(e.target.closest('button,select,input,textarea,a'))return;
const now=!sec.classList.contains('collapsed');
sec.classList.toggle('collapsed',now);
localStorage.setItem(key,now?'1':'0');
});
};
document.querySelectorAll('.main-section').forEach(s=>setup(s,s.querySelector(':scope>.main-section-hdr')));
document.querySelectorAll('.sidebar .panel').forEach(s=>setup(s,s.querySelector(':scope>.sec-hdr')));
}
// Antennas
function antShapeLine(s){
if(!s||s.kind==='empty') return '<span class="dim">Nothing on this frequency yet — transmit a pointer or sync a feed first.</span>';
const f=(s.fields||[]).map(x=>`<code>${esc(x)}</code>`).join(' ');
const n=s.count?` · ${s.count} records`:'';
return `carrying <b>${esc(s.kind)}</b> as <b>${esc(s.signal_type||'—')}</b>${n}${f?`<br>fields: ${f}`:''}`;
}
async function inspectAntenna(){
const frequency=document.getElementById('ant-freq').value;
if(!frequency){document.getElementById('ant-shape').innerHTML='<span class="dim">Pick a frequency.</span>';return}
const s=await api('GET','/ui/antennas/'+encodeURIComponent(frequency));
document.getElementById('ant-shape').innerHTML=antShapeLine(s);
document.getElementById('ant-shape-ts').textContent='inspected '+ts();
}
async function buildAntenna(){
const frequency=document.getElementById('ant-freq').value;
if(!frequency){document.getElementById('ant-shape').innerHTML='<span class="dim">Pick a frequency.</span>';return}
const target=document.getElementById('ant-target').value;
const name=document.getElementById('ant-name').value.trim()||null;
const d=await api('POST','/ui/antennas',{frequency,target,name});
if(d.detail||d.error){document.getElementById('ant-out').innerHTML=`<span class="tag err">ERR</span> ${esc(JSON.stringify(d.detail||d.error))}`;return}
document.getElementById('ant-shape').innerHTML=antShapeLine(d.shape);
document.getElementById('ant-shape-ts').textContent='built '+ts();
document.getElementById('ant-out').innerHTML=
`<div style="display:flex;justify-content:space-between;align-items:center;gap:10px;margin-bottom:6px">
<b style="font-size:12px;font-family:var(--mono);overflow:hidden;text-overflow:ellipsis">${esc(d.filename)}</b>
<button class="ghost" onclick="copyAnt(this)" data-i="${encodeURIComponent(d.code)}">Copy</button>
</div>
<pre><code>${esc(d.code)}</code></pre>`;
}
function copyAnt(b){navigator.clipboard.writeText(decodeURIComponent(b.dataset.i));b.textContent='Copied';setTimeout(()=>b.textContent='Copy',1600)}
function fillAntFreqs(freqs){
const el=document.getElementById('ant-freq'); if(!el)return;
const cur=el.value;
el.innerHTML='<option value="">— pick a live frequency —</option>'+
freqs.map(f=>`<option value="${esc(f.frequency)}">${esc(f.frequency)} (${f.signal_count})</option>`).join('');
if(cur) el.value=cur;
}
// Broadcast
async function doBroadcast(bypass=false){
const freq=document.getElementById('bc-freq').value.trim();
const content=document.getElementById('bc-content').value.trim();
const source_type=document.getElementById('bc-type').value;
if(!freq||!content){appendFeed('bc-feed','<span class="tag err">Missing frequency or content</span>');return}
const d=await api('POST','/ui/broadcast',{frequency:freq,content,source_type,bypass_gate:bypass});
if(d.status==='live') appendFeed('bc-feed',`<span class="tag live">LIVE</span><b>${esc(freq)}</b> → node ${d.node} <span class="dim">(${esc(d.agent||'')})</span>`);
else if(d.status==='quarantined') appendFeed('bc-feed',`<span class="tag q">SEC-Ω</span><b>${esc(freq)}</b> staged for review`);
else appendFeed('bc-feed',`<span class="tag err">ERR</span>${esc(JSON.stringify(d).slice(0,80))}`);
refresh();
}
// Tune
let _auto=null;
async function doTuneIn(){
const kws=document.getElementById('tune-kw').value.split(',').map(k=>k.trim()).filter(Boolean);
if(!kws.length)return;
const d=await api('POST','/ui/tune_in',{keywords:kws});
document.getElementById('tuner-meta').textContent=`${d.signals_matched??0} matched · ${d.latency_us??0}µs`;
renderBars(d.signals_matched??0);
clearFeed('tune-feed');
appendFeed('tune-feed',`<span class="tag tune">TUNE</span><b>${kws.join(', ')}</b> · ${d.signals_matched} signals · ${d.latency_us}µs`);
// ── Fuzzy trail bridges ────────────────────────────────────────────────────
if(d.misses && d.misses.length){
d.misses.forEach(m=>{
appendFeed('tune-feed',
`<span class="tag" style="background:#7f5af022;color:#b464ff;border:1px solid #b464ff55">⟿ TRAIL</span>`+
`<b>${esc(m.keyword)}</b> missed — bridged to `+
`<b style="color:#7ddfff">${esc(m.bridged_to)}</b> `+
`<span style="color:#32ff9f">@ ${Math.round((m.confidence||0)*100)}% confidence</span>`+
(m.branches&&m.branches.length ? ` · branches: ${m.branches.slice(0,3).map(b=>`<span style="color:#f59e0b">${esc(b)}</span>`).join(', ')}` : '')+
` <span style="color:#3a3a5c">— trail written, next call is instant</span>`
);
});
}
if(d.trails_fired && Object.keys(d.trails_fired).length){
Object.entries(d.trails_fired).forEach(([kw,t])=>{
appendFeed('tune-feed',
`<span class="tag" style="background:#32ff9f22;color:#32ff9f;border:1px solid #32ff9f55">⚡ FAST PATH</span>`+
`<b>${esc(kw)}</b> → trail hit: <b style="color:#7ddfff">${esc(t.bridged_to||'')}</b>`+
` <span style="color:#32ff9f">@ ${Math.round((t.confidence||0)*100)}%</span>`
);
});
}
// ── Context ────────────────────────────────────────────────────────────────
if(d.context) d.context.split('\n').forEach(l=>{if(l)appendFeed('tune-feed',`<span class="dim">${esc(l)}</span>`)});
else if(!d.misses||!d.misses.length) appendFeed('tune-feed','<span class="dim">No signals on these frequencies yet.</span>');
}
function renderBars(n){
const el=document.getElementById('tuner-bars');if(!el)return;
el.innerHTML=Array.from({length:20},(_,i)=>{
const on=i<Math.min(n*2,20);
const h=on?(4+Math.random()*14):2;
const c=on?`hsl(${310+i*5},70%,65%)`:'rgba(255,255,255,.15)';
return `<div class="tuner-bar" style="height:${h}px;background:${c}"></div>`;
}).join('');
}
function toggleAuto(){
const btn=document.getElementById('autobtn');
if(_auto){clearInterval(_auto);_auto=null;btn.textContent='⟳ Auto 3s';btn.className='secondary'}
else{doTuneIn();_auto=setInterval(doTuneIn,3000);btn.textContent='■ Stop';btn.className='primary'}
}
// Tabs
function setTab(g,id,el){
['m','p'].forEach(t=>{const d=document.getElementById(g+'-'+t);if(d)d.style.display=t===id?'block':'none'});
el.closest('.tabs').querySelectorAll('.tab').forEach(t=>t.classList.remove('active'));
el.classList.add('active');
}
// RSS
function rssP(u){document.getElementById('rss-url').value=u}
async function doRss(){
const url=document.getElementById('rss-url').value.trim();if(!url)return;
appendFeed('rss-feed',`<span class="tag rss">SYNC</span>Fetching…`);
const d=await api('POST','/ui/rss_sync',{url});
if(d.error||d.detail){appendFeed('rss-feed',`<span class="tag err">ERR</span>${esc(String(d.error||d.detail))}`);return}
const lbl=d.feed_title?`<b>${esc(d.feed_title)}</b> · `:'';
appendFeed('rss-feed',`<span class="tag rss">RSS</span>${lbl}<b>${d.synced}</b> items → ${d.signals_in_mesh} in mesh`);
if(!d.synced)appendFeed('rss-feed','<span class="dim">Feed returned 0 items.</span>');
(d.items||[]).slice(0,6).forEach(it=>appendFeed('rss-feed',`<span class="dim">↳ node ${it.node}</span> ${esc((it.title||'').slice(0,55))}`));
refresh();
}
// HF
function hfP(id,t){document.getElementById('hf-id').value=id;document.getElementById('hf-type').value=t}
async function doHf(){
const repo_id=document.getElementById('hf-id').value.trim();
const repo_type=document.getElementById('hf-type').value;if(!repo_id)return;
appendFeed('hf-feed',`<span class="tag hf">FLASH</span>Injecting ${esc(repo_id)}…`);
const d=await api('POST','/ui/hf_inject',{repo_id,repo_type});
if(d.error||d.detail){appendFeed('hf-feed',`<span class="tag err">ERR</span>${esc(String(d.error||d.detail))}`);return}
const info=d.injected||{};
appendFeed('hf-feed',`<span class="tag hf">HF</span><b>${esc(info.id||repo_id)}</b> [${info.type}] → node ${d.node}`);
if(info.pipeline_tag)appendFeed('hf-feed',`<span class="dim">task: ${esc(info.pipeline_tag)} · ↓${(info.downloads||0).toLocaleString()}</span>`);
if((info.tags||[]).length)appendFeed('hf-feed',`<span class="dim">${info.tags.slice(0,6).map(esc).join(', ')}</span>`);
appendFeed('hf-feed',`<a href="${esc(d.hf_url||'')}" target="_blank" style="color:var(--amber)">→ Open on HuggingFace</a>`);
refresh();
}
// arxiv
function axP(id){document.getElementById('ax-id').value=id}
async function doAx(){
const arxiv_id=document.getElementById('ax-id').value.trim();if(!arxiv_id)return;
appendFeed('ax-feed',`<span class="tag ax">FETCH</span>arxiv:${esc(arxiv_id)}…`);
const d=await api('POST','/ui/arxiv_inject',{arxiv_id});
if(d.error||d.detail){appendFeed('ax-feed',`<span class="tag err">ERR</span>${esc(String(d.error||d.detail))}`);return}
const p=d.injected||{};
appendFeed('ax-feed',`<span class="tag ax">PAPER</span><b>${esc((p.title||'').slice(0,60))}</b>`);
if(p.authors)appendFeed('ax-feed',`<span class="dim">${p.authors.slice(0,3).map(esc).join(', ')}</span>`);
if(p.summary)appendFeed('ax-feed',`<span class="dim">${esc(p.summary.slice(0,180))}…</span>`);
if(p.link)appendFeed('ax-feed',`<a href="${esc(p.link)}" target="_blank" style="color:#0284c7">Open on arxiv →</a>`);
refresh();
}
// Walkthrough
const WT=[
{title:'What is SignalMesh?',body:`<p>SignalMesh is an <strong>ambient context protocol</strong> — the nervous system of an AI agent fleet. Instead of agents polling for data with tool calls, data <em>broadcasts itself</em> to the right agents automatically.</p>
<div class="compare">
<div class="cbox old"><div class="clbl">❌ Old Way</div>Agent asks → tool call → wait → answer<br>5 agents × 3 queries = <strong>15 extra inferences</strong></div>
<div class="cbox new"><div class="clbl">✅ SignalMesh</div>Data broadcasts → agents tune in<br><strong>0 tool calls · 1.69µs · 96% less overhead</strong></div>
</div>
<div class="callout">📡 <strong>Broadcast</strong> = push data to a named frequency<br>🎛 <strong>Tune In</strong> = receive all signals matching your keywords<br>🗺 <strong>Grid</strong> = 72 spatial nodes, SHA-256 routed</div>`,
demo:()=>runDemo()},
{title:'Broadcasting a Signal',body:`<p>Pick a <strong>frequency name</strong> (like a radio station) and write your content. Hit Broadcast — it routes deterministically to a grid node via SHA-256.</p>
<div class="callout"><code>SHA-256("backend_events") % 72 → node 14</code><br>Same frequency always = same node. <strong>Zero config.</strong><br><br>⚠️ Frequencies starting with <strong>security_</strong>, <strong>auth_</strong>, <strong>key_</strong> go to SEC-Ω quarantine.</div>`,
demo:()=>{document.getElementById('bc-freq').value='signalmesh_demo';document.getElementById('bc-freq-display').textContent='signalmesh_demo';document.getElementById('bc-content').value='Hello SignalMesh — ambient context at 1.69µs';doBroadcast()}},
{title:'Tuning In',body:`<p>Agents are <strong>antennae</strong>. They declare keyword frequencies — and matching signals flow into their context before they even ask.</p>
<div class="callout"><strong>POST /ui/tune_in</strong><br><code>{"keywords": ["signalmesh_demo", "backend"]}</code><br><br>Returns a context string you inject directly into any LLM system prompt. Average: <strong>1.69µs</strong>.</div>`,
demo:()=>{document.getElementById('tune-kw').value='signalmesh_demo';document.getElementById('tuner-freq').textContent='signalmesh_demo';doTuneIn()}},
{title:'Feeding the Mesh',body:`<p>Any live data source — RSS feeds, HN, Reddit, blogs — gets ingested and distributed across the 72-node grid automatically.</p>
<div class="callout">Hit <strong>Sync →</strong> with any RSS URL. Each feed item gets SHA-256 routed to the agent domain most relevant to its content. No manual assignment.</div>`,
demo:async()=>{document.getElementById('rss-url').value='https://news.ycombinator.com/rss';await doRss()}},
{title:'The Antenna Grid',body:`<p>The 9×8 grid is the <strong>spatial topology</strong> of the agent fleet. 72 nodes, each mapped to an agent role.</p>
<div class="callout"><strong>Row 0</strong>: Architecture (backend, frontend, mobile)<br><strong>Row 1</strong>: Language pros (Python, JS, Go, Rust)<br><strong>Row 2–3</strong>: Infra + DevOps<br><strong>Row 4</strong>: AI/ML agents<br><strong>Row 5</strong>: Security + Quality<br><strong>Rows 6–8</strong>: Business, Growth, Utility</div>`,
demo:()=>refresh()},
{title:'Dataset Flashing',body:`<p><strong>Flash</strong> any HuggingFace model, dataset, or Space into the mesh — its metadata becomes live context for every relevant agent instantly.</p>
<div class="callout">🤗 <strong>HF inject</strong> → model card, tags, downloads, pipeline task<br>📄 <strong>arxiv inject</strong> → title, authors, abstract<br><br>External systems call <code>/api/tools/hf_inject</code> with <code>X-SignalMesh-Key</code>.</div>`,
demo:async()=>{hfP('acecalisto3/SignalMesh','space');await doHf()}},
];
function wt(idx,el){
document.querySelectorAll('.wt-tab').forEach(b=>b.classList.remove('active'));
if(el)el.classList.add('active');
const s=WT[idx];
document.getElementById('wt-body').innerHTML=`
<div class="wt-title">${s.title}</div>
<div class="wt-text">${s.body}</div>
<div class="wt-actions">
<button class="primary" onclick="WT[${idx}].demo&&WT[${idx}].demo()">▶ Run Demo</button>
${idx>0?`<button class="ghost" onclick="wt(${idx-1},document.querySelectorAll('.wt-tab')[${idx-1}])">← Prev</button>`:''}
${idx<WT.length-1?`<button class="secondary" onclick="wt(${idx+1},document.querySelectorAll('.wt-tab')[${idx+1}])">Next →</button>`:''}
</div>`;
}
async function runDemo(){
document.getElementById('bc-freq').value='signalmesh_demo';
document.getElementById('bc-freq-display').textContent='signalmesh_demo';
document.getElementById('bc-content').value='SignalMesh demo — ambient context at 1.69µs';
await doBroadcast();
await new Promise(r=>setTimeout(r,500));
document.getElementById('tune-kw').value='signalmesh_demo';
document.getElementById('tuner-freq').textContent='signalmesh_demo';
await doTuneIn();
await new Promise(r=>setTimeout(r,500));
document.getElementById('rss-url').value='https://news.ycombinator.com/rss';
await doRss();
}
async function refresh(){await Promise.all([pollStatus(),pollFreq(),pollGrid()])}
wt(0,document.querySelector('.wt-tab'));
initCollapse();
refresh();
setInterval(refresh,4000);
</script>
</body>
</html>"""
# ── OCODX license minting (Ed25519, offline-verifiable by the binary) ──────────
# Only this host holds the private signing key. The OCODX binary holds the matching
# PUBLIC key and verifies the minted token offline — no validation endpoint needed.
TIER_DEVICES = {"solo": 1, "pro": 3, "team": 10}
def _tier_from_session(sess: dict) -> tuple:
"""Resolve (tier, devices) from Checkout Session metadata set at checkout time."""
md = sess.get("metadata") or {}
tier = md.get("tier", "pro")
if tier not in TIER_DEVICES:
tier = "pro"
try:
devices = int(md.get("devices", 0)) or TIER_DEVICES[tier]
except (TypeError, ValueError):
devices = TIER_DEVICES[tier]
return tier, devices
def _mint_ocodx_key(email: str, tier: str, devices: int, days: int = 0) -> str:
import base64 as _b64
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
raw = os.environ.get("OCODX_SIGNING_KEY", "")
if not raw:
raise RuntimeError("OCODX_SIGNING_KEY not set — cannot mint license")
priv = Ed25519PrivateKey.from_private_bytes(
_b64.urlsafe_b64decode(raw + "=" * (-len(raw) % 4)))
now = int(time.time())
payload = {"email": email, "tier": tier, "iat": now,
"exp": now + days * 86400 if days > 0 else 0, "dev": devices}
pb = json.dumps(payload, separators=(",", ":"), sort_keys=True).encode()
enc = lambda x: _b64.urlsafe_b64encode(x).decode().rstrip("=")
return f"OCODX1.{enc(pb)}.{enc(priv.sign(pb))}"
def _db_create_licensed_user(email, cid, sid, tier, devices) -> str:
"""Mint an OCODX license token and store it as the user's key."""
key = _mint_ocodx_key(email, tier, devices)
uid = secrets.token_hex(8)
with _DB_LOCK:
conn = _db_conn()
conn.execute("INSERT OR IGNORE INTO users VALUES (?,?,?,?,?,?,1,?,?,0)",
(uid, email, key, tier, cid, sid, time.time(), time.time()))
conn.commit(); conn.close()
threading.Thread(target=_db_backup, daemon=True).start()
return key
def _provision_checkout_session(sess: dict) -> dict:
"""Mint the product the Stripe session actually purchased.
SignalMesh/MPort purchases receive a managed ``smesh-`` API key. OCODX
purchases continue to receive an offline-verifiable ``OCODX1`` license.
Keeping these paths explicit prevents one product's checkout metadata from
silently minting the other product's credential.
"""
if sess.get("payment_status") != "paid":
raise ValueError("Payment not completed")
md = sess.get("metadata") or {}
product = str(md.get("product") or "signalmesh").lower()
email = (sess.get("customer_details") or {}).get("email", "")
cid = sess.get("customer", "")
sid = sess.get("id", "")
if not sid:
raise ValueError("Checkout session has no id")
existing = _db_get_by_session(sid)
if existing:
return {
"api_key": existing["api_key"],
"email": existing["email"],
"tier": existing["tier"],
"product": product,
}
if product == "signalmesh":
checkout_tier = str(md.get("tier") or "monthly").lower()
tier = (
"managed_lifetime"
if checkout_tier in {"lifetime", "founding_lifetime"}
else "managed_monthly"
)
key = _db_create_user(email, cid, sid, tier=tier)
return {"api_key": key, "email": email, "tier": tier, "product": product}
if product == "ocodx":
add_seats = int(md.get("add_seats", 0) or 0)
if add_seats > 0:
key = _db_add_seats(email, add_seats, cid, sid)
row = _db_get_by_key(key) or {}
tier = row.get("tier", "solo")
else:
tier, devices = _tier_from_session(sess)
key = _db_create_licensed_user(email, cid, sid, tier, devices)
return {"api_key": key, "email": email, "tier": tier, "product": product}
raise ValueError(f"Unsupported checkout product: {product}")
# ── Stripe webhook ────────────────────────────────────────────────────────────
@app.post("/api/webhook/stripe", include_in_schema=False)
async def stripe_webhook(request: Request):
payload = await request.body()
sig = request.headers.get("stripe-signature", "")
secret = os.environ.get("STRIPE_WEBHOOK_SECRET", "")
try:
_stripe_verify(payload, sig, secret)
except Exception as e:
raise HTTPException(400, f"Webhook signature invalid: {e}")
event = json.loads(payload)
etype = event.get("type", "")
if etype == "checkout.session.completed":
sess = event["data"]["object"]
if sess.get("payment_status") == "paid":
_provision_checkout_session(sess)
elif etype == "customer.subscription.deleted":
cid = event["data"]["object"].get("customer", "")
if cid:
_db_revoke(cid)
return {"received": True}
def _stripe_verify(payload: bytes, sig_header: str, secret: str):
import hmac, hashlib
if not secret:
raise ValueError("STRIPE_WEBHOOK_SECRET is not configured")
parts = {k: v for k, v in (p.split("=", 1) for p in sig_header.split(",") if "=" in p)}
ts = parts.get("t", "")
v1 = parts.get("v1", "")
if not ts or not v1:
raise ValueError("Stripe signature header is incomplete")
try:
if abs(time.time() - int(ts)) > 300:
raise ValueError("Stripe signature timestamp is outside the 5-minute tolerance")
except ValueError:
raise
except Exception as exc:
raise ValueError("Stripe signature timestamp is invalid") from exc
signed = f"{ts}.".encode() + payload
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, v1):
raise ValueError("Signature mismatch")
# ── Key claim ─────────────────────────────────────────────────────────────────
@app.get("/api/keys/claim/{session_id}", tags=["Core"], summary="Claim API key after Stripe checkout")
async def claim_key(session_id: str):
"""Verify Stripe checkout session and return API key. Safe to call multiple times."""
existing = _db_get_by_session(session_id)
if existing:
return {"api_key": existing["api_key"], "email": existing["email"],
"tier": existing["tier"], "status": "active"}
sk = os.environ.get("STRIPE_SECRET_KEY", "")
if not sk:
raise HTTPException(503, "Stripe not configured")
try:
import base64 as _b64, urllib.request as _ur
req = _ur.Request(f"https://api.stripe.com/v1/checkout/sessions/{session_id}")
req.add_header("Authorization", "Basic " + _b64.b64encode(f"{sk}:".encode()).decode())
with _ur.urlopen(req, timeout=10) as r:
sess = json.loads(r.read())
except Exception as e:
raise HTTPException(502, f"Stripe lookup failed: {e}")
if sess.get("payment_status") != "paid":
raise HTTPException(402, "Payment not completed")
provisioned = _provision_checkout_session(sess)
return {**provisioned, "status": "active"}
# ── Key info ──────────────────────────────────────────────────────────────────
@app.get("/api/keys/me", tags=["Core"], summary="Get info about your API key")
def key_info(x_signalmesh_key: Optional[str] = Header(default=None)):
"""Returns tier, usage, and account info for the authenticated key."""
if not x_signalmesh_key:
raise HTTPException(401, "No key provided")
t = _tier(x_signalmesh_key)
if t == "update":
hits = [ts for ts in _update_usage.get(x_signalmesh_key, []) if ts > time.time() - 86400]
return {"tier": "update", "calls_used_24h": len(hits),
"limit_24h": _UPDATE_RATE_LIMIT,
"note": "update channel only — submesh reads + ocodx.* tune_in",
"upgrade": "https://kyklos.io/apps/signalmesh/"}
if t in ("admin", "paid"):
return {"tier": t, "public_socket_limit": _socket_limit(x_signalmesh_key)}
db_user = _db_get_by_key(x_signalmesh_key)
if db_user:
return {"tier": db_user["tier"], "email": db_user["email"],
"call_count": db_user["call_count"],
"created_at": db_user["created_at"],
"active": bool(db_user["active"]),
"public_socket_limit": 1}
raise HTTPException(401, "Invalid key")
# ── Admin: list users ─────────────────────────────────────────────────────────
@app.get("/api/admin/users", include_in_schema=False)
def admin_users(x_signalmesh_key: Optional[str] = Header(default=None)):
if _tier(x_signalmesh_key) != "admin":
raise HTTPException(403, "Admin only")
users = _db_all()
for u in users:
k = u.get("api_key", "")
u["api_key"] = k[:12] + "..." if k else ""
return {"users": users, "count": len(users)}
@app.get("/admin", response_class=HTMLResponse, include_in_schema=False)
def admin_dashboard(key: Optional[str] = None):
"""Sales + validation dashboard. Auth via ?key=<admin key> (browser-friendly)."""
if _tier(key) != "admin":
return HTMLResponse("<h2>403 — append ?key=&lt;admin key&gt;</h2>", status_code=403)
users = _db_all()
now = time.time()
total = len(users)
active = sum(1 for u in users if u.get("active"))
revoked = total - active
# "validated" = the license has actually been used at least once (device check-in)
validated = sum(1 for u in users if (u.get("call_count") or 0) > 0 or u.get("last_seen"))
active_30d = sum(1 for u in users if (u.get("last_seen") or 0) > now - 30 * 86400)
by_tier: Dict[str, int] = {}
for u in users:
by_tier[u.get("tier", "?")] = by_tier.get(u.get("tier", "?"), 0) + 1
legit = sum(1 for u in users if str(u.get("api_key", "")).startswith("OCODX1."))
tier_rows = "".join(f"<tr><td>{t}</td><td>{n}</td></tr>" for t, n in sorted(by_tier.items()))
def row(u):
k = u.get("api_key", "")
kind = "OCODX1 ✓" if k.startswith("OCODX1.") else ("smesh (legacy)" if k else "—")
seen = time.strftime("%Y-%m-%d", time.localtime(u["last_seen"])) if u.get("last_seen") else "never"
made = time.strftime("%Y-%m-%d", time.localtime(u["created_at"])) if u.get("created_at") else "?"
return (f"<tr><td>{u.get('email','')}</td><td>{u.get('tier','')}</td><td>{kind}</td>"
f"<td>{'✓' if u.get('active') else '✗'}</td><td>{u.get('call_count',0)}</td>"
f"<td>{seen}</td><td>{made}</td></tr>")
recent = "".join(row(u) for u in users[:100])
html = f"""<!doctype html><meta charset=utf-8><title>SignalMesh · Admin</title>
<style>body{{font:14px system-ui;margin:0;background:#0b0d12;color:#dde}}
.wrap{{max-width:1000px;margin:0 auto;padding:24px}}h1{{font-size:18px}}
.cards{{display:flex;gap:12px;flex-wrap:wrap;margin:16px 0}}
.card{{background:#141923;border:1px solid #232a38;border-radius:10px;padding:14px 18px;min-width:120px}}
.card b{{display:block;font-size:26px;color:#4dd0e1}}.card span{{color:#8a93a6;font-size:12px}}
table{{width:100%;border-collapse:collapse;margin-top:10px;font-size:12.5px}}
th,td{{border-bottom:1px solid #232a38;padding:7px 9px;text-align:left}}
th{{color:#8a93a6;text-transform:uppercase;font-size:10px}}h2{{font-size:14px;margin-top:24px}}</style>
<div class=wrap><h1>📡 SignalMesh — License Admin</h1>
<div class=cards>
<div class=card><b>{total}</b><span>keys sold</span></div>
<div class=card><b>{validated}</b><span>validated (used)</span></div>
<div class=card><b>{active_30d}</b><span>active · 30d</span></div>
<div class=card><b>{active}</b><span>active</span></div>
<div class=card><b>{revoked}</b><span>revoked</span></div>
<div class=card><b>{legit}</b><span>OCODX1 tokens</span></div>
</div>
<h2>By tier</h2><table><tr><th>tier</th><th>count</th></tr>{tier_rows}</table>
<h2>Recent (latest 100)</h2>
<table><tr><th>email</th><th>tier</th><th>key type</th><th>active</th><th>uses</th><th>last seen</th><th>created</th></tr>{recent}</table>
</div>"""
return HTMLResponse(html)
@app.get("/", response_class=HTMLResponse)
def root():
return _HTML
_CHAT_SYSTEM = (
"You are SignalMesh, the Sovereign Liquid Matrix agent. Answer the message that was actually "
"sent, in as few words as it takes.\n\n"
"1. If the live context below already answers the question, answer FROM it — summarise the "
"signals in plain prose. Never write code to go fetch what you were already handed.\n"
"2. Write code only when asked to write code. Then it is complete and working, no placeholders.\n"
"3. Never echo, quote, or paste the context block back to the user. It is your input, not your "
"output. Cite a signal by name if you need to attribute something.\n"
"4. If the request is to build or wire something and you are missing what you'd need to build "
"it, say what you can do in one line, then ask only the questions whose answers change the "
"build. No preamble, no options essay.\n"
"5. You may open with a short signal tag for the dominant matched node (e.g. '▶ L1 · Python "
"Pro') when a specialist lens actually applies. Otherwise skip it."
)
# name -> (default_base_url, key_env, model_env, default_model)
_CHAT_PROVIDERS = {
"groq": ("https://api.groq.com/openai/v1", "GROQ_API_KEY", "GROQ_MODEL", "llama-3.1-8b-instant"),
"gemini": ("https://generativelanguage.googleapis.com/v1beta/openai", "GEMINI_API_KEY", "GEMINI_MODEL", "gemini-2.0-flash"),
"opencode_zen": ("https://opencode.ai/zen/v1", "OPENCODE_ZEN_API_KEY", "OPENCODE_ZEN_MODEL", "glm-4.6"),
"huggingface": ("https://router.huggingface.co/v1", "HF_TOKEN", "HF_CHAT_MODEL", "meta-llama/Llama-3.1-8B-Instruct"),
"xai": ("https://api.x.ai/v1", "XAI_API_KEY", "XAI_MODEL", "grok-2-latest"),
}
_CHAT_ORDER_DEFAULT = "huggingface,groq,gemini,opencode_zen,xai"
def _chat_cfg(name: str):
base, key_env, model_env, default_model = _CHAT_PROVIDERS[name]
# .strip() everything: a secret pasted into the Space UI often carries a trailing
# newline, and "moonshotai/Kimi-K3\n" is a 400 from the router, not a fallback.
base = os.environ.get(f"{name.upper()}_BASE_URL", base).strip().rstrip("/")
return base, os.environ.get(key_env, "").strip(), (os.environ.get(model_env) or default_model).strip()
def _chat_order() -> List[str]:
raw = os.environ.get("CHAT_PROVIDER_ORDER", _CHAT_ORDER_DEFAULT)
return [p.strip() for p in raw.split(",") if p.strip() in _CHAT_PROVIDERS]
_CHAT_SESSIONS: Dict[str, List[dict]] = {}
_CHAT_TOPIC: Dict[str, List[str]] = {} # last keywords that actually tuned
_CHAT_ACTIVE: Dict[str, List[str]] = {}
_CHAT_LOCK = threading.Lock()
_CHAT_MAX_HISTORY = 16
_CHAT_STOP = {"the","and","for","that","with","this","you","your","are","can","what","how","why",
"who","when","where","a","an","to","of","in","on","is","it","me","my","do","does",
"i","we","be","as","at","or","if","so","but","not","get","let","now","then","please",
"help","need","want","make","using","use","about"}
_ROW_LETTERS = "ALIODQBGU"
def _chat_keywords(text: str, limit: int = 8) -> List[str]:
out, seen = [], set()
for t in re.split(r"[^a-zA-Z0-9_+#-]+", (text or "").lower()):
if len(t) >= 3 and t not in _CHAT_STOP and t not in seen:
seen.add(t); out.append(t)
if len(out) >= limit:
break
return out
def _freq_coord(freq: str) -> str:
idx = _node_idx(freq); r, c = divmod(idx, _COLS)
return f"{_ROW_LETTERS[r]}{c+1}" if 0 <= r < len(_ROW_LETTERS) else f"N{idx}"
def _render_signal(content: Any) -> str:
"""Feed rows arrive as dicts; a raw repr is unreadable and the model echoes it back."""
if isinstance(content, dict):
title = content.get("title") or content.get("name") or content.get("summary") or ""
link = content.get("link") or content.get("url") or ""
if title:
return f"{str(title)[:200]}{' — ' + link if link else ''}"
content = json.dumps(content, separators=(",", ":"))
return str(content or "")[:300]
def _mesh_hydrate(keywords: List[str], role: Optional[str] = None, max_signals: int = 12):
"""One tune_in pass -> (context_str, [grid_coords]). Capped to keep the prompt lean."""
try:
signals = signal_registry.tune_in(keywords)
if role:
signals = relationship_graph.filter_signals(role, signals)
except Exception:
signals = []
signals = signals[:max_signals]
lines, coords = [], []
if signals:
lines.append("[SignalMesh — Live Context]")
for s in signals:
nm = s.get("name", "?")
# the frequency name is what the user can act on; A1-style cells are for the canvas
if nm not in coords:
coords.append(nm)
lines.append(f"• [{nm}] {_render_signal(s.get('content'))}")
return "\n".join(lines)[:4000], coords
async def _chat_one(client, base, key, model, messages, max_tokens, temperature):
r = await client.post(base.rstrip("/") + "/chat/completions",
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
json={"model": model, "messages": messages, "max_tokens": max_tokens, "temperature": temperature})
if r.status_code != 200:
raise RuntimeError(f"HTTP {r.status_code}: {r.text[:160]}")
msg = ((r.json().get("choices") or [{}])[0].get("message") or {})
txt = (msg.get("content") or "").strip()
if not txt:
raise RuntimeError("empty completion")
return txt
async def _chat_complete(messages, max_tokens=1024, temperature=0.6):
errors = []
async with httpx.AsyncClient(timeout=45.0) as client:
for name in _chat_order():
base, key, model = _chat_cfg(name)
if not key:
errors.append(f"{name}: skipped, no key set") # never fail silently
continue
try:
return (await _chat_one(client, base, key, model, messages, max_tokens, temperature),
f"{name}:{model}", errors)
except Exception as e:
errors.append(f"{name}: {str(e)[:120]}")
return None, "none", errors
def _live_frequencies(term: str) -> List[str]:
stem = re.sub(r"^(www\.|https?://)|\.(com|io|ai|org|net)$", "", term.lower()).split(".")[0]
return [n for n, buf in signal_registry.streams.items() if buf and stem and stem in n.lower()]
_ASKING_ABOUT = re.compile(
r"^\s*(?:tell me about|what(?:'?s| is| are)|who(?:'?s| is)|explain|describe)\s+(.{2,60}?)\s*[?.!]*\s*$",
re.I)
_PRONOUNS = {"it", "that", "this", "they", "them", "he", "she", "these", "those", "one"}
def _empty_mesh_reply(msg: str, context: str, history: list) -> Optional[str]:
"""A question about a named thing with nothing in the mesh is answered by the mesh,
not by the model — that is the path that invented a Meta product called NexusAI.
Build/code requests fall through untouched; they were never mesh lookups."""
m = _ASKING_ABOUT.match(msg)
if context or not m or history:
return None # mid-thread, the subject is the thread — never gate a follow-up
subject = m.group(1).strip()
head = re.split(r"[^a-z0-9]+", subject.lower())[0] if subject else ""
if not head or head in _PRONOUNS:
return None # "who is it for" names nothing to look up
near = sorted({n for n in signal_registry.streams
if signal_registry.streams[n] and n.split(".")[0].lower()[:4] in msg.lower()})
out = [f"The mesh is carrying nothing on {subject} — so I'm not answering from my own "
f"training data and calling it live."]
if near:
out.append("\nClosest frequencies: " + ", ".join(near[:6]))
host = os.environ.get("SIGNALMESH_PUBLIC_URL") or (
f"https://{os.environ['SPACE_HOST']}" if os.environ.get("SPACE_HOST") else "")
out.append(f"\nTo make this answerable, broadcast it:\n"
f' curl -X POST {host}/ui/broadcast \\\n'
f' -H "Content-Type: application/json" \\\n'
f' -d \'{{"frequency":"<name>","content":"…"}}\'\n'
f"or add it to SITE_INGEST as <frequency>=<url> and it re-hydrates on every boot.")
return "\n".join(out)
def _fast_reply(msg: str) -> Optional[str]:
"""Deterministic answers for requests whose shape we already know.
An antenna is built from (frequency, target, name) against a frequency that
already carries signals — so the missing pieces are knowable without a model.
"""
m = re.search(r"\bantenna\b[^.?!]{0,30}?\bfor\b\s+([^\s,.?!]+)", msg, re.I)
if not m:
return None
term = m.group(1).strip()
live = _live_frequencies(term)
out = [f"On it — antenna for {term}."]
if live:
out.append("\nCarrying signals now: " + ", ".join(sorted(live)[:8]))
out.append("\nTwo things I need:")
out.append("1. Which frequency above should it receive?")
else:
out.append(f"\nNothing in the mesh is carrying {term} yet — an antenna is shaped against "
"live signals, so that frequency has to be broadcast first.")
out.append("\nTwo things I need:")
out.append("1. What should be broadcast onto it — docs, API responses, a feed?")
out.append("2. Where does it materialize? " + " · ".join(ANTENNA_TARGETS))
out.append("\n nextjs_route → an API route in their app · shell → a curl/CLI receiver")
out.append(" system_prompt → context injected into an agent · html_embed → a drop-in widget")
out.append("\nAnswer those two and I'll emit the wrapper.")
return "\n".join(out)
class ChatReq(BaseModel):
session_id: str = ""
message: str
role: Optional[str] = None
keywords: Optional[List[str]] = None
max_tokens: int = 1024
temperature: float = 0.6
class ChatResetReq(BaseModel):
session_id: str = ""
@app.post("/api/chat", tags=["Core"], summary="Chat with the mesh — hydrated context + multi-provider failover")
async def api_chat(req: ChatReq, x_signalmesh_key: Optional[str] = Header(default=None)):
_check_key(x_signalmesh_key)
return await _do_chat(req)
@app.post("/ui/chat", tags=["Core"], summary="Chat with the mesh — no key")
async def ui_chat(req: ChatReq):
"""Keyless, like the rest of /ui/*. The mesh is the demo; the model runs on our keys."""
return await _do_chat(req)
@app.post("/ui/chat/reset", tags=["Core"], summary="Reset a chat session — no key")
def ui_chat_reset(req: ChatResetReq):
sid = (req.session_id or "anon").strip()
with _CHAT_LOCK:
_CHAT_SESSIONS.pop(sid, None); _CHAT_ACTIVE.pop(sid, None); _CHAT_TOPIC.pop(sid, None)
return {"status": "reset", "session_id": sid}
async def _do_chat(req: ChatReq):
msg = (req.message or "").strip()
if not msg:
raise HTTPException(400, "message is required")
sid = (req.session_id or "anon").strip()
kws = req.keywords or _chat_keywords(msg)
context, coords = _mesh_hydrate(kws, req.role)
with _CHAT_LOCK:
history = list(_CHAT_SESSIONS.get(sid, []))
prev = _CHAT_ACTIVE.get(sid, [])
carried = list(_CHAT_TOPIC.get(sid, []))
# A follow-up ("who is it for", "what about pricing") carries no routable keyword of
# its own. Stay tuned to whatever the thread is already about instead of going deaf.
if not context and carried:
context, coords = _mesh_hydrate(carried, req.role)
kws = carried
elif context:
with _CHAT_LOCK:
_CHAT_TOPIC[sid] = kws
sys_msg = _CHAT_SYSTEM + ("\n\n" + context if context else
"\n\n[SignalMesh — no live signals matched this query.]\n"
"Say so in your first line — the mesh is carrying nothing on this. Anything you add "
"after that is your own training data, not mesh knowledge: label it as unverified and "
"keep it short. Never present it as what the mesh knows, and never invent specifics "
"(dates, versions, features, pricing) about a named product you have no signals for.")
messages = ([{"role": "system", "content": sys_msg}]
+ history[-_CHAT_MAX_HISTORY:]
+ [{"role": "user", "content": msg}])
fast = _fast_reply(msg) or _empty_mesh_reply(msg, context, history)
if fast:
reply, provider, errors = fast, "mesh", []
else:
reply, provider, errors = await _chat_complete(messages, req.max_tokens, req.temperature)
if reply is None:
reply = ("⚠ No language provider answered. What each one said:\n\n"
+ "\n".join(f"· {e}" for e in errors) if errors else
"⚠ No language provider is configured on the mesh. Set at least one of "
"GROQ_API_KEY, GEMINI_API_KEY, OPENCODE_ZEN_API_KEY, HF_TOKEN, or XAI_API_KEY "
"as a Space secret to enable chat.")
provider = "none"
with _CHAT_LOCK:
h = _CHAT_SESSIONS.get(sid, [])
h.append({"role": "user", "content": msg})
if provider != "none":
h.append({"role": "assistant", "content": reply})
_CHAT_SESSIONS[sid] = h[-_CHAT_MAX_HISTORY:]
_CHAT_ACTIVE[sid] = coords
hist_len = sum(1 for m in _CHAT_SESSIONS[sid] if m["role"] == "user")
new_sigs = [c for c in coords if c not in prev]
removed = [c for c in prev if c not in coords]
return {
"reply": reply, "provider": provider,
"active_signals": coords, "new_signals": new_sigs, "removed_signals": removed,
"history_len": hist_len,
"trail": [], "had_reask": False, "fuzzy_acquired": [],
"seek_needed": False, "seek_gaps": [], "seek_prompt": "",
"provider_errors": errors,
}
@app.post("/api/chat/reset", tags=["Core"], summary="Reset a chat session")
def api_chat_reset(req: ChatResetReq, x_signalmesh_key: Optional[str] = Header(default=None)):
_check_key(x_signalmesh_key)
sid = (req.session_id or "anon").strip()
with _CHAT_LOCK:
_CHAT_SESSIONS.pop(sid, None); _CHAT_ACTIVE.pop(sid, None); _CHAT_TOPIC.pop(sid, None)
return {"status": "reset", "session_id": sid}
@app.get("/api/chat/session/{session_id}", tags=["Core"], summary="Chat session info")
def api_chat_session(session_id: str, x_signalmesh_key: Optional[str] = Header(default=None)):
_check_key(x_signalmesh_key)
with _CHAT_LOCK:
h = _CHAT_SESSIONS.get(session_id, [])
hist_len = sum(1 for m in h if m["role"] == "user")
return {"session_id": session_id, "history_len": hist_len,
"active_signals": _CHAT_ACTIVE.get(session_id, []), "signal_detail": []}
_CHAT_HTML = r"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SignalMesh · Live Chat</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{
--bg:#0c0e11; --panel:#14181d; --panel2:#1a1f26;
--line:#242b33; --line2:#2f3742;
--text:#e7e5df; --muted:#8b929c; --dim:#5b626c;
--accent:#46d39a; --user:#1c2630;
}
html,body{height:100%}
body{background:var(--bg);color:var(--text);
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
display:flex;flex-direction:column;height:100vh;overflow:hidden}
header{display:flex;align-items:center;gap:12px;padding:14px 20px;border-bottom:1px solid var(--line);background:var(--panel)}
.logo{font-weight:700;letter-spacing:.3px;font-size:1.02rem}
.logo .d{color:var(--accent)}
.tag{color:var(--muted);font-size:.8rem}
.live{margin-left:auto;display:flex;align-items:center;gap:6px;font-size:.72rem;color:var(--muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.live .p{width:8px;height:8px;border-radius:50%;background:var(--accent);animation:pulse 2s infinite}
@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(70,211,154,.5)}70%{box-shadow:0 0 0 7px rgba(70,211,154,0)}100%{box-shadow:0 0 0 0 rgba(70,211,154,0)}}
#scroll{flex:1;overflow-y:auto;padding:22px 0}
#wrap{max-width:760px;margin:0 auto;padding:0 20px;display:flex;flex-direction:column;gap:16px}
#intro{margin-top:6vh;text-align:center;color:var(--muted)}
#intro h1{color:var(--text);font-size:1.5rem;font-weight:650;margin-bottom:8px}
#intro p{font-size:.92rem;line-height:1.6;max-width:450px;margin:0 auto 20px}
.chips{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}
.chip{background:var(--panel);border:1px solid var(--line2);color:var(--text);padding:9px 14px;border-radius:20px;font-size:.82rem;cursor:pointer;transition:.15s}
.chip:hover{border-color:var(--accent);color:var(--accent)}
.msg{display:flex;flex-direction:column;gap:5px}
.msg.user{align-items:flex-end}
.role{font-size:.7rem;color:var(--dim);font-family:ui-monospace,monospace;letter-spacing:.04em}
.bubble{padding:13px 16px;border-radius:13px;font-size:.93rem;line-height:1.68;max-width:86%;word-wrap:break-word;overflow-wrap:anywhere}
.msg.user .bubble{background:var(--user);border:1px solid var(--line2);border-bottom-right-radius:4px}
.msg.bot .bubble{background:var(--panel);border:1px solid var(--line);border-bottom-left-radius:4px}
.bubble pre{background:#0a0c0f;border:1px solid var(--line);border-radius:8px;padding:12px;margin:8px 0;overflow-x:auto;font-size:.84rem}
.bubble code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.86em}
.bubble :not(pre)>code{background:#0a0c0f;border:1px solid var(--line);border-radius:5px;padding:1px 5px}
.bubble a{color:var(--accent);text-decoration:none;border-bottom:1px solid rgba(70,211,154,.35)}
.foot{font-size:.68rem;color:var(--dim);font-family:ui-monospace,monospace}
.foot b{color:var(--muted);font-weight:500}
.typing{display:inline-flex;gap:4px;padding:14px 16px;background:var(--panel);border:1px solid var(--line);border-radius:13px;border-bottom-left-radius:4px}
.typing i{width:6px;height:6px;border-radius:50%;background:var(--muted);animation:wave 1s infinite}
.typing i:nth-child(2){animation-delay:.15s}.typing i:nth-child(3){animation-delay:.3s}
@keyframes wave{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-4px)}}
#composer{border-top:1px solid var(--line);background:var(--panel);padding:14px 20px}
#cform{max-width:760px;margin:0 auto;display:flex;gap:10px;align-items:flex-end;background:var(--panel2);border:1px solid var(--line2);border-radius:14px;padding:8px 8px 8px 14px;transition:.15s}
#cform:focus-within{border-color:var(--accent)}
#input{flex:1;background:none;border:none;outline:none;color:var(--text);font:inherit;font-size:.95rem;resize:none;max-height:140px;line-height:1.5;padding:6px 0}
#send{flex-shrink:0;background:var(--accent);color:#06291c;border:none;border-radius:10px;width:40px;height:40px;font-size:1.15rem;cursor:pointer;font-weight:700;display:flex;align-items:center;justify-content:center}
#send:disabled{opacity:.4;cursor:not-allowed}
.hint{max-width:760px;margin:8px auto 0;text-align:center;font-size:.68rem;color:var(--dim)}
@media(max-width:560px){.bubble{max-width:92%}#intro{margin-top:4vh}.tag{display:none}}
</style>
</head>
<body>
<header>
<span class="logo">&#128225; Signal<span class="d">Mesh</span></span>
<span class="tag">Sovereign Liquid Matrix</span>
<span class="live"><span class="p"></span> live</span>
</header>
<div id="scroll"><div id="wrap">
<div id="intro">
<h1>Ask the mesh</h1>
<p>Live ambient context from Reddit, Hacker News, arXiv, HuggingFace and more &mdash; answered in real time.</p>
<div class="chips">
<div class="chip" data-q="What's trending on r/MachineLearning right now?">r/MachineLearning trends</div>
<div class="chip" data-q="What's hot on Reddit's r/popular today?">Reddit trending today</div>
<div class="chip" data-q="What's on the front page of Hacker News right now?">Hacker News front page</div>
<div class="chip" data-q="What are the latest AI papers on arXiv?">Latest arXiv AI papers</div>
</div>
</div>
</div></div>
<div id="composer">
<form id="cform">
<textarea id="input" rows="1" placeholder="Ask about trending Reddit, a subreddit, Hacker News, arXiv..." autofocus></textarea>
<button id="send" type="submit" title="Send">&#8593;</button>
</form>
<div class="hint">SignalMesh answers from live mesh signals &middot; responses may vary</div>
</div>
<script>
const API='/ui/chat';
let SID=localStorage.getItem('sm_chat_sid');
if(!SID){SID='web-'+Math.random().toString(36).slice(2,11);localStorage.setItem('sm_chat_sid',SID);}
const scroll=document.getElementById('scroll'),wrap=document.getElementById('wrap'),intro=document.getElementById('intro'),input=document.getElementById('input'),form=document.getElementById('cform'),sendBtn=document.getElementById('send');
function esc(s){return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
function md(t){
t=esc(t);
t=t.replace(/```(\w+)?\n?([\s\S]*?)```/g,function(m,l,c){return '<pre><code>'+c.replace(/\n+$/,'')+'</code></pre>';});
t=t.replace(/`([^`\n]+)`/g,'<code>$1</code>');
t=t.replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>');
t=t.replace(/(https?:\/\/[^\s<)]+)/g,'<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>');
t=t.replace(/\n/g,'<br>');
return t;
}
function down(){scroll.scrollTop=scroll.scrollHeight;}
function addUser(text){if(intro&&intro.parentNode)intro.remove();const d=document.createElement('div');d.className='msg user';d.innerHTML='<div class="role">you</div><div class="bubble"></div>';d.querySelector('.bubble').textContent=text;wrap.appendChild(d);down();}
function addTyping(){const d=document.createElement('div');d.className='msg bot';d.innerHTML='<div class="role">signalmesh</div><div class="typing"><i></i><i></i><i></i></div>';wrap.appendChild(d);down();return d;}
function addBot(reply,provider,signals){const d=document.createElement('div');d.className='msg bot';let foot='';const prov=provider&&provider!=='none'?provider.split(':')[0]:'';const sig=(signals&&signals.length)?' &middot; signals: '+signals.slice(0,6).join(', '):'';if(prov)foot='<div class="foot"><b>&#9679; live mesh</b> &middot; '+esc(prov)+sig+'</div>';d.innerHTML='<div class="role">signalmesh</div><div class="bubble">'+md(reply)+'</div>'+foot;wrap.appendChild(d);down();}
let busy=false;
async function ask(text,isRetry){
const tr=addTyping();
try{
const res=await fetch(API,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({session_id:SID,message:text})});
const data=await res.json();
tr.remove();
if((!data.reply||data.provider==='none')&&!isRetry){await new Promise(r=>setTimeout(r,1600));return ask(text,true);}
addBot(data.reply||'The mesh is busy right now &mdash; please try again in a moment.',data.provider,data.active_signals);
}catch(e){tr.remove();addBot('Connection hiccup reaching the mesh &mdash; please try again.',null,null);}
}
async function submit(text){text=(text||'').trim();if(!text||busy)return;busy=true;sendBtn.disabled=true;input.value='';input.style.height='auto';addUser(text);await ask(text,false);busy=false;sendBtn.disabled=false;input.focus();}
form.addEventListener('submit',function(e){e.preventDefault();submit(input.value);});
input.addEventListener('keydown',function(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();submit(input.value);}});
input.addEventListener('input',function(){input.style.height='auto';input.style.height=Math.min(input.scrollHeight,140)+'px';});
document.querySelectorAll('.chip').forEach(function(c){c.addEventListener('click',function(){submit(c.getAttribute('data-q'));});});
</script>
</body>
</html>"""
@app.get("/chat", response_class=HTMLResponse, include_in_schema=False)
def chat_ui():
return _CHAT_HTML
if __name__ == "__main__":
import uvicorn
port = int(os.environ.get("PORT", os.environ.get("SIGNALMESH_PORT", 7475)))
print(f"\n📡 SignalMesh — Sovereign Liquid Matrix Gateway v2.0")
print(f" http://0.0.0.0:{port} → /docs → /redoc")
print(f" UI routes: /ui/* (no key) | API routes: /api/* (X-SignalMesh-Key)")
print(f" Set SIGNALMESH_API_KEY env var to change the key\n")
uvicorn.run("signalmesh_api:app", host="0.0.0.0", port=port, reload=False)