pyproject.toml
Rama main · réplica de lectura del repositorio original.
[project]
name = "muselab"
version = "2.1.0"
description = "Self-hosted multi-model Agent workbench for local workspaces, files, terminals, and artifacts."
readme = "README.md"
license = { file = "LICENSE" }
authors = [
{ name = "hesorchen", email = "hesorchen@gmail.com" },
]
keywords = [
"claude",
"anthropic",
"claude-agent-sdk",
"mcp",
"self-hosted",
"llm",
"ai-assistant",
"agent-workspace",
"deepseek",
"pwa",
]
classifiers = [
# PyPI Trove classifiers — surface project status / audience / license /
# platform / Python version so PyPI search and dependency-graph tools
# can categorise muselab even though it's not meant to be `pip install`-able
# (it's a server you self-host, not a library).
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: FastAPI",
"Intended Audience :: End Users/Desktop",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: POSIX :: Linux",
"Operating System :: MacOS",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
"Topic :: Communications :: Chat",
"Topic :: Office/Business",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
]
requires-python = ">=3.12"
dependencies = [
# Exact pin is deliberate: muselab adapts both SDK and bundled-CLI contracts
# that are not capability-negotiated — the harness-tool denylist, JSONL
# transcript shape, and native AskUserQuestion answer injection. Every SDK
# upgrade must refresh the tool catalog and rerun the native question matrix.
# Path/effort drift is already auto-eliminated via
# project_key_for_directory() + EffortLevel.
"claude-agent-sdk==0.2.157",
# Security floor for CVE-2026-63374 and CVE-2026-64847.
"anyio>=4.14.2",
"fastapi>=0.138.1",
# Pin starlette above the fastapi-transitive 1.0.0, which carries
# PYSEC-2026-161 (fixed in 1.0.1). Direct constraint so the pip-audit
# CVE-scan CI job stays green.
"starlette>=1.3.1",
"python-dotenv>=1.2.2",
"python-multipart>=0.0.32",
"uvicorn[standard]>=0.49.0",
# Live file-tree refresh for Agent / terminal / external-editor changes.
# One on-demand watcher per subscribed workspace feeds the durable SQLite
# index; offline reconciliation runs when that workspace is reactivated.
"watchfiles>=1.2.0",
# xlsx preview — read-only, used by /api/files/xlsx. Pure-Python, no
# native deps; safe to ship in the muselab Docker image.
"openpyxl>=3.1.5",
# Web Push: VAPID-signed pushes to browsers / PWAs subscribed to
# /api/push/subscribe. Has a transitive cryptography dep but no
# external binaries.
"pywebpush>=2.0.0",
# Keep aiohttp at the currently audited security floor rather than the
# older pywebpush-transitive range. Direct constraint keeps fresh lock
# resolutions aligned with the pip-audit CI baseline.
"aiohttp>=3.14.3",
# Security floor for the C-extension reference leak in CVE-2026-104874.
"multidict>=6.9.1",
"pillow>=12.3.0",
# Security floors for the claim-verification and parser advisories
# affecting PyJWT 2.13.0 and the proxy/redirect advisories in urllib3 2.7.0.
# Keep both explicit so future lock resolutions retain the fixes.
"pyjwt[crypto]>=2.15.1",
"urllib3>=2.8.0",
# Direct async HTTP client. Used by backend/memory_client.py to talk to the
# optional self-hosted mem0 daemon. It is already an SDK/httpcore transitive
# dep today, but we import it directly, so declare it explicitly — otherwise
# an upstream drop would make `import httpx` fail and (because mem0 is
# fail-soft) silently disable memory with no signal.
"httpx>=0.27",
# Optional pgvector adapter for the long-term memory index. Imported only
# when pgvector is selected; Qdrant deployments never open a Postgres
# connection, but keeping the driver installed makes provider switching a
# runtime setting instead of a redeploy.
"psycopg[binary]>=3.2.9",
]
[project.urls]
Homepage = "https://github.com/hesorchen/muselab"
Source = "https://github.com/hesorchen/muselab"
Issues = "https://github.com/hesorchen/muselab/issues"
Documentation = "https://github.com/hesorchen/muselab/blob/main/docs/quickstart.md"
Container = "https://github.com/hesorchen/muselab/pkgs/container/muselab"
[dependency-groups]
dev = [
"pytest>=9.1.1",
"pytest-asyncio>=1.4.0",
# Parallelize the large unit/integration suite on multi-core development
# machines and CI. Browser E2E and upgrade smoke tests stay serial because
# they intentionally share one live server/runtime.
"pytest-xdist>=3.8.0",
# Starlette 1.2+ prefers httpx2 for TestClient. Keep production httpx
# separately because memory_client imports that package directly.
"httpx2>=2.0.0",
# Browser regressions cover Alpine rendering races and trusted mobile
# touch gestures that static source assertions cannot exercise.
"pytest-playwright>=0.7.0",
# Pinned alongside dev deps so `scripts/lint.sh` and CI both have a
# deterministic ruff version. Without this each dev / CI run pulled
# latest via `uv run --with ruff`, occasionally causing rule churn.
"ruff>=0.15.20",
# CI collects coverage in its existing primary test run; lock the plugin
# so worker instrumentation and the later report use the same toolchain.
"pytest-cov>=7.1.0",
]
# Ruff config — keep targeted, not aggressive. Goal: catch real bugs
# (unused imports / variables, broken syntax-adjacent patterns) without
# fighting a project that values terse multi-statement-on-one-line where
# it reads naturally. Style enforcement is left to human review.
[tool.ruff]
target-version = "py312"
line-length = 100 # informational; we don't auto-format
[tool.ruff.lint]
# Default ruleset (E, F, W) — pyflakes + pycodestyle errors only.
# Explicitly NO opinionated rule families (B, I, N, UP) — they'd churn
# 6k LOC of working code for marginal gain.
select = ["E", "F", "W"]
# Project-specific tolerances:
# - E501 line-too-long: many existing lines are 100-120 chars by deliberate
# choice (one full sentence per comment line). Not worth the churn.
ignore = ["E501"]