Download apps/api.py from tmepass000/matter-os: direct link, hf CLI and curl.
- Browser
- Download file 21.5 kB
-
https://huggingface.co/tmepass000/matter-os/resolve/main/apps/api.py
- Command line
-
hf download hf://tmepass000/matter-os/apps/api.py
-
curl -L -o api.py https://huggingface.co/tmepass000/matter-os/resolve/main/apps/api.py
21.5 kB
| """FastAPI application exposing the versioned section-14 APIs (/api/v1) and the dashboard (/). | |
| Run: uvicorn apps.api:create_app --factory --port 8000 | |
| """ | |
| from __future__ import annotations | |
| import threading | |
| from pathlib import Path | |
| from typing import Any, Optional | |
| from fastapi import Body, FastAPI, HTTPException, Query, Request | |
| from fastapi.responses import FileResponse, HTMLResponse, JSONResponse, PlainTextResponse, Response | |
| from pydantic import BaseModel, Field | |
| from core.errors import ErrorCode, MatterOSError | |
| from core.representation import MatterStructure | |
| DASHBOARD = Path(__file__).resolve().parent / "dashboard" | |
| VIEWER_STATIC = Path(__file__).resolve().parent.parent / "visualization" / "static" | |
| STATUS = {ErrorCode.INVALID_INPUT: 400, ErrorCode.UNSUPPORTED_METHOD: 422, ErrorCode.RESOURCE_LIMIT: 429, ErrorCode.TIMEOUT: 504, | |
| ErrorCode.CHECKSUM_MISMATCH: 409, ErrorCode.CANCELLED: 409, ErrorCode.DATA_SOURCE_UNAVAILABLE: 503} | |
| # ---------------- request models ---------------- | |
| class ProjectIn(BaseModel): | |
| name: str | |
| description: str = "" | |
| goal: Optional[dict] = None | |
| constraints: Optional[dict] = None | |
| autonomy_mode: str = "bounded-autonomous" | |
| class MissionIn(BaseModel): | |
| project_id: str | |
| research_question: str | |
| spec: dict = Field(default_factory=dict) | |
| goal: Optional[dict] = None | |
| horizon: str = "short_experiment" | |
| budget: Optional[dict] = None | |
| autonomy_mode: Optional[str] = None | |
| class GenerateIn(BaseModel): | |
| project_id: str | |
| generator: str # random_cluster | known_family | symmetry_aware_crystal | graph_grammar | smiles | lj_random_cluster | motif | |
| params: dict = Field(default_factory=dict) | |
| mission_id: Optional[str] = None | |
| screen: bool = True | |
| constraints: dict = Field(default_factory=dict) | |
| class TransformIn(BaseModel): | |
| operation: str | |
| params: dict = Field(default_factory=dict) | |
| mission_id: Optional[str] = None | |
| class SubmitIn(BaseModel): | |
| candidate_id: str | |
| solver_id: str | |
| observable: str | |
| params: dict = Field(default_factory=dict) | |
| mission_id: Optional[str] = None | |
| priority: str = "normal" | |
| budget: Optional[dict] = None | |
| seed: int = 0 | |
| class MessageIn(BaseModel): | |
| sender: str | |
| recipient: str | |
| kind: str = "info" | |
| body: dict = Field(default_factory=dict) | |
| mission_id: Optional[str] = None | |
| refs: list[str] = Field(default_factory=list) | |
| class EventIn(BaseModel): | |
| subject: str | |
| predicate: str | |
| object: Any = None | |
| actor: str = "owner" | |
| evidence_refs: list[str] = Field(default_factory=list) | |
| def create_app(home: Optional[str] = None, db_path: Optional[str] = None) -> FastAPI: | |
| from matter_os.app import MatterOS | |
| mos = MatterOS(db_path=db_path, home=home) | |
| api = FastAPI(title="MATTER OS API", version="1.0.0", description="Versioned typed interfaces (spec section 14). Evidence first.") | |
| api.state.mos = mos | |
| threads: dict[str, threading.Thread] = {} | |
| V = "/api/v1" | |
| async def _err(request: Request, exc: MatterOSError): | |
| return JSONResponse(status_code=STATUS.get(exc.code, 500), content=exc.to_dict()) | |
| def dump(x): | |
| if hasattr(x, "model_dump"): | |
| return x.model_dump(mode="json") | |
| if isinstance(x, list): | |
| return [dump(i) for i in x] | |
| return x | |
| # ---------------- dashboard ---------------- | |
| def dashboard(): | |
| return (DASHBOARD / "index.html").read_text() | |
| def viewer_js(): | |
| return FileResponse(VIEWER_STATIC / "viewer.js", media_type="application/javascript") | |
| # ---------------- Project API ---------------- | |
| def create_project(p: ProjectIn): | |
| return dump(mos.create_project(p.name, p.description, p.goal, p.constraints, p.autonomy_mode)) | |
| def list_projects(include_archived: bool = False): | |
| return dump(mos.repo.list_projects(include_archived)) | |
| def update_goal(project_id: str, goal: dict = Body(...)): | |
| return dump(mos.update_goal(project_id, goal)) | |
| def set_constraints(project_id: str, constraints: dict = Body(...)): | |
| return dump(mos.set_constraints(project_id, constraints)) | |
| def archive_project(project_id: str, confirm: bool = False): | |
| return dump(mos.archive_project(project_id, confirm)) | |
| # ---------------- Mission API ---------------- | |
| def create_mission(m: MissionIn): | |
| return dump(mos.missions.create_mission(m.project_id, m.research_question, goal=m.goal, spec=m.spec, horizon=m.horizon, | |
| budget=m.budget, autonomy_mode=m.autonomy_mode)) | |
| def list_missions(project_id: Optional[str] = None): | |
| return dump(mos.repo.list_missions(project_id)) | |
| def get_mission(mission_id: str): | |
| return {**mos.missions.status(mission_id), "mission": dump(mos.repo.get_mission(mission_id)), | |
| "running_thread": mission_id in threads and threads[mission_id].is_alive()} | |
| def plan_tasks(mission_id: str): | |
| return dump(mos.missions.plan_tasks(mission_id)) | |
| def run_mission(mission_id: str, background: bool = True): | |
| if background: | |
| if mission_id in threads and threads[mission_id].is_alive(): | |
| return {"status": "already_running"} | |
| t = threading.Thread(target=lambda: mos.missions.run(mission_id), daemon=True) | |
| threads[mission_id] = t; t.start() | |
| return {"status": "started", "mission_id": mission_id} | |
| return dump(mos.missions.run(mission_id)) | |
| for action in ("pause", "resume", "approve"): | |
| def _mk(action=action): | |
| def handler(mission_id: str): | |
| return dump(getattr(mos.missions, action)(mission_id)) | |
| handler.__name__ = f"mission_{action}" | |
| return handler | |
| api.post(f"{V}/missions/{{mission_id}}/{action}")(_mk()) | |
| def cancel(mission_id: str, confirm: bool = False): | |
| return dump(mos.missions.cancel(mission_id, confirm)) | |
| def reject(mission_id: str, reason: str = ""): | |
| return dump(mos.missions.reject(mission_id, reason)) | |
| def branch(mission_id: str, body: dict = Body(default={})): | |
| return dump(mos.missions.branch(mission_id, body.get("research_question"), body.get("spec_overrides"))) | |
| def change_budget(mission_id: str, budget: dict = Body(...)): | |
| return dump(mos.missions.change_budget(mission_id, budget)) | |
| # ---------------- Candidate API ---------------- | |
| def generate(g: GenerateIn): | |
| from discovery import generators as gen | |
| from core.io import from_smiles | |
| fns = {"random_cluster": gen.random_cluster, "known_family": gen.known_family, "symmetry_aware_crystal": gen.symmetry_aware_crystal, | |
| "lj_random_cluster": gen.lj_random_cluster, "motif": gen.cluster_motif, "smiles": from_smiles, | |
| "graph_grammar": lambda **kw: gen.graph_grammar_molecule(**kw)[0]} | |
| if g.generator == "learned_model": | |
| return gen.LearnedProposalModel().propose(1, 0) | |
| if g.generator not in fns: | |
| raise MatterOSError(ErrorCode.INVALID_INPUT, f"unknown generator; allowed {sorted(fns) + ['learned_model (stub)']}") | |
| ms = fns[g.generator](**g.params) | |
| c = mos.candidates.register(ms, g.project_id, g.generator, mission_id=g.mission_id, constraints=g.constraints, screen=g.screen) | |
| return dump(c) | |
| def list_candidates(project_id: Optional[str] = None, mission_id: Optional[str] = None, maturity: Optional[str] = None): | |
| from storage.indexes import search_candidates | |
| return search_candidates(mos, project_id=project_id, maturity=maturity) if not mission_id else \ | |
| [r for r in search_candidates(mos, project_id=project_id, maturity=maturity) if r["mission_id"] == mission_id] | |
| def compare(a: str, b: str): | |
| return mos.candidates.compare(a, b) | |
| def get_candidate(candidate_id: str): | |
| c = mos.repo.get_candidate(candidate_id) | |
| return {"candidate": dump(c), "unified": MatterStructure.from_candidate(c).unified_view(), | |
| "versions": [{"version": v["version"], "checksum": v["checksum"]} for v in mos.repo.candidate_versions(candidate_id)]} | |
| def transform(candidate_id: str, t: TransformIn): | |
| return dump(mos.candidates.transform(candidate_id, t.operation, t.params, t.mission_id)) | |
| def screen(candidate_id: str, constraints: dict = Body(default={})): | |
| return dump(mos.candidates.screen(candidate_id, constraints or None)) | |
| def validate_schema(payload: dict = Body(...)): | |
| return mos.candidates.validate_schema(payload) | |
| def import_structure(project_id: str, fmt: str, text: str = Body(..., media_type="text/plain")): | |
| return dump(mos.candidates.import_structure(text, fmt, project_id)) | |
| def export_candidate(candidate_id: str, fmt: str = "xyz"): | |
| return mos.candidates.export(candidate_id, fmt) | |
| # ---------------- Simulation API ---------------- | |
| def solvers(): | |
| return mos.registry.describe() | |
| def list_compatible_solvers(candidate_id: str, observable: str): | |
| return mos.simulation.list_compatible_solvers(candidate_id, observable) | |
| def plan(candidate_id: str, observable: str): | |
| return mos.router.plan(MatterStructure.from_candidate(mos.repo.get_candidate(candidate_id)), observable) | |
| def estimate_cost(candidate_id: str, solver_id: str, observable: str): | |
| return mos.simulation.estimate_cost(candidate_id, solver_id, observable) | |
| def submit_run(s: SubmitIn): | |
| return dump(mos.simulation.submit_run(s.candidate_id, s.solver_id, s.observable, s.params, mission_id=s.mission_id, | |
| priority=s.priority, budget=s.budget, seed=s.seed)) | |
| def list_runs(candidate_id: Optional[str] = None, mission_id: Optional[str] = None, limit: int = 200): | |
| runs = mos.repo.list_runs(candidate_id=candidate_id, mission_id=mission_id)[-limit:] | |
| return [{"run_id": r.run_id, "candidate_id": r.candidate_id, "method_id": r.method_id, "exit_status": r.exit_status, | |
| "convergence_status": r.convergence_status, "error_code": r.error_code, "finished_at": r.timestamps.get("finished_at"), | |
| "wall_s": r.timestamps.get("wall_s"), "router_rationale": r.router_rationale, | |
| "observables": {k: v for k, v in r.observables.items() if k not in ("forces", "frequencies", "electronic_descriptors")}} for r in runs] | |
| def get_run(run_id: str): | |
| return dump(mos.repo.get_run(run_id)) | |
| def list_jobs(status: Optional[str] = None, mission_id: Optional[str] = None): | |
| return mos.jobs.list(status, mission_id) | |
| def get_status(job_id: str): | |
| return mos.simulation.get_status(job_id) | |
| def cancel_job(job_id: str): | |
| mos.jobs.cancel(job_id); return mos.jobs.get(job_id) | |
| def fetch_artifacts(run_id: str): | |
| return mos.simulation.fetch_artifacts(run_id) | |
| def get_artifact(artifact_id: str): | |
| return Response(mos.artifacts.get(artifact_id), media_type="text/plain") | |
| # ---------------- Agent API ---------------- | |
| def roster(): | |
| return mos.agents.roster() | |
| def assign_task(role: str, mission_id: str, stage: str): | |
| return mos.agents.assign_task(role, mission_id, stage) | |
| def send_message(m: MessageIn): | |
| return dump(mos.agents.send_message(m.sender, m.recipient, m.kind, m.body, m.mission_id, m.refs)) | |
| def messages(mission_id: str): | |
| return mos.agents.bus.thread(mission_id) | |
| def publish_result(role: str, mission_id: str, body: dict = Body(...), refs: list[str] = Query(default=[])): | |
| return mos.agents.publish_result(role, mission_id, body, refs) | |
| def request_review(requester: str, reviewer: str, mission_id: str, question: str, refs: list[str] = Query(default=[])): | |
| return dump(mos.agents.request_review(requester, reviewer, mission_id, refs, question)) | |
| def evaluations(role: Optional[str] = None): | |
| from agents.evaluation import history | |
| return history(mos.db, role) | |
| def run_role_benchmarks(): | |
| from agents.evaluation import role_benchmarks | |
| return role_benchmarks(mos) | |
| def improvements(): | |
| return [dict(r, doc=mos.db.loads(r["doc"])) for r in mos.db.query("SELECT * FROM improvements ORDER BY created_at")] | |
| def deploy(iid: str, approved_by_owner: bool = False): | |
| from agents.meta import deploy as _d | |
| return _d(mos, iid, approved_by_owner) | |
| def rollback(iid: str): | |
| from agents.meta import rollback as _r | |
| return _r(mos, iid) | |
| # ---------------- Evidence API ---------------- | |
| def compute_maturity(candidate_id: str): | |
| return mos.evidence.compute_maturity(candidate_id) | |
| def attach_claim(candidate_id: str, claim_text: str = Body(..., embed=True), laboratory_evidence: Optional[dict] = Body(default=None, embed=True)): | |
| from core.schemas import LaboratoryEvidence | |
| lab = LaboratoryEvidence(**laboratory_evidence) if laboratory_evidence else None | |
| return dump(mos.evidence.attach_claim(candidate_id, claim_text, lab)) | |
| def claims(candidate_id: Optional[str] = None): | |
| return dump(mos.repo.list_claims(candidate_id)) | |
| def request_replication(candidate_id: str, run_id: str, seed: int = 1): | |
| return mos.evidence.request_replication(candidate_id, run_id, seed=seed) | |
| def compare_sources(values: list[dict] = Body(...)): | |
| return mos.evidence.compare_sources(values) | |
| def benchmarks(project_id: str, ids: list[str] = Query(default=[])): | |
| from simulation.benchmarks import run_all | |
| return run_all(mos, project_id, ids or None) | |
| # ---------------- Knowledge API ---------------- | |
| def propose_event(e: EventIn): | |
| return mos.knowledge.propose_event(e.subject, e.predicate, e.object, e.actor, e.evidence_refs) | |
| def verify_event(fact_id: str, actor: str = "data_steward", evidence_refs: list[str] = Query(default=[])): | |
| return mos.knowledge.verify_event(fact_id, actor, evidence_refs) | |
| def fact_history(fact_id: str): | |
| return mos.knowledge.kg.history(fact_id) | |
| def search_graph(text: str = "", status: Optional[str] = None, etype: Optional[str] = None): | |
| return mos.knowledge.search_graph(text, status, etype) | |
| def get_lineage(candidate_id: str): | |
| return mos.knowledge.get_lineage(candidate_id) | |
| def kg_counts(): | |
| return mos.knowledge.kg.status_counts() | |
| def sources(): | |
| from knowledge.provenance import list_sources | |
| return list_sources(mos.db) | |
| # ---------------- Resource API ---------------- | |
| def get_capacity(): | |
| return mos.resources.get_capacity() | |
| def allocate(job_id: str, priority: str = "normal", request: dict = Body(default={})): | |
| a = mos.resources.allocate(job_id, priority, request) | |
| return {"allocation": a, "granted": a is not None} | |
| def release(job_id: str): | |
| mos.resources.release(job_id); return {"released": job_id} | |
| def checkpoint(target_id: str): | |
| from orchestration.checkpoints import checkpoint as ck | |
| return ck(mos, target_id) | |
| def enforce_quota(request: dict = Body(...)): | |
| return mos.resources.enforce_quota(request) | |
| def snapshot(): | |
| from storage.archive import snapshot as snap | |
| return {"snapshot": snap(mos).name} | |
| def integrity(): | |
| from storage.archive import verify_integrity | |
| return verify_integrity(mos) | |
| def queue(): | |
| from orchestration.queues import queue_snapshot | |
| return queue_snapshot(mos) | |
| def pause_all(paused: bool = True): | |
| mos.paused_global = paused | |
| mos.db.audit("owner", "pause_all" if paused else "resume_all", "*", {}) | |
| return {"paused_global": paused} | |
| # ---------------- Export API ---------------- | |
| def export_structure(candidate_id: str, fmt: str = "xyz"): | |
| return mos.candidates.export(candidate_id, fmt) | |
| def export_run_bundle(run_id: str): | |
| from storage.archive import export_run_bundle as e | |
| return Response(e(mos, run_id), media_type="application/gzip", headers={"Content-Disposition": f"attachment; filename={run_id}.tar.gz"}) | |
| def export_report(mission_id: str, fmt: str = "md"): | |
| from storage.archive import export_report as e | |
| return Response(e(mos, mission_id, fmt), media_type="text/markdown" if fmt == "md" else "application/json") | |
| def export_project(project_id: str): | |
| from storage.archive import export_project as e | |
| return Response(e(mos, project_id), media_type="application/gzip", headers={"Content-Disposition": f"attachment; filename={project_id}.tar.gz"}) | |
| # ---------------- Observability / dashboard data ---------------- | |
| def audit(limit: int = 200, actor: Optional[str] = None): | |
| if actor: | |
| rows = mos.db.query("SELECT * FROM audit_log WHERE actor=? ORDER BY id DESC LIMIT ?", (actor, limit)) | |
| else: | |
| rows = mos.db.query("SELECT * FROM audit_log ORDER BY id DESC LIMIT ?", (limit,)) | |
| return [dict(r, details=mos.db.loads(r["details"])) for r in rows] | |
| def metrics(limit: int = 500): | |
| return mos.db.query("SELECT * FROM metrics ORDER BY id DESC LIMIT ?", (limit,)) | |
| def failures(mission_id: Optional[str] = None): | |
| rows = mos.db.query("SELECT * FROM failures" + (" WHERE mission_id=?" if mission_id else "") + " ORDER BY created_at DESC LIMIT 200", | |
| (mission_id,) if mission_id else ()) | |
| return [dict(r, doc=mos.db.loads(r["doc"])) for r in rows] | |
| def viewer_data(candidate_id: str, run_id: Optional[str] = None): | |
| from visualization.viewer import structure_payload | |
| return structure_payload(mos, candidate_id, run_id) | |
| def summary(): | |
| from visualization.dashboards import summary as s | |
| return s(mos) | |
| return api | |