-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathrequirements.txt
More file actions
136 lines (136 loc) · 8.07 KB
/
Copy pathrequirements.txt
File metadata and controls
136 lines (136 loc) · 8.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
quart>=0.20
hypercorn>=0.17
# cryptography — auto-generates TLS certificates for zero-config HTTP/2.
# Also pulls in the standard Python crypto stack (used transitively by many packages).
cryptography>=42.0
# flask + flask-compress kept for import compatibility (quart depends on flask)
flask>=3.0
flask-compress>=1.14
requests>=2.31
# urllib3 — transitive via requests; pinned explicitly to a floor that clears
# the redirect-leak CVE trio (CVE-2023-43804 / CVE-2023-45803 Cookie+body leak
# on cross-origin redirect, CVE-2024-37891 proxy-auth leak), fixed in 1.26.18/.19.
urllib3>=1.26.19
# Jinja2 — transitive via flask/quart; pinned to a floor past the sandbox/attr
# escaping bypasses (CVE-2024-22195/34064/56201/56326, CVE-2025-27516), fixed
# across 3.1.3–3.1.6. Flask 3.x already supports it.
Jinja2>=3.1.6
psutil>=5.9
# sqlite3 is built into Python — no external package needed
# tofu-search — standalone multi-engine web search + content fetch pipeline,
# extracted from this repo's former lib/search + lib/fetch. chatui wires its
# own LLM routing / browser-extension / auth-source behavior into tofu-search's
# provider seams via lib/search_bridge.py at startup.
# >=0.3.1: the browser-search fallback now relies on the BrowserProvider.fetch_html
# seam (the SERP parser lives IN the library); the bridge no longer ships its own
# parser, so an older tofu-search would leave browser-search dead.
# >=0.3.2: adds the pre-fetch relevance gate (skips fetching zero-query-overlap
# SERP junk before it costs a fetch / floods the browser bridge); default-on,
# so chatui search + Reading-Mode reports stop pulling off-topic pages.
# >=0.4.0: carries the `tofu_search.verify` subpackage (zero-LLM citation
# verifier). Below this floor, paper-mode's citation-integrity card silently
# never appears (build_citation_audit degrades to None on the missing import).
# >=0.4.1: adaptive per-engine dual-path proxy (proxied↔direct, sticky+TTL'd)
# — the bridge passes proxy_dual_attempt; below this floor that kwarg is
# rejected by an older configure(), so keep the floor at the version that
# defines it.
# >=0.4.2: docs/packaging hygiene (lxml transitive-dep note); no API change —
# floor bumped to always resolve the latest published release.
# >=0.4.3: entity-diversified rerank top-K for multi-entity comparison queries
# (search/rerank.py::_diversify_by_entity + shared authority.host_brand_labels)
# — internal reranking improvement, no public-API change.
# >=0.5.0: hard wall-clock deadlines (search_deadline_secs / fetch_url_deadline_secs).
# HARD FLOOR — not optional: lib/search_bridge.py::sync_search_config passes both
# kwargs to tofu_search.configure() UNCONDITIONALLY, and server.py calls
# install_search_bridge() at boot with no guard. An older configure() rejects the
# unknown kwargs with `TypeError: SearchConfig.__init__() got an unexpected keyword
# argument 'search_deadline_secs'`, so the server crashes on startup against any
# tofu-search < 0.5.0. Do not lower this floor without first making the bridge pass
# the deadline kwargs defensively.
# >=0.5.1: per-engine request throttle (min_request_interval_ms, default 400ms) that
# stops two concurrent search calls from self-inflicting an engine rate-limit (the
# DDG 202). SOFT floor (unlike the 0.5.0 deadline kwargs): the bridge does NOT pass
# min_request_interval_ms to configure(), so an older tofu-search does not crash — it
# just lacks the throttle. Live-tune via the TOFU_SEARCH_MIN_REQUEST_INTERVAL_MS env
# var (configure() picks it up for any field the bridge leaves unset).
tofu-search>=0.5.1
trafilatura>=1.6
# playwright is optional — powers the JS-rendered fallback in tofu_search.fetch.
# On Linux, Chromium needs X11/GTK shared libs (libatk, libgbm, libXcomposite, …).
# With root: sudo python -m playwright install-deps chromium
# Without root: install.sh falls back to `conda install -c conda-forge`
# (atk-1.0, xorg-libxcomposite, mesa-libgbm-cos7-x86_64, …) and
# tofu_search/fetch/playwright_pool.py auto-augments LD_LIBRARY_PATH.
playwright>=1.40
Pillow>=10.0
python-pptx>=0.6.21
lxml>=4.9
# lxml.html.clean was extracted into a separate package in lxml 5.2+;
# justext (a trafilatura dep) still does `from lxml.html.clean import Cleaner`,
# so we must ensure the extracted package is present.
lxml_html_clean>=0.4
# BeautifulSoup — HTML fallback parser in tofu_search/fetch/html_extract.py.
# Usually pulled in transitively by trafilatura, but listed here so it's
# guaranteed even if trafilatura's deps change.
beautifulsoup4>=4.12
# python-dateutil — robust date parsing for HTML publish-date extraction
# in tofu_search/fetch/html_extract.py (imported eagerly, no ImportError fallback).
python-dateutil>=2.8
# Office document parsing — lib/doc_parser.py handles .docx/.pptx/.xlsx/
# .doc/.xls/.ppt uploads. Each has a graceful ImportError fallback, but
# shipping them by default means uploads Just Work.
python-docx>=1.0
openpyxl>=3.1
xlrd>=2.0
olefile>=0.46
mcp>=1.0
# orjson — fast C JSON encoder. REQUIRED (not optional): routes/chat.py's SSE
# state snapshot serializes the ENTIRE conversation (content+thinking+toolRounds,
# 10+ MB for long convs). Plain json.dumps holds the GIL for the whole call, so
# even via asyncio.to_thread it stalls the event loop ~40 ms and overflows the
# accept queue → the page goes dark (the 15000 incident, 2026-06). orjson encodes
# the same payload in ~5 ms, dropping the loop stall below the danger threshold.
# A stdlib iterencode fallback covers the rare inputs orjson rejects (non-str keys).
orjson>=3.9
# tiktoken — exact BPE tokenizer (cl100k/o200k) used by lib/token_counter as
# the local "exact" tier for OpenAI/Claude-family models. Without it the
# resolver chain falls through to the CJK/entropy heuristic, which under-counts
# high-entropy content (base64/minified data) and can let an oversized prompt
# slip past the proactive-compaction trigger. Optional at runtime (the
# heuristic is the always-present fallback), but shipping it makes the
# compaction token-gate substantially tighter.
tiktoken>=0.7
# PDF parsing stack — pymupdf (fitz) is used across lib/pdf_parser, routes/paper,
# and tofu_search.fetch for fast local PDF text/image extraction. pymupdf4llm is an
# optional LLM-oriented Markdown extractor built on top of pymupdf.
pymupdf>=1.24
pymupdf4llm>=0.0.17
# Markdown — server-side renderer for paper-report HTML export
# (routes/paper.py:export_report). Frontend still uses marked.js for live
# rendering; this dep is only used for downloadable .html exports.
markdown>=3.5
# PyYAML — serves the YAML variant of the OpenAPI spec
# (routes/api_docs.py::openapi_yaml). The route degrades to JSON on
# ImportError, so this is a soft feature dep; declared explicitly because it
# was previously only present transitively and went missing in clean envs.
PyYAML>=6.0
# uv powers several MCP servers (via `uvx`) — see lib/mcp/client.py. Installing
# it here guarantees uvx is on PATH inside the conda env without requiring a
# separate curl|sh bootstrap.
uv>=0.4
# SQLAlchemy Core (NOT the ORM) — used by lib/database/_core_schema.py as a
# single-source table-definition + dual-dialect DDL/DML *compiler* for NEW
# tables (PG primary, SQLite fallback), retiring the hand-maintained twin-DDL
# + regex _sql_translate path for those tables. Compile-only: no Engine is
# opened; execution stays on the existing get_db() connection. Importing the
# _core_schema module is optional — the legacy DB path does not depend on it.
sqlalchemy>=2.0
# zhconv — pure-Python (MediaWiki tables, MIT) Traditional↔Simplified Chinese
# converter. Used by lib/transcription/_zh.py as a FAIL-SAFE last gate on voice
# transcripts: Whisper-family / omni-chat ASR models emit Mandarin as Traditional
# by default, so a Simplified-Chinese user sees garbled variant text. No native
# build step (fits a vanilla self-hosted box + bootstrap.py). Soft dep at runtime:
# normalize_zh_variant() degrades to a no-op on ImportError, so the transcribe
# path works without it — shipping it makes voice input Just Work in Simplified.
# Disable/retarget via TOFU_ASR_ZH_VARIANT (default zh-cn; empty/off = raw).
zhconv>=1.4