"""
@app.route("/api/status")
def status():
return jsonify(ok=True, marker="{marker}", prompt=PROMPT, build_note=BUILD_NOTE, port=os.environ.get("PORT"))
@app.route("/api/echo", methods=["GET", "POST"])
def echo():
value = request.values.get("text", "")
return jsonify(ok=True, echo=value)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 9000)))
'''
return {
"name": f"fallback-{slugify(marker)}",
"description": "Runnable Flask backend generated when the LLM returned malformed app JSON.",
"start_command": "python3 app.py",
"files": [{"path": "app.py", "content": content}],
}
def normalize_generated_app_spec(app_spec: dict, prompt: str = "") -> dict:
if not isinstance(app_spec, dict):
return app_spec
files = app_spec.get("files")
if not isinstance(files, list):
return app_spec
for file_item in files:
path = str(file_item.get("path", ""))
content = str(file_item.get("content", ""))
if path.endswith(".py") and "Flask(" in content and "app.run" in content:
lines = content.splitlines()
cleaned = []
i = 0
while i < len(lines):
stripped = lines[i].strip()
next_stripped = lines[i + 1].strip() if i + 1 < len(lines) else ""
if stripped.startswith("if __name__") and "app.run" in next_stripped:
i += 2
continue
if re.match(r"^app\.run\s*\(", stripped):
i += 1
continue
cleaned.append(lines[i])
i += 1
cleaned_text = "\n".join(cleaned).rstrip()
cleaned_text += (
"\n\nif __name__ == \"__main__\":\n"
" app.run(host=\"0.0.0.0\", port=int(os.environ.get(\"PORT\", 9000)))\n"
)
if "import os" not in cleaned_text:
cleaned_text = "import os\n" + cleaned_text
prompt_routes = sorted(set(re.findall(r"(/api/[A-Za-z0-9_./-]+)", prompt or "")))
missing_routes = [route.rstrip(".") for route in prompt_routes if route.rstrip(".") not in cleaned_text]
if missing_routes:
if "jsonify" not in cleaned_text:
if "from flask import Flask" in cleaned_text:
cleaned_text = cleaned_text.replace("from flask import Flask", "from flask import Flask, jsonify", 1)
else:
cleaned_text = "from flask import jsonify\n" + cleaned_text
extra_routes = []
for route in missing_routes:
func = "generated_" + re.sub(r"[^A-Za-z0-9_]", "_", route.strip("/"))
extra_routes.append(
f'\n@app.route("{route}")\n'
f"def {func}():\n"
f' return jsonify(ok=True, path="{route}")\n'
)
marker = '\n\nif __name__ == "__main__":'
if marker in cleaned_text:
cleaned_text = cleaned_text.replace(marker, "\n".join(extra_routes) + marker, 1)
else:
cleaned_text += "\n" + "\n".join(extra_routes)
file_item["content"] = cleaned_text
app_spec["start_command"] = "python3 app.py"
if "flask run" in str(app_spec.get("start_command", "")).lower():
app_spec["start_command"] = "python3 app.py"
return app_spec
def call_llm(prompt: str, system: str = "", **options) -> dict:
llm_cfg = settings.get("llm", {})
api_base = str(options.get("api_base") or llm_cfg.get("api_base") or "https://api.openai.com/v1").rstrip("/")
model = str(options.get("model") or llm_cfg.get("model") or "gpt-4o-mini")
api_key = (
options.get("api_key")
or settings.get("env", {}).get("LLM_API_KEY")
or settings.get("env", {}).get("OPENAI_API_KEY")
or settings.get("env", {}).get("OPENROUTER_API_KEY")
or settings.get("env", {}).get("GROQ_API_KEY")
or os.environ.get("LLM_API_KEY")
or os.environ.get("OPENAI_API_KEY")
or os.environ.get("OPENROUTER_API_KEY")
or os.environ.get("GROQ_API_KEY")
)
if not api_key:
raise ValueError("No LLM API key configured.")
messages = []
if system:
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
payload = {
"model": model,
"messages": messages,
"temperature": float(options.get("temperature", 0.25)),
"max_tokens": int(options.get("max_tokens", 1800)),
}
if options.get("response_format"):
payload["response_format"] = options["response_format"]
response = requests.post(
f"{api_base}/chat/completions",
headers={"authorization": f"Bearer {api_key}", "content-type": "application/json"},
json=payload,
timeout=bounded_timeout(options.get("timeout", 90)),
)
result = response.json()
content = ""
try:
content = result["choices"][0]["message"]["content"]
except Exception:
pass
usage = result.get("usage", {})
input_tokens = usage.get("prompt_tokens", 0) or usage.get("input_tokens", 0) or len(prompt) // 4
output_tokens = usage.get("completion_tokens", 0) or usage.get("output_tokens", 0) or len(content) // 4
proof = generate_inference_proof(
model=model,
prompt=prompt,
response=content,
provider=api_base.split("//")[-1].split(".")[0],
api_base=api_base,
latency_ms=0.0,
input_tokens=input_tokens,
output_tokens=output_tokens,
)
return {"api_base": api_base, "model": model, "response": content, "raw": result, "proof": proof}
def get_kernel():
global kernel_manager, kernel_client
with kernel_lock:
if kernel_manager and kernel_client:
return kernel_manager, kernel_client
from jupyter_client import KernelManager
os.environ.update(runtime_env())
kernel_manager = KernelManager(kernel_name="python3")
kernel_manager.start_kernel(cwd=runtime_cwd())
kernel_client = kernel_manager.client()
kernel_client.start_channels()
kernel_client.wait_for_ready(timeout=30)
# Inject notebook-exposed helpers into kernel namespace
try:
helper_code = (
"import json, os, requests, time, textwrap, uuid\n"
"from datetime import datetime, timezone\n"
"from typing import Optional\n"
"\n"
"LLM_ROUTES = {\n"
" 'fast': {'provider': 'groq', 'model': 'llama-3.1-8b-instant', 'api_base': 'https://api.groq.com/openai/v1'},\n"
" 'cheap': {'provider': 'groq', 'model': 'llama-3.1-8b-instant', 'api_base': 'https://api.groq.com/openai/v1'},\n"
" 'quality': {'provider': 'openrouter', 'model': 'openai/gpt-4o', 'api_base': 'https://openrouter.ai/api/v1'},\n"
" 'coding': {'provider': 'groq', 'model': 'llama-3.3-70b-versatile', 'api_base': 'https://api.groq.com/openai/v1'},\n"
" 'json': {'provider': 'groq', 'model': 'llama-3.1-8b-instant', 'api_base': 'https://api.groq.com/openai/v1'},\n"
"}\n"
"\n"
"def _resolve_key(provider):\n"
" env = dict(os.environ)\n"
" if provider == 'groq':\n"
" return env.get('GROQ_API_KEY') or env.get('LLM_API_KEY')\n"
" if provider == 'openrouter':\n"
" return env.get('OPENROUTER_API_KEY') or env.get('LLM_API_KEY')\n"
" return env.get('LLM_API_KEY')\n"
"\n"
"def llm_infer(mode='cheap', task='', messages=None, system='', temperature=0.25, max_tokens=1800, timeout=90):\n"
" messages = messages or []\n"
" if not messages and task:\n"
" messages = [{'role': 'user', 'content': task}]\n"
" if not messages:\n"
" raise ValueError('Provide messages or task')\n"
" route = LLM_ROUTES.get(mode, LLM_ROUTES['cheap'])\n"
" provider = route['provider']\n"
" model = route['model']\n"
" api_base = route['api_base']\n"
" api_key = _resolve_key(provider)\n"
" if not api_key:\n"
" raise ValueError(f'No API key for {provider}')\n"
" prompt = messages[-1].get('content', '') if messages else ''\n"
" if mode == 'json':\n"
" system = (system or '') + '\\nReturn only valid JSON. No markdown fences.'\n"
" if mode == 'coding':\n"
" system = (system or '') + '\\nYou are an expert programmer. Write clean, production-ready code.'\n"
" payload = {'model': model, 'messages': [{'role': 'system', 'content': system}] + messages if system else messages, 'temperature': temperature, 'max_tokens': max_tokens}\n"
" if mode == 'json':\n"
" payload['response_format'] = {'type': 'json_object'}\n"
" started = time.time()\n"
" r = requests.post(f'{api_base}/chat/completions', headers={'authorization': f'Bearer {api_key}', 'content-type': 'application/json'}, json=payload, timeout=timeout)\n"
" latency_ms = round((time.time() - started) * 1000, 2)\n"
" result = r.json()\n"
" answer = result.get('choices', [{}])[0].get('message', {}).get('content', '')\n"
" usage = result.get('usage', {})\n"
" inp = usage.get('prompt_tokens', 0) or len(prompt)//4\n"
" out = usage.get('completion_tokens', 0) or len(answer)//4\n"
" cost = round((inp + out) / 1000 * {'llama-3.1-8b-instant': 0.00005, 'llama-3.3-70b-versatile': 0.00059, 'openai/gpt-4o': 0.005}.get(model, 0.0001), 6)\n"
" return {'answer': answer, 'provider': provider, 'model': model, 'latency_ms': latency_ms, 'cost_usd': cost, 'input_tokens': inp, 'output_tokens': out, 'route_reason': f'mode={mode} -> {provider} -> {model}', 'raw': result}\n"
)
kernel_client.execute(helper_code, silent=True, user_expressions={})
except Exception:
logger.warning("Failed to inject helpers into kernel namespace")
try:
kernel_client.execute("globals()['llm_infer'] = llm_infer\n", silent=True, user_expressions={})
except Exception:
pass
return kernel_manager, kernel_client
def shutdown_kernel():
global kernel_manager, kernel_client
with kernel_lock:
if kernel_client:
try:
kernel_client.stop_channels()
except Exception:
pass
if kernel_manager:
try:
kernel_manager.shutdown_kernel(now=True)
except Exception:
pass
kernel_manager = None
kernel_client = None
def execute_kernel_code(code: str, timeout: int = 60) -> dict:
timeout = bounded_timeout(timeout)
with kernel_lock:
_, client = get_kernel()
msg_id = client.execute(code, allow_stdin=False)
stdout_chunks = []
stderr_chunks = []
display_data = []
error = None
started = time.time()
while True:
if time.time() - started > timeout:
try:
kernel_manager.interrupt_kernel()
except Exception:
pass
return {
"success": False,
"execution_state": "timeout",
"stdout": "".join(stdout_chunks),
"stderr": "".join(stderr_chunks) + "\nKernel execution timed out",
"display_data": display_data,
"error": "timeout",
}
msg = client.get_iopub_msg(timeout=1)
if msg.get("parent_header", {}).get("msg_id") != msg_id:
continue
msg_type = msg["header"]["msg_type"]
content = msg.get("content", {})
if msg_type == "stream":
if content.get("name") == "stderr":
stderr_chunks.append(content.get("text", ""))
else:
stdout_chunks.append(content.get("text", ""))
elif msg_type in {"display_data", "execute_result"}:
display_data.append(content.get("data", {}))
elif msg_type == "error":
error = {
"ename": content.get("ename"),
"evalue": content.get("evalue"),
"traceback": content.get("traceback", []),
}
stderr_chunks.append("\n".join(error["traceback"]))
elif msg_type == "status" and content.get("execution_state") == "idle":
break
return {
"success": error is None,
"execution_state": "idle",
"stdout": "".join(stdout_chunks),
"stderr": "".join(stderr_chunks),
"display_data": display_data,
"error": error,
}
# ── Flask App ───────────────────────────────────────────────────
app = Flask(__name__)
@app.route("/")
def index():
html = """
HF VM Studio
VM
HF VM Studio
Agent-native cloud workbench on a cheap Hugging Face Space
Prompt to backend. Running, remembered, deployable.
HF VM Studio turns a Hugging Face Space into a prompt-to-backend factory, memory vault, notebook runtime, and deployment bridge. The primitive is simple: prompt -> files -> process -> proxy URL -> memory receipt -> deploy action.
$ python3 app.py ✓ persistent Jupyter kernel ✓ shell cells and background processes ✓ /apps/<id>/proxy live endpoint ✓ memory saved from every meaningful run
--apps
--memories
--processes
VM Workbench
Shell, Python cells, background processes, logs, previews, and deploy controls from one protected browser surface.
Agent Builder
Prompt a backend, write files to disk, start it on an internal port, then preview it through the Space proxy.
Execution Memory
Commands, notebooks, LLM output, generated apps, and deployments become searchable memory.
Proof Receipts
Every important action gets prompt hashes, file hashes, command metadata, app URLs, model info, and timestamps.
"""
return Response(html, mimetype="text/html")
@app.route("/api")
def api_index():
return jsonify({
"status": "running",
"message": "HF VM Studio",
"auth_required": True,
"endpoints": {
"GET /status": "Agent status & uptime",
"GET /logs": "Recent logs",
"GET /settings": "Runtime settings with secrets redacted",
"POST /settings": "Update cwd, env, LLM, and deploy settings",
"GET /memory": "List saved memories",
"POST /memory": "Save a memory",
"POST /memory/search": "Search saved memories",
"GET /receipts": "List provenance receipts",
"POST /receipts/search": "Search provenance receipts",
"GET /receipts/": "Inspect one receipt",
"GET /tasks": "List tasks",
"POST /execute": "Execute command",
"POST /execute/background": "Launch a background shell command",
"GET /processes": "List background processes",
"POST /kernel/execute": "Execute code in a persistent Jupyter kernel",
"POST /kernel/restart": "Restart the Jupyter kernel",
"POST /notebook/run": "Run a multi-cell notebook through the kernel",
"POST /llm": "Run an OpenAI-compatible LLM request",
"POST /api/v1/llm/infer": "Inference mesh — mode-based routed LLM with cost/latency/receipt",
"GET /apps": "List generated backend apps",
"POST /apps": "Create a generated backend app from files",
"POST /agent/build": "Ask the configured LLM to generate a backend app",
"POST /apps//start": "Start a generated backend app",
"POST /apps//stop": "Stop a generated backend app",
"GET /apps//proxy/...": "Proxy to the running backend app",
"GET /stripe/config": "Stripe publishable key + app origin (public)",
"POST /stripe/checkout": "Create a Stripe Checkout session",
"POST /stripe/webhook": "Stripe webhook handler",
"GET /wallet/nonce": "Get challenge nonce for wallet signature",
"POST /wallet/connect": "Connect MetaMask or Phantom wallet",
"GET /wallet/": "Get wallet balance and info",
"GET /wallet//history": "Token transaction history",
"GET /tokens/leaderboard": "Token balance leaderboard",
"POST /tokens/buy": "Buy token packs via Stripe",
"POST /tokens/launch": "Launch an SPL token on Solana (costs tokens)",
"GET /tokens/launched": "List tokens launched by a wallet",
"POST /claimos/evaluate": "Create/evaluate a claim: evidence + probability state + receipt",
"GET /claimos/": "Get full claim state with evidence and contradictions",
"POST /claimos//contradictions": "Run contradiction scan on a claim",
"GET /claimos//greeks": "Compute Claim Greeks (Δ, Θ, Γ, V, K)",
"GET /claimos//liquidity": "Compute finance readiness / liquidity score",
"POST /claimos//assess": "LLM-powered evidence quality assessment (auto-rates strength)",
"GET /claimos//appraise": "Full legal appraisal report via LLM",
"GET /tokens/verify/": "On-chain Solana token mint verification via RPC",
"POST /pixelator/ingest": "Ingest HTML → glyph units (costs tokens)",
"GET /pixelator/page//glyphs": "Get glyph units for a page",
"GET /pixelator/page//activation": "Page activation summary with glyph stats",
"GET /pixelator/website//top-glyphs": "Highest-value glyphs across a website",
"POST /pixelator/learn": "Retrain DOM weights and lexicon from actual page results",
"GET /costs": "Get all token costs (DB-backed, no hardcoded values)",
"POST /costs": "Update a token cost (admin)",
"GET /crawler/targets": "List crawl target websites (GA-RL population)",
"POST /crawler/targets": "Register a new crawl target website",
"POST /crawler/queue": "Enqueue URL into rotator buffer",
"GET /crawler/queue": "List crawl queue",
"POST /crawler/ingest": "Run one RL crawl step: fetch + pixelate + reward",
"GET /crawler/results": "Crawl results with glyph metrics",
"POST /crawler/evolve": "Run one GA generation on target population",
"GET /crawler/policy": "Get RL Q-table policy state",
"GET /finance/collateral": "Underwriting proof: revenue, deferred revenue, token velocity",
"GET /finance/revenue": "Revenue ledger with period/source breakdown",
"POST /finance/reconcile": "Reconcile Stripe sessions with token credits",
"POST /finance/rollback": "Rollback a transaction by tx_id",
"POST /deploy/vercel": "Deploy a project directory with Vercel CLI",
"POST /deploy/netlify": "Deploy a project directory with Netlify CLI",
"GET /terminal": "Web terminal UI",
},
})
@app.route("/status")
def get_status():
return jsonify({
"running": True,
"start_time": state.get("start_time"),
"uptime": get_uptime(),
"scheduled_tasks": len(schedule.jobs),
"executed_tasks_count": len(state.get("executed_tasks", [])),
"background_processes": len(processes),
"apps": len(apps),
"receipts": len(receipts),
"memories": len([m for m in memories.values() if not m.get("tombstone_at")]),
"kernel_running": kernel_manager is not None,
"cwd": str(DEFAULT_CWD),
"runtime_cwd": runtime_cwd(),
"token_rewards": {k: v for k, v in TOKEN_REWARDS.items()},
"settings": redacted_settings(),
})
@app.route("/healthz")
def healthz():
return jsonify({"ok": True, "status": "healthy", "uptime": get_uptime()})
@app.route("/settings", methods=["GET"])
def get_settings():
auth = require_auth()
if auth:
return auth
return jsonify(redacted_settings())
@app.route("/settings", methods=["POST"])
def update_settings():
auth = require_auth()
if auth:
return auth
data = request.json or {}
with settings_lock:
if "cwd" in data:
settings["cwd"] = str(data["cwd"])
if "max_timeout" in data:
settings["max_timeout"] = int(data["max_timeout"])
if isinstance(data.get("env"), dict):
for key, value in data["env"].items():
key = str(key).strip()
if not key:
continue
if value is None or value == "":
settings["env"].pop(key, None)
else:
settings["env"][key] = str(value)
if isinstance(data.get("llm"), dict):
settings["llm"].update({k: str(v) for k, v in data["llm"].items() if v is not None})
if isinstance(data.get("deploy"), dict):
settings["deploy"].update({k: str(v) for k, v in data["deploy"].items() if v is not None})
save_settings()
os.environ.update(runtime_env())
try:
shutdown_kernel()
except Exception:
logger.exception("Failed to reset kernel after settings update")
add_memory(
title="Runtime settings updated",
content=json.dumps(redacted_settings(), indent=2),
source="settings",
tags=["settings", "runtime"],
metadata={"keys": list(data.keys())},
importance=0.65,
)
return jsonify(redacted_settings())
@app.route("/logs")
def get_logs():
auth = require_auth()
if auth:
return auth
if log_file.exists():
lines = log_file.read_text().splitlines()
return jsonify({"logs": lines[-100:]})
return jsonify({"logs": [], "message": "No logs yet"})
@app.route("/tasks", methods=["GET"])
def list_tasks():
auth = require_auth()
if auth:
return auth
return jsonify({"tasks": tasks})
@app.route("/execute", methods=["POST"])
def execute():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"exec:{request.remote_addr}", window=60, max_requests=20):
return rate_limit_response()
data = request.json or {}
cmd = _clamp_str(data.get("command", ""), max_len=8000).strip()
timeout = bounded_timeout(data.get("timeout", 60))
cwd = data.get("cwd")
if not cmd:
return jsonify({"error": "Missing command"}), 400
result = run_command(cmd, timeout, cwd=cwd)
add_memory(
title=f"Terminal command: {cmd[:80]}",
content=f"command: {cmd}\nstdout:\n{result.get('stdout','')}\nstderr:\n{result.get('stderr','')}",
source="terminal",
tags=["terminal", "command"],
metadata={"exit_code": result.get("exit_code"), "success": result.get("success"), "cwd": result.get("cwd")},
importance=0.6 if result.get("success") else 0.75,
)
state["executed_tasks"].append({
"command": cmd,
"timestamp": datetime.now(timezone.utc).isoformat(),
"success": result["success"],
})
state["executed_tasks"] = state["executed_tasks"][-1000:]
save_state()
receipt = create_receipt(
kind="command",
title=f"Shell command: {cmd[:80]}",
status="success" if result.get("success") else "failed",
command=cmd,
metadata={"result": result},
)
result["receipt_id"] = receipt["receipt_id"]
result["token_reward"] = maybe_credit(data, "shell_execute", TOKEN_REWARDS["shell_execute"])
return jsonify(result)
@app.route("/memory", methods=["GET"])
def list_memory():
auth = require_auth()
if auth:
return auth
limit = max(1, min(int(request.args.get("limit", 50)), 200))
active = [m for m in memories.values() if not m.get("tombstone_at")]
active.sort(key=lambda item: item.get("created_at", ""), reverse=True)
return jsonify({"memories": active[:limit], "count": len(active)})
@app.route("/memory", methods=["POST"])
def create_memory():
auth = require_auth()
if auth:
return auth
data = request.json or {}
content = _clamp_str(data.get("content", ""), max_len=50000).strip()
if not content:
return jsonify({"error": "Missing content"}), 400
item = add_memory(
title=_clamp_str(data.get("title") or "Manual memory", 256),
content=content,
source=_clamp_str(data.get("source") or "manual", 64),
tags=data.get("tags") if isinstance(data.get("tags"), list) else ["manual"],
metadata=data.get("metadata") if isinstance(data.get("metadata"), dict) else {},
importance=float(data.get("importance", 0.7)),
)
return jsonify(item), 201
@app.route("/memory/search", methods=["POST"])
def memory_search():
auth = require_auth()
if auth:
return auth
data = request.json or {}
query = _clamp_str(data.get("query", ""), max_len=2000).strip()
limit = max(1, min(int(data.get("limit", 8)), 50))
return jsonify({"query": query, "memories": search_memory(query, limit=limit)})
@app.route("/memory/", methods=["GET"])
def get_memory(memory_id):
auth = require_auth()
if auth:
return auth
item = memories.get(memory_id)
if not item:
return jsonify({"error": "Memory not found"}), 404
return jsonify(item)
@app.route("/memory/", methods=["DELETE"])
def delete_memory(memory_id):
auth = require_auth()
if auth:
return auth
item = memories.get(memory_id)
if not item or item.get("tombstone_at"):
return jsonify({"error": "Active memory not found"}), 404
item["tombstone_at"] = datetime.now(timezone.utc).isoformat()
save_memory()
return jsonify({"memory_id": memory_id, "status": "tombstoned"})
@app.route("/receipts", methods=["GET"])
def list_receipts():
auth = require_auth()
if auth:
return auth
limit = max(1, min(int(request.args.get("limit", 50)), 200))
with receipt_lock:
active = list(receipts.values())
active.sort(key=lambda item: item.get("created_at", ""), reverse=True)
return jsonify({"receipts": active[:limit], "count": len(active)})
@app.route("/receipts/search", methods=["POST"])
def receipt_search():
auth = require_auth()
if auth:
return auth
data = request.json or {}
query = _clamp_str(data.get("query", ""), max_len=2000).strip()
limit = max(1, min(int(data.get("limit", 20)), 100))
return jsonify({"query": query, "receipts": search_receipts(query, limit=limit)})
@app.route("/receipts/", methods=["GET"])
def get_receipt(receipt_id):
auth = require_auth()
if auth:
return auth
item = receipts.get(receipt_id)
if not item:
return jsonify({"error": "Receipt not found"}), 404
return jsonify(item)
@app.route("/llm", methods=["POST"])
def run_llm():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"llm:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
data = request.json or {}
prompt = _clamp_str(data.get("prompt", ""), max_len=20000).strip()
if not prompt:
return jsonify({"error": "Missing prompt"}), 400
try:
result = call_llm(
prompt,
system=str(data.get("system") or ""),
api_base=data.get("api_base"),
model=data.get("model"),
api_key=data.get("api_key"),
temperature=data.get("temperature", 0.3),
max_tokens=data.get("max_tokens", 800),
timeout=data.get("timeout", 60),
)
except ValueError as e:
return jsonify({"error": str(e)}), 400
except Exception as e:
return jsonify({"error": str(e)}), 502
add_memory(
title=f"LLM run: {result['model']}",
content=f"prompt:\n{prompt}\n\nresponse:\n{result.get('response') or json.dumps(result.get('raw', {}))[:4000]}",
source="llm",
tags=["llm", result["model"]],
metadata={"api_base": result["api_base"], "model": result["model"]},
importance=0.8,
)
receipt = create_receipt(
kind="llm",
title=f"LLM run: {result['model']}",
status="completed",
prompt=prompt,
model={"api_base": result["api_base"], "model": result["model"]},
metadata={"response_hash": sha256_text(result.get("response") or json.dumps(result.get("raw", {})))},
)
result["receipt_id"] = receipt["receipt_id"]
return jsonify(result)
# ── Inference Mesh ──────────────────────────────────────────────
LLM_ROUTES = {
"fast": {"provider": "groq", "model": "llama-3.1-8b-instant", "api_base": "https://api.groq.com/openai/v1"},
"cheap": {"provider": "groq", "model": "llama-3.1-8b-instant", "api_base": "https://api.groq.com/openai/v1"},
"quality": {"provider": "openrouter", "model": "openai/gpt-4o", "api_base": "https://openrouter.ai/api/v1"},
"local": {"provider": "ollama", "model": "llama3.1:8b", "api_base": "http://localhost:11434/v1"},
"coding": {"provider": "groq", "model": "llama-3.3-70b-versatile", "api_base": "https://api.groq.com/openai/v1"},
"json": {"provider": "groq", "model": "llama-3.1-8b-instant", "api_base": "https://api.groq.com/openai/v1"},
"private": {"provider": "ollama", "model": "llama3.1:8b", "api_base": "http://localhost:11434/v1"},
}
COST_PER_1K_TOKENS: Dict[str, float] = {
"llama-3.1-8b-instant": 0.00005,
"llama-3.3-70b-versatile": 0.00059,
"openai/gpt-4o": 0.005,
"openai/gpt-4o-mini": 0.00015,
"llama3.1:8b": 0.0,
}
def resolve_api_key(provider: str) -> Optional[str]:
env = settings.get("env", {})
if provider == "groq":
return env.get("GROQ_API_KEY") or env.get("LLM_API_KEY") or os.environ.get("GROQ_API_KEY") or os.environ.get("LLM_API_KEY")
if provider == "openrouter":
return env.get("OPENROUTER_API_KEY") or env.get("LLM_API_KEY") or os.environ.get("OPENROUTER_API_KEY") or os.environ.get("LLM_API_KEY")
if provider == "ollama":
return "ollama" # Ollama doesn't need a key
return env.get("LLM_API_KEY") or os.environ.get("LLM_API_KEY")
def estimate_cost(model: str, input_tokens: int, output_tokens: int) -> float:
rate = COST_PER_1K_TOKENS.get(model, 0.0001)
return round((input_tokens + output_tokens) / 1000 * rate, 6)
def route_llm_infer(data: dict) -> dict:
mode = str(data.get("mode", "cheap")).strip().lower()
task = _clamp_str(data.get("task", ""), max_len=20000).strip()
messages = data.get("messages", [])
if messages:
messages = [
{"role": _clamp_str(m.get("role", "user"), 20), "content": _clamp_str(m.get("content", ""), 20000)}
for m in messages
]
if not messages and task:
messages = [{"role": "user", "content": task}]
if not messages:
raise ValueError("Provide messages or task")
route = LLM_ROUTES.get(mode)
if not route:
route = LLM_ROUTES["cheap"]
provider = route["provider"]
model = str(data.get("model") or route["model"])
api_base = str(data.get("api_base") or route["api_base"])
api_key = resolve_api_key(provider)
if provider != "ollama" and not api_key:
# Fallback chain: groq -> openrouter -> error
fallback_order = ["groq", "openrouter"]
for fb in fallback_order:
if fb == provider:
continue
fb_key = resolve_api_key(fb)
if fb_key:
provider = fb
model = LLM_ROUTES[fb]["model"]
api_base = LLM_ROUTES[fb]["api_base"]
api_key = fb_key
break
if not api_key:
raise ValueError(f"No API key available for provider {provider}")
system = str(data.get("system") or "")
if mode == "json":
system = system + "\nReturn only valid JSON. No markdown fences." if system else "Return only valid JSON. No markdown fences."
if mode == "coding":
system = system + "\nYou are an expert programmer. Write clean, production-ready code." if system else "You are an expert programmer. Write clean, production-ready code."
prompt = ""
if messages and isinstance(messages, list) and messages[-1].get("role") == "user":
prompt = str(messages[-1].get("content", ""))
started = time.time()
llm_result = call_llm(
prompt,
system=system,
api_base=api_base,
model=model,
api_key=api_key,
temperature=float(data.get("temperature", 0.25)),
max_tokens=int(data.get("max_tokens", 1800)),
timeout=data.get("timeout", 90),
response_format={"type": "json_object"} if mode == "json" else None,
)
latency_ms = round((time.time() - started) * 1000, 2)
raw = llm_result.get("raw", {})
usage = raw.get("usage", {})
input_tokens = usage.get("prompt_tokens", 0) or usage.get("input_tokens", 0) or len(prompt) // 4
output_tokens = usage.get("completion_tokens", 0) or usage.get("output_tokens", 0) or len(str(llm_result.get("response", ""))) // 4
cost_usd = estimate_cost(model, input_tokens, output_tokens)
add_memory(
title=f"Inference mesh [{mode}]: {model}",
content=f"task: {task}\nprompt: {prompt[:500]}\nresponse: {str(llm_result.get('response', ''))[:2000]}",
source="inference-mesh",
tags=["llm", provider, model, mode],
metadata={"provider": provider, "model": model, "mode": mode, "latency_ms": latency_ms, "cost_usd": cost_usd},
importance=0.85,
)
# Generate Proof of Inference for every mesh call
proof = generate_inference_proof(
model=model,
prompt=prompt,
response=str(llm_result.get("response", "")),
provider=provider,
api_base=api_base,
latency_ms=latency_ms,
input_tokens=input_tokens,
output_tokens=output_tokens,
)
receipt = create_receipt(
kind="inference-mesh",
title=f"Inference mesh [{mode}]: {model}",
status="completed",
prompt=prompt,
model={"provider": provider, "model": model, "api_base": api_base, "mode": mode},
metadata={
"latency_ms": latency_ms,
"cost_usd": cost_usd,
"input_tokens": input_tokens,
"output_tokens": output_tokens,
"route_reason": f"mode={mode} -> provider={provider} -> model={model}",
"proof_id": proof["proof_id"],
},
)
return {
"answer": llm_result.get("response", ""),
"provider": provider,
"model": model,
"latency_ms": latency_ms,
"cost_usd": cost_usd,
"receipt_hash": receipt["receipt_id"],
"proof": proof,
"route_reason": f"mode={mode} -> provider={provider} -> model={model}",
"input_tokens": input_tokens,
"output_tokens": output_tokens,
"api_base": api_base,
"raw": raw,
}
# Notebook-exposed helper (injected into kernel globals)
def llm_infer(mode: str = "cheap", task: str = "", messages: Optional[list] = None, **kwargs) -> dict:
"""Cell-friendly inference mesh call. Returns answer + metadata."""
payload = {"mode": mode, "task": task, "messages": messages or [], **kwargs}
return route_llm_infer(payload)
@app.route("/api/v1/llm/infer", methods=["POST"])
def api_llm_infer():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"llm:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
data = request.json or {}
try:
result = route_llm_infer(data)
except ValueError as e:
return jsonify({"error": str(e)}), 400
except Exception as e:
return jsonify({"error": str(e)}), 502
return jsonify(result)
@app.route("/apps", methods=["GET"])
def list_apps():
auth = require_auth()
if auth:
return auth
return jsonify({"apps": [redact_app(item) for item in apps.values()]})
@app.route("/apps", methods=["POST"])
def create_app():
auth = require_auth()
if auth:
return auth
result = create_generated_app(request.json or {})
if result.get("error"):
return jsonify(result), 400
receipt = create_receipt(
kind="generated-app",
title=f"Generated app: {result['name']}",
status=result.get("status", "created"),
prompt=str((request.json or {}).get("prompt") or ""),
app_record=result,
command=result.get("start_command", ""),
metadata={"source": "manual-app-create"},
)
result["receipt_id"] = receipt["receipt_id"]
attach_receipt_to_app(result["app_id"], receipt["receipt_id"])
return jsonify(result), 201
@app.route("/apps/", methods=["GET"])
def get_app(app_id):
auth = require_auth()
if auth:
return auth
item = apps.get(app_id)
if not item:
return jsonify({"error": "App not found"}), 404
return jsonify(redact_app(item))
@app.route("/apps//files", methods=["GET"])
def get_app_files(app_id):
auth = require_auth()
if auth:
return auth
item = apps.get(app_id)
if not item:
return jsonify({"error": "App not found"}), 404
app_dir = Path(item["path"])
files = []
for file_name in item.get("files", []):
file_path = safe_app_file(app_dir, file_name)
files.append({"path": file_name, "content": file_path.read_text() if file_path.exists() else ""})
return jsonify({"app_id": app_id, "files": files})
@app.route("/apps//start", methods=["POST"])
def start_app(app_id):
auth = require_auth()
if auth:
return auth
result, status = start_generated_app(app_id)
if not result.get("error"):
receipt = create_receipt(
kind="app-start",
title=f"App started: {result.get('name', app_id)}",
status=result.get("status", "running"),
app_record=result,
command=result.get("start_command", ""),
process={"pid": result.get("pid"), "status": result.get("status"), "stdout": result.get("stdout", ""), "stderr": result.get("stderr", "")},
metadata={"app_id": app_id, "proxy_url": result.get("proxy_url")},
)
result["start_receipt_id"] = receipt["receipt_id"]
return jsonify(result), status
@app.route("/apps//stop", methods=["POST"])
def stop_app(app_id):
auth = require_auth()
if auth:
return auth
result = stop_generated_app(app_id)
if result.get("error"):
return jsonify(result), 404
return jsonify(result)
@app.route("/apps//proxy/", defaults={"subpath": ""}, methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"])
@app.route("/apps//proxy/", methods=["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"])
def proxy_app(app_id, subpath):
auth = require_auth()
if auth:
return auth
item = apps.get(app_id)
if not item:
return jsonify({"error": "App not found"}), 404
target = f"http://127.0.0.1:{int(item['port'])}/{subpath}"
try:
upstream = requests.request(
request.method,
target,
params=request.args,
data=request.get_data(),
headers={k: v for k, v in request.headers if k.lower() not in {"host", "content-length"}},
timeout=30,
allow_redirects=False,
)
except Exception as e:
return Response(f"App proxy error: {e}", status=502, mimetype="text/plain")
excluded = {"content-encoding", "content-length", "transfer-encoding", "connection"}
headers = [(k, v) for k, v in upstream.headers.items() if k.lower() not in excluded]
return Response(upstream.content, status=upstream.status_code, headers=headers)
@app.route("/agent/build", methods=["POST"])
def agent_build_app():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"build:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
prompt = _clamp_str(data.get("prompt", ""), max_len=12000).strip()
if not prompt:
return jsonify({"error": "Missing prompt"}), 400
system = (
"You are an expert backend app generator for a Hugging Face Spaces Linux VM. "
"Return only valid JSON with keys: name, description, start_command, files. "
"files must be an array of objects with path and content. "
"For Python web apps, use Flask, read PORT from os.environ, bind host 0.0.0.0, and keep dependencies to installed packages when possible. "
"Do not include markdown fences."
)
try:
llm_result = call_llm(
prompt,
system=system,
temperature=float(data.get("temperature", 0.25)),
max_tokens=int(data.get("max_tokens", 2600)),
timeout=data.get("timeout", 120),
response_format={"type": "json_object"},
)
try:
app_spec = parse_llm_json(llm_result["response"])
except Exception as first_error:
repair = call_llm(
"Repair this into strict valid JSON only. It must contain name, description, start_command, and files. "
"Every files[].content value must be a properly escaped JSON string.\n\n"
f"{llm_result['response']}",
system=system,
temperature=0,
max_tokens=int(data.get("max_tokens", 2600)),
timeout=data.get("timeout", 120),
response_format={"type": "json_object"},
)
llm_result = repair
try:
app_spec = parse_llm_json(llm_result["response"])
except Exception as repair_error:
app_spec = fallback_app_spec(prompt, reason=f"LLM JSON repair failed: {first_error}; {repair_error}")
except ValueError as e:
return jsonify({"error": str(e)}), 400
except Exception as e:
return jsonify({"error": f"LLM app generation failed: {e}"}), 502
app_spec = normalize_generated_app_spec(app_spec, prompt=prompt)
created = create_generated_app(app_spec)
if created.get("error"):
return jsonify({"error": created["error"], "llm_response": llm_result.get("response")}), 400
if bool(data.get("run", True)):
started, status = start_generated_app(created["app_id"])
created.update(started)
add_memory(
title=f"LLM-built backend: {created['name']}",
content=f"prompt:\n{prompt}\n\napp:\n{json.dumps(created, indent=2)}",
source="llm-app-builder",
tags=["llm", "backend", "generated-app"],
metadata={"app_id": created["app_id"], "model": llm_result["model"]},
importance=0.9,
)
receipt = create_receipt(
kind="prompt-to-backend",
title=f"Prompt-to-backend: {created['name']}",
status=created.get("status", "created"),
prompt=prompt,
app_record=created,
model={"api_base": llm_result["api_base"], "model": llm_result["model"]},
command=created.get("start_command", ""),
metadata={"loop": "prompt -> files -> process -> proxy -> memory", "llm_response_hash": sha256_text(llm_result.get("response", ""))},
)
created["receipt_id"] = receipt["receipt_id"]
attach_receipt_to_app(created["app_id"], receipt["receipt_id"])
created["token_reward"] = maybe_credit(data, "agent_build", TOKEN_REWARDS["agent_build"])
return jsonify({"app": created, "receipt": receipt, "llm": {"api_base": llm_result["api_base"], "model": llm_result["model"]}}), 201
def deploy_command(provider: str, data: dict) -> tuple[str, str]:
deploy_cfg = settings.get("deploy", {})
if provider == "vercel":
token = settings.get("env", {}).get("VERCEL_TOKEN") or os.environ.get("VERCEL_TOKEN")
if not token:
raise ValueError("VERCEL_TOKEN is not configured in settings.")
project_dir = str(data.get("project_dir") or deploy_cfg.get("vercel_project_dir") or runtime_cwd())
prod = bool(data.get("prod", True))
cmd = f"vercel deploy --yes {'--prod' if prod else ''} --token \"$VERCEL_TOKEN\""
return cmd, project_dir
if provider == "netlify":
token = settings.get("env", {}).get("NETLIFY_AUTH_TOKEN") or os.environ.get("NETLIFY_AUTH_TOKEN")
if not token:
raise ValueError("NETLIFY_AUTH_TOKEN is not configured in settings.")
project_dir = str(data.get("project_dir") or deploy_cfg.get("netlify_project_dir") or runtime_cwd())
publish_dir = str(data.get("publish_dir") or deploy_cfg.get("netlify_publish_dir") or project_dir)
prod = bool(data.get("prod", True))
cmd = f"netlify deploy --dir \"{publish_dir}\" {'--prod' if prod else ''} --auth \"$NETLIFY_AUTH_TOKEN\""
if data.get("site"):
cmd += f" --site \"{data['site']}\""
return cmd, project_dir
raise ValueError(f"Unsupported provider: {provider}")
# ── Stripe ──────────────────────────────────────────────────────
def get_app_origin() -> str:
"""Return the full HTTPS app origin for Stripe redirects."""
configured = settings.get("env", {}).get("APP_ORIGIN") or os.environ.get("APP_ORIGIN", "")
if configured:
return configured.rstrip("/")
# Fallback to request origin if available
if request:
host = request.headers.get("X-Forwarded-Host") or request.headers.get("Host", "")
proto = request.headers.get("X-Forwarded-Proto", "https")
if host:
return f"{proto}://{host}"
return "https://localhost"
@app.route("/stripe/config", methods=["GET"])
def stripe_config():
"""Public endpoint returning safe Stripe config (publishable key + origin)."""
pk = settings.get("env", {}).get("STRIPE_PUBLISHABLE_KEY") or os.environ.get("STRIPE_PUBLISHABLE_KEY", "")
return jsonify({
"publishable_key": pk,
"origin": get_app_origin(),
"status": "ready" if pk else "missing_publishable_key",
})
@app.route("/stripe/checkout", methods=["POST"])
def stripe_checkout():
auth = require_auth()
if auth:
return auth
import stripe as stripe_lib
sk = settings.get("env", {}).get("STRIPE_SECRET_KEY") or os.environ.get("STRIPE_SECRET_KEY", "")
if not sk:
return jsonify({"error": "Stripe secret key not configured"}), 400
stripe_lib.api_key = sk
data = request.json or {}
origin = get_app_origin()
success_url = f"{origin}/?session_id={{CHECKOUT_SESSION_ID}}#success"
cancel_url = f"{origin}/?canceled=true"
try:
session = stripe_lib.checkout.Session.create(
payment_method_types=["card"],
line_items=[{
"price_data": {
"currency": str(data.get("currency", "usd")),
"product_data": {"name": str(data.get("product_name", "HF VM Studio Service"))},
"unit_amount": int(data.get("amount_cents", 500)),
},
"quantity": int(data.get("quantity", 1)),
}],
mode="payment",
success_url=success_url,
cancel_url=cancel_url,
metadata={
"source": "hf-vm-studio",
"user_tag": str(data.get("user_tag", "")),
},
)
receipt = create_receipt(
kind="stripe-checkout",
title=f"Stripe checkout created: {data.get('product_name', 'Service')}",
status="created",
command=f"checkout_session:{session.id}",
metadata={
"session_id": session.id,
"amount_cents": data.get("amount_cents", 500),
"currency": data.get("currency", "usd"),
"origin": origin,
},
)
return jsonify({
"session_id": session.id,
"url": session.url,
"receipt_id": receipt["receipt_id"],
})
except Exception as e:
return jsonify({"error": str(e)}), 502
@app.route("/stripe/webhook", methods=["POST"])
def stripe_webhook():
import stripe as stripe_lib
sk = settings.get("env", {}).get("STRIPE_SECRET_KEY") or os.environ.get("STRIPE_SECRET_KEY", "")
if not sk:
return jsonify({"error": "Stripe secret key not configured"}), 400
payload = request.get_data(as_text=True)
sig_header = request.headers.get("Stripe-Signature", "")
webhook_secret = settings.get("env", {}).get("STRIPE_WEBHOOK_SECRET") or os.environ.get("STRIPE_WEBHOOK_SECRET", "")
try:
if webhook_secret:
event = stripe_lib.Webhook.construct_event(payload, sig_header, webhook_secret)
else:
event = json.loads(payload)
except Exception as e:
return jsonify({"error": f"Webhook verification failed: {e}"}), 400
event_type = event.get("type", "unknown")
obj = event.get("data", {}).get("object", {})
session_id = str(obj.get("id", ""))
now = datetime.now(timezone.utc).isoformat()
period = now[:7]
# ── Idempotency guard ─────────────────────────────────────────
with token_lock:
with _db() as conn:
processed = conn.execute("SELECT session_id, tx_id FROM stripe_sessions WHERE session_id = ?", (session_id,)).fetchone()
if processed:
logger.info("Stripe webhook idempotent skip: session=%s already processed with tx=%s", session_id, processed["tx_id"])
return jsonify({"received": True, "type": event_type, "idempotent": True, "session_id": session_id}), 200
# ── Token purchase fulfillment ──────────────────────────────
credited = None
if event_type in ("checkout.session.completed", "checkout.session.async_payment_succeeded"):
metadata = obj.get("metadata", {})
if metadata.get("source") == "hf-vm-studio" and metadata.get("wallet"):
wallet = str(metadata["wallet"]).lower()
# Integer tokens only — no floats for money (C53)
tokens_str = str(metadata.get("tokens", "0")).strip()
try:
tokens = int(tokens_str)
except ValueError:
tokens = 0
amount_cents = int(obj.get("amount_total", 0))
currency = str(obj.get("currency", "usd")).lower()
pack = str(metadata.get("pack", "unknown"))
if tokens > 0:
tx_id = f"stripe_{session_id}"
credited = credit_tokens(
wallet, tokens,
reason=f"stripe_purchase:{pack}",
metadata={"session_id": session_id, "pack": pack, "currency": currency},
idempotency_key=tx_id,
revenue_cents=amount_cents,
)
# Record processed session for idempotency
with token_lock:
with _db() as conn:
conn.execute(
"INSERT INTO stripe_sessions (session_id, event_type, status, amount_cents, currency, wallet, pack, tokens, processed_at, tx_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(session_id, event_type, "completed", amount_cents, currency, wallet, pack, tokens, now, tx_id),
)
# Revenue ledger entry
rev_id = f"rev_{uuid.uuid4().hex}"
conn.execute(
"INSERT INTO revenue (revenue_id, source, session_id, amount_cents, currency, period, wallet, created_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
(rev_id, "stripe_webhook", session_id, amount_cents, currency, period, wallet, now, json.dumps({"pack": pack, "tokens": tokens, "event_type": event_type})),
)
conn.commit()
add_memory(
title=f"Stripe webhook: {event_type}",
content=json.dumps(event, indent=2)[:5000],
source="stripe-webhook",
tags=["stripe", event_type],
metadata={"session_id": session_id, "event_type": event_type, "tokens_credited": credited},
importance=0.85,
)
create_receipt(
kind="stripe-webhook",
title=f"Stripe webhook: {event_type}",
status="received",
command=f"webhook:{event_type}:{session_id}",
metadata={"session_id": session_id, "event_type": event_type, "tokens_credited": credited},
)
return jsonify({"received": True, "type": event_type, "tokens_credited": credited, "session_id": session_id})
@app.route("/deploy/vercel", methods=["POST"])
def deploy_vercel():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"deploy:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
data = request.json or {}
try:
cmd, cwd = deploy_command("vercel", data)
except ValueError as e:
return jsonify({"error": str(e)}), 400
result = launch_background_process(cmd, timeout=int(data.get("timeout", 0) or 0), cwd=cwd)
result["provider"] = "vercel"
receipt = create_receipt(
kind="deployment",
title="Vercel deployment launched",
status="launched",
command=redact_command_secret(cmd, os.environ.get("VERCEL_TOKEN", "")),
process=result,
deployment={"provider": "vercel", "project_dir": cwd, "prod": bool(data.get("prod", True))},
metadata={"process_id": result.get("process_id")},
)
result["receipt_id"] = receipt["receipt_id"]
result["token_reward"] = maybe_credit(data, "deploy", TOKEN_REWARDS["deploy"])
return jsonify(result), 202
@app.route("/deploy/netlify", methods=["POST"])
def deploy_netlify():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"deploy:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
data = request.json or {}
try:
cmd, cwd = deploy_command("netlify", data)
except ValueError as e:
return jsonify({"error": str(e)}), 400
result = launch_background_process(cmd, timeout=int(data.get("timeout", 0) or 0), cwd=cwd)
result["provider"] = "netlify"
receipt = create_receipt(
kind="deployment",
title="Netlify deployment launched",
status="launched",
command=redact_command_secret(cmd, os.environ.get("NETLIFY_AUTH_TOKEN", "")),
process=result,
deployment={"provider": "netlify", "project_dir": cwd, "publish_dir": data.get("publish_dir"), "prod": bool(data.get("prod", True))},
metadata={"process_id": result.get("process_id")},
)
result["receipt_id"] = receipt["receipt_id"]
result["token_reward"] = maybe_credit(data, "deploy", TOKEN_REWARDS["deploy"])
return jsonify(result), 202
@app.route("/execute/background", methods=["POST"])
def execute_background():
auth = require_auth()
if auth:
return auth
data = request.json or {}
cmd = data.get("command", "").strip()
timeout = int(data.get("timeout", 0) or 0)
cwd = data.get("cwd")
if not cmd:
return jsonify({"error": "Missing command"}), 400
return jsonify(launch_background_process(cmd, timeout=timeout, cwd=cwd)), 202
@app.route("/processes", methods=["GET"])
def list_processes():
auth = require_auth()
if auth:
return auth
return jsonify({"processes": [redact_process(p) for p in processes.values()]})
@app.route("/processes/", methods=["GET"])
def get_process(process_id):
auth = require_auth()
if auth:
return auth
proc = processes.get(process_id)
if not proc:
return jsonify({"error": "Process not found"}), 404
return jsonify(redact_process(proc))
@app.route("/processes/", methods=["DELETE"])
def stop_process(process_id):
auth = require_auth()
if auth:
return auth
proc = processes.get(process_id)
if not proc:
return jsonify({"error": "Process not found"}), 404
popen = proc.get("_popen")
if popen and proc.get("status") == "running":
try:
if hasattr(os, "killpg"):
os.killpg(os.getpgid(popen.pid), signal.SIGTERM)
else:
popen.terminate()
proc["status"] = "stopping"
except Exception as e:
return jsonify({"error": str(e)}), 500
return jsonify(redact_process(proc))
@app.route("/kernel/status", methods=["GET"])
def kernel_status():
auth = require_auth()
if auth:
return auth
return jsonify({
"kernel_running": kernel_manager is not None,
"cwd": str(DEFAULT_CWD),
"kernel_name": "python3",
})
@app.route("/kernel/execute", methods=["POST"])
def kernel_execute():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"kernel:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
data = request.json or {}
code = _clamp_str(data.get("code", ""), max_len=50000)
timeout = data.get("timeout", 60)
if not code.strip():
return jsonify({"error": "Missing code"}), 400
result = execute_kernel_code(code, timeout=timeout)
add_memory(
title="Kernel execution",
content=f"code:\n{code}\nstdout:\n{result.get('stdout','')}\nstderr:\n{result.get('stderr','')}",
source="kernel",
tags=["jupyter", "kernel"],
metadata={"success": result.get("success"), "display_data": bool(result.get("display_data"))},
importance=0.7,
)
state["executed_tasks"].append({
"command": "kernel.execute",
"timestamp": datetime.now(timezone.utc).isoformat(),
"success": result["success"],
})
state["executed_tasks"] = state["executed_tasks"][-1000:]
save_state()
receipt = create_receipt(
kind="kernel",
title="Jupyter kernel execution",
status="success" if result.get("success") else "failed",
command="kernel.execute",
metadata={"code_hash": sha256_text(code), "result": result},
)
result["receipt_id"] = receipt["receipt_id"]
result["token_reward"] = maybe_credit(data, "kernel_execute", TOKEN_REWARDS["kernel_execute"])
return jsonify(result)
@app.route("/kernel/restart", methods=["POST"])
def kernel_restart():
auth = require_auth()
if auth:
return auth
shutdown_kernel()
get_kernel()
return jsonify({"kernel_running": True, "status": "restarted"})
@app.route("/notebook/run", methods=["POST"])
def notebook_run():
auth = require_auth()
if auth:
return auth
if not _rate_check(f"notebook:{request.remote_addr}", window=60, max_requests=15):
return rate_limit_response()
import nbformat
data = request.json or {}
cells = data.get("cells")
if cells is None and data.get("code"):
cells = [data["code"]]
if not isinstance(cells, list) or not cells:
return jsonify({"error": "Provide cells: [...] or code: '...'"}), 400
cells = [_clamp_str(c, max_len=50000) for c in cells]
if len(cells) > 50:
return jsonify({"error": "Too many cells (max 50)"}), 400
timeout = data.get("timeout", 60)
notebook_id = f"nb_{uuid.uuid4().hex[:12]}"
results = []
nb = nbformat.v4.new_notebook()
nb_cells = []
for source in cells:
source = str(source)
result = execute_kernel_code(source, timeout=timeout)
results.append(result)
output_text = ""
if result.get("stdout"):
output_text += result["stdout"]
if result.get("stderr"):
output_text += result["stderr"]
cell = nbformat.v4.new_code_cell(source=source)
if output_text:
cell.outputs = [nbformat.v4.new_output("stream", name="stdout", text=output_text)]
nb_cells.append(cell)
nb.cells = nb_cells
path = NOTEBOOK_DIR / f"{notebook_id}.ipynb"
nbformat.write(nb, path)
add_memory(
title=f"Notebook run: {notebook_id}",
content="\n\n".join([f"cell:\n{source}" for source in cells]),
source="notebook",
tags=["notebook", "jupyter"],
metadata={"notebook_id": notebook_id, "path": str(path), "success": all(r.get("success") for r in results)},
importance=0.75,
)
response = {
"notebook_id": notebook_id,
"path": str(path),
"success": all(r.get("success") for r in results),
"results": results,
}
receipt = create_receipt(
kind="notebook",
title=f"Notebook run: {notebook_id}",
status="success" if response["success"] else "failed",
command="notebook.run",
metadata={"notebook_id": notebook_id, "path": str(path), "cell_count": len(cells), "cells_hash": sha256_text(json.dumps(cells))},
)
response["receipt_id"] = receipt["receipt_id"]
response["token_reward"] = maybe_credit(data, "notebook_run", TOKEN_REWARDS["notebook_run"])
return jsonify(response)
@app.route("/terminal")
@app.route("/colab")
def terminal_ui():
auth = require_auth()
if auth:
return Response(
"Unauthorized. Open /terminal?token=YOUR_TERMINAL_AGENT_TOKEN",
status=401,
mimetype="text/plain",
)
return render_template("terminal.html",
brand_name="HF VM Studio",
brand_tag="Prompt-to-Backend Factory",
brand_emoji="◆",
)
# ── Wallet & Tokens ─────────────────────────────────────────────
@app.route("/wallet/nonce", methods=["GET"])
def wallet_nonce():
"""Get a challenge nonce for wallet signature."""
if not _rate_check(f"nonce:{request.remote_addr}", window=60, max_requests=20):
return rate_limit_response()
n = _nonce()
return jsonify({"nonce": n, "message": f"HF VM Studio auth: {n}"})
def _is_valid_evm_address(addr: str) -> bool:
return bool(re.fullmatch(r"0x[a-f0-9]{40}", addr))
def _is_valid_solana_address(addr: str) -> bool:
try:
import base58
decoded = base58.b58decode(addr)
return len(decoded) == 32
except Exception:
return False
@app.route("/wallet/connect", methods=["POST"])
def wallet_connect():
"""Register a wallet connection with cryptographic signature verification."""
data = request.json or {}
raw_address = _clamp_str(data.get("address", ""), 128).strip()
provider = str(data.get("provider", "")).strip().lower()
signature = _clamp_str(data.get("signature", ""), 2048).strip()
nonce = _clamp_str(data.get("nonce", ""), 128).strip()
if not raw_address or not provider:
return jsonify({"error": "address and provider required"}), 400
if provider not in ("metamask", "phantom"):
return jsonify({"error": "provider must be metamask or phantom"}), 400
# EVM: lowercase; Solana: preserve base58 case
address = raw_address.lower() if provider == "metamask" else raw_address
if provider == "metamask" and not _is_valid_evm_address(address):
return jsonify({"error": "Invalid EVM address format"}), 400
if provider == "phantom" and not _is_valid_solana_address(address):
return jsonify({"error": "Invalid Solana address format"}), 400
if not _rate_check(f"wallet_connect:{request.remote_addr}", window=3600, max_requests=10):
return rate_limit_response()
if not signature or not nonce:
return jsonify({"error": "signature and nonce required"}), 400
# Verify signature
verified = False
if provider == "metamask":
verified = _verify_evm_signature(address, signature, nonce)
elif provider == "phantom":
verified = _verify_solana_signature(address, signature, nonce)
if not verified:
return jsonify({"error": "Signature verification failed"}), 401
now = datetime.now(timezone.utc).isoformat()
with wallet_lock:
with _db() as conn:
existing = conn.execute("SELECT address FROM wallets WHERE address = ?", (address,)).fetchone()
is_new = existing is None
conn.execute(
"INSERT OR REPLACE INTO wallets (address, provider, signature, nonce, connected_at, last_seen) VALUES (?, ?, ?, ?, COALESCE((SELECT connected_at FROM wallets WHERE address = ?), ?), ?)",
(address, provider, signature, nonce, address, now, now),
)
conn.commit()
welcome_bonus = 0
if is_new:
welcome_bonus = 1000 # 1000 integer tokens welcome bonus
credit_tokens(address, welcome_bonus, "welcome_bonus")
return jsonify({
"wallet": address,
"provider": provider,
"verified": True,
"balance": get_balance(address),
"welcome_bonus": welcome_bonus,
})
@app.route("/wallet/", methods=["GET"])
def wallet_info(address):
"""Get wallet balance and connection info."""
addr = _normalize_wallet(address)
with wallet_lock:
with _db() as conn:
row = conn.execute("SELECT * FROM wallets WHERE address = ?", (addr,)).fetchone()
if not row:
return jsonify({"wallet": addr, "balance": 0, "connected": False}), 404
return jsonify({
"wallet": addr,
"balance": get_balance(addr),
"provider": row["provider"],
"connected_at": row["connected_at"],
"last_seen": row["last_seen"],
"connected": True,
})
@app.route("/wallet//history", methods=["GET"])
def wallet_history(address):
"""Get token transaction history for a wallet."""
addr = _normalize_wallet(address)
limit = max(1, min(int(request.args.get("limit", 50)), 200))
return jsonify({"wallet": addr, "transactions": tx_history(addr, limit)})
@app.route("/tokens/leaderboard", methods=["GET"])
def tokens_leaderboard():
limit = max(1, min(int(request.args.get("limit", 20)), 100))
return jsonify({"leaderboard": leaderboard(limit)})
@app.route("/tokens/buy", methods=["POST"])
def tokens_buy():
"""Create a Stripe checkout to buy token packs."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"tokens_buy:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
raw_wallet = str(data.get("wallet_address", "")).strip()
# Detect address type: EVM starts with 0x, Solana is base58
is_evm = raw_wallet.startswith("0x")
wallet = raw_wallet.lower() if is_evm else raw_wallet
if is_evm and not _is_valid_evm_address(wallet):
return jsonify({"error": "Invalid EVM wallet address"}), 400
if not is_evm and not _is_valid_solana_address(wallet):
return jsonify({"error": "Invalid Solana wallet address"}), 400
if not _rate_check(f"tokens_buy_wallet:{wallet}", window=3600, max_requests=5):
return rate_limit_response()
pack = str(data.get("pack", "small")).strip().lower()
packs = {
"small": {"amount_cents": 500, "tokens": 100, "label": "100 Tokens"},
"medium": {"amount_cents": 2000, "tokens": 500, "label": "500 Tokens"},
"large": {"amount_cents": 5000, "tokens": 1500, "label": "1500 Tokens"},
}
if pack not in packs:
return jsonify({"error": f"Unknown pack: {pack}. Choose small, medium, or large."}), 400
selected = packs[pack]
import stripe as stripe_lib
sk = settings.get("env", {}).get("STRIPE_SECRET_KEY") or os.environ.get("STRIPE_SECRET_KEY", "")
if not sk:
return jsonify({"error": "Stripe secret key not configured"}), 400
stripe_lib.api_key = sk
origin = get_app_origin()
try:
session = stripe_lib.checkout.Session.create(
payment_method_types=["card"],
line_items=[{
"price_data": {
"currency": "usd",
"product_data": {"name": f"HF VM Studio — {selected['label']}"},
"unit_amount": selected["amount_cents"],
},
"quantity": 1,
}],
mode="payment",
success_url=f"{origin}/?session_id={{CHECKOUT_SESSION_ID}}&wallet={wallet}&pack={pack}#tokens",
cancel_url=f"{origin}/?canceled=true#tokens",
metadata={
"source": "hf-vm-studio",
"wallet": wallet,
"pack": pack,
"tokens": str(selected["tokens"]),
},
)
receipt = create_receipt(
kind="token-purchase",
title=f"Token purchase initiated: {selected['label']}",
status="created",
command=f"checkout_session:{session.id}",
metadata={"session_id": session.id, "wallet": wallet, "pack": pack, "tokens": selected["tokens"]},
)
return jsonify({
"session_id": session.id,
"url": session.url,
"receipt_id": receipt["receipt_id"],
"pack": pack,
"tokens": selected["tokens"],
"amount_cents": selected["amount_cents"],
})
except Exception as e:
return jsonify({"error": str(e)}), 502
# ── Solana Token Launch Service ─────────────────────────────────
def _service_keypair_path() -> str:
"""Persist service keypair to disk for CLI use."""
if not SOLANA_SERVICE_KEY_B58:
raise ValueError("SOLANA_SERVICE_KEY_B58 not configured")
import base58 as b58
kp_path = Path("service_keypair.json")
if kp_path.exists():
return str(kp_path)
secret = b58.b58decode(SOLANA_SERVICE_KEY_B58)
# Phantom / solana-keygen exports 64 bytes [32 secret + 32 pubkey]
if len(secret) not in (32, 64):
raise ValueError("Invalid service keypair length")
from solders.keypair import Keypair
if len(secret) == 64:
kp = Keypair.from_bytes(secret)
else:
kp = Keypair.from_seed(secret)
arr = list(bytes(kp))
kp_path.write_text(json.dumps(arr))
return str(kp_path)
def _solana_cli(cmd: list[str], timeout: int = 60) -> dict:
"""Run a Solana CLI command with configured RPC and keypair."""
kp = _service_keypair_path()
full = ["solana", "--url", SOLANA_RPC_URL, "--keypair", kp] + cmd
result = subprocess.run(full, capture_output=True, text=True, timeout=timeout)
return {
"stdout": result.stdout,
"stderr": result.stderr,
"rc": result.returncode,
}
def _spl_token_cli(cmd: list[str], timeout: int = 60) -> dict:
"""Run spl-token CLI with configured RPC and fee-payer."""
kp = _service_keypair_path()
full = ["spl-token", "--url", SOLANA_RPC_URL, "--owner", kp, "--fee-payer", kp] + cmd
result = subprocess.run(full, capture_output=True, text=True, timeout=timeout)
return {
"stdout": result.stdout,
"stderr": result.stderr,
"rc": result.returncode,
}
def launch_spl_token(owner_address: str, name: str, symbol: str, decimals: int, supply: int) -> dict:
"""Launch a new SPL token on Solana. Returns mint address and tx signature."""
if not SOLANA_SERVICE_KEY_B58:
raise ValueError("SOLANA_SERVICE_KEY_B58 not configured; token launch unavailable")
if SOLANA_MAINNET_ENABLED:
logger.warning("Token launch executing on SOLANA MAINNET")
now = datetime.now(timezone.utc).isoformat()
launch_id = _new_tx_id()
# Generate mint keypair
from solders.keypair import Keypair
mint_kp = Keypair()
mint_path = Path(f"mint_{launch_id}.json")
mint_path.write_text(json.dumps(list(bytes(mint_kp))))
try:
# Create token mint
create_res = _spl_token_cli(["create-token", str(mint_path), "--decimals", str(decimals)])
if create_res["rc"] != 0:
raise RuntimeError(f"create-token failed: {create_res['stderr']}")
# Extract mint address from output
mint_addr = None
for line in create_res["stdout"].splitlines():
if "Creating token" in line:
parts = line.split()
if len(parts) >= 3:
mint_addr = parts[-1]
if line.startswith("Address:"):
mint_addr = line.split("Address:")[1].strip()
if not mint_addr:
# Fallback: use pubkey from keypair
mint_addr = str(mint_kp.pubkey())
# Create associated token account for owner
ata_res = _spl_token_cli(["create-account", mint_addr])
if ata_res["rc"] != 0:
logger.warning(f"create-account warning: {ata_res['stderr']}")
# Get ATA address
ata_addr = owner_address # For simple transfer, we need the ATA
# Actually spl-token create-account creates an ATA for the fee-payer
# We need to create an ATA for the owner_address instead
ata_for_owner = _spl_token_cli(["address", "--token", mint_addr, "--owner", owner_address])
owner_ata = None
for line in ata_for_owner["stdout"].splitlines():
if line.startswith("Associated token address"):
owner_ata = line.split(":")[-1].strip()
if not owner_ata:
# Create ATA for the actual owner
create_ata = _spl_token_cli(["create-account", mint_addr, "--owner", owner_address])
if create_ata["rc"] != 0:
logger.warning(f"create-account for owner warning: {create_ata['stderr']}")
# Try to extract ATA
for line in create_ata["stdout"].splitlines():
if line.startswith("Creating associated token account"):
owner_ata = line.split()[-1].strip()
if not owner_ata:
owner_ata = owner_address # Fallback (will likely fail but recorded)
# Mint tokens to owner
mint_res = _spl_token_cli(["mint", mint_addr, str(supply), owner_ata])
if mint_res["rc"] != 0:
raise RuntimeError(f"mint failed: {mint_res['stderr']}")
# Record in DB
with token_lock:
with _db() as conn:
conn.execute(
"INSERT INTO launched_tokens (launch_id, mint_address, owner_address, name, symbol, decimals, supply, tx_signature, network, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(launch_id, mint_addr, owner_address, name, symbol, decimals, supply, "", "mainnet" if SOLANA_MAINNET_ENABLED else "devnet", now),
)
conn.commit()
return {
"launch_id": launch_id,
"mint_address": mint_addr,
"owner_ata": owner_ata,
"network": "mainnet" if SOLANA_MAINNET_ENABLED else "devnet",
"name": name,
"symbol": symbol,
"decimals": decimals,
"supply": supply,
}
finally:
# Cleanup temp keypair
if mint_path.exists():
mint_path.unlink()
@app.route("/tokens/launch", methods=["POST"])
def tokens_launch():
"""Launch a new SPL token on Solana. Costs tokens from user balance."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"token_launch:{request.remote_addr}", window=3600, max_requests=3):
return rate_limit_response()
data = request.json or {}
raw_owner = _clamp_str(data.get("owner_address", ""), 128).strip()
name = _clamp_str(data.get("name", ""), 64).strip()
symbol = _clamp_str(data.get("symbol", ""), 16).strip().upper()
decimals = max(0, min(int(data.get("decimals", 9)), 18))
supply = max(1, int(data.get("supply", 1_000_000_000)))
if not raw_owner:
return jsonify({"error": "owner_address required"}), 400
if not name or not symbol:
return jsonify({"error": "name and symbol required"}), 400
if not _is_valid_solana_address(raw_owner):
return jsonify({"error": "Invalid Solana owner address"}), 400
owner = _normalize_wallet(raw_owner)
cost = _get_token_cost("token_launch")
bal = get_balance(owner)
if bal < cost:
return jsonify({"error": f"Insufficient tokens. Need {cost}, have {bal}."}), 402
try:
# Debit launch cost
debit_tokens(owner, cost, "token_launch")
result = launch_spl_token(owner, name, symbol, decimals, supply)
result["cost"] = cost
result["balance_after"] = get_balance(owner)
create_receipt(
kind="token-launch",
title=f"Launched {symbol} on {result['network']}",
status="completed",
metadata=result,
)
return jsonify(result), 201
except ValueError as e:
return jsonify({"error": str(e)}), 400
except RuntimeError as e:
return jsonify({"error": str(e)}), 502
except Exception as e:
logger.exception("Token launch failed")
return jsonify({"error": "Token launch failed. Check logs."}), 500
@app.route("/tokens/launched", methods=["GET"])
def tokens_launched():
"""List launched tokens for a wallet."""
wallet = request.args.get("wallet", "").strip()
limit = max(1, min(int(request.args.get("limit", 20)), 100))
if not wallet:
return jsonify({"error": "wallet query param required"}), 400
addr = _normalize_wallet(wallet)
with token_lock:
with _db() as conn:
rows = conn.execute(
"SELECT * FROM launched_tokens WHERE owner_address = ? ORDER BY created_at DESC LIMIT ?",
(addr, limit),
).fetchall()
return jsonify({
"wallet": addr,
"tokens": [dict(r) for r in rows],
"network": "mainnet" if SOLANA_MAINNET_ENABLED else "devnet",
})
# ── CLAIMOS API ────────────────────────────────────────────────
@app.route("/claimos/evaluate", methods=["POST"])
def claimos_evaluate():
"""Create or evaluate a claim: POST evidence + signals, get probability state + receipt."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"claimos_evaluate:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
claim_id = str(data.get("claim_id", f"claim_{uuid.uuid4().hex}")).strip()
title = str(data.get("title", "Untitled Claim")).strip()
description = str(data.get("description", "")).strip()[:2000]
wallet = str(data.get("wallet", "")).strip()
# Upsert claim
now = datetime.now(timezone.utc).isoformat()
with _db() as conn:
existing = conn.execute("SELECT claim_id FROM claims WHERE claim_id = ?", (claim_id,)).fetchone()
if not existing:
conn.execute(
"INSERT INTO claims (claim_id, title, description, status, created_at, updated_at, wallet) VALUES (?, ?, ?, ?, ?, ?, ?)",
(claim_id, title, description, "evidence_received", now, now, wallet or None),
)
else:
conn.execute(
"UPDATE claims SET title = ?, description = ?, updated_at = ? WHERE claim_id = ?",
(title, description, now, claim_id),
)
conn.commit()
# Store evidence items
evidence_items = data.get("evidence", [])
if evidence_items:
with _db() as conn:
for ev in evidence_items:
ev_id = str(ev.get("evidence_id", f"ev_{uuid.uuid4().hex}")).strip()
source_type = str(ev.get("source_type", "other")).strip().lower()
if source_type not in ("audio","document","transcript","witness","hospital","police","screenshot","email","timeline","other"):
source_type = "other"
source_ref = str(ev.get("source_ref", "")).strip()[:500]
content = str(ev.get("content", "")).strip()[:4000]
content_hash = hashlib.sha256(content.encode("utf-8")).hexdigest()
strength = float(ev.get("evidence_strength", 0.5))
conn.execute(
"""INSERT OR REPLACE INTO evidence
(evidence_id, claim_id, source_type, source_ref, content_hash, content, evidence_strength, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
(ev_id, claim_id, source_type, source_ref, content_hash, content, strength, now),
)
conn.commit()
# Debit tokens for evaluation
if wallet:
addr = _normalize_wallet(wallet)
bal = get_balance(addr)
cost = _get_token_cost("claim_evaluate")
if bal < cost:
return jsonify({"error": f"Insufficient tokens. Need {cost}, have {bal}"}), 402
debit_tokens(addr, cost, "claim_evaluate", {"claim_id": claim_id})
# Evaluate probability
try:
inputs = {
"evidence_strength": data.get("evidence_strength"),
"counsel_signal": data.get("counsel_signal"),
"procedural_survival": data.get("procedural_survival"),
"settlement_signal": data.get("settlement_signal"),
"uncertainty": data.get("uncertainty"),
}
inputs = {k: float(v) for k, v in inputs.items() if v is not None}
prob = ClaimProbabilityEngine.evaluate(claim_id, inputs if inputs else None)
except ValueError as e:
return jsonify({"error": str(e)}), 404
# Create proof receipt
receipt = create_receipt(
kind="claim-evaluation",
title=f"Claim evaluated: {title}",
status="completed",
command=f"claimos_evaluate:{claim_id}",
metadata={"claim_id": claim_id, "p_recovery": prob["p_recovery"], "wallet": wallet},
)
return jsonify({
"claim_id": claim_id,
"probability_state": prob,
"receipt_id": receipt["receipt_id"],
"tokens_debited": _get_token_cost("claim_evaluate") if wallet else 0,
})
@app.route("/claimos/", methods=["GET"])
def claimos_get(claim_id: str):
"""Get full claim state including evidence and contradictions."""
if not _rate_check(f"claimos_get:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
with _db() as conn:
claim = conn.execute("SELECT * FROM claims WHERE claim_id = ?", (claim_id,)).fetchone()
if not claim:
return jsonify({"error": "Claim not found"}), 404
evidence = conn.execute("SELECT * FROM evidence WHERE claim_id = ?", (claim_id,)).fetchall()
contradictions = conn.execute("SELECT * FROM contradictions WHERE claim_id = ? AND resolved = 0", (claim_id,)).fetchall()
return jsonify({
"claim": dict(claim),
"evidence": [dict(r) for r in evidence],
"contradictions": [dict(r) for r in contradictions],
})
@app.route("/claimos//contradictions", methods=["POST"])
def claimos_contradictions(claim_id: str):
"""Run contradiction scan on a claim. Costs tokens."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"claimos_cx:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
wallet = str(data.get("wallet", "")).strip()
if wallet:
addr = _normalize_wallet(wallet)
bal = get_balance(addr)
cost = _get_token_cost("claim_contradiction_scan")
if bal < cost:
return jsonify({"error": f"Insufficient tokens. Need {cost}, have {bal}"}), 402
debit_tokens(addr, cost, "claim_contradiction_scan", {"claim_id": claim_id})
cx = ContradictionDetector.detect(claim_id)
receipt = create_receipt(
kind="claim-contradiction-scan",
title=f"Contradiction scan: {len(cx)} found",
status="completed",
command=f"claimos_contradictions:{claim_id}",
metadata={"claim_id": claim_id, "contradictions_found": len(cx)},
)
return jsonify({
"claim_id": claim_id,
"contradictions": cx,
"contradiction_count": len(cx),
"receipt_id": receipt["receipt_id"],
"tokens_debited": _get_token_cost("claim_contradiction_scan") if wallet else 0,
})
@app.route("/claimos//greeks", methods=["GET", "POST"])
def claimos_greeks(claim_id: str):
"""Compute and return Claim Greeks (Δ, Θ, Γ, V, K). Costs tokens if wallet provided."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"claimos_greeks:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
wallet = str(data.get("wallet", "")).strip()
if wallet:
addr = _normalize_wallet(wallet)
bal = get_balance(addr)
cost = _get_token_cost("claim_greeks")
if bal < cost:
return jsonify({"error": f"Insufficient tokens. Need {cost}, have {bal}"}), 402
debit_tokens(addr, cost, "claim_greeks", {"claim_id": claim_id})
try:
greeks = ClaimGreeks.compute(claim_id)
except ValueError as e:
return jsonify({"error": str(e)}), 404
receipt = create_receipt(
kind="claim-greeks",
title="Claim Greeks computed",
status="completed",
command=f"claimos_greeks:{claim_id}",
metadata={"claim_id": claim_id, "greeks": greeks},
)
return jsonify({
"claim_id": claim_id,
"greeks": greeks,
"receipt_id": receipt["receipt_id"],
"tokens_debited": _get_token_cost("claim_greeks") if wallet else 0,
})
@app.route("/claimos//liquidity", methods=["GET"])
def claimos_liquidity(claim_id: str):
"""Compute finance readiness / liquidity score for a claim."""
if not _rate_check(f"claimos_liq:{request.remote_addr}", window=60, max_requests=20):
return rate_limit_response()
try:
liq = ClaimLiquidity.compute(claim_id)
except ValueError as e:
return jsonify({"error": str(e)}), 404
receipt = create_receipt(
kind="claim-liquidity",
title=f"Liquidity score: {liq['liquidity_score']:.4f}",
status="completed",
command=f"claimos_liquidity:{claim_id}",
metadata={"claim_id": claim_id, "liquidity": liq["liquidity_score"]},
)
return jsonify({
"claim_id": claim_id,
"liquidity": liq,
"receipt_id": receipt["receipt_id"],
})
@app.route("/claimos//assess", methods=["POST"])
def claimos_assess(claim_id: str):
"""Use LLM to assess evidence quality and auto-update evidence_strength scores. Costs tokens."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"claimos_assess:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
wallet = str(data.get("wallet", "")).strip()
if wallet:
addr = _normalize_wallet(wallet)
bal = get_balance(addr)
cost = _get_token_cost("claim_evaluate")
if bal < cost:
return jsonify({"error": f"Insufficient tokens. Need {cost}, have {bal}"}), 402
debit_tokens(addr, cost, "claim_assess", {"claim_id": claim_id})
with _db() as conn:
rows = conn.execute("SELECT * FROM evidence WHERE claim_id = ?", (claim_id,)).fetchall()
if not rows:
return jsonify({"error": "No evidence found for claim"}), 404
# Build LLM prompt for evidence assessment
ev_text = "\n\n".join(
f"[{i+1}] {r['source_type'].upper()} (ref: {r['source_ref']}): {r['content'][:1000]}"
for i, r in enumerate(rows)
)
system_prompt = (
"You are a legal evidence assessor. Rate each evidence item on: credibility (0-1), "
"relevance (0-1), completeness (0-1), and overall_strength (0-1). Return ONLY a JSON array "
"where each item has: index (1-based), credibility, relevance, completeness, overall_strength, "
"rationale (string). Be strict and realistic."
)
try:
result = call_llm(prompt=f"Assess the following evidence items for claim {claim_id}:\n\n{ev_text}", system=system_prompt, model="json")
parsed = parse_llm_json(result.get("response", "[]"))
if not isinstance(parsed, list):
raise ValueError("LLM returned non-array")
now = datetime.now(timezone.utc).isoformat()
updated = []
with _db() as conn:
for item in parsed:
idx = int(item.get("index", 0)) - 1
if 0 <= idx < len(rows):
ev_id = rows[idx]["evidence_id"]
strength = round(min(1.0, max(0.0, float(item.get("overall_strength", 0.5)))), 4)
conn.execute(
"UPDATE evidence SET evidence_strength = ?, metadata = ? WHERE evidence_id = ?",
(strength, json.dumps({"assessment": item}), ev_id),
)
updated.append({"evidence_id": ev_id, "strength": strength, "rationale": item.get("rationale", "")})
conn.commit()
receipt = create_receipt(
kind="claim-assess",
title=f"Evidence assessed: {len(updated)} items",
status="completed",
command=f"claimos_assess:{claim_id}",
metadata={"claim_id": claim_id, "items_assessed": len(updated)},
)
return jsonify({
"claim_id": claim_id,
"assessments": updated,
"receipt_id": receipt["receipt_id"],
"tokens_debited": _get_token_cost("claim_evaluate") if wallet else 0,
})
except Exception as e:
logger.warning(f"Claim assessment LLM failed: {e}")
return jsonify({"error": f"LLM assessment failed: {e}"}), 502
@app.route("/claimos//appraise", methods=["GET"])
def claimos_appraise(claim_id: str):
"""Generate a full legal appraisal report via LLM. Returns narrative + structured metrics."""
if not _rate_check(f"claimos_appraise:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
with _db() as conn:
claim = conn.execute("SELECT * FROM claims WHERE claim_id = ?", (claim_id,)).fetchone()
evidence = conn.execute("SELECT * FROM evidence WHERE claim_id = ?", (claim_id,)).fetchall()
contradictions = conn.execute("SELECT * FROM contradictions WHERE claim_id = ? AND resolved = 0", (claim_id,)).fetchall()
if not claim:
return jsonify({"error": "Claim not found"}), 404
claim_data = dict(claim)
ev_data = [dict(r) for r in evidence]
cx_data = [dict(r) for r in contradictions]
prompt = (
f"Generate a legal claim appraisal report.\n\n"
f"CLAIM: {claim_data.get('title', '')}\n"
f"DESCRIPTION: {claim_data.get('description', '')}\n"
f"STATUS: {claim_data.get('status', '')}\n"
f"P(RECOVERY): {claim_data.get('p_recovery', 0)}\n"
f"EVIDENCE COUNT: {len(ev_data)}\n"
f"CONTRADICTIONS: {len(cx_data)}\n\n"
f"EVIDENCE:\n" + "\n".join(
f"- {e['source_type']} ({e['source_ref']}): strength={e['evidence_strength']}"
for e in ev_data[:10]
) + "\n\n"
f"Return ONLY JSON with: summary (string), strengths (array), risks (array), "
f"recommended_next_steps (array), settlement_likelihood (0-1), expected_recovery_range (string)."
)
try:
result = call_llm(prompt=prompt, system="You are a senior legal claim appraiser. Be concise, realistic, and structured.", model="quality")
parsed = parse_llm_json(result.get("response", "{}"))
if not isinstance(parsed, dict):
parsed = {"summary": "Appraisal generated", "raw": result.get("response", "")}
receipt = create_receipt(
kind="claim-appraisal",
title=f"Appraisal: {claim_data.get('title', claim_id)[:60]}",
status="completed",
command=f"claimos_appraise:{claim_id}",
metadata={"claim_id": claim_id, "appraisal": parsed},
)
return jsonify({
"claim_id": claim_id,
"appraisal": parsed,
"probability_state": {
"p_recovery": claim_data.get("p_recovery"),
"liquidity_score": claim_data.get("liquidity_score"),
"status": claim_data.get("status"),
},
"receipt_id": receipt["receipt_id"],
})
except Exception as e:
logger.warning(f"Claim appraisal LLM failed: {e}")
return jsonify({"error": f"Appraisal failed: {e}"}), 502
@app.route("/tokens/verify/", methods=["GET"])
def tokens_verify(mint_address: str):
"""Verify an SPL token mint exists on-chain via Solana RPC. No simulation."""
if not _rate_check(f"token_verify:{request.remote_addr}", window=60, max_requests=20):
return rate_limit_response()
# Call Solana RPC getAccountInfo for the mint
rpc_payload = {
"jsonrpc": "2.0",
"id": 1,
"method": "getAccountInfo",
"params": [mint_address, {"encoding": "jsonParsed"}],
}
try:
resp = requests.post(SOLANA_RPC_URL, json=rpc_payload, timeout=15)
resp.raise_for_status()
data = resp.json()
if data.get("error"):
return jsonify({"mint": mint_address, "exists": False, "error": data["error"]}), 404
result = data.get("result", {})
value = result.get("value")
if not value:
return jsonify({"mint": mint_address, "exists": False, "on_chain": False}), 404
# Mint account exists — parse token data if available
parsed = value.get("data", {}).get("parsed", {}).get("info", {}) if isinstance(value.get("data"), dict) else {}
return jsonify({
"mint": mint_address,
"exists": True,
"on_chain": True,
"rpc": SOLANA_RPC_URL,
"lamports": value.get("lamports"),
"owner": value.get("owner"),
"executable": value.get("executable"),
"parsed_info": parsed,
"verified_at": datetime.now(timezone.utc).isoformat(),
})
except Exception as e:
logger.warning(f"Solana RPC verification failed for {mint_address}: {e}")
return jsonify({"mint": mint_address, "exists": False, "error": str(e)}), 502
# ── Finance / Underwriting Proof ────────────────────────────────
@app.route("/finance/collateral", methods=["GET"])
def finance_collateral():
"""Underwriting proof: verifiable income, deferred revenue, token velocity."""
if not _rate_check(f"finance:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
with token_lock:
with _db() as conn:
# Total revenue
rev_row = conn.execute("SELECT COALESCE(SUM(amount_cents), 0) AS total FROM revenue").fetchone()
total_revenue_cents = rev_row["total"] if rev_row else 0
# Deferred revenue (outstanding token liability)
def_row = conn.execute("SELECT COALESCE(SUM(deferred_cents), 0) AS total, COALESCE(SUM(tokens_purchased), 0) AS purchased, COALESCE(SUM(tokens_spent), 0) AS spent FROM deferred_revenue").fetchone()
deferred_cents = def_row["total"] if def_row else 0
tokens_purchased = def_row["purchased"] if def_row else 0
tokens_spent = def_row["spent"] if def_row else 0
# Wallet count
wallet_row = conn.execute("SELECT COUNT(*) AS cnt FROM wallets").fetchone()
wallet_count = wallet_row["cnt"] if wallet_row else 0
# Active paying wallets (have purchased tokens)
pay_row = conn.execute("SELECT COUNT(DISTINCT wallet) AS cnt FROM stripe_sessions").fetchone()
paying_wallets = pay_row["cnt"] if pay_row else 0
# Period revenue (last 6 months)
period_rows = conn.execute(
"SELECT period, SUM(amount_cents) AS cents FROM revenue GROUP BY period ORDER BY period DESC LIMIT 6"
).fetchall()
# Token velocity: spend rate
vel_row = conn.execute(
"SELECT COALESCE(SUM(amount), 0) AS spent FROM transactions WHERE type = 'debit' AND created_at > datetime('now', '-30 days')"
).fetchone()
monthly_spend = vel_row["spent"] if vel_row else 0
return jsonify({
"underwriting_version": "1.0.0",
"generated_at": datetime.now(timezone.utc).isoformat(),
"total_revenue_usd": round(total_revenue_cents / 100, 2),
"deferred_revenue_usd": round(deferred_cents / 100, 2),
"recognized_revenue_usd": round((total_revenue_cents - deferred_cents) / 100, 2),
"wallet_count": wallet_count,
"paying_wallets": paying_wallets,
"tokens_purchased": tokens_purchased,
"tokens_spent": tokens_spent,
"token_velocity_30d": monthly_spend,
"revenue_by_period": [{"period": r["period"], "usd": round(r["cents"] / 100, 2)} for r in period_rows],
"collateral_score": round(min(100, (total_revenue_cents / 1000) + (paying_wallets * 10) + (monthly_spend / 100)), 2),
})
@app.route("/finance/revenue", methods=["GET"])
def finance_revenue():
"""Revenue dashboard with period and source breakdown."""
if not _rate_check(f"finance:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
period_filter = request.args.get("period", "")
source_filter = request.args.get("source", "")
limit = max(1, min(int(request.args.get("limit", 100)), 500))
with token_lock:
with _db() as conn:
query = "SELECT * FROM revenue WHERE 1=1"
params = []
if period_filter:
query += " AND period = ?"
params.append(period_filter)
if source_filter:
query += " AND source = ?"
params.append(source_filter)
query += " ORDER BY created_at DESC LIMIT ?"
params.append(limit)
rows = conn.execute(query, params).fetchall()
# Aggregates
agg = conn.execute("SELECT source, SUM(amount_cents) AS cents FROM revenue GROUP BY source").fetchall()
return jsonify({
"entries": [{"revenue_id": r["revenue_id"], "source": r["source"], "amount_cents": r["amount_cents"], "currency": r["currency"], "period": r["period"], "wallet": r["wallet"], "created_at": r["created_at"]} for r in rows],
"by_source": {r["source"]: r["cents"] for r in agg},
"total_usd": round(sum(r["cents"] for r in agg) / 100, 2),
})
@app.route("/finance/reconcile", methods=["POST"])
def finance_reconcile():
"""Reconcile Stripe sessions with token credits and revenue ledger."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"finance:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
with token_lock:
with _db() as conn:
# Find Stripe sessions without matching transactions
orphan_sessions = conn.execute(
"""SELECT s.session_id, s.amount_cents, s.wallet, s.pack, s.tokens, s.tx_id
FROM stripe_sessions s
LEFT JOIN transactions t ON s.tx_id = t.tx_id
WHERE t.tx_id IS NULL"""
).fetchall()
# Find transactions without matching revenue
orphan_tx = conn.execute(
"""SELECT t.tx_id, t.address, t.amount, t.reason
FROM transactions t
LEFT JOIN revenue r ON t.tx_id = r.session_id
WHERE t.type = 'credit' AND r.revenue_id IS NULL AND t.reason LIKE 'stripe_purchase%'"""
).fetchall()
return jsonify({
"orphan_stripe_sessions": len(orphan_sessions),
"orphan_transactions": len(orphan_tx),
"orphan_session_details": [{"session_id": s["session_id"], "wallet": s["wallet"], "tokens": s["tokens"]} for s in orphan_sessions],
"reconciled": len(orphan_sessions) == 0 and len(orphan_tx) == 0,
})
@app.route("/finance/rollback", methods=["POST"])
def finance_rollback():
"""Rollback a transaction by tx_id. Returns tokens to wallet and reverses revenue."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"finance:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
data = request.json or {}
tx_id = str(data.get("tx_id", "")).strip()
reason = str(data.get("reason", "rollback")).strip()
if not tx_id:
return jsonify({"error": "tx_id required"}), 400
now = datetime.now(timezone.utc).isoformat()
with token_lock:
with _db() as conn:
tx = conn.execute("SELECT * FROM transactions WHERE tx_id = ?", (tx_id,)).fetchone()
if not tx:
return jsonify({"error": "Transaction not found"}), 404
addr = tx["address"]
amount = tx["amount"]
tx_type = tx["type"]
# Reverse the transaction
if tx_type == "credit":
# Was a credit → debit back
bal_row = conn.execute("SELECT balance FROM balances WHERE address = ?", (addr,)).fetchone()
current = bal_row["balance"] if bal_row else 0
if current < amount:
return jsonify({"error": f"Cannot rollback: wallet balance {current} < {amount}"}), 400
conn.execute("UPDATE balances SET balance = balance - ? WHERE address = ?", (amount, addr))
# Reverse deferred revenue only for purchased tokens
if tx["reason"].startswith("stripe_purchase"):
conn.execute(
"""UPDATE deferred_revenue SET
tokens_purchased = MAX(0, tokens_purchased - ?),
deferred_cents = MAX(0, deferred_cents - (SELECT deferred_cents FROM deferred_revenue WHERE address = ?) / NULLIF(tokens_purchased, 0) * ?),
last_updated = ? WHERE address = ? AND tokens_purchased > 0""",
(amount, addr, amount, now, addr),
)
elif tx_type == "debit":
# Was a debit → credit back
conn.execute(
"INSERT OR REPLACE INTO balances (address, balance) VALUES (?, COALESCE((SELECT balance FROM balances WHERE address = ?), 0) + ?)",
(addr, addr, amount),
)
# Restore deferred revenue liability
if tx["reason"].startswith("token_") or tx["reason"].startswith("shell_") or tx["reason"].startswith("kernel_") or tx["reason"].startswith("notebook_") or tx["reason"].startswith("deploy_") or tx["reason"].startswith("agent_"):
conn.execute(
"""UPDATE deferred_revenue SET
tokens_spent = MAX(0, tokens_spent - ?),
deferred_cents = deferred_cents + (SELECT deferred_cents FROM deferred_revenue WHERE address = ?) / NULLIF(tokens_purchased, 0) * ?,
last_updated = ? WHERE address = ? AND tokens_purchased > 0""",
(amount, addr, amount, now, addr),
)
# Mark original as rolled back
rollback_tx_id = f"rollback_{tx_id}_{uuid.uuid4().hex[:8]}"
conn.execute(
"INSERT INTO transactions (tx_id, address, amount, type, reason, created_at, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)",
(rollback_tx_id, addr, amount, "rollback", reason, now, json.dumps({"original_tx_id": tx_id, "original_type": tx_type})),
)
# Reverse revenue if linked
rev = conn.execute("SELECT revenue_id FROM revenue WHERE session_id = ?", (tx_id,)).fetchone()
if rev:
conn.execute("DELETE FROM revenue WHERE revenue_id = ?", (rev["revenue_id"],))
conn.commit()
add_memory(
title=f"Rollback: {tx_id}",
content=f"Rolled back transaction {tx_id} for wallet {addr}. Reason: {reason}",
source="finance-rollback",
tags=["rollback", "finance"],
metadata={"original_tx_id": tx_id, "wallet": addr, "amount": amount, "reason": reason},
importance=0.9,
)
return jsonify({"rollback_tx_id": rollback_tx_id, "original_tx_id": tx_id, "wallet": addr, "amount": amount, "reason": reason})
# ── Pixelator / GlyphIndex API ────────────────────────────────
@app.route("/pixelator/ingest", methods=["POST"])
def pixelator_ingest():
"""Ingest HTML, tokenize to glyph units, emit proof receipt."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"pixelator_ingest:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
data = request.json or {}
html = str(data.get("html", ""))
url = str(data.get("url", "")).strip() or "about:blank"
website_id = str(data.get("website_id", "")).strip() or f"site_{uuid.uuid4().hex[:8]}"
title = str(data.get("title", "")).strip()
wallet = str(data.get("wallet", "")).strip()
if not html:
return jsonify({"error": "html required"}), 400
# Cap HTML size to prevent abuse (C30)
if len(html) > 2_000_000:
return jsonify({"error": "HTML too large. Max 2MB."}), 413
# Debit tokens
if wallet:
addr = _normalize_wallet(wallet)
bal = get_balance(addr)
cost = _get_token_cost("pixelator_ingest")
if bal < cost:
return jsonify({"error": f"Insufficient tokens. Need {cost}, have {bal}."}), 402
debit_tokens(addr, cost, "pixelator_ingest", {"url": url, "website_id": website_id})
try:
result = MembraPixelator.ingest(html, url, website_id, title)
receipt = create_receipt(
kind="pixelator-ingest",
title=f"Pixelated: {result['title'] or url}",
status="completed",
command=f"pixelator_ingest:{result['page_id']}",
metadata=result,
)
result["receipt_id"] = receipt["receipt_id"]
result["tokens_debited"] = _get_token_cost("pixelator_ingest") if wallet else 0
return jsonify(result), 201
except Exception as e:
logger.exception("Pixelator ingest failed")
return jsonify({"error": "Pixelator ingest failed. Check logs."}), 500
@app.route("/pixelator/page//glyphs", methods=["GET"])
def pixelator_page_glyphs(page_id: str):
"""Get glyph units for a page."""
if not _rate_check(f"pixelator_glyphs:{request.remote_addr}", window=60, max_requests=20):
return rate_limit_response()
limit = max(1, min(int(request.args.get("limit", 1000)), 5000))
offset = max(0, int(request.args.get("offset", 0)))
try:
glyphs = MembraPixelator.get_page_glyphs(page_id, limit, offset)
return jsonify({
"page_id": page_id,
"glyphs": glyphs,
"count": len(glyphs),
"limit": limit,
"offset": offset,
})
except Exception as e:
logger.exception("Pixelator glyphs fetch failed")
return jsonify({"error": str(e)}), 500
@app.route("/pixelator/page//activation", methods=["GET"])
def pixelator_page_activation(page_id: str):
"""Get page activation summary with glyph statistics."""
if not _rate_check(f"pixelator_activation:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
try:
result = MembraPixelator.get_page_activation(page_id)
return jsonify(result)
except ValueError as e:
return jsonify({"error": str(e)}), 404
except Exception as e:
logger.exception("Pixelator activation fetch failed")
return jsonify({"error": str(e)}), 500
@app.route("/pixelator/website//top-glyphs", methods=["GET"])
def pixelator_top_glyphs(website_id: str):
"""Get highest-value glyphs across a website."""
if not _rate_check(f"pixelator_top:{request.remote_addr}", window=60, max_requests=20):
return rate_limit_response()
limit = max(1, min(int(request.args.get("limit", 50)), 200))
try:
glyphs = MembraPixelator.get_top_glyphs(website_id, limit)
return jsonify({
"website_id": website_id,
"glyphs": glyphs,
"count": len(glyphs),
})
except Exception as e:
logger.exception("Pixelator top glyphs fetch failed")
return jsonify({"error": str(e)}), 500
@app.route("/pixelator/learn", methods=["POST"])
def pixelator_learn():
"""Retrain DOM weights and semantic lexicon from actual page results.
Higher page_activation → reinforce tag weights and term confidence."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"pixelator_learn:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
data = request.json or {}
min_samples = max(1, int(data.get("min_samples", 3)))
now = datetime.now(timezone.utc).isoformat()
with _db() as conn:
# Learn DOM weights: update each tag's weight toward the average page_activation of pages using that tag
tag_rows = conn.execute("""
SELECT tag, COUNT(*) AS n, AVG(page_activation_value) AS avg_pa
FROM pages p
JOIN (
SELECT DISTINCT page_id, SUBSTR(dom_path, INSTR(dom_path, '>') + 2) AS tag
FROM glyph_units
) g ON p.page_id = g.page_id
GROUP BY tag HAVING n >= ?
""", (min_samples,)).fetchall()
dom_updated = 0
for row in tag_rows:
tag, n, avg_pa = row["tag"], row["n"], row["avg_pa"] or 0.0
# New weight = (old_weight * old_samples + avg_pa) / (old_samples + 1)
old = conn.execute("SELECT weight, sample_count FROM dom_weights WHERE tag = ?", (tag,)).fetchone()
if old:
new_weight = (old["weight"] * old["sample_count"] + avg_pa) / (old["sample_count"] + n)
new_count = old["sample_count"] + n
else:
new_weight = avg_pa
new_count = n
conn.execute(
"""INSERT OR REPLACE INTO dom_weights (tag, weight, sample_count, avg_page_activation, updated_at)
VALUES (?, ?, ?, ?, ?)""",
(tag, round(new_weight, 4), new_count, round(avg_pa, 4), now),
)
dom_updated += 1
# Learn semantic lexicon: reinforce terms that appear on high-activation pages
term_rows = conn.execute("""
SELECT char_value AS term, semantic_role AS category, COUNT(*) AS freq,
AVG(glyph_value) AS avg_gv, AVG(page_activation_value) AS avg_pa
FROM glyph_units g
JOIN pages p ON g.page_id = p.page_id
WHERE semantic_role IN ('entity','action','commercial','legal')
GROUP BY term, category HAVING freq >= ?
""", (min_samples,)).fetchall()
lex_updated = 0
for row in term_rows:
term, category, freq, avg_gv, avg_pa = row["term"], row["category"], row["freq"], row["avg_gv"], row["avg_pa"]
# Confidence proportional to average glyph value and page activation
confidence = min(0.99, (avg_gv or 0.0) * 0.1 + (avg_pa or 0.0) * 0.01)
old = conn.execute(
"SELECT frequency, confidence FROM semantic_lexicon WHERE term = ? AND category = ?",
(term, category),
).fetchone()
if old:
freq = old["frequency"] + freq
confidence = (old["confidence"] + confidence) / 2
conn.execute(
"""INSERT OR REPLACE INTO semantic_lexicon
(term, category, frequency, confidence, source_count, updated_at)
VALUES (?, ?, ?, ?, ?, ?)""",
(term, category, freq, round(confidence, 4), freq, now),
)
lex_updated += 1
conn.commit()
return jsonify({
"dom_weights_updated": dom_updated,
"lexicon_terms_updated": lex_updated,
"min_samples": min_samples,
"learned_at": now,
})
@app.route("/costs", methods=["GET", "POST"])
def manage_costs():
"""Get or update token costs. No hardcoded values — DB is source of truth."""
if request.method == "GET":
with _db() as conn:
rows = conn.execute("SELECT operation, cost, source, updated_at FROM token_costs ORDER BY operation").fetchall()
return jsonify({"costs": [dict(r) for r in rows]})
auth = require_auth()
if auth:
return auth
data = request.json or {}
operation = str(data.get("operation", "")).strip()
cost = data.get("cost")
if not operation or cost is None:
return jsonify({"error": "operation and cost required"}), 400
try:
cost = int(cost)
except (TypeError, ValueError):
return jsonify({"error": "cost must be an integer"}), 400
if cost < 0:
return jsonify({"error": "cost must be non-negative"}), 400
now = datetime.now(timezone.utc).isoformat()
with _db() as conn:
conn.execute(
"INSERT OR REPLACE INTO token_costs (operation, cost, source, updated_at) VALUES (?, ?, 'admin', ?)",
(operation, cost, now),
)
conn.commit()
return jsonify({"operation": operation, "cost": cost, "updated_at": now}), 200
# ── GA-RL Crawler API ─────────────────────────────────────────
@app.route("/crawler/targets", methods=["GET", "POST"])
def crawler_targets():
"""List or register crawl target websites."""
if request.method == "GET":
if not _rate_check(f"crawler_targets:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
with _db() as conn:
rows = conn.execute("SELECT * FROM crawl_targets ORDER BY fitness_score DESC").fetchall()
return jsonify({"targets": [dict(r) for r in rows], "count": len(rows)})
# POST: register new target
auth = require_auth()
if auth:
return auth
data = request.json or {}
website_id = str(data.get("website_id", "")).strip()
root_url = str(data.get("root_url", "")).strip()
if not website_id or not root_url:
return jsonify({"error": "website_id and root_url required"}), 400
try:
crawler = GARLCrawler()
result = crawler.add_target(
website_id=website_id,
root_url=root_url,
name=str(data.get("name", "")).strip(),
depth=max(1, min(int(data.get("crawl_depth", 2)), 5)),
priority=float(data.get("priority", 1.0)),
selector_rules=str(data.get("selector_rules", "")),
)
return jsonify(result), 201
except ValueError as e:
return jsonify({"error": str(e)}), 409
except Exception as e:
logger.exception("Crawler add_target failed")
return jsonify({"error": "Failed to add target"}), 500
@app.route("/crawler/targets/", methods=["DELETE"])
def crawler_target_delete(target_id: str):
auth = require_auth()
if auth:
return auth
with _db() as conn:
conn.execute("DELETE FROM crawl_targets WHERE target_id = ?", (target_id,))
conn.commit()
return jsonify({"deleted": target_id})
@app.route("/crawler/queue", methods=["POST"])
def crawler_enqueue():
"""Add a URL to the rotator buffer crawl queue."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"crawler_queue:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
target_id = str(data.get("target_id", "")).strip()
url = str(data.get("url", "")).strip()
if not target_id or not url:
return jsonify({"error": "target_id and url required"}), 400
depth = max(0, min(int(data.get("depth", 0)), 5))
priority_score = float(data.get("priority_score", 0.0))
try:
crawler = GARLCrawler()
result = crawler.enqueue(target_id, url, depth, priority_score)
return jsonify(result), 201
except Exception as e:
logger.exception("Crawler enqueue failed")
return jsonify({"error": str(e)}), 500
@app.route("/crawler/queue", methods=["GET"])
def crawler_queue_list():
if not _rate_check(f"crawler_queue_list:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
limit = max(1, min(int(request.args.get("limit", 100)), 500))
with _db() as conn:
rows = conn.execute("SELECT * FROM crawl_queue ORDER BY added_at DESC LIMIT ?", (limit,)).fetchall()
return jsonify({"queue": [dict(r) for r in rows], "count": len(rows)})
@app.route("/crawler/ingest", methods=["POST"])
def crawler_ingest():
"""Run one crawl step: select next URL via RL, fetch, pixelate, reward."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"crawler_ingest:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
data = request.json or {}
wallet = str(data.get("wallet", "")).strip()
crawler = GARLCrawler()
next_item = crawler.select_next()
if not next_item:
return jsonify({"status": "idle", "message": "No pending items in queue"})
queue_id = next_item["queue_id"]
target_id = next_item["target_id"]
url = next_item["url"]
try:
result = crawler.ingest_url(url, target_id, queue_id, wallet)
return jsonify(result)
except Exception as e:
logger.exception("Crawler ingest failed")
return jsonify({"error": str(e)}), 500
@app.route("/crawler/results", methods=["GET"])
def crawler_results():
if not _rate_check(f"crawler_results:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
website_id = request.args.get("website_id", "").strip() or None
limit = max(1, min(int(request.args.get("limit", 100)), 500))
crawler = GARLCrawler()
results = crawler.get_results(website_id, limit)
return jsonify({"results": results, "count": len(results)})
@app.route("/crawler/evolve", methods=["POST"])
def crawler_evolve():
"""Run one GA generation on the target population."""
auth = require_auth()
if auth:
return auth
if not _rate_check(f"crawler_evolve:{request.remote_addr}", window=60, max_requests=5):
return rate_limit_response()
try:
crawler = GARLCrawler()
result = crawler.run_evolution()
return jsonify(result)
except Exception as e:
logger.exception("Crawler evolution failed")
return jsonify({"error": str(e)}), 500
@app.route("/crawler/policy", methods=["GET"])
def crawler_policy():
if not _rate_check(f"crawler_policy:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
crawler = GARLCrawler()
policy = crawler.get_policy()
return jsonify({"policy": policy, "count": len(policy)})
# ── ETHR Oracle ───────────────────────────────────────────────
ETHR_ADMIN_KEY = os.environ.get("ETHR_ADMIN_KEY", "")
@app.route("/ethr/proof-index", methods=["GET"])
def ethr_proof_index():
"""Compute ETHR proof index from live CLAIMOS metrics."""
if not _rate_check(f"ethr:{request.remote_addr}", window=60, max_requests=30):
return rate_limit_response()
with _db() as conn:
# Proof metrics
verified_receipts = conn.execute(
"SELECT COUNT(*) AS c FROM receipts WHERE kind LIKE 'claim-%' AND status = 'completed'"
).fetchone()["c"]
reviewed_packets = conn.execute(
"SELECT COUNT(*) AS c FROM evidence WHERE evidence_strength > 0"
).fetchone()["c"]
resolved_contradictions = conn.execute(
"SELECT COUNT(*) AS c FROM contradictions WHERE resolved = 1"
).fetchone()["c"]
# Risk metrics
disputes = conn.execute(
"SELECT COUNT(*) AS c FROM contradictions WHERE resolved = 0"
).fetchone()["c"]
invalid_evidence = conn.execute(
"SELECT COUNT(*) AS c FROM evidence WHERE evidence_strength < 0.3"
).fetchone()["c"]
procedural_failures = conn.execute(
"SELECT COUNT(*) AS c FROM claims WHERE status IN ('unreviewed','closed')"
).fetchone()["c"]
# Aggregate claim state
claim_stats = conn.execute(
"SELECT AVG(p_recovery) AS avg_p, AVG(liquidity_score) AS avg_liq, AVG(contradiction_density) AS avg_cx FROM claims"
).fetchone()
delta_proof = verified_receipts + reviewed_packets + resolved_contradictions
delta_risk = disputes + invalid_evidence + procedural_failures
net_change = delta_proof - delta_risk
# Normalize to small increments
normalized = net_change / max(1, delta_proof + delta_risk)
return jsonify({
"token": "ETHR",
"description": "Elastic proof-index token for Membra verification capacity",
"delta": {
"verified_receipts": verified_receipts,
"reviewed_packets": reviewed_packets,
"resolved_contradictions": resolved_contradictions,
"disputes": disputes,
"invalid_evidence": invalid_evidence,
"procedural_failures": procedural_failures,
},
"net_change": round(normalized, 8),
"claim_stats": {
"avg_p_recovery": round(claim_stats["avg_p"] or 0, 4),
"avg_liquidity": round(claim_stats["avg_liq"] or 0, 4),
"avg_contradiction_density": round(claim_stats["avg_cx"] or 0, 4),
},
"updated_at": datetime.now(timezone.utc).isoformat(),
})
@app.route("/ethr/update-multiplier", methods=["POST"])
def ethr_update_multiplier():
"""Oracle endpoint to update ETHR multiplier. Requires ETHR_ADMIN_KEY."""
if not _rate_check(f"ethr_admin:{request.remote_addr}", window=60, max_requests=10):
return rate_limit_response()
data = request.json or {}
auth_key = str(data.get("admin_key", "")).strip()
if not ETHR_ADMIN_KEY or auth_key != ETHR_ADMIN_KEY:
return jsonify({"error": "Unauthorized"}), 401
multiplier = float(data.get("multiplier", 1.0))
if multiplier <= 0:
return jsonify({"error": "Multiplier must be > 0"}), 400
now = datetime.now(timezone.utc).isoformat()
return jsonify({
"token": "ETHR",
"multiplier": multiplier,
"status": "updated",
"updated_at": now,
})
# ── Main ────────────────────────────────────────────────────────
if __name__ == "__main__":
load_config()
load_settings()
load_memory()
load_apps()
load_receipts()
_init_token_db()
save_state()
if not TERMINAL_AGENT_TOKEN:
logger.warning("TERMINAL_AGENT_TOKEN is not set; command routes will reject all requests.")
logger.info(f"Starting Terminal Agent on port {PORT}")
app.run(host="0.0.0.0", port=PORT, threaded=True)