[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "webfetch-llm" version = "0.1.3" description = "Own your LLM's web search: a local search -> fetch -> rank pipeline that replaces hosted web_search tools at a fraction of the cost" readme = "README.md" requires-python = ">=3.10" license = { text = "MIT" } authors = [{ name = "Rishi Gulati" }] keywords = [ "llm", "web-search", "agents", "tool-use", "rag", "anthropic", "openai", "mcp", "semantic-cache", ] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Internet :: WWW/HTTP :: Indexing/Search", "Topic :: Scientific/Engineering :: Artificial Intelligence", ] # Core deps kept lean - no heavy ML libs by default. Cache uses stdlib # sqlite3. Ranking degrades to BM25 (rank-bm25, pure Python) without the # rerank extra. readability-lxml and newspaper4k are core because they run # in the DEFAULT extraction chain - the benchmark numbers assume them. dependencies = [ "trafilatura>=1.8", "readability-lxml>=0.8", "newspaper4k>=0.9", "rank-bm25>=0.2.2", "requests>=2.31", # ddgs is the maintained successor of duckduckgo-search; ddg.py imports it. "ddgs>=6.0", "anthropic>=0.25", "mcp>=1.0", # Entry points (webfetch-mcp/-status/-savings) load .env from cwd; # the library itself never reads it. See webfetch/_env.py. "python-dotenv>=1.0", ] [project.optional-dependencies] # Semantic reranking, semantic query cache, compression scoring rerank = [ "sentence-transformers>=3.0", "numpy>=1.26", ] # JS-rendered page fallback (playwright must also run `playwright install`) browser = [ "playwright>=1.44", ] # PDF datasheet extraction pdf = [ "pdfplumber>=0.11", ] # HTML table extraction (pandas.read_html appended as markdown; # tabulate is what DataFrame.to_markdown actually calls) tables = [ "pandas>=2.0", "tabulate>=0.9", ] # Kept as a no-op alias (mcp moved to core in 0.1.1 so uvx # one-liners work); harmless for existing install commands. mcp = [] # Full install all = ["webfetch-llm[rerank,browser,pdf,tables,mcp]"] # Development: tests, lint, .env loading for examples/evals dev = [ "pytest>=8.0", "ruff>=0.4", ] [project.urls] Homepage = "https://github.com/firish/webfetch" Repository = "https://github.com/firish/webfetch" Issues = "https://github.com/firish/webfetch/issues" [project.scripts] webfetch-mcp = "webfetch.mcp:main" webfetch-savings = "webfetch.receipts:main" webfetch-status = "webfetch.status:main" # Alias named after the PyPI package so `uvx webfetch-llm` starts the MCP # server directly - uvx runs the script matching the package name, and # MCP registry clients build run commands from the package identifier. webfetch-llm = "webfetch.mcp:main" [tool.hatch.build.targets.wheel] packages = ["webfetch"] [tool.ruff] line-length = 88 target-version = "py310" [tool.ruff.lint] # E/F: pycodestyle+pyflakes defaults; I: import sorting; UP: modernize. select = ["E", "F", "I", "UP"] # E501 in evals: report tables and URLs run long; the library itself complies. [tool.ruff.lint.per-file-ignores] "evals/*" = ["E501"] "examples/*" = ["E501"] [tool.pytest.ini_options] testpaths = ["tests"]