Files
OpenJarvis/pyproject.toml
T
26bc7efb09 fix(packaging): make openjarvis-rust a uv-only group to unblock pip install openjarvis[desktop] (#624)
* fix(packaging): make openjarvis-rust a uv-only dependency group (unblock pip[desktop])

#615 added openjarvis-rust to the published `desktop` extra so
`uv sync --extra desktop` builds the native PyO3 extension for the desktop
app. But openjarvis-rust is not on PyPI and `[tool.uv.sources]` is stripped
from published wheel metadata, so `pip install openjarvis[desktop]` from PyPI
failed at install trying to resolve openjarvis-rust from PyPI (#584).

Move openjarvis-rust into a uv `desktop-native` dependency group (PEP 735 —
excluded from wheel metadata) and sync it in the desktop app via
`uv sync --group desktop-native`. The extension is still built from the local
path source; only the published metadata changes.

Verified: the built wheel no longer lists openjarvis-rust in any Requires-Dist
(nowhere in the metadata), and uv.lock still resolves it from the local path
source under the group. Adds tests/deployment/test_packaging.py to guard the
split (not in the published extra, present in the group, path source, and the
desktop app syncs the group).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(packaging): sync native group in install paths

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Elliot Slusky <elliot@slusky.com>
2026-07-01 13:02:13 -07:00

250 lines
8.6 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[project]
name = "OpenJarvis"
dynamic = ["version"]
description = "OpenJarvis — modular AI assistant backend with composable intelligence primitives"
readme = "README.md"
# Upper bound: numpy 2.2.x (pinned transitively via datasets/pandas) ships no
# cp314 Windows wheel, so under Python 3.14 uv would compile numpy from source
# (Meson) and fail on Windows boxes without a C toolchain (#350). Cap to the
# range that has prebuilt wheels; matches the classifiers (3.103.13).
requires-python = ">=3.10,<3.14"
license = {text = "Apache-2.0"}
authors = [
{name = "Open Jarvis Contributors"},
]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
dependencies = [
"click>=8",
"datasets>=4.5.0",
"ddgs>=9.11.4",
"httpx>=0.27",
"openai>=1.30",
"nvidia-ml-py>=12.560.30",
"posthog>=3.0",
"python-telegram-bot>=22.6",
"rich>=13",
"tomli>=2.0; python_version < '3.11'",
"tomlkit>=0.12",
"websockets>=15.0.1",
]
[project.optional-dependencies]
dev = [
"maturin>=1.12.6",
"pytest>=8",
"pytest-asyncio>=0.24",
"pytest-cov>=5",
"pytest-xdist>=3",
"respx>=0.22",
"ruff>=0.4",
"pre-commit>=3.0",
]
inference-mlx = ["mlx-lm>=0.31.1; sys_platform == 'darwin'"]
inference-vllm = ["vllm>=0.16.0"]
inference-cloud = [
"openai>=1.30",
"anthropic>=0.30",
]
inference-google = [
"google-genai>=1.0",
]
inference-litellm = ["litellm>=1.40"]
inference-gemma = ["pygemma>=0.1.3"]
tools-search = [
"tavily-python>=0.3",
"ddgs>=9.11.4",
]
memory-faiss = [
"faiss-cpu>=1.7",
"sentence-transformers>=2.2",
"numpy>=1.24",
]
memory-colbert = [
"colbert-ai>=0.2",
"torch>=2.0",
]
memory-pdf = ["pdfplumber>=0.10"]
memory-bm25 = ["rank-bm25>=0.2.2"]
server = [
"fastapi>=0.110",
"uvicorn>=0.30",
"pydantic>=2.0",
"python-multipart>=0.0.9",
]
desktop = [
"fastapi>=0.110",
"uvicorn>=0.30",
"pydantic>=2.0",
"python-multipart>=0.0.9",
"faster-whisper>=1.0",
]
openhands = ["openhands-sdk>=1.0; python_version >= '3.12'"]
gpu-metrics = ["pynvml>=12.0"]
energy-amd = ["amdsmi>=6.1"]
energy-apple = ["zeus-ml[apple]"]
energy-all = ["pynvml>=12.0", "amdsmi>=6.1", "zeus-ml[apple]"]
orchestrator-training = ["torch>=2.0", "transformers>=4.40"]
learning-dspy = ["dspy>=2.6"]
learning-gepa = ["gepa>=0.1"]
channel-telegram = ["python-telegram-bot>=21.0"]
channel-discord = ["discord.py>=2.3"]
channel-slack = ["slack-sdk>=3.27"]
channel-line = ["line-bot-sdk>=3.0"]
channel-viber = ["viberbot>=1.0"]
channel-messenger = ["pymessenger>=0.0.7"]
channel-reddit = ["praw>=7.0"]
channel-mastodon = ["Mastodon.py>=1.8"]
channel-xmpp = ["slixmpp>=1.8"]
channel-rocketchat = ["rocketchat-API>=1.30"]
channel-zulip = ["zulip>=0.9"]
channel-twitter = ["httpx>=0.27"]
channel-twitch = ["twitchio>=2.6"]
channel-nostr = ["pynostr>=0.6"]
channel-twilio = ["twilio>=9.0"]
channel-gmail = [
"google-api-python-client>=2.0",
"google-auth-oauthlib>=1.0",
"google-auth-httplib2>=0.2",
]
browser = ["playwright>=1.40"]
media = ["openai>=1.30"]
mining-pearl-vllm = ["docker>=7.0", "httpx>=0.27"]
pdf = ["pdfplumber>=0.10"]
scheduler = ["croniter>=2.0"]
security-signing = ["cryptography>=43"]
sandbox-wasm = ["wasmtime>=25"]
sandbox-docker = ["docker>=7.0"]
dashboard = ["textual>=0.80"]
speech = ["faster-whisper>=1.0"]
speech-deepgram = ["deepgram-sdk>=3.0"]
eval-wandb = ["wandb>=0.17"]
eval-sheets = ["gspread>=6.0", "google-auth>=2.0"]
mining-pearl-cpu = [
# Pearl Python packages (py-pearl-mining, miner-base, pearl-gateway) are
# not on PyPI yet. They are installed at first `mine init` via the
# build-from-pin path in src/openjarvis/mining/_install.py:build_from_pin().
# When Pearl publishes wheels, replace the line below with version pins.
#
# The extra remains as a feature-flag namespace so users can run
# `uv sync --extra mining-pearl-cpu` to opt-in (it succeeds with no
# additional resolution today; the actual install happens on demand).
]
framework-comparison = ["polars>=1.0"]
docs = [
"mkdocs>=1.6",
"mkdocs-material>=9.5",
"mkdocstrings[python]>=0.25",
"mkdocs-gen-files>=0.5",
"mkdocs-literate-nav>=0.6",
]
[project.urls]
Homepage = "https://github.com/open-jarvis/OpenJarvis"
Documentation = "https://open-jarvis.github.io/OpenJarvis/"
Repository = "https://github.com/open-jarvis/OpenJarvis"
Issues = "https://github.com/open-jarvis/OpenJarvis/issues"
[project.scripts]
jarvis = "openjarvis.cli:main"
openjarvis-eval = "openjarvis.evals.cli:main"
# Version is derived from git tags by hatch-vcs (see #526). For source/editable
# checkouts this yields the true `git describe` version (e.g. 1.0.3.dev109+g<sha>)
# rather than a stale static string. CI release builds override this with
# SETUPTOOLS_SCM_PRETEND_VERSION so the published version equals the pushed tag.
#
# setuptools_scm cannot bump custom `.devN` tags (only `.dev0`), so the autotag
# `vX.Y.Z.devN` tags are deliberately EXCLUDED from version derivation here; the
# base is taken from the latest plain release tag (vX.Y.Z) and the dev distance
# is computed from commit count since that release.
[tool.hatch.version]
source = "vcs"
[tool.hatch.version.raw-options]
tag_regex = '^v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)$'
git_describe_command = [
"git", "describe", "--dirty", "--tags", "--long",
"--match", "v[0-9]*", "--exclude", "*dev*", "--exclude", "*rc*", "--exclude", "desktop-*",
]
# Builds without a git checkout (e.g. the `COPY src/ src/` Docker stages, which
# never include .git) can't run `git describe`. Without a fallback that would
# hard-fail the build. Mirror the runtime sentinel in src/openjarvis/__init__.py.
# Such builds can inject the real version via SETUPTOOLS_SCM_PRETEND_VERSION.
fallback_version = "0.0.0+unknown"
[tool.uv.sources]
openjarvis-rust = { path = "rust/crates/openjarvis-python" }
[tool.hatch.build.targets.wheel]
packages = ["src/openjarvis"]
[tool.hatch.build.targets.wheel.force-include]
"src/openjarvis/agents/claude_code_runner" = "_node_modules/claude_code_runner"
"src/openjarvis/channels/whatsapp_baileys_bridge" = "_node_modules/whatsapp_baileys_bridge"
"scripts/install" = "_install_scripts"
"deploy/windows" = "_deploy/windows"
[tool.pytest.ini_options]
testpaths = ["tests"]
markers = [
"amd: requires AMD GPU",
"apple: requires Apple Silicon",
"cloud: requires cloud API keys",
"docker: requires a working Docker daemon (no GPU required)",
"live: requires running inference engine",
"macos15: requires macOS 15+ (Sequoia) for Apple FM",
"live_channel: requires real channel credentials (env vars)",
"nvidia: requires NVIDIA GPU",
"slow: long-running test",
"hub: downloads real datasets from the HuggingFace Hub at runtime; excluded from the default CI lane (run with -m hub)",
"live_external: requires HERMES_AGENT_PATH and OPENCLAW_PATH; spawns real foreign-framework subprocesses",
"modal: requires Modal token + network; runs real swebench harness on Modal",
]
[tool.ruff]
target-version = "py310"
src = ["src", "tests"]
[tool.ruff.lint]
select = ["E", "F", "I", "W"]
[tool.ruff.lint.per-file-ignores]
"src/openjarvis/evals/datasets/*.py" = ["E501"]
"src/openjarvis/evals/scorers/*.py" = ["E501"]
# hybrid/ is research code with long prompt strings and paradigm-specific
# config dicts — same relaxation as evals research code above. The ``**`` glob
# also covers subpackages (e.g. hybrid/skillorchestra/), which the prior
# ``hybrid/*.py`` glob missed.
"src/openjarvis/agents/hybrid/**/*.py" = ["E501"]
# research_loop.py carries long prompt strings too (documented in CLAUDE.md);
# the ignore was missing here.
"src/openjarvis/agents/research_loop.py" = ["E501"]
[dependency-groups]
dev = [
"maturin>=1.12.6",
]
# openjarvis_rust is the native PyO3 extension, built from the local Rust
# workspace. It lives in a uv dependency group (PEP 735) — not the published
# `desktop` extra — so `uv sync --group desktop-native` builds it from source
# for the desktop app, while `pip install openjarvis[desktop]` from PyPI does
# NOT try to resolve openjarvis-rust from PyPI, where it isn't published
# (dependency groups are excluded from wheel metadata). See #584 / #615.
desktop-native = [
"openjarvis-rust",
]