[build-system] requires = ["setuptools>=61.0", "wheel", "setuptools-scm>=8.0"] build-backend = "setuptools.build_meta" [project] name = "hart-backend" dynamic = ["version"] description = "HART OS - Hevolve Hive Agentic Runtime: Crowdsourced compute infrastructure for autonomous Hive AI Training. Distributed thought process across crowdsourced agents, distributed coding agents incentivizing compute providers, self-sustaining economy at national scale so no single entity, government, or corporation monopolizes AI. Intelligence belongs to the people. Only the master key (held by human stewards) can halt the being. Every engineering decision is transparent by design." readme = "README.md" license = {text = "Apache-2.0"} requires-python = ">=3.9" authors = [ {name = "HART Team", email = "contact@hevolve.ai"} ] keywords = [ "hart", "hevolve", "ai", "agents", "hivemind", "crowdsourced", "multi-agent", "orchestration", "langchain", "llm", ] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ # Pin versions to match installed — prevents pip backtracking. # Updated 2026-03-03. # Multi-agent orchestration "autogen-agentchat==0.2.37", "autogen-agentchat[long-context]~=0.2", "apscheduler>=3.10.0,<4.0.0", "json-repair>=0.59.4,<1.0.0", # Communication (autobahn + extras on one line to avoid duplicates) "autobahn>=23.1.2", "autobahn[serialization]", "autobahn[twisted]", "crossbarhttp3>=1.1,<2.0", "websockets>=11.0.0,<17.0", # Web framework (aligned with requirements.txt) "Flask>=2.3.0,<4.0.0", "waitress>=2.1.0,<4.0.0", "fastapi>=0.100.0,<1.0.0", "uvicorn>=0.22.0,<1.0.0", "starlette>=0.40.0,<1.0.0", # Database — hevolve-database is the single source of truth for all models "hevolve-database @ git+https://github.com/hertz-ai/Hevolve_Database.git@realistic_intro_video", "SQLAlchemy>=2.0.0,<3.0.0", "redis>=4.6.0,<8.0.0", # LangChain ecosystem — pinned to avoid pip backtracking (40+ version checks) "langchain-classic>=1.0.0,<2.0.0", "langchain-core>=1.2.0,<2.0.0", "langchain-text-splitters>=1.0.0,<2.0.0", "langsmith>=0.3.0,<1.0.0", # LLM providers "openai>=1.0.0,<3.0.0", "groq>=0.5.0,<1.0.0", # ML/Vector stores (optional heavy deps — install separately if needed) # "chromadb>=0.3.0", # "faiss-cpu>=1.7.0", # "sentence-transformers>=2.2.0", # Core utilities "python-dotenv>=1.0.0,<2.0.0", "pydantic>=2.0.0,<3.0.0", "aiohttp>=3.9.0,<4.0.0", "aiofiles>=23.2.0,<26.0.0", "requests>=2.31.0,<3.0.0", "httpx>=0.27.0,<1.0.0", # Data processing "numpy>=1.25.0,<2.0.0", "pandas>=2.0.0,<4.0.0", "beautifulsoup4>=4.12.0,<5.0.0", # Keyless web search — tier A of helper.py:_keyless_serp (`from ddgs import # DDGS` at :348), first in the ladder. Undeclared until 2026-08-29, so it had # never run once and google_search returned [] on every install; the other # keyless tiers are blocked (Mojeek serves a captcha behind HTTP 200, DDG html # 202) and tier D needs SEARXNG_URL, set nowhere. Pulls primp (browser TLS # impersonation, the reason this tier survives) and lxml transitively. "ddgs>=9.16.0", # The book pipeline's one PDF engine (see requirements.txt for why). "pypdfium2>=5.13.0,<6.0.0", # Tokenization "tiktoken>=0.5.0,<1.0.0", "transformers>=4.46.0,<6.0.0", "huggingface_hub>=0.27.0,<0.29.0", # 0.29+ removes is_offline_mode needed by transformers # Embodied AI — HevolveAI is closed-source, loaded as encrypted native binary. # NEVER cloned in public CI. Ships as .so.enc, decrypted at runtime in tmpfs. # Install separately: pip install hevolve-ai (from private registry) # Or: download signed binary from GitHub Release → ~/.hevolve/lib/ # "embodied-ai @ git+https://github.com/hertz-ai/HevolveAI.git@main", # Security "cryptography>=41.0.0,<47.0.0", "PyJWT>=2.14.0,<3.0.0", # Image processing "Pillow>=9.5.0,<13.0.0", "opencv-python", # Video assembly — imageio + the bundled-ffmpeg plugin. Used by # integrations/remote_desktop/frame_capture.py::record_to_video # (demo/call capture, invoked from agent_engine/marketing_tools.py) # and integrations/vision/ltx2_server.py (LTX2 video generation). # The imports are guarded (graceful GIF fallback when absent), but # listing them here makes the mp4/H.264 path work out-of-the-box on # flat/regional/central topologies across Win/macOS/Linux. imageio # is pure-Python; imageio-ffmpeg ships a per-OS ffmpeg wheel pip # auto-selects. Compatible with the numpy<2 + Pillow pins above. "imageio>=2.30.0,<3.0.0", "imageio-ffmpeg>=0.5.0,<1.0.0", # Speech-to-text (ONNX runtime — no PyTorch needed, CPU-optimized) "sherpa-onnx>=1.11.0", # Other utilities "pytz>=2023.3", "python-multipart>=0.0.6,<1.0.0", "tenacity>=8.2.0,<10.0.0", "tqdm>=4.65.0,<5.0.0", "coloredlogs>=15.0.0,<16.0.0", "PyYAML>=6.0,<7.0", # LiveKit (Phase 7d.B) — voice/video/screen-share SFU. # Hard dep so `pip install -e .` includes the JWT-signing SDK # by default; the LiveKitService auto-generates dev keys when # LIVEKIT_API_KEY/SECRET aren't set, so flat/regional installs # work without manual provisioning. External SFU (LiveKit # Cloud or self-hosted livekit-server binary) is a separate # piece of infra; HARTOS only ships the token issuer. "livekit-api>=1.0.0,<2.0.0", ] [project.optional-dependencies] telegram = ["python-telegram-bot>=21.0"] discord = ["discord.py>=2.3.0"] torch = [ "torch>=2.1.0", "torchvision>=0.16.0", ] google = [ "google-cloud-aiplatform>=1.36.0", "google-cloud-bigquery>=3.13.0", "google-cloud-storage>=2.13.0", "google-api-python-client>=2.90.0", ] memory = ["simplemem>=0.1.0"] remote-desktop = [ "mss>=9.0.0", "websockets>=12.0", "av>=12.0.0,<19", "pynput>=1.7.0", ] sdk = [] mobile = [] dev = [ "pytest>=7.0.0", "pytest-asyncio>=0.21.0", "pytest-cov>=4.0.0", "black>=23.0.0", "flake8>=6.0.0", "mypy>=1.0.0", "bandit[toml]>=1.7.0", "pip-audit>=2.6.0", "pre-commit>=3.5.0", ] all = [ "python-telegram-bot>=21.0", "discord.py>=2.3.0", "torch>=2.1.0", "torchvision>=0.16.0", "google-cloud-aiplatform>=1.36.0", "google-cloud-bigquery>=3.13.0", "google-cloud-storage>=2.13.0", "google-api-python-client>=2.90.0", "simplemem>=0.1.0", ] [project.scripts] hart = "hart_cli:hart" hart-server = "hart_intelligence_entry:main" hart-crossbar = "crossbar_server:main" [project.urls] Homepage = "https://github.com/hertz-ai/HARTOS" Documentation = "https://docs.hevolve.ai" Repository = "https://github.com/hertz-ai/HARTOS" Issues = "https://github.com/hertz-ai/HARTOS/issues" [tool.setuptools] # Entry/facade modules only; the implementation lives in the hartos/ # package (moved from the repo root 2026-08-30). Nunba's freeze scripts # auto-discover this list, so it must stay in lockstep with the repo root. py-modules = [ "hart_version", "hart_intelligence", "hart_intelligence_entry", "embedded_main", "asgi", ] # packages.find walks BOTH the repo root (for core/integrations/security/ # hart_sdk and all their subpackages) AND agent-ledger-opensource/ (for # the vendored agent_ledger top-level import). The package_dir mapping # below tells setuptools where on disk to read agent_ledger sources; # without it, install would fail with "package directory does not exist". # Future: when agent-ledger is published to PyPI standalone, drop # `agent_ledger*` from include + the package_dir mapping below + the # corresponding find_packages(where=...) call in setup.py, and add # `agent-ledger>=1.2.0` to [project.dependencies] above instead. [tool.setuptools.packages.find] where = [".", "agent-ledger-opensource"] # NOTE desktop/ is deliberately NOT shipped: Nunba owns the top-level # `desktop` package (14 app modules). HARTOS's desktop/ is a 2-file # standalone fallback; shipping it shadows Nunba's package in the frozen # app (12 ModuleNotFoundError, build 2026-08-31). In the co-located app # `import desktop.ai_key_vault` resolves Nunba's copy at runtime. include = ["core*", "hartos", "integrations*", "security*", "hart_sdk*", "agent_ledger*"] exclude = ["venv*", "tests*", "docs*", "examples*"] [tool.setuptools.package-dir] agent_ledger = "agent-ledger-opensource/agent_ledger" [tool.setuptools.package-data] # *.js/*.svg/*.css bundle the glass-shell static assets (the desktop 404s without them) "*" = ["*.yaml", "*.yml", "*.json", "*.txt", "*.md", "*.js", "*.svg", "*.css"] [tool.setuptools_scm] version_scheme = "guess-next-dev" local_scheme = "no-local-version" fallback_version = "0.0.0" write_to = "hart_version.py" tag_regex = "^v(?P\\d+\\.\\d+\\.\\d+)$" # Pre-filter at the `git describe` level so CI-created `nightly-*` # tags (which are commit-id + run-id artifacts, NOT semver) never # reach the version parser. Without this, vcs_versioning asserts on # the unparseable tag before tag_regex (above) gets a chance to # fall back — build dies with `AssertionError: version is not None` # at vcs_versioning/_scm_version.py:329. git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--match", "v[0-9]*"] [tool.black] line-length = 100 target-version = ['py39', 'py310', 'py311', 'py312'] include = '\.pyi?$' exclude = ''' /( \.git | \.mypy_cache | \.pytest_cache | \.venv | venv | venv310 | build | dist | __pycache__ )/ ''' [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py", "*_test.py"] python_functions = ["test_*"] asyncio_mode = "auto" addopts = "-v --tb=short" # agent_ledger is vendored in-tree (agent-ledger-opensource/agent_ledger) and # packaged by setup.py at INSTALL time — but tests run from the SOURCE # checkout, where `from agent_ledger import ...` (13+ call sites) has nothing # on the path. Ini-level pythonpath (works under --noconftest, unlike a # conftest shim) resolves the ONE canonical in-tree package for every test # invocation; production resolution (installed wheel / frozen bundle) is # unchanged. Fixed 8 standing test_lifecycle_hooks reds (task #15-adjacent). pythonpath = [".", "agent-ledger-opensource"] [tool.mypy] python_version = "3.9" warn_return_any = true warn_unused_configs = true ignore_missing_imports = true exclude = [ "venv", "venv310", "tests", "build", "dist", ] [tool.flake8] max-line-length = 100 exclude = [ ".git", "__pycache__", "venv", "venv310", "build", "dist", ] ignore = ["E501", "W503", "E203"] [tool.bandit] exclude_dirs = ["venv", "venv310", "tests", "autogen-0.2.37", ".pycharm_plugin", "build", "dist"] skips = ["B101", "B404", "B603", "B607"] # Ruff config — singleton-pattern enforcement for the canonical # hart_intelligence facade. See `core/safe_hartos_attr.py` for the # accessor pattern. Rationale: worker-thread `from hart_intelligence # import …` calls race the canonical loader on Python's per-module # import lock, causing multi-minute agent_daemon freezes (Tier-1 init # never completes). Resolving via the singleton accessor reads # sys.modules directly — no import lock acquisition. # # TID251 (banned-api) lints AST nodes only — it will NOT trip on the # string appearing in comments or docstrings, which is why we picked it # over a grep CI step. [tool.ruff] exclude = [ ".git", ".venv", "venv", "venv310", "build", "dist", "tests", "autogen-0.2.37", ".pycharm_plugin", ] [tool.ruff.lint] extend-select = ["TID"] # flake8-tidy-imports — gives us TID251 [tool.ruff.lint.flake8-tidy-imports.banned-api] "hart_intelligence".msg = """ Worker code must not import hart_intelligence directly — that triggers \ Python's per-module import lock and races the canonical loader \ (routes/hartos_backend_adapter.py:_attempt_hartos_init), causing \ multi-minute agent_daemon freezes when worker threads compete with \ the loader on the langchain_core / transformers import chain. \ Use core.safe_hartos_attr.safe_hartos_attr('symbol_name') instead — \ it's a sys.modules dict lookup that returns None until the canonical \ loader finishes (caller no-ops gracefully). Only the loader carries \ `# noqa: TID251` to opt out of this rule. """ "hart_intelligence_entry".msg = """ Same singleton-pattern rule as hart_intelligence — workers must use \ core.safe_hartos_attr.safe_hartos_attr() instead of importing this \ module directly. """