7a0da7932b
Backwards Compatibility / Verify Encryption Constants (push) Waiting to run
Backwards Compatibility / PyPI Version Compatibility (push) Waiting to run
Backwards Compatibility / Database Migration Tests (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Blocked by required conditions
Docker Tests (Consolidated) / detect-changes (push) Waiting to run
Docker Tests (Consolidated) / Build Test Image (push) Waiting to run
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Blocked by required conditions
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Blocked by required conditions
Docker Tests (Consolidated) / Accessibility Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Unit Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / LLM Example Tests (push) Blocked by required conditions
Docker Tests (Consolidated) / Production Image Smoke Test (push) Blocked by required conditions
Docker Tests (Consolidated) / Infrastructure Tests (push) Blocked by required conditions
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Waiting to run
OSV-Scanner (Scheduled) / scan-scheduled (push) Waiting to run
Create Release / test-gate (push) Blocked by required conditions
Create Release / release-gate (push) Blocked by required conditions
Create Release / ci-gate (push) Blocked by required conditions
Create Release / version-check (push) Waiting to run
Create Release / e2e-test-gate (push) Blocked by required conditions
Create Release / responsive-test-gate (push) Blocked by required conditions
Create Release / compat-test-gate (push) Blocked by required conditions
Create Release / compose-integration-gate (push) Blocked by required conditions
Create Release / vulture-gate (push) Blocked by required conditions
Create Release / build (push) Blocked by required conditions
Create Release / provenance (push) Blocked by required conditions
Create Release / prerelease-docker (push) Blocked by required conditions
Create Release / publish-docker (push) Blocked by required conditions
Create Release / create-release (push) Blocked by required conditions
Create Release / cleanup-changelog (push) Blocked by required conditions
Create Release / trigger-pypi (push) Blocked by required conditions
Create Release / monitor-pypi (push) Blocked by required conditions
Create Release / Clean up orphan prerelease tags and signatures (push) Blocked by required conditions
490 lines
19 KiB
TOML
490 lines
19 KiB
TOML
[build-system]
|
|
requires = ["pdm-backend>=2.4.3"]
|
|
build-backend = "pdm.backend"
|
|
|
|
[project]
|
|
name = "local-deep-research"
|
|
dynamic = ["version"]
|
|
description = "AI-powered research assistant with deep, iterative analysis using LLMs and web searches"
|
|
readme = "README.md"
|
|
requires-python = ">=3.12,<3.15"
|
|
license = {file = "LICENSE"}
|
|
authors = [
|
|
{name = "LearningCircuit", email = "185559241+LearningCircuit@users.noreply.github.com"},
|
|
{name = "HashedViking", email = "6432677+HashedViking@users.noreply.github.com"},
|
|
{name = "djpetti", email = "djpetti@gmail.com"},
|
|
]
|
|
classifiers = [
|
|
"Programming Language :: Python :: 3",
|
|
"License :: OSI Approved :: MIT License",
|
|
"Operating System :: OS Independent",
|
|
]
|
|
dependencies = [
|
|
"langchain~=1.2", # lock pulls 1.3.9: GHSA-gr75-jv2w-4656 fix
|
|
"langchain-community~=0.4",
|
|
"langchain-core~=1.2",
|
|
"langchain-ollama~=1.0",
|
|
"langchain-openai~=1.1",
|
|
"langchain-anthropic~=1.3", # lock pulls 1.4.6: GHSA-gr75-jv2w-4656 fix
|
|
"openai>=2", # direct dep: error_handling/openai_compat_errors.py imports exception classes
|
|
"httpx>=0.27", # direct dep: error_handling/openai_compat_errors.py imports ConnectError/ReadTimeout
|
|
"duckduckgo-search~=8.1",
|
|
"python-dateutil~=2.9",
|
|
"typing-extensions~=4.15",
|
|
"justext~=3.0",
|
|
"readabilipy~=0.3",
|
|
"trafilatura~=2.0",
|
|
"extruct~=0.18",
|
|
"playwright~=1.58",
|
|
"beautifulsoup4~=4.14",
|
|
"flask~=3.1.3", # CVE-2026-27205 fix: session Vary: Cookie header
|
|
"werkzeug~=3.1.6", # CVE-2026-27199 fix: safe_join() Windows device names
|
|
"flask-cors~=6.0",
|
|
"flask-socketio~=5.6.1", # Fix for Flask 3.1.3 session property compatibility
|
|
"alembic~=1.17",
|
|
"sqlalchemy~=2.0",
|
|
"sqlalchemy-utc~=0.14",
|
|
"wikipedia~=1.4",
|
|
"arxiv~=2.4",
|
|
"pypdf~=6.12", # CVE-2026-33123, CVE-2026-31826, GHSA-9m86-7pmv-2852, CVE-2026-27888, CVE-2026-27024, CVE-2026-0777, CVE-2025-55197, GHSA-3crg-w4f6-42mx, GHSA-248m-82v9-q6g6, GHSA-cj93-chg6-vgv8, GHSA-jm82-fx9c-mx94 fixes
|
|
"sentence-transformers~=5.2",
|
|
"faiss-cpu~=1.13.0", # 1.14.x wheels SIGILL on CPUs without AVX2 (#4480); unpin criteria tracked in #4499
|
|
"pydantic~=2.12",
|
|
"pydantic-settings~=2.12", # lock pulls 2.14.2: GHSA-4xgf-cpjx-pc3j fix
|
|
"toml~=0.10",
|
|
"platformdirs~=4.5",
|
|
"dynaconf~=3.2",
|
|
"requests>=2.32", # CVE-2026-25645 patched in 2.33; PDM override ensures 2.33+ in dev
|
|
"urllib3~=2.7", # CVE-2026-44431 CVE-2026-44432 fix
|
|
"tiktoken~=0.12",
|
|
"xmltodict~=1.0",
|
|
"lxml>=5.3", # >=5.3 to satisfy crawl4ai; PDM override ensures >=6.0 in dev
|
|
"newspaper4k~=0.9",
|
|
"crawl4ai~=0.9", # 0.9.0: GHSA-r253-r9jw-qg44 (RCE via Chromium launch-arg injection), GHSA-2jq4-q6vv-4cp3 (path-traversal file write), GHSA-wm69-2pc3-rmmf fixes; supersedes 0.8.9 fixes
|
|
"defusedxml~=0.7", # XXE-safe XML parsing
|
|
"nh3~=0.3", # Backend HTML sanitization
|
|
"pdfplumber~=0.11",
|
|
"unstructured~=0.18",
|
|
# Runtime parsers for the unstructured office-document loaders. These are
|
|
# NOT pulled in by bare `unstructured` (only by its `[docx]`/`[odt]`/`[pptx]`/
|
|
# `[xlsx]` extras), yet the loader registry advertises .doc/.docx/.odt/.ppt/
|
|
# .pptx/.xls/.xlsx as supported. Without them those uploads fail at runtime
|
|
# with `ModuleNotFoundError: No module named 'docx'` (see issue #4414).
|
|
"python-docx~=1.2", # .doc, .docx, .odt (odt parser imports python-docx)
|
|
"python-pptx~=1.0", # .ppt, .pptx
|
|
"python-slugify~=8.0", # citation_formatter._slugify_title
|
|
"openpyxl~=3.1", # .xlsx (unstructured Excel partition)
|
|
"msoffcrypto-tool~=6.0", # imported at module load by unstructured.partition.xlsx
|
|
"xlrd~=2.0", # legacy .xls reading (pandas engine)
|
|
"google-search-results~=2.4",
|
|
"jaraco-context~=6.1", # CVE GHSA-58pv-8j8x-9vj2 fix for path traversal (also pinned as transitive dep)
|
|
"flask-wtf~=1.2",
|
|
"optuna~=4.7",
|
|
"elasticsearch~=9.3",
|
|
"methodtools~=0.4",
|
|
"loguru~=0.7",
|
|
"cachetools~=7.0",
|
|
"matplotlib~=3.10",
|
|
"pandas~=3.0",
|
|
"plotly~=6.5",
|
|
"kaleido~=1.2",
|
|
"aiohttp~=3.13", # lock pulls 3.14.1: CVE-2026-54273..54280 fixes
|
|
"tenacity~=9.1",
|
|
"apscheduler~=3.11",
|
|
"rich~=14.3",
|
|
"click~=8.3",
|
|
"flask-login~=0.6",
|
|
"flask-limiter~=4.1",
|
|
"sqlcipher3-binary~=0.6; sys_platform == \"linux\" and platform_machine == \"x86_64\"",
|
|
"sqlcipher3~=0.6; (platform_machine == \"aarch64\" or platform_machine == \"arm64\") and sys_platform == \"linux\"",
|
|
"sqlcipher3~=0.6; sys_platform != \"linux\"",
|
|
"lxml-html-clean>=0.4.4", # CVE-2026-28350: base tag injection bypass
|
|
"weasyprint~=68.1",
|
|
"Pillow>=12.1.1", # CVE-2026-25990: out-of-bounds write in PSD
|
|
"cryptography>=48.0.1,<49", # CVE-2026-26007 (SECT curves), CVE-2026-39892 (buffer overflow), GHSA-537c-gmf6-5ccf (bundled OpenSSL, fixed by 48.0.1's OpenSSL 4.0.1 recompile); <49 avoids cryptography 49.0.0 breaking changes (removed PUBLIC/PRIVATE_KEY_TYPES aliases, stricter X.509 loading)
|
|
"apprise~=1.9",
|
|
"markdown~=3.10",
|
|
"pypandoc-binary~=1.16",
|
|
"datasets~=4.5",
|
|
"pyarrow~=23.0",
|
|
"langchain-experimental~=0.4",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
mcp = [
|
|
"mcp[cli]~=1.2",
|
|
]
|
|
|
|
[project.urls]
|
|
"Homepage" = "https://github.com/LearningCircuit/local-deep-research"
|
|
"Bug Tracker" = "https://github.com/LearningCircuit/local-deep-research/issues"
|
|
|
|
[project.scripts]
|
|
# `ldr` was removed in commit c1f80e7a8 ("Remove deprecated CLI", #319) but the
|
|
# entry-point line was left behind, so the installed binary has crashed on
|
|
# import for every release since. Caught by the entry-point smoke in
|
|
# release-gate.yml. Restore only when a replacement CLI exists.
|
|
ldr-web = "local_deep_research.web.app:main"
|
|
ldr-mcp = "local_deep_research.mcp:run_server"
|
|
|
|
# Note: build backend is pdm.backend (see [build-system]). These
|
|
# [tool.setuptools] sections are kept for compatibility with editable
|
|
# installs via `pip install -e .` which may fall back to setuptools.
|
|
[tool.setuptools]
|
|
include-package-data = true
|
|
|
|
[tool.setuptools.package-data]
|
|
"local_deep_research.web" = ["templates/*", "static/*", "static/**/*"]
|
|
"local_deep_research.defaults" = ["*.toml", "*.py", "*.template", ".env.template", "*.json"]
|
|
"local_deep_research.notifications" = ["templates/*.jinja2"]
|
|
# Note: there is no `local_deep_research.data` package any more. Every
|
|
# academic dataset is downloaded at runtime into the user data directory
|
|
# by the `local_deep_research.journal_quality.data_sources` package.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[tool.pdm]
|
|
distribution = true
|
|
version = { source = "file", path = "src/local_deep_research/__version__.py" }
|
|
[[tool.pdm.source]]
|
|
url = "https://download.pytorch.org/whl/cpu"
|
|
name = "torch"
|
|
include_packages = ["torch", "torch*"]
|
|
|
|
[tool.pdm.resolution.overrides]
|
|
# arxiv pins requests~=2.32.0, but 2.32.x has CVE-2026-25645
|
|
requests = ">=2.33"
|
|
# newspaper4k and crawl4ai pin lxml<6.0 but work fine with 6.x
|
|
# (tested). Override to get Python 3.14 pre-built wheels.
|
|
lxml = ">=6.0"
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"virtualenv~=20.36",
|
|
"pre-commit~=4.5",
|
|
"cookiecutter~=2.6",
|
|
"pytest-mock~=3.15",
|
|
"pytest~=9.0",
|
|
"pytest-cov~=7.0",
|
|
"pytest-timeout~=2.4",
|
|
"pytest-asyncio~=1.3",
|
|
"pytest-xdist~=3.8",
|
|
"ruff~=0.15",
|
|
"freezegun~=1.5",
|
|
"mypy~=1.19",
|
|
"types-requests~=2.32",
|
|
"types-toml~=0.10",
|
|
"types-flask~=1.1",
|
|
"hypothesis~=6.151",
|
|
"vulture~=2.14",
|
|
"towncrier~=24.8",
|
|
"xlwt~=1.3", # test-only: writes legacy .xls fixtures for XLSLoader tests
|
|
]
|
|
|
|
[tool.pytest.ini_options]
|
|
markers = [
|
|
"requires_llm: marks tests that require a real LLM (not fallback)",
|
|
"integration: marks integration tests",
|
|
"slow: marks slow tests",
|
|
"asyncio: marks async tests that use asyncio",
|
|
"fd_canary: heavy file-descriptor-leak regression tests (#3816). CPU-bound real-event-loop spins that exceeded the legacy 60s timeout under coverage + '-n auto' contention, and whose FD-count assertions are noisy under parallel execution; run in a dedicated serial, no-coverage CI step instead of the parallel suite.",
|
|
]
|
|
# Global timeout for all tests - fail fast instead of hanging.
|
|
# "thread" (not "signal") because SIGALRM was firing inside weakref/GC on
|
|
# 3.14 in CI, corrupting xdist workers and losing their coverage data.
|
|
timeout = 180
|
|
timeout_method = "thread"
|
|
|
|
[tool.coverage.run]
|
|
source = ["src"]
|
|
branch = true
|
|
omit = [
|
|
"*/tests/*",
|
|
"*/__pycache__/*",
|
|
"*/migrations/*",
|
|
# Experimental strategies (will be cleaned up)
|
|
"*/strategies/*",
|
|
# CLI entry points (hard to unit test)
|
|
"*/cli.py",
|
|
"*/cli/*",
|
|
# Visualization code
|
|
"*/visualization.py",
|
|
# Experimental browsecomp decoding
|
|
"*/answer_decoding/*",
|
|
]
|
|
|
|
[tool.coverage.report]
|
|
exclude_lines = [
|
|
"pragma: no cover",
|
|
"if TYPE_CHECKING:",
|
|
"raise NotImplementedError",
|
|
]
|
|
# Conservative baseline — ratchet up as coverage improves
|
|
fail_under = 50
|
|
show_missing = true
|
|
|
|
[tool.coverage.html]
|
|
directory = "coverage/htmlcov"
|
|
|
|
[tool.ruff]
|
|
# Exclude a variety of commonly ignored directories.
|
|
exclude = [
|
|
".bzr",
|
|
".direnv",
|
|
".eggs",
|
|
".git",
|
|
".git-rewrite",
|
|
".hg",
|
|
".ipynb_checkpoints",
|
|
".mypy_cache",
|
|
".nox",
|
|
".pants.d",
|
|
".pyenv",
|
|
".pytest_cache",
|
|
".pytype",
|
|
".ruff_cache",
|
|
".svn",
|
|
".tox",
|
|
".venv",
|
|
".vscode",
|
|
"__pypackages__",
|
|
"_build",
|
|
"buck-out",
|
|
"build",
|
|
"dist",
|
|
"node_modules",
|
|
"site-packages",
|
|
"venv",
|
|
]
|
|
|
|
# Same as Black.
|
|
line-length = 80
|
|
indent-width = 4
|
|
|
|
[tool.ruff.lint]
|
|
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
|
select = [
|
|
"E4", "E7", "E9", "F", "S",
|
|
# --- Wave 2: logging, performance, return style, exceptions, print, comprehensions ---
|
|
"G", # flake8-logging-format: lazy formatting in logger calls
|
|
"PERF", # perflint: performance anti-patterns
|
|
"RET", # flake8-return: unnecessary assign-before-return, superfluous else
|
|
"TRY", # tryceratops: exception handling patterns
|
|
"T20", # flake8-print: print statement detection in production code
|
|
"C4", # flake8-comprehensions: unnecessary comprehensions/calls
|
|
]
|
|
ignore = [
|
|
# --- Bandit (S) rules suppressed globally for existing code patterns ---
|
|
# try-except-pass/continue: pervasive cleanup pattern throughout codebase
|
|
"S110", # try-except-pass
|
|
"S112", # try-except-continue
|
|
# subprocess calls with known-safe partial paths (e.g. "git", "pip")
|
|
"S603", # subprocess-without-shell-equals-true
|
|
"S606", # start-process-with-no-shell
|
|
"S607", # start-process-with-partial-path
|
|
# --- Wave 2: rules ignored initially due to high violation counts ---
|
|
# TODO: fix violations and remove ignore
|
|
"TRY003", # raise-vanilla-args — overly pedantic for built-in exceptions
|
|
"TRY004", # type-check-without-type-error — breaks API contracts; ruff autofix was removed
|
|
"TRY300", # try-consider-else — unintuitive syntax; conflicts with RET505
|
|
"PERF401", # manual-list-comprehension — no reliable autofix; negligible real-world impact
|
|
]
|
|
|
|
# Allow fix for all enabled rules (when `--fix`) is provided.
|
|
fixable = ["ALL"]
|
|
unfixable = []
|
|
|
|
# Allow unused variables when underscore-prefixed.
|
|
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
# Tests: assert is the standard pattern; hardcoded values are test fixtures; print is fine
|
|
"tests/**" = ["S101", "S104", "S105", "S106", "S107", "S108", "S113", "S311", "S324", "S602", "S608", "T20", "TRY201", "G004", "C420", "TRY002", "C408", "C401", "C416", "C414", "PERF102", "PERF402", "PERF403", "RET503", "RET504", "TRY301"]
|
|
# Examples: hardcoded values are demo fixtures; print is fine; bare exceptions acceptable
|
|
"examples/**" = ["S105", "S311", "T201", "TRY002", "C408", "C401", "C416", "PERF102", "PERF402", "PERF403", "RET503", "RET502", "RET504", "TRY301"]
|
|
# Cookiecutter hooks: shell=True is needed for cross-platform compat
|
|
"cookiecutter-docker/**" = ["S602", "T201"]
|
|
# CI scripts: test password is intentional
|
|
"scripts/ci/**" = ["S105"]
|
|
# Pre-commit hooks: print is the interface
|
|
".pre-commit-hooks/**" = ["T201", "RET503", "RET504"]
|
|
# Scripts: print is the interface
|
|
"scripts/**" = ["T201"]
|
|
".github/scripts/**" = ["T201"]
|
|
# CLI modules: print is the interface
|
|
"src/local_deep_research/cli/**" = ["T201"]
|
|
# Benchmarks: print is used for output/reporting
|
|
"src/local_deep_research/benchmarks/**" = ["T201"]
|
|
# Web/settings files with intentional print for startup/debug
|
|
"src/local_deep_research/settings/logger.py" = ["T201"]
|
|
"src/local_deep_research/web/routes/route_registry.py" = ["T201"]
|
|
"src/local_deep_research/web_search_engines/rate_limiting/cli.py" = ["T201"]
|
|
# Server config: binding to 0.0.0.0 is intentional for containerized deployment
|
|
"src/local_deep_research/web/server_config.py" = ["S104"]
|
|
"src/local_deep_research/web/routes/settings_routes.py" = ["S104"]
|
|
"src/local_deep_research/security/network_utils.py" = ["S104"]
|
|
"src/local_deep_research/security/notification_validator.py" = ["S104"]
|
|
"src/local_deep_research/security/url_builder.py" = ["S104"]
|
|
"src/local_deep_research/utilities/llm_utils.py" = ["S104"]
|
|
"src/local_deep_research/web_search_engines/rate_limiting/llm/wrapper.py" = ["S104"]
|
|
# Non-cryptographic random used for jitter/sampling, not security
|
|
"src/local_deep_research/scheduler/background.py" = ["S311"]
|
|
"src/local_deep_research/web/auth/middleware_optimizer.py" = ["S311"]
|
|
"src/local_deep_research/web_search_engines/engines/search_engine_google_pse.py" = ["S311"]
|
|
"src/local_deep_research/web_search_engines/rate_limiting/tracker.py" = ["S311"]
|
|
# Hardcoded password strings are default/placeholder values, not real secrets
|
|
"src/local_deep_research/database/models/library.py" = ["S105"]
|
|
"src/local_deep_research/web/auth/database_middleware.py" = ["S105"]
|
|
# Requests without timeout: safe_requests module handles timeouts at a higher level
|
|
"src/local_deep_research/security/safe_requests.py" = ["S113"]
|
|
# Markup usage is intentional and inputs are pre-sanitized
|
|
"src/local_deep_research/web/themes/__init__.py" = ["S704"]
|
|
"src/local_deep_research/web/utils/vite_helper.py" = ["S704"]
|
|
# SQL expressions use parameterized queries; ruff flags f-string construction
|
|
"src/local_deep_research/advanced_search_system/filters/followup_relevance_filter.py" = ["S608"]
|
|
"src/local_deep_research/web_search_engines/search_engine_base.py" = ["S608"]
|
|
# XML parsing uses defusedxml elsewhere; this specific usage is on trusted data
|
|
"src/local_deep_research/research_library/downloaders/arxiv.py" = ["S314"]
|
|
|
|
[tool.ruff.format]
|
|
# Like Black, use double quotes for strings.
|
|
quote-style = "double"
|
|
# Like Black, indent with spaces, rather than tabs.
|
|
indent-style = "space"
|
|
# Like Black, respect magic trailing commas.
|
|
skip-magic-trailing-comma = false
|
|
# Like Black, automatically detect the appropriate line ending.
|
|
line-ending = "auto"
|
|
|
|
[tool.mypy]
|
|
python_version = "3.12"
|
|
warn_return_any = true
|
|
warn_unused_configs = true
|
|
disallow_untyped_defs = false
|
|
check_untyped_defs = true
|
|
warn_redundant_casts = true
|
|
warn_unused_ignores = true
|
|
no_implicit_optional = true
|
|
strict_equality = true
|
|
show_error_codes = true
|
|
|
|
# Start permissive - allow missing imports for third-party packages without stubs
|
|
ignore_missing_imports = true
|
|
|
|
# Ignore test files
|
|
[[tool.mypy.overrides]]
|
|
module = "tests.*"
|
|
ignore_errors = true
|
|
|
|
# Third-party packages without type stubs — suppress import-untyped errors
|
|
[[tool.mypy.overrides]]
|
|
module = ["cachetools", "cachetools.*", "dateutil", "dateutil.*"]
|
|
ignore_missing_imports = true
|
|
|
|
# Existing modules with type errors — ignore until cleaned up.
|
|
# New modules are checked by default. Remove entries as modules are fixed.
|
|
[[tool.mypy.overrides]]
|
|
module = [
|
|
"local_deep_research.advanced_search_system.*",
|
|
"local_deep_research.api.*",
|
|
"local_deep_research.benchmarks.*",
|
|
"local_deep_research.config.*",
|
|
"local_deep_research.database.*",
|
|
"local_deep_research.domain_classifier.*",
|
|
"local_deep_research.embeddings.splitters.*",
|
|
"local_deep_research.library.*",
|
|
"local_deep_research.metrics.*",
|
|
"local_deep_research.research_library.*",
|
|
"local_deep_research.security.*",
|
|
"local_deep_research.settings.*",
|
|
"local_deep_research.storage.*",
|
|
"local_deep_research.utilities.*",
|
|
"local_deep_research.web.*",
|
|
]
|
|
ignore_errors = true
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# towncrier — release-notes news fragments
|
|
# ---------------------------------------------------------------------------
|
|
# Each PR drops a tiny markdown file under changelog.d/ named
|
|
# <id>.<category>.md (or +slug.<category>.md for orphan fragments
|
|
# without a PR/issue number). At release prep time the maintainer runs:
|
|
#
|
|
# pdm run towncrier build --version <X.Y.Z> --yes
|
|
#
|
|
# which renders the fragments into docs/release_notes/<X.Y.Z>.md (per
|
|
# the {version}-templated filename below) and `git rm`s the consumed
|
|
# fragments. The release workflow (.github/workflows/release.yml) then
|
|
# reads that per-version file as the human-narrative input to the
|
|
# release body (alongside the AI TL;DR and the auto-generated PR list).
|
|
#
|
|
# Categories are intentionally lean — the auto-generated PR list already
|
|
# catches dep bumps, CI churn, etc., so changelog.d/ fragments are just
|
|
# for user-visible changes worth highlighting.
|
|
[tool.towncrier]
|
|
# `name` is set explicitly so towncrier never tries to import the
|
|
# `local_deep_research` package. The release workflow runs towncrier
|
|
# in a sparse checkout that omits src/, so an import-based lookup
|
|
# would fail with ModuleNotFoundError. `package`/`package_dir` are
|
|
# intentionally not set — with `name` provided and `--version` always
|
|
# passed on the CLI, towncrier has no remaining reason to import.
|
|
name = "local-deep-research"
|
|
# single_file=false + a {version}-templated filename makes towncrier
|
|
# write a fresh per-release file each build instead of appending to one
|
|
# growing CHANGELOG. Matches the pre-existing
|
|
# docs/release_notes/<version>.md convention used by the release
|
|
# workflow.
|
|
single_file = false
|
|
filename = "docs/release_notes/{version}.md"
|
|
directory = "changelog.d"
|
|
# title_format=false suppresses the `## <version> (<date>)` header in
|
|
# the rendered output — the GitHub release page already shows the
|
|
# version as its title, and per-version files don't need an inline
|
|
# version header either.
|
|
title_format = false
|
|
issue_format = "[#{issue}](https://github.com/LearningCircuit/local-deep-research/pull/{issue})"
|
|
underlines = ["", "", ""]
|
|
|
|
[[tool.towncrier.type]]
|
|
directory = "breaking"
|
|
name = "💥 Breaking Changes"
|
|
showcontent = true
|
|
|
|
[[tool.towncrier.type]]
|
|
directory = "security"
|
|
name = "🔒 Security"
|
|
showcontent = true
|
|
|
|
[[tool.towncrier.type]]
|
|
directory = "feature"
|
|
name = "✨ New Features"
|
|
showcontent = true
|
|
|
|
[[tool.towncrier.type]]
|
|
directory = "bugfix"
|
|
name = "🐛 Bug Fixes"
|
|
showcontent = true
|
|
|
|
[[tool.towncrier.type]]
|
|
directory = "removal"
|
|
name = "🗑️ Removed"
|
|
showcontent = true
|
|
|
|
[[tool.towncrier.type]]
|
|
directory = "misc"
|
|
name = "📝 Other Changes"
|
|
showcontent = true
|