e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
467 lines
16 KiB
TOML
467 lines
16 KiB
TOML
# Python project configuration for DeepTutor
|
|
# This file configures Black, Ruff, and other Python tools
|
|
|
|
[build-system]
|
|
requires = ["setuptools>=61.0", "wheel"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "deeptutor"
|
|
dynamic = ["version"]
|
|
description = "An agent-native intelligent learning companion with multi-agent collaboration and RAG"
|
|
requires-python = ">=3.11"
|
|
readme = "README.md"
|
|
license = {text = "Apache-2.0"}
|
|
dependencies = [
|
|
# Core runtime
|
|
"PyYAML>=6.0",
|
|
"jinja2>=3.1.0",
|
|
"openai>=1.30.0",
|
|
"tiktoken>=0.5.0",
|
|
"aiohttp>=3.9.4",
|
|
"httpx>=0.27.0",
|
|
"requests>=2.32.2",
|
|
"ddgs>=9.9.1",
|
|
"nest_asyncio>=1.5.8",
|
|
"tenacity>=8.0.0",
|
|
"pydantic>=2.0.0",
|
|
"pydantic-settings>=2.0.0",
|
|
"aiosqlite>=0.19.0",
|
|
"typer[all]>=0.9.0",
|
|
"rich>=13.0.0",
|
|
"prompt_toolkit>=3.0.36",
|
|
"pyte>=0.8.1", # in-memory terminal emulator: scrape Claude Code's /model TUI on sync
|
|
# Full app dependencies included by default for `pip install deeptutor`.
|
|
"anthropic>=0.30.0",
|
|
"dashscope>=1.14.0",
|
|
"perplexityai>=0.1.0",
|
|
"oauth-cli-kit>=0.1.1",
|
|
"llama-index>=0.14.12",
|
|
"llama-index-retrievers-bm25>=0.7.1,<0.8.0",
|
|
# FAISS vector store: vectorized ANN retrieval that replaces SimpleVectorStore's
|
|
# brute-force per-query scan for large knowledge bases (issue #552). The
|
|
# pipeline imports it lazily and falls back to SimpleVectorStore if absent.
|
|
"llama-index-vector-stores-faiss>=0.4.0,<1.0.0",
|
|
"faiss-cpu>=1.8.0,<2.0.0",
|
|
"PyMuPDF>=1.26.0",
|
|
"numpy>=1.24.0,<3.0.0",
|
|
"arxiv>=2.0.0",
|
|
"python-docx>=1.1.0",
|
|
"openpyxl>=3.1.0",
|
|
"python-pptx>=1.0.0",
|
|
"pypdf>=4.0.0",
|
|
"pdfplumber>=0.11.0,<0.11.8", # 0.11.8+ pins pdfminer.six==20251230, conflicts with mineru (via raganything)
|
|
"reportlab>=4.0.0",
|
|
"defusedxml>=0.7.1",
|
|
"fastapi>=0.100.0",
|
|
"uvicorn[standard]>=0.24.0",
|
|
"websockets>=12.0",
|
|
"python-multipart>=0.0.6",
|
|
"bcrypt>=4.0.0",
|
|
"python-jose[cryptography]>=3.3.0",
|
|
"pocketbase>=0.12.0",
|
|
"loguru>=0.7.3,<1.0.0",
|
|
"json-repair>=0.57.0,<1.0.0",
|
|
]
|
|
|
|
[project.scripts]
|
|
deeptutor = "deeptutor_cli.main:main"
|
|
|
|
[project.optional-dependencies]
|
|
# Compatibility extra for source installs and older docs. These packages are
|
|
# already included in the public `deeptutor` wheel; the local CLI-only project
|
|
# under `packaging/deeptutor-cli` uses the same list without Web assets/server deps.
|
|
cli = [
|
|
# LLM provider SDKs
|
|
"anthropic>=0.30.0",
|
|
"dashscope>=1.14.0",
|
|
"perplexityai>=0.1.0",
|
|
"oauth-cli-kit>=0.1.1",
|
|
# RAG (LlamaIndex)
|
|
"llama-index>=0.14.12",
|
|
"llama-index-retrievers-bm25>=0.7.1,<0.8.0",
|
|
# FAISS vector store: vectorized ANN retrieval that replaces SimpleVectorStore's
|
|
# brute-force per-query scan for large knowledge bases (issue #552). The
|
|
# pipeline imports it lazily and falls back to SimpleVectorStore if absent.
|
|
"llama-index-vector-stores-faiss>=0.4.0,<1.0.0",
|
|
"faiss-cpu>=1.8.0,<2.0.0",
|
|
"PyMuPDF>=1.26.0",
|
|
"numpy>=1.24.0,<3.0.0",
|
|
"arxiv>=2.0.0",
|
|
# Document text extraction (chat attachments) + office-skill authoring libs
|
|
"python-docx>=1.1.0",
|
|
"openpyxl>=3.1.0",
|
|
"python-pptx>=1.0.0",
|
|
"pypdf>=4.0.0",
|
|
"pdfplumber>=0.11.0,<0.11.8", # 0.11.8+ pins pdfminer.six==20251230, conflicts with mineru (via raganything)
|
|
"reportlab>=4.0.0",
|
|
"defusedxml>=0.7.1",
|
|
]
|
|
|
|
# Compatibility extra for source installs and older docs. These packages are
|
|
# already included in the public `deeptutor` wheel.
|
|
server = [
|
|
"deeptutor[cli]",
|
|
"fastapi>=0.100.0",
|
|
"uvicorn[standard]>=0.24.0",
|
|
"websockets>=12.0",
|
|
"python-multipart>=0.0.6",
|
|
"bcrypt>=4.0.0",
|
|
"python-jose[cryptography]>=3.3.0",
|
|
"pocketbase>=0.12.0",
|
|
"loguru>=0.7.3,<1.0.0",
|
|
"json-repair>=0.57.0,<1.0.0",
|
|
"croniter>=6.0.0,<7.0.0",
|
|
]
|
|
|
|
# Partner channel SDKs + MCP client. Mirrors requirements/partners.txt.
|
|
# Partners run on the chat agent loop, so there is no engine here — just the
|
|
# IM platform SDKs and the MCP client used for deferred tools.
|
|
partners = [
|
|
"deeptutor[server]",
|
|
"mcp>=1.26.0,<2.0.0",
|
|
"python-telegram-bot[socks]>=22.6,<23.0",
|
|
"wecom-aibot-sdk>=1.0.8,<2.0.0",
|
|
"lark-oapi>=1.5.0,<2.0.0",
|
|
"dingtalk-stream>=0.24.0,<1.0.0",
|
|
"slack-sdk>=3.39.0,<4.0.0",
|
|
"slackify-markdown>=0.2.0,<1.0.0",
|
|
"qq-botpy>=1.2.0,<2.0.0",
|
|
"python-socketio>=5.16.0,<6.0.0",
|
|
"msgpack>=1.1.0,<2.0.0",
|
|
"python-socks[asyncio]>=2.8.0,<3.0.0",
|
|
"socksio>=1.0.0,<2.0.0",
|
|
"websocket-client>=1.9.0,<2.0.0",
|
|
"zulip>=0.8.0,<1.0.0",
|
|
# slack-sdk Socket Mode + napcat need the async `websockets` lib — pin it
|
|
# explicitly instead of relying on dingtalk-stream/lark-oapi transitives.
|
|
"websockets>=12.0",
|
|
# napcat (OneBot v11) media downloads
|
|
"aiohttp>=3.10.0,<4.0.0",
|
|
# msteams Bot Framework token validation
|
|
"PyJWT[crypto]>=2.8.0,<3.0.0",
|
|
# weixin QR-code login
|
|
"qrcode>=7.4.0,<9.0.0",
|
|
]
|
|
|
|
# Optional document-parsing engines for the shared parse layer
|
|
# (deeptutor/services/parsing). MinerU is an external CLI / hosted API and is
|
|
# not a pip dependency. Engines import lazily, so these stay opt-in and an
|
|
# absent engine simply reports unavailable in Settings → Document Parsing.
|
|
parse-markitdown = ["markitdown[pdf,docx,pptx,xlsx]>=0.0.1a2"]
|
|
parse-docling = ["docling>=2.0.0"]
|
|
# PyMuPDF4LLM rides on PyMuPDF (already a core dep); the extra adds only the
|
|
# thin Markdown layer, so it is the lightest image-capable engine. Pinned to the
|
|
# pre-1.0 line on purpose: 1.x defaults to an onnxruntime layout-AI path that
|
|
# pulls a heavy dep, downloads a model, and can't extract images — defeating the
|
|
# "lightweight, runs on a Pi, extracts images" point of this engine.
|
|
parse-pymupdf4llm = ["pymupdf4llm>=0.0.17,<1.0"]
|
|
parse = [
|
|
"deeptutor[parse-markitdown]",
|
|
"deeptutor[parse-docling]",
|
|
"deeptutor[parse-pymupdf4llm]",
|
|
]
|
|
|
|
# Legacy alias kept for one release: `pip install deeptutor[tutorbot]`.
|
|
tutorbot = ["deeptutor[partners]"]
|
|
|
|
# Matrix (Element) channel for partners. Mirrors requirements/matrix.txt.
|
|
# Default Matrix install is non-E2EE so it works without libolm/python-olm.
|
|
matrix = [
|
|
"matrix-nio>=0.25.2,<1.0.0",
|
|
"mistune>=3.0.0,<4.0.0",
|
|
"nh3>=0.2.18,<1.0.0",
|
|
]
|
|
|
|
# Optional Matrix E2EE addon. Mirrors requirements/matrix-e2e.txt and requires libolm.
|
|
matrix-e2e = [
|
|
"deeptutor[matrix]",
|
|
"matrix-nio[e2e]>=0.25.2,<1.0.0",
|
|
]
|
|
|
|
# Math Animator addon (Manim). Mirrors requirements/math-animator.txt.
|
|
# System prerequisites (installed outside pip): LaTeX, pkg-config, cairo, cmake, ffmpeg.
|
|
math-animator = ["manim>=0.19.0"]
|
|
|
|
# GraphRAG knowledge-base engine (microsoft/graphrag). Optional, heavy
|
|
# (LiteLLM + lancedb + graspologic) and kept out of `all` so it stays a
|
|
# deliberate opt-in. The pipeline imports lazily and the adapter targets the
|
|
# 3.x API (see services/rag/pipelines/graphrag/engine.py). Every graphrag 3.x
|
|
# release is capped at python <3.14; the `python_version` marker mirrors that
|
|
# so on 3.14+ the extra resolves to a no-op instead of an unsatisfiable hard
|
|
# dep — otherwise pip backtracks deeptutor to the last extra-free version
|
|
# (1.4.5) and silently downgrades. Floor is 3.0.1 (3.0.0/3.0.3 were yanked).
|
|
graphrag = ["graphrag>=3.0.1,<4.0.0; python_version < '3.14'"]
|
|
|
|
# LightRAG knowledge-base engine (HKUDS/LightRAG) with multimodal parsing via
|
|
# RAG-Anything (HKUDS/RAG-Anything). Optional, heavy (pulls MinerU transitively —
|
|
# see the pdfplumber pin above). The pipeline imports lazily and the adapter is
|
|
# isolated in services/rag/pipelines/lightrag/engine.py. raganything pulls
|
|
# `mineru[core]`, which is capped at python <3.14, so this carries the same
|
|
# `python_version` marker as graphrag to avoid a silent backtrack/downgrade on
|
|
# 3.14+. Floor is 1.0.1 (no 1.0.0 was ever published) with a <2.0.0 ceiling so
|
|
# a future API-breaking 2.x isn't pulled in silently.
|
|
rag-lightrag = ["raganything>=1.0.1,<2.0.0; python_version < '3.14'"]
|
|
|
|
# Dev/test tooling. Mirrors requirements/dev.txt.
|
|
dev = [
|
|
"deeptutor[server]",
|
|
"pytest>=7.0.0",
|
|
"pytest-asyncio>=0.23.0",
|
|
"pre-commit>=3.0.0",
|
|
"safety<3.0.0",
|
|
"bandit>=1.8.0",
|
|
# Test fixture builders for document-loader tests. Runtime pulls these via
|
|
# cli/server, but dev keeps them explicit for pytest collection.
|
|
"python-docx>=1.1.0",
|
|
"openpyxl>=3.1.0",
|
|
"python-pptx>=1.0.0",
|
|
"pypdf>=4.0.0",
|
|
"defusedxml>=0.7.1",
|
|
]
|
|
|
|
# Everything: server + partners + non-E2EE matrix + math-animator + dev tools.
|
|
all = [
|
|
"deeptutor[partners]",
|
|
"deeptutor[matrix]",
|
|
"deeptutor[math-animator]",
|
|
"deeptutor[dev]",
|
|
]
|
|
|
|
[tool.setuptools]
|
|
include-package-data = true
|
|
|
|
[tool.setuptools.dynamic]
|
|
version = {attr = "deeptutor.__version__.__version__"}
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["."]
|
|
include = ["deeptutor*", "deeptutor_cli*"]
|
|
|
|
[tool.setuptools.package-data]
|
|
# Runtime data shipped inside the deeptutor package: prompt YAMLs (loaded by
|
|
# PromptManager from PACKAGE_ROOT/deeptutor/.../prompts/*.yaml), markdown
|
|
# templates (builtin SKILL.md files, vision_solver prompts), and helper shell
|
|
# scripts. Without these, ``pip install deeptutor`` ships a wheel missing
|
|
# every agent prompt and capability fails at first use.
|
|
deeptutor = [
|
|
"**/*.yaml",
|
|
"**/*.yml",
|
|
"**/*.md",
|
|
"**/*.json",
|
|
"**/*.sh",
|
|
"**/*.j2",
|
|
"**/*.jinja",
|
|
]
|
|
deeptutor_cli = ["**/*.md"]
|
|
deeptutor_web = ["**/*", ".next/**/*"]
|
|
|
|
# ============================================
|
|
# Black code formatter configuration
|
|
# ============================================
|
|
[tool.black]
|
|
line-length = 100
|
|
target-version = ['py311', 'py312', 'py313', 'py314']
|
|
include = '\.pyi?$'
|
|
extend-exclude = '''
|
|
/(
|
|
# Exclude directories
|
|
\.eggs
|
|
| \.git
|
|
| \.hg
|
|
| \.mypy_cache
|
|
| \.tox
|
|
| \.venv
|
|
| venv
|
|
| _build
|
|
| buck-out
|
|
| build
|
|
| dist
|
|
| __pycache__
|
|
| node_modules
|
|
| \.next
|
|
)/
|
|
'''
|
|
|
|
# ============================================
|
|
# Ruff linter and formatter configuration
|
|
# ============================================
|
|
[tool.ruff]
|
|
# Target Python version
|
|
target-version = "py311"
|
|
line-length = 100
|
|
|
|
[tool.ruff.lint]
|
|
# Enable only foundational lint rules (intentionally relaxed)
|
|
select = [
|
|
"E", # pycodestyle errors (语法错误)
|
|
"F", # pyflakes (未使用的导入、变量等)
|
|
"I", # isort (import 排序)
|
|
# Keep only essential checks; other rules stay relaxed
|
|
]
|
|
|
|
extend-select = [
|
|
"B006", # Do not use mutable data structures for argument defaults
|
|
]
|
|
|
|
# Ignore specific rules (keep the lint profile relaxed)
|
|
ignore = [
|
|
"E501", # Line too long (handled by formatter)
|
|
"B008", # Do not perform function calls in argument defaults
|
|
"PLR0911", # Too many return statements
|
|
"PLR0912", # Too many branches
|
|
"PLR0913", # Too many arguments
|
|
"PLR0915", # Too many statements
|
|
"PLR2004", # Magic value used in comparison
|
|
"TRY003", # Avoid specifying long messages outside exception class
|
|
"T201", # print found (allowed for debugging scripts)
|
|
"E722", # Do not use bare except (kept relaxed for legacy paths)
|
|
"E402", # Module level import not at top of file (kept relaxed)
|
|
"PLC0415", # import should be at top-level (kept relaxed)
|
|
"PTH123", # open() should be replaced by Path.open() (standard open allowed)
|
|
"PTH103", # os.makedirs() should be replaced by Path.mkdir() (os.makedirs allowed)
|
|
"PTH118", # os.path.join() should be replaced by Path (os.path.join allowed)
|
|
"EM101", # Exception must not use a string literal
|
|
"EM102", # Exception must not use an f-string literal
|
|
"TRY002", # Create your own exception
|
|
"TRY300", # Consider moving this statement to an else block
|
|
"DTZ005", # datetime.now() called without tz argument
|
|
"RET504", # Unnecessary assignment before return
|
|
"PLW2901", # for loop variable overwritten by assignment target
|
|
"F841", # Local variable assigned but never used
|
|
"ERA001", # Found commented-out code (kept relaxed)
|
|
]
|
|
|
|
# Exclude patterns
|
|
exclude = [
|
|
".bzr",
|
|
".direnv",
|
|
".eggs",
|
|
".git",
|
|
".git-rewrite",
|
|
".hg",
|
|
".mypy_cache",
|
|
".nox",
|
|
".pants.d",
|
|
".pyenv",
|
|
".pytest_cache",
|
|
".pytype",
|
|
".ruff_cache",
|
|
".svn",
|
|
".tox",
|
|
".venv",
|
|
".vscode",
|
|
"__pypackages__",
|
|
"_build",
|
|
"buck-out",
|
|
"build",
|
|
"dist",
|
|
"node_modules",
|
|
".next",
|
|
"out",
|
|
"venv",
|
|
"__pycache__",
|
|
]
|
|
|
|
# Allow autofix for all enabled rules
|
|
fixable = ["ALL"]
|
|
unfixable = []
|
|
|
|
# Allow unused variables when underscore-prefixed
|
|
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
|
|
[tool.ruff.format]
|
|
# Use double quotes for strings
|
|
quote-style = "double"
|
|
# Indent with spaces
|
|
indent-style = "space"
|
|
# Respect magic trailing comma
|
|
skip-magic-trailing-comma = false
|
|
# Automatically detect the appropriate line ending
|
|
line-ending = "auto"
|
|
|
|
# ============================================
|
|
# Ruff import sorting (isort replacement)
|
|
# ============================================
|
|
[tool.ruff.lint.isort]
|
|
known-first-party = ["deeptutor", "deeptutor_cli", "scripts"]
|
|
force-sort-within-sections = true
|
|
split-on-trailing-comma = true
|
|
|
|
# ============================================
|
|
# Ruff per-file-ignores
|
|
# ============================================
|
|
[tool.ruff.lint.per-file-ignores]
|
|
# Allow longer lines in test files
|
|
# F401: Allow unused imports for availability checks in tests
|
|
"**/test_*.py" = ["E501", "PLR2004", "F401"]
|
|
"**/__init__.py" = ["F401"] # Allow unused imports in __init__.py
|
|
|
|
# ============================================
|
|
# Ruff mccabe complexity
|
|
# ============================================
|
|
[tool.ruff.lint.mccabe]
|
|
max-complexity = 10
|
|
|
|
# ============================================
|
|
# Pytest configuration
|
|
# ============================================
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests", "deeptutor/learning/tests"]
|
|
pythonpath = ["."]
|
|
markers = [
|
|
"asyncio: mark async tests that require pytest-asyncio",
|
|
]
|
|
asyncio_default_fixture_loop_scope = "function"
|
|
addopts = [
|
|
"--strict-markers",
|
|
"--strict-config",
|
|
"--disable-warnings",
|
|
"--tb=short",
|
|
"--import-mode=importlib",
|
|
]
|
|
|
|
# ============================================
|
|
# MyPy type checking configuration
|
|
# ============================================
|
|
[tool.mypy]
|
|
python_version = "3.11"
|
|
# Relaxed type checking for gradual adoption
|
|
pretty = false
|
|
show_error_context = false
|
|
warn_return_any = false
|
|
warn_no_return = false
|
|
show_error_codes = true
|
|
ignore_missing_imports = true
|
|
follow_imports = "silent"
|
|
# Disable strict checks that generate too many errors
|
|
check_untyped_defs = false
|
|
disallow_untyped_defs = false
|
|
disallow_incomplete_defs = false
|
|
no_implicit_optional = false
|
|
|
|
# Module-specific overrides
|
|
[[tool.mypy.overrides]]
|
|
module = "tests.*"
|
|
ignore_errors = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "deeptutor.tools.*"
|
|
ignore_errors = true # Some tools may have dynamic imports
|
|
|
|
# ============================================
|
|
# Bandit security linting configuration
|
|
# ============================================
|
|
[tool.bandit]
|
|
exclude_dirs = ["tests", "scripts"]
|
|
# B101=assert, B311=random, B403/B404=pickle/subprocess imports
|
|
# B110=try_except_pass (intentional for non-critical error handling)
|
|
# B104=hardcoded_bind_all_interfaces (required for server binding)
|
|
# B112=try_except_continue (intentional for iteration)
|
|
# B105=hardcoded_password_string (false positive on empty string initialization)
|
|
# B301=pickle (used for internal embedding cache, not untrusted data)
|
|
# B501=request_with_no_cert_validation (opt-in via env var for dev/testing)
|
|
# B603=subprocess_without_shell_equals_true (controlled execution)
|
|
# B202=tarfile_unsafe_members (already using safe_members filter)
|
|
skips = ["B101", "B311", "B403", "B404", "B110", "B104", "B112", "B105", "B301", "B501", "B603", "B202"]
|