aiofiles==23.2.1 aiohttp==3.9.5 aiosignal==1.3.1 annotated-types==0.6.0 anyio==4.8.0 # APScheduler — BackgroundScheduler used by create_recipe.py (scheduled tasks), # agent_engine daemon, time_agent, etc. Was only satisfied transitively via the # Nunba bundle's requirements, so HARTOS standalone + CI hit # ModuleNotFoundError: apscheduler (2 unit tests failed collection, #82). Pin # to the version the shipped bundle uses. apscheduler==3.11.2 async-timeout==4.0.2 attrs==23.1.0 backoff==2.2.1 beautifulsoup4==4.12.3 blinker==1.6.2 bs4==0.0.2 cachetools==5.3.1 certifi==2023.5.7 charset-normalizer==3.1.0 chromadb==0.3.23 click==8.1.8 clickhouse-connect==0.6.4 cmake==3.26.4 colorama==0.4.6 cryptography==43.0.0 # autobahn (+ its txaio dep) is a MODULE-SCOPE import of production code # (reuse_recipe.py / create_recipe.py: `import txaio; txaio.use_asyncio()` # before autobahn) -- it was never declared here, so every dev box happened # to have it while the CI runner did not, and the whole WAMP-adjacent test # family failed collection there (gate run 31938229518). A hard production # import must be a declared dependency. # Pinned to 23.1.2, NOT the latest: both images install `autobahn==23.1.2` # explicitly right after this file (Dockerfile:61, deploy/cloud/Dockerfile.prod:37), # so 23.1.2 is what actually runs -- and autobahn >=25.9 requires Python >=3.11, # which the py3.10 image cannot satisfy at all (it failed the whole build here). autobahn==23.1.2 # autogen-agentchat: production imports `autogen` (core/labeled_autogen_function.py # at module scope; create_recipe lazily). It was only ever satisfied by a # LOOSE VENDORED autogen-0.2.37/ directory that was never committed, so # every fresh checkout (CI included) failed. # # ONE autogen distribution everywhere: autogen-agentchat==0.2.37, the same pin # as pyproject.toml, Dockerfile, deploy/cloud/Dockerfile.prod, # nixos/packages/hart-app.nix and Nunba (requirements.txt, requirements-lock.txt, # scripts/deps.py). It provides the same top-level `autogen` package, so never # install pyautogen alongside it (both write into autogen/). # # This line used to pin pyautogen==0.2.35 on the claim that "0.2.37 was never # published to PyPI under any name". That was false: autogen-agentchat 0.2.36.. # 0.2.40 are on PyPI. And 0.2.35 is NOT the same API the code is written for: # - GroupChat has no select_speaker_transform_messages= (added in 0.2.36); # reuse_recipe.create_agents_for_role passes it, so the role group raised # TypeError at construction (CI: 3 setup ERRORs in the group-log tests). # - MessageHistoryLimiter / MessageTokenLimiter do not pop a window that # opens on a tool result; helper._context_limiter_classes corrects the # 0.2.37 pop, so under 0.2.35 it duplicated the newest message and ran # past the token budget (CI: 85 failures in # test_context_limiters_keep_the_newest.py). # Requires-Dist is identical to pyautogen 0.2.35; Requires-Python is >=3.8,<3.13. # ddgs SERP parsing (see the ddgs note above) - NOT transitive in this image lxml==6.1.2 # ddgs HTTP layer, browser TLS impersonation - NOT transitive in this image primp==2.0.0 autogen-agentchat==0.2.37 coloredlogs==15.0.1 config==0.5.1 crossbarhttp3==1.1 dataclasses-json==0.6.7 # Keyless web search. helper.py:348 `from ddgs import DDGS` is tier A of # _keyless_serp and sits FIRST in the ladder, but the package was never declared # anywhere, so that tier has never executed. Measured 2026-08-29 from a # residential desktop, every other keyless tier is dead: Mojeek returns HTTP 200 # WITH A CAPTCHA (raises nothing, logs nothing, yields []), DDG html returns 202, # and tier D needs SEARXNG_URL which is set nowhere. So google_search returns [] # on every install. ddgs survives because its transport (primp) does browser TLS # impersonation rather than being fingerprinted as a bot; verified against the # exact tier-A path, 5 rows with titles/urls/snippets. primp + lxml are # PINNED BELOW, not left transitive: this comment used to claim they # resolve transitively, and the image build proved otherwise. Measured # 2026-08-31 inside the live central container: ddgs imported fine while # primp and lxml were both ABSENT, so every tier-A query died with # ModuleNotFoundError: No module named 'lxml' and search was dead on # central for weeks. Adding them to a throwaway container off the same # image returned 3 real results from central's own IP, which also # refutes the datacenter-IP-block theory that #34 carried. # transitively and are deliberately not pinned here. ddgs==9.16.0 dill==0.3.7 distro==1.8.0 duckdb==0.8.1 exceptiongroup==1.1.1 fastapi==0.115.6 filelock==3.12.2 Flask==2.3.2 flatbuffers==23.5.26 frozenlist==1.3.3 fsspec==2023.6.0 future==1.0.0 grpcio==1.57.0 grpcio-status==1.57.0 google-auth==2.49.0 google-api-core==2.28.0 google-api-python-client==2.190.0 google-auth-httplib2==0.2.0 google-cloud-core==2.4.3 google-cloud-storage==3.9.0 google-cloud-aiplatform==1.130.0 google-cloud-bigquery==3.13.0 google-cloud-resource-manager==1.10.4 google-crc32c==1.5.0 google-resumable-media==2.8.0 google-search-results==2.4.2 googleapis-common-protos==1.59.1 graphlib-backport==1.0.3 greenlet==2.0.2 groq==0.30.0 h11==0.16.0 hnswlib==0.7.0 httpcore==1.0.9 httplib2==0.22.0 httptools==0.5.0 httpx==0.28.1 huggingface-hub==0.15.1 humanfriendly==10.0 idna==3.4 imageio==2.37.3 imageio-ffmpeg==0.6.0 importlib-metadata==6.7.0 itsdangerous==2.1.2 # jeepney — pure-Python D-Bus for the TYPED + NATIVE Shell<->OS bridge (#133 / W3, # integrations/agent_engine/os_bridge/logind.py). Lets the power ops # (hartOS.power.reboot/shutdown/firmwareSetup) talk to logind # (org.freedesktop.login1) over the system bus DIRECTLY — no busctl/systemctl # subprocess. The import is GUARDED: on a box with no jeepney or no system bus # (the Windows dev box) it falls back to the bounded, result-checked `busctl call` # path, so this dependency is purely an upgrade to the native transport — never a # hard requirement. Pure-Python (no C ext), so it bundles cleanly under cx_Freeze # and packages trivially in Nix. jeepney>=0.8.0 Jinja2==3.1.2 joblib==1.2.0 jsonpatch==1.33 jsonpointer==2.4 langchain-classic==1.0.1 langchain-community==0.4.1 langchain-anthropic==1.0.0 langchain-core==1.2.15 langchain-text-splitters==1.1.1 langchain-google-genai==4.2.1 langchain-groq==1.1.2 langsmith==0.3.45 lit==16.0.6 livekit-api==1.0.7 livekit-protocol==1.1.8 lz4==4.3.2 MarkupSafe==2.1.3 marshmallow==3.19.0 marshmallow-enum==1.5.1 momento==1.6.1 momento-wire-types==0.64.1 monotonic==1.6 mpmath==1.3.0 multidict==6.0.4 multiprocess==0.70.15 mypy-extensions==1.0.0 networkx==3.1 nltk==3.8.1 numexpr==2.8.4 numpy==1.26.4 onnxruntime==1.16.3 openai==1.82.0 # openapi-schema-pydantic==1.2.4 # pydantic v1 only, not used opencv-python==4.8.0.76 orjson==3.10.1 overrides==7.3.1 packaging==23.2 pandas==2.0.2 Pillow==9.5.0 posthog==3.0.1 proto-plus==1.22.3 protobuf==4.23.3 pulsar-client==3.2.0 pyarrow==14.0.1 pyarrow-hotfix==0.6 pyasn1==0.5.0 pyasn1-modules==0.3.0 pydantic==2.9.2 PyJWT==2.14.0 pyparsing==3.1.0 pypdf==3.17.1 # The book pipeline's one PDF engine (integrations/learning/book_pipeline.py): # PDFium renders each page, extracts its text and reads the outline. No # dependencies of its own, so it is safe under the Dockerfile's --no-deps # install; prebuilt wheels for Windows, macOS 13+, Linux glibc+musl (x86/ARM) # and Android. It replaced PyPDF2, which nothing imports any more and whose # final release (3.0.1) loops forever on a crafted content stream # (CVE-2023-36464, reproduced 2026-09-13). pypdfium2==5.13.0 pyreadline3==3.4.1 ; sys_platform == "win32" python-dateutil==2.8.2 python-dotenv==1.0.0 python-multipart==0.0.6 pytz==2023.3 PyYAML==6.0 redis==4.6.0 regex==2023.6.3 requests==2.32.5 rsa==4.9 safetensors==0.4.1 scikit-learn==1.3.2 scipy==1.10.1 sentence-transformers==2.2.2 sentencepiece==0.1.99 shapely==2.0.2 six==1.16.0 sniffio==1.3.0 soupsieve==2.5 SQLAlchemy==2.0.16 starlette==0.41.3 sympy==1.12 tenacity==8.2.3 threadpoolctl==3.1.0 tiktoken==0.5.1 tokenizers==0.13.3 torch>=2.1.2 torchvision>=0.16.2 tqdm==4.65.0 transformers>=4.30.2 typing-inspect>=0.9.0 typing_extensions>=4.12.0,<5.0.0 tzdata==2023.3 uritemplate==4.1.1 urllib3==1.26.16 uvicorn==0.22.0 uvloop==0.17.0 ; sys_platform != "win32" waitress==2.1.2 # Hypercorn = primary ASGI server. Single binary on desktop + central # (Nunba bundle and central Docker run the same hart_intelligence_entry). # Scales from 1 worker (today) to N (HEVOLVE_WORKERS) once in-process # singletons (EventBus, ResourceGovernor, agent_daemon, watchdog) are # sharded for fork-safety. Waitress kept above as a fallback path. hypercorn==0.17.3 # A DEV BOX needs this too, not only the image. Without it # tests/standalone/peer_link_proof.py cannot start its second node at all # (`No module named 'hypercorn'`), so the one harness that proves an inbound # PeerLink forms looks like an environment failure rather than a result. # Verified 2026-09-05: with the pinned subtree below installed, that proof # passes 11/11 on Windows. # hypercorn's own dependency subtree, listed EXPLICITLY because the root # ./Dockerfile installs with `pip install --no-deps -r requirements.txt` # (Dockerfile:56). Under --no-deps pip resolves nothing, so anything not named # here is simply absent from the image. # # This was not theoretical. On central (192.168.0.9, container `langchain`, # 2026-08-19) hypercorn imported but `from hypercorn.asyncio import serve` # raised, and the node logged: # Hypercorn unavailable (No module named 'h2') - falling back to Waitress # Waitress is pure WSGI, so that silently cost the node every websocket: # ws:///peer_link was unservable and PeerLink.accept() could never fire, # leaving PeerLinkManager._links empty for skill broadcast, # claude_hive_session._publish_via_peer_link and collect() shard fan-out. # The degradation is logged once at boot and looks like a normal fallback. # # hypercorn 0.17.3 requires: h11, h2>=3.1.0, priority, wsproto>=0.14.0. # h2 in turn requires hpack>=4.0,<5 and hyperframe>=6.0,<7; wsproto requires # h11 (already pinned above at 0.16.0). Keep this block in step with the # hypercorn pin -- if hypercorn moves, re-check `importlib.metadata.requires`. # # hpack is 4.2.0, not 4.0.0: CVE-2026-59980 / GHSA-8v8h-hg4w-mvq2 (published # 2026-09-24) -- hpack <4.2.0 decodes an unbounded varint in O(n^2) CPU, so one # malformed HTTP/2 header block pins a core (a 200 KB payload took ~14 s to # reject on 4.0.0, ~1 ms on 4.2.0). 4.2.0 is inside h2 4.1.0's declared # hpack>=4.0,<5, so the --no-deps image stays consistent. hpack 4.2.0 requires # Python >=3.10, which this file already needs (langchain-core). Fixed by the # pin, NOT by an entry in .github/security-scan/pip-audit-ignore.txt. h2==4.1.0 hpack==4.2.0 hyperframe==6.0.1 priority==2.0.0 wsproto==1.2.0 # hypercorn ALSO has python_version < "3.11" conditionals, and central runs # Python 3.10.20 -- so these are required there, not optional. Adding only the # unconditional five above was an incomplete fix: after they landed, central's # log moved from "No module named 'h2'" to "No module named 'taskgroup'" and it # still fell back to Waitress. Verified live in container `langchain` # 2026-08-19: h2/hpack/hyperframe/priority/wsproto/h11 all PRESENT, # `from hypercorn.asyncio import serve` still ModuleNotFoundError on taskgroup. # # exceptiongroup (L52) and typing_extensions (L184) are already pinned, so only # these two were missing. tomli was present by luck, not by declaration -- # under --no-deps that is a latent break, so declare it. # # taskgroup is left unpinned deliberately: its PyPI releases are # prerelease-versioned, and guessing a pin blind is the riskier error than # letting the marker resolve it. The marker means neither installs on 3.11+. taskgroup ; python_version < "3.11" tomli==2.0.1 ; python_version < "3.11" watchfiles==0.19.0 websockets==14.2 Werkzeug==2.3.6 xxhash==3.4.1 yarl==1.9.2 zipp==3.15.0 zstandard==0.23.0 # Transitive deps — exact pins to prevent pip resolution-too-deep in Docker jiter==0.9.0 httpx-sse==0.4.0 grpc-google-iam-v1==0.14.2 uuid-utils==0.14.0 anthropic==0.83.0 docstring-parser==0.16 google-genai==1.56.0 pydantic-core==2.23.4 #streamlit~=1.19.0 # Agent Lightning - Custom implementation in integrations/agent_lightning/ # No external package required - using our own implementation python-telegram-bot==21.7 discord.py==2.4.0 # Slack channel adapter (Socket Mode) — needs bot token (xoxb-) + app token (xapp-) slack-bolt==1.30.0 slack-sdk==3.43.0 # SimpleMem - Lifelong memory for LLM agents (optional) # simplemem>=0.1.0 # RSS/Atom feed parsing and generation feedparser==6.0.11 # SSH for network provisioning (HART OS remote install) paramiko==3.5.1 # System tray indicator (HART OS desktop, optional) pystray==0.19.5 # LuxTTS — 48kHz voice cloning TTS (150x realtime GPU, Apache 2.0) # luxtts>=0.1.0 # not on PyPI — install from source soundfile==0.12.1 # MySQL driver for cloud/Docker deployments (pure Python, no C compiler needed) pymysql==1.1.1 # Aider Core — vendored modules for code intelligence (repo map, search/replace, linting) diskcache==5.6.3 grep-ast==0.9.0 tree-sitter==0.23.2 tree-sitter-language-pack==0.6.0 diff-match-patch==20230430 gitpython==3.1.44 json-repair>=0.59.4 psutil>=5.9.0 pyautogui>=0.9.54; sys_platform != "linux" # Screen capture, the primary tier in integrations/remote_desktop/frame_capture.py. # It was reachable only through the `remote-desktop` extra, and the pyautogui pin # above is excluded on Linux, so a plain `pip install -r requirements.txt` on Linux # left `hart desktop record` and the remote desktop with no capture backend at all. # Small, pure Python, nothing to compile. Wayland sessions still want a portal path. mss>=9.0.0 # TTS text normalizer — expand numbers, currency, percentages to spoken form # before any TTS engine (OmniVoice, Indic-Parler, F5, CosyVoice can't pronounce # "Rs.200" or "12.5%" on their own). Used by # integrations/channels/media/tts_text_normalizer.py num2words>=0.5.13 # Stripe SDK — used by integrations/ap2/ap2_protocol.py:StripePaymentGateway # for live USD card charges on the commercial API /upgrade endpoint. # Lazy-imported inside the gateway's connect() so a missing install # falls back to MockPaymentGateway gracefully (revenue stays mocked in # dev; baked into the image so production rebuilds don't need a manual # `pip install stripe` on the central container). stripe>=7.0.0 # YouTube caption fetch for the agent's browser_research transcript tool # (integrations/browser_research/scripts/youtube.py). Lazy-imported with an # ImportError fallthrough, so a missing install does not crash -- it silently # demotes every transcript request to the yt-dlp + local-Whisper path, which # downloads the media and runs STT for a video that already publishes captions. # It was in NEITHER requirements.txt nor hart-app.nix, so that demotion is what # every host has actually been doing, and the three tests covering the caption # path could not even import on CI. youtube-transcript-api>=1.0.0