Download dense_evolution/cli.py from Tatopenn/dense-Evolution: direct link, hf CLI and curl.
- Browser
- Download file 8.4 kB
-
https://huggingface.co/Tatopenn/dense-Evolution/resolve/main/dense_evolution/cli.py
- Command line
-
hf download hf://Tatopenn/dense-Evolution/dense_evolution/cli.py
-
curl -L -o cli.py https://huggingface.co/Tatopenn/dense-Evolution/resolve/main/dense_evolution/cli.py
8.4 kB
| """ | |
| `dense-evolution` console script (see pyproject.toml [project.scripts]). | |
| Three real subcommands: | |
| serve starts the local Composer kernel (local_site.app.server) | |
| that the published Composer page (docs/composer.md) | |
| talks to. | |
| offline-composer downloads the real published Composer page (the same | |
| HTML Github Pages serves, not a hand-rolled copy) plus | |
| the same-origin assets it references, into a local | |
| folder -- so it opens via file:// with no internet at | |
| all, while still talking to the local kernel above. | |
| mcp starts the dense_evolution_mcp MCP server (mcp_server/), | |
| a thin adapter that exposes the same Composer kernel | |
| endpoints as MCP tools for an agent to call directly. | |
| Requires `serve` running separately -- this process | |
| talks to that kernel over HTTP, it doesn't embed it. | |
| fastapi/uvicorn/pydantic (composer) and mcp/httpx (mcp) are optional | |
| extras, not core dependencies -- imported here, inside their own command | |
| branch, not at module level, so `import dense_evolution` itself never | |
| requires them. | |
| """ | |
| import sys | |
| USAGE = """usage: dense-evolution <command> | |
| commands: | |
| serve Start the local Composer kernel (http://127.0.0.1:8800) | |
| that the published Composer page (docs/composer.md) | |
| connects to. | |
| offline-composer [DEST] Download the real published Composer page and its | |
| assets into DEST (default: ./composer-offline) so | |
| it works via file:// with no internet. | |
| mcp Start the dense_evolution_mcp MCP server (stdio | |
| transport) so an agent can call the Composer | |
| kernel's endpoints directly. Requires `serve` | |
| running separately (default http://127.0.0.1:8800, | |
| override with DENSE_EVOLUTION_KERNEL_URL). | |
| Requires the composer extra: pip install dense-evolution[composer] | |
| The mcp command requires the mcp extra: pip install dense-evolution[mcp] | |
| """ | |
| COMPOSER_PAGE_URL = "https://tatopenn-cell.github.io/Dense-Evolution/composer/" | |
| def _require_composer_extra(): | |
| try: | |
| import fastapi, uvicorn, pydantic # noqa: F401 | |
| except ImportError as exc: | |
| print( | |
| "dense-evolution needs the composer extra:\n" | |
| " pip install dense-evolution[composer]\n" | |
| f"(missing: {exc.name})", | |
| file=sys.stderr, | |
| ) | |
| sys.exit(1) | |
| def _cmd_serve(): | |
| _require_composer_extra() | |
| from local_site.app.server import main as serve_main | |
| serve_main() | |
| def _require_mcp_extra(): | |
| try: | |
| import mcp, httpx # noqa: F401 | |
| except ImportError as exc: | |
| print( | |
| "dense-evolution needs the mcp extra:\n" | |
| " pip install dense-evolution[mcp]\n" | |
| f"(missing: {exc.name})", | |
| file=sys.stderr, | |
| ) | |
| sys.exit(1) | |
| def _cmd_mcp(): | |
| _require_mcp_extra() | |
| from mcp_server.server import main as mcp_main | |
| mcp_main() | |
| def _cmd_offline_composer(dest: str): | |
| """Mirrors COMPOSER_PAGE_URL into `dest`: the page itself plus every | |
| same-origin <link href>/<script src> it references (Material's shared | |
| theme CSS/JS bundle, the Composer-specific app.js/style.css), each | |
| saved at the same relative path it already uses on the live site -- | |
| mkdocs/Material already generate those as page-relative, precisely so | |
| a subtree like this stays self-consistent once copied elsewhere. Not a | |
| full recursive mirror (fonts referenced only from inside a CSS url() | |
| are not followed -- Material falls back to system fonts without them, | |
| a cosmetic gap, not a functional one): scoped to what the page's own | |
| <head>/<body> actually link to, which is everything the Composer UI | |
| itself needs to run.""" | |
| import os | |
| import urllib.request | |
| from html.parser import HTMLParser | |
| from urllib.parse import urljoin, urlparse | |
| class _AssetFinder(HTMLParser): | |
| def __init__(self): | |
| super().__init__() | |
| self.assets = [] | |
| def handle_starttag(self, tag, attrs): | |
| attrs = dict(attrs) | |
| # mkdocs Material's <head> has plenty of other <link> rels | |
| # (canonical, prev, next, preconnect, ...) that point at other | |
| # *pages* (directories, not files) or aren't fetchable assets | |
| # at all -- verified directly against the real page: following | |
| # rel="prev"/"next" tried to write a file at a directory-shaped | |
| # path and failed with a permission error. Only stylesheet/icon | |
| # links are real same-origin files worth mirroring. | |
| if tag == "link" and attrs.get("href") and attrs.get("rel") in ("stylesheet", "icon"): | |
| self.assets.append(attrs["href"]) | |
| elif tag == "script" and attrs.get("src"): | |
| self.assets.append(attrs["src"]) | |
| elif tag == "img" and attrs.get("src"): | |
| self.assets.append(attrs["src"]) | |
| print(f"Scarico {COMPOSER_PAGE_URL} ...") | |
| with urllib.request.urlopen(COMPOSER_PAGE_URL, timeout=30) as resp: | |
| html_bytes = resp.read() | |
| html_text = html_bytes.decode("utf-8", errors="replace") | |
| parser = _AssetFinder() | |
| parser.feed(html_text) | |
| page_url = urlparse(COMPOSER_PAGE_URL) | |
| base_origin = f"{page_url.scheme}://{page_url.netloc}" | |
| # mkdocs generates every relative link (../assets/...) relative to the | |
| # SITE root, not to whatever folder happens to hold index.html -- so | |
| # the page itself has to be saved at the same depth under `dest` it | |
| # already has under the site root (site_root_path stripped from its | |
| # own path leaves "composer/"), or its own "../assets/..." references | |
| # end up pointing one directory above `dest` instead of inside it. | |
| # site_root_path is derived from COMPOSER_PAGE_URL itself (this | |
| # project's one fixed, known URL), not guessed from each asset URL. | |
| site_root_path = page_url.path.rsplit("composer/", 1)[0] | |
| def _relative_to_site_root(url: str) -> str: | |
| path = urlparse(url).path | |
| if path.startswith(site_root_path): | |
| path = path[len(site_root_path):] | |
| return path.lstrip("/") | |
| os.makedirs(dest, exist_ok=True) | |
| page_relative_path = _relative_to_site_root(COMPOSER_PAGE_URL) + "index.html" | |
| page_local_path = os.path.join(dest, page_relative_path) | |
| os.makedirs(os.path.dirname(page_local_path), exist_ok=True) | |
| with open(page_local_path, "w", encoding="utf-8") as f: | |
| f.write(html_text) | |
| seen = set() | |
| for href in parser.assets: | |
| absolute_url = urljoin(COMPOSER_PAGE_URL, href) | |
| if not absolute_url.startswith(base_origin) or absolute_url in seen: | |
| continue # a genuinely external resource (e.g. a CDN) -- not ours to mirror | |
| seen.add(absolute_url) | |
| relative_path = _relative_to_site_root(absolute_url) | |
| local_path = os.path.join(dest, relative_path) | |
| os.makedirs(os.path.dirname(local_path), exist_ok=True) | |
| try: | |
| with urllib.request.urlopen(absolute_url, timeout=30) as resp: | |
| data = resp.read() | |
| with open(local_path, "wb") as f: | |
| f.write(data) | |
| print(f" scaricato: {relative_path}") | |
| except Exception as exc: | |
| print(f" saltato (non essenziale): {relative_path} ({exc})") | |
| print(f"\nCopia offline pronta: {page_local_path}") | |
| return page_local_path | |
| def main(argv=None): | |
| args = argv if argv is not None else sys.argv[1:] | |
| if args == ["serve"]: | |
| _cmd_serve() | |
| return | |
| if args and args[0] == "offline-composer": | |
| dest = args[1] if len(args) > 1 else "composer-offline" | |
| _cmd_offline_composer(dest) | |
| return | |
| if args == ["mcp"]: | |
| _cmd_mcp() | |
| return | |
| print(USAGE, file=sys.stderr if args else sys.stdout) | |
| sys.exit(1 if args else 0) | |
| if __name__ == "__main__": | |
| main() | |