requirements.txt
Rama main · réplica de lectura del repositorio original.
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://<node>/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