diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..be0b08c --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,49 @@ +name: Docs + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: docs-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-python@v7 + with: + python-version: "3.13" + - name: Install + run: pip install -r docs/requirements.txt + - name: Build + run: mkdocs build --strict + - if: github.ref == 'refs/heads/main' + uses: actions/upload-pages-artifact@v5 + with: + path: site + + # Pull requests only build the site; main also deploys it. + deploy: + if: github.ref == 'refs/heads/main' && github.repository == 'ThinkFlowLab/system1-omni' + needs: build + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + uses: actions/deploy-pages@v5 diff --git a/.gitignore b/.gitignore index 3857937..fd0f343 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,7 @@ target .venv/ __pycache__/ .DS_Store + +# Documentation site build and environment +/site/ +.venv-docs/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b06c929..53fa46c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,3 +49,22 @@ A coding agent can help review the diff and identify issues, but contributors remain responsible for understanding the changes and verifying the results. Self-review helps maintainers focus on design and correctness; it does not replace maintainer review. + +## Documentation site + +The site at is built with MkDocs +from the README, this guide, the frontend README and the Markdown files under +`recipe/` and `docs/`. `mkdocs.yml` sets the navigation and, in `exclude_docs`, +the published files. Pages keep their repository paths, so write links as +relative paths that work on GitHub; links to files that are not published go to +GitHub. Put images in `docs/assets/`. + +To run the check from the Docs workflow and preview the site, with Python 3.10 or +later: + +```sh +python3 -m venv .venv-docs +.venv-docs/bin/pip install -r docs/requirements.txt +.venv-docs/bin/mkdocs build --strict +.venv-docs/bin/mkdocs serve # http://127.0.0.1:8001/system1-omni/ +``` diff --git a/README.md b/README.md index 76944aa..3d00ab3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # System1-Omni +Documentation: + A community-maintained inference engine for prefill-only System1-Omni models, designed around a Rust frontend, model-owned execution, and high-performance CUDA and Metal backends. The Rust frontend forwards requests to a separately running model worker. In-repository model engines and GPU backends are not implemented yet. diff --git a/docs/hooks.py b/docs/hooks.py new file mode 100644 index 0000000..7f86b2d --- /dev/null +++ b/docs/hooks.py @@ -0,0 +1,58 @@ +"""MkDocs hooks that build the site from the repository root. + +MkDocs rejects `docs_dir: .`, so the root is set here, after the config is +checked, and `exclude_docs` in mkdocs.yml picks the published files. Pages keep +their repository paths, so relative links work as they do on GitHub. Inline +links to files that are not published, or to directories without a README, go +to GitHub. +""" + +import logging +import posixpath +import re +from pathlib import Path + +log = logging.getLogger("mkdocs.hooks") +ROOT = Path(__file__).resolve().parent.parent +IMAGES = (".gif", ".jpeg", ".jpg", ".png", ".svg", ".webp") +# The target of an inline link that is a relative path: ](path#anchor) +LINK = re.compile(r"\]\((?![a-z][a-z0-9+.-]*:|#|/)([^)\s#]+)(#[^)\s]*)?\)") + + +def on_config(config): + config.docs_dir = str(ROOT) + return config + + +def on_serve(server, config, builder): + # Watch the published sources only, not target/ or virtual environments. + server.unwatch(config.docs_dir) + for name in ("README.md", "CONTRIBUTING.md", "docs", "recipe", "src"): + server.watch(str(ROOT / name)) + return server + + +def on_page_markdown(markdown, page, config, files): + base = posixpath.dirname(page.file.src_uri) + github = config.repo_url.rstrip("/") + + def published(path): + file = files.get_file_from_path(path) + return file is not None and file.inclusion.is_included() + + def fix(m): + target, anchor = m[1], m[2] or "" + path = posixpath.normpath(posixpath.join(base, target)) + if path.split("/")[0] == ".." or not (ROOT / path).exists() or published(path): + return m[0] # a page, or a missing file for MkDocs to report + if (ROOT / path).is_dir(): + if published(posixpath.join(path, "README.md")): + return f"]({posixpath.join(target, 'README.md')}{anchor})" + return f"]({github}/tree/main/{path}{anchor})" + if path.lower().endswith(IMAGES): + # A GitHub page is not an image; the image has to be published. + log.warning("%s: %s is not published, see exclude_docs", page.file.src_uri, target) + return m[0] + return f"]({github}/blob/main/{path}{anchor})" + + return LINK.sub(fix, markdown) diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..4d732ea --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,3 @@ +mkdocs==1.6.1 +mkdocs-material==9.7.7 +pymdown-extensions==12.1 diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..2d63d2e --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,53 @@ +site_name: System1-Omni +site_url: https://thinkflowlab.github.io/system1-omni/ +repo_url: https://github.com/ThinkFlowLab/system1-omni +edit_uri: edit/main/ +# The recipes run their workers on port 8000. +dev_addr: 127.0.0.1:8001 + +theme: + name: material + features: + - content.action.edit + - content.code.copy + - navigation.indexes + - navigation.sections + - search.highlight + +# docs/hooks.py builds the site from the repository root, so each page keeps its +# repository path and relative links work here as they do on GitHub. +hooks: + - docs/hooks.py +# The published files; assets/ is the theme's. Nothing in hidden directories. +exclude_docs: | + * + !/README.md + !/CONTRIBUTING.md + !/docs/**/*.md + !/docs/assets/** + !/recipe/**/*.md + !/src/frontend/README.md + !/assets/** + **/.*/** + +validation: + absolute_links: warn + unrecognized_links: warn + anchors: warn + +markdown_extensions: + - toc: + permalink: true + # Heading anchors as GitHub makes them. + slugify: !!python/object/apply:pymdownx.slugs.slugify + kwds: + case: lower + - pymdownx.superfences + +nav: + - Overview: README.md + - Frontend: src/frontend/README.md + - Recipes: + - recipe/README.md + - Laya text worker: recipe/laya/README.md + - Contributing: CONTRIBUTING.md