paperhub 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. paperhub-0.1.0/.env.example +21 -0
  2. paperhub-0.1.0/.gitignore +59 -0
  3. paperhub-0.1.0/LICENSE +21 -0
  4. paperhub-0.1.0/PKG-INFO +253 -0
  5. paperhub-0.1.0/README.md +207 -0
  6. paperhub-0.1.0/docs/API_KEYS.md +67 -0
  7. paperhub-0.1.0/docs/ARCHITECTURE.md +123 -0
  8. paperhub-0.1.0/docs/HOW_TO_START.md +112 -0
  9. paperhub-0.1.0/examples/03_jupyter_quickstart.ipynb +741 -0
  10. paperhub-0.1.0/examples/03_jupyter_quickstart_tr.ipynb +741 -0
  11. paperhub-0.1.0/examples/README.md +50 -0
  12. paperhub-0.1.0/pyproject.toml +124 -0
  13. paperhub-0.1.0/src/paperhub/__init__.py +222 -0
  14. paperhub-0.1.0/src/paperhub/agents/__init__.py +14 -0
  15. paperhub-0.1.0/src/paperhub/agents/anthropic_client.py +66 -0
  16. paperhub-0.1.0/src/paperhub/agents/base.py +100 -0
  17. paperhub-0.1.0/src/paperhub/agents/google_client.py +77 -0
  18. paperhub-0.1.0/src/paperhub/agents/openai_client.py +72 -0
  19. paperhub-0.1.0/src/paperhub/agents/paper_agent.py +187 -0
  20. paperhub-0.1.0/src/paperhub/agents/prompts.py +195 -0
  21. paperhub-0.1.0/src/paperhub/cache.py +202 -0
  22. paperhub-0.1.0/src/paperhub/config.py +105 -0
  23. paperhub-0.1.0/src/paperhub/dates.py +113 -0
  24. paperhub-0.1.0/src/paperhub/fetchers/__init__.py +8 -0
  25. paperhub-0.1.0/src/paperhub/fetchers/base.py +14 -0
  26. paperhub-0.1.0/src/paperhub/fetchers/hf_api.py +140 -0
  27. paperhub-0.1.0/src/paperhub/fetchers/hf_html.py +145 -0
  28. paperhub-0.1.0/src/paperhub/fetchers/range.py +70 -0
  29. paperhub-0.1.0/src/paperhub/formatter.py +130 -0
  30. paperhub-0.1.0/src/paperhub/interactive_cli.py +850 -0
  31. paperhub-0.1.0/src/paperhub/localization.py +18 -0
  32. paperhub-0.1.0/src/paperhub/models.py +131 -0
  33. paperhub-0.1.0/src/paperhub/orchestrator.py +65 -0
  34. paperhub-0.1.0/src/paperhub/pdf/__init__.py +6 -0
  35. paperhub-0.1.0/src/paperhub/pdf/downloader.py +70 -0
  36. paperhub-0.1.0/src/paperhub/pdf/extractor.py +72 -0
  37. paperhub-0.1.0/src/paperhub/utils.py +126 -0
  38. paperhub-0.1.0/tests/__init__.py +0 -0
  39. paperhub-0.1.0/tests/conftest.py +99 -0
  40. paperhub-0.1.0/tests/test_cache.py +78 -0
  41. paperhub-0.1.0/tests/test_cli.py +47 -0
  42. paperhub-0.1.0/tests/test_dates.py +82 -0
  43. paperhub-0.1.0/tests/test_fetchers.py +180 -0
  44. paperhub-0.1.0/tests/test_formatter.py +57 -0
  45. paperhub-0.1.0/tests/test_models.py +69 -0
  46. paperhub-0.1.0/tests/test_orchestrator.py +131 -0
  47. paperhub-0.1.0/tests/test_paper_agent.py +144 -0
  48. paperhub-0.1.0/tests/test_pdf_extract.py +61 -0
  49. paperhub-0.1.0/tests/test_public_api.py +225 -0
  50. paperhub-0.1.0/tests/test_utils.py +43 -0
@@ -0,0 +1,21 @@
1
+ # Copy to .env for local live-provider runs. Do not commit .env.
2
+ OPENAI_API_KEY=
3
+ ANTHROPIC_API_KEY=
4
+ GOOGLE_API_KEY=
5
+
6
+ # Defaults may be overridden by PaperHub(...).
7
+ PAPERHUB_PROVIDER=openai
8
+
9
+ # Optional global override. Leave empty to use the selected provider's default.
10
+ PAPERHUB_MODEL=
11
+
12
+ # Provider-specific defaults used when PaperHub(..., model=None).
13
+ PAPERHUB_OPENAI_MODEL=gpt-5.4-mini
14
+ PAPERHUB_OPENAI_REASONING_EFFORT=xhigh
15
+ PAPERHUB_ANTHROPIC_MODEL=claude-haiku-4-5-20251001
16
+ PAPERHUB_GOOGLE_MODEL=gemini-3-flash-preview
17
+
18
+ PAPERHUB_CONCURRENCY=5
19
+ PAPERHUB_MAX_PDF_CHARS=60000
20
+ PAPERHUB_CACHE_DIR=
21
+ PAPERHUB_REQUEST_TIMEOUT_S=30
@@ -0,0 +1,59 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.egg-info/
6
+ .eggs/
7
+ *.egg
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ .ruff_cache/
11
+ dist/
12
+ build/
13
+ .tox/
14
+ .nox/
15
+ .coverage
16
+ .coverage.*
17
+ coverage.xml
18
+ htmlcov/
19
+ site/
20
+ .venv/
21
+ venv/
22
+ env/
23
+
24
+ # PaperHub runtime artifacts
25
+ .paperhub/
26
+ *.sqlite
27
+ *.sqlite3
28
+ *.db
29
+ *.pdf
30
+
31
+ # Jupyter
32
+ .ipynb_checkpoints/
33
+
34
+ # Development-only AI / agent scaffolding
35
+ .claude/
36
+ .codex/
37
+ .cursor/
38
+ .continue/
39
+ .aider*
40
+ .mcp.json
41
+ CLAUDE.md
42
+ CLAUDE.local.md
43
+ START_PROMPT.md
44
+ SETUP.md
45
+ starter-template/
46
+ paperhub_roadmap.md
47
+ docs/PUBLISHING.md
48
+
49
+ # Secrets
50
+ .env
51
+ .env.*
52
+ !.env.example
53
+ *.pem
54
+ secrets/
55
+
56
+ # OS/editor
57
+ .DS_Store
58
+ .idea/
59
+ .vscode/
paperhub-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PaperHub maintainers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,253 @@
1
+ Metadata-Version: 2.4
2
+ Name: paperhub
3
+ Version: 0.1.0
4
+ Summary: Fetch HuggingFace Daily Papers and produce Jupyter-friendly AI summaries — one paper, one agent.
5
+ Project-URL: Homepage, https://github.com/paperhub/paperhub
6
+ Project-URL: Issues, https://github.com/paperhub/paperhub/issues
7
+ Author: PaperHub maintainers
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: arxiv,huggingface,llm,papers,summarization
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: beautifulsoup4>=4.12
23
+ Requires-Dist: httpx>=0.27
24
+ Requires-Dist: ipython>=8
25
+ Requires-Dist: openai>=2.32
26
+ Requires-Dist: pdfplumber>=0.11
27
+ Requires-Dist: platformdirs>=4
28
+ Requires-Dist: pydantic-settings>=2
29
+ Requires-Dist: pydantic>=2
30
+ Requires-Dist: pypdf>=4
31
+ Requires-Dist: python-dateutil>=2.9
32
+ Requires-Dist: rich>=13
33
+ Requires-Dist: tenacity>=8
34
+ Provides-Extra: anthropic
35
+ Requires-Dist: anthropic>=0.95; extra == 'anthropic'
36
+ Provides-Extra: dev
37
+ Requires-Dist: build>=1.2; extra == 'dev'
38
+ Requires-Dist: mypy>=1.8; extra == 'dev'
39
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
40
+ Requires-Dist: pytest>=8; extra == 'dev'
41
+ Requires-Dist: ruff>=0.4; extra == 'dev'
42
+ Requires-Dist: types-python-dateutil; extra == 'dev'
43
+ Provides-Extra: google
44
+ Requires-Dist: google-genai>=1.56; extra == 'google'
45
+ Description-Content-Type: text/markdown
46
+
47
+ # PaperHub
48
+
49
+ PaperHub fetches HuggingFace Daily Papers by programmatic date filters, assigns
50
+ each paper to its own AI summarization agent, and renders Jupyter-friendly
51
+ summaries by default.
52
+
53
+ Two ways to use PaperHub:
54
+
55
+ 1. **Terminal CLI** (`paperhub`) — interactive launcher with a REPL interface. **Primary mode.**
56
+ 2. **Python / Jupyter** — import `PaperHub` and call `hub.run(...)` directly.
57
+
58
+ ## Install
59
+
60
+ ```bash
61
+ python3 -m pip install -e ".[dev]"
62
+ ```
63
+
64
+ Optional provider extras:
65
+
66
+ ```bash
67
+ python3 -m pip install -e ".[anthropic]" # adds the Anthropic client
68
+ python3 -m pip install -e ".[google]" # adds the Google Gemini client
69
+ ```
70
+
71
+ ## Environment Variables
72
+
73
+ PaperHub reads configuration from environment variables (or a `.env` file at
74
+ the project root). Copy `.env.example` to `.env` to start:
75
+
76
+ ```bash
77
+ cp .env.example .env
78
+ ```
79
+
80
+ | Variable | Purpose |
81
+ |------------------------------------|---------------------------------------------------------------|
82
+ | `OPENAI_API_KEY` | Default provider key |
83
+ | `ANTHROPIC_API_KEY` | Optional, used when `--provider anthropic` |
84
+ | `GOOGLE_API_KEY` | Optional, used when `--provider google` |
85
+ | `PAPERHUB_PROVIDER` | Override default provider (default: openai) |
86
+ | `PAPERHUB_MODEL` | Optional global model override |
87
+ | `PAPERHUB_OPENAI_MODEL` | OpenAI default model (default: gpt-5.4-mini) |
88
+ | `PAPERHUB_OPENAI_REASONING_EFFORT` | OpenAI reasoning effort (default: xhigh) |
89
+ | `PAPERHUB_ANTHROPIC_MODEL` | Anthropic default model (default: claude-haiku-4-5-20251001) |
90
+ | `PAPERHUB_GOOGLE_MODEL` | Google default model (default: gemini-3-flash-preview) |
91
+ | `PAPERHUB_CONCURRENCY` | Max concurrent paper agents (default: 5) |
92
+ | `PAPERHUB_MAX_PDF_CHARS` | Truncation cap for PDF text (default: 60000) |
93
+ | `PAPERHUB_CACHE_DIR` | Override the on-disk cache location |
94
+
95
+ ## Terminal CLI (Primary)
96
+
97
+ Start the interactive launcher:
98
+
99
+ ```bash
100
+ paperhub
101
+ ```
102
+
103
+ The launcher opens a REPL with a status dashboard showing the current provider,
104
+ model, API key state, date range, and top paper count. Use commands to configure
105
+ and run:
106
+
107
+ ```text
108
+ /provider
109
+ /provider openai
110
+ /model
111
+ /model gpt-5.4-mini
112
+ /model default
113
+ /language
114
+ /date 2026-05
115
+ /date 2026-05-15
116
+ /date 2026-W18
117
+ /date 2026-05-01 2026-05-31
118
+ /top 5
119
+ /metadata
120
+ /run
121
+ /api-keys
122
+ /quit
123
+ ```
124
+
125
+ ### Date formats for `/date`
126
+
127
+ | Example | Period | Description |
128
+ |-------------------------------|----------|-----------------------|
129
+ | `/date 2026-05` | month | May 2026 |
130
+ | `/date 2026` | year | Full year 2026 |
131
+ | `/date 2026-05-15` | day | Single day |
132
+ | `/date 2026-W18` | week | ISO week 18 of 2026 |
133
+ | `/date 2026-05-01 2026-05-31` | custom | Inclusive date range |
134
+
135
+ `/metadata` fetches HuggingFace paper metadata only and does not call an LLM.
136
+ If the selected provider key is missing, `/run` prints setup guidance and the
137
+ launcher can render `docs/API_KEYS.md` with `/api-keys`.
138
+
139
+ You can also pass startup flags:
140
+
141
+ ```bash
142
+ paperhub --provider anthropic
143
+ paperhub --model claude-haiku-4-5-20251001
144
+ paperhub --top-n 10
145
+ ```
146
+
147
+ ## Python / Jupyter API
148
+
149
+ ```python
150
+ from datetime import date
151
+ from paperhub import PaperHub
152
+
153
+ hub = PaperHub(provider="openai")
154
+
155
+ # Month
156
+ hub.run(period="month", year=2026, month=5, top_n=10)
157
+
158
+ # Single day
159
+ hub.run(period="day", year=2026, month=5, day=1, top_n=5)
160
+
161
+ # ISO week
162
+ hub.run(period="week", year=2026, week=18, top_n=5)
163
+
164
+ # Full year
165
+ hub.run(period="year", year=2026, top_n=20)
166
+
167
+ # Custom range
168
+ hub.run(period="custom", start=date(2026, 4, 15), end=date(2026, 4, 30), top_n=15)
169
+ ```
170
+
171
+ `run` returns a `list[PaperSummary]`; in non-Jupyter contexts pass
172
+ `display=False` and call `render_plain` yourself if you do not need the
173
+ Markdown side effect.
174
+
175
+ For a step-by-step notebook, open `examples/03_jupyter_quickstart.ipynb`.
176
+
177
+ ## Provider Selection
178
+
179
+ ```python
180
+ PaperHub(provider="openai") # OpenAI default model
181
+ PaperHub(provider="openai", model="gpt-5.4-mini")
182
+ PaperHub(provider="anthropic") # Anthropic default model
183
+ PaperHub(model="claude-haiku-4-5-20251001", provider="anthropic")
184
+ PaperHub(model="gemini-3-flash-preview", provider="google")
185
+ ```
186
+
187
+ If `model` is omitted, PaperHub picks the selected provider's default model.
188
+ Provider-specific `.env` values such as `PAPERHUB_OPENAI_MODEL` override those
189
+ defaults. `PAPERHUB_MODEL` remains available as a global override. OpenAI uses
190
+ `PAPERHUB_OPENAI_REASONING_EFFORT=xhigh` by default; set it to an empty value
191
+ to let the OpenAI API choose its model default.
192
+
193
+ Provider SDKs are imported lazily — installing `paperhub` includes OpenAI by
194
+ default, and does not require Anthropic or Google packages unless you use those
195
+ providers.
196
+
197
+ ## Caching
198
+
199
+ PaperHub caches metadata, PDF text, and summaries in
200
+ `~/.cache/paperhub/paperhub.sqlite` (override with `PAPERHUB_CACHE_DIR`).
201
+ Summary entries are keyed by `(arxiv_id, model, language)`, so swapping models
202
+ or output language gives you a clean re-run while keeping the PDF download
203
+ free.
204
+
205
+ A second invocation with the same papers and model:
206
+
207
+ - Reuses the cached PDF text (no arXiv hit, no extraction).
208
+ - Reuses the cached summary (no LLM call).
209
+
210
+ ## Tests, Lint, Typecheck, Build
211
+
212
+ ```bash
213
+ python3 -m pytest # unit tests, no live network or LLM keys needed
214
+ python3 -m ruff check .
215
+ python3 -m ruff format --check .
216
+ python3 -m mypy src tests
217
+ python3 -m build # build wheel + sdist
218
+ ```
219
+
220
+ The unit tests use a fake LLM client and `httpx.MockTransport`; no real
221
+ provider keys are required.
222
+
223
+ ## Project Layout
224
+
225
+ ```
226
+ src/paperhub/
227
+ __init__.py # PaperHub public API
228
+ config.py # Settings (pydantic-settings)
229
+ models.py # PaperMeta, PaperSummary, RunRequest
230
+ dates.py # period → (start, end)
231
+ fetchers/ # HF JSON API (default) + HTML fallback
232
+ pdf/ # arXiv download + text extraction
233
+ agents/ # LLMClient protocol + provider clients + PaperAgent
234
+ orchestrator.py # asyncio.Semaphore parallelism
235
+ cache.py # SQLite cache
236
+ formatter.py # Markdown / plain-text rendering
237
+ interactive_cli.py # `paperhub` interactive launcher
238
+ tests/ # pytest suite, mocked HTTP and fake LLM
239
+ docs/ARCHITECTURE.md
240
+ docs/HOW_TO_START.md
241
+ docs/API_KEYS.md
242
+ examples/README.md
243
+ examples/03_jupyter_quickstart.ipynb
244
+ ```
245
+
246
+ ## Troubleshooting
247
+
248
+ - *"No papers found"*: HuggingFace may not yet have published Daily Papers
249
+ for that date. Use `/metadata` in the interactive launcher to check the
250
+ fetcher without an LLM call.
251
+ - *PDF text comes back tiny*: some arXiv PDFs use unusual layouts. PaperHub
252
+ falls back to `pdfplumber`; if both extractors are short, the agent will
253
+ pass through the abstract as the input text instead of failing.
@@ -0,0 +1,207 @@
1
+ # PaperHub
2
+
3
+ PaperHub fetches HuggingFace Daily Papers by programmatic date filters, assigns
4
+ each paper to its own AI summarization agent, and renders Jupyter-friendly
5
+ summaries by default.
6
+
7
+ Two ways to use PaperHub:
8
+
9
+ 1. **Terminal CLI** (`paperhub`) — interactive launcher with a REPL interface. **Primary mode.**
10
+ 2. **Python / Jupyter** — import `PaperHub` and call `hub.run(...)` directly.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ python3 -m pip install -e ".[dev]"
16
+ ```
17
+
18
+ Optional provider extras:
19
+
20
+ ```bash
21
+ python3 -m pip install -e ".[anthropic]" # adds the Anthropic client
22
+ python3 -m pip install -e ".[google]" # adds the Google Gemini client
23
+ ```
24
+
25
+ ## Environment Variables
26
+
27
+ PaperHub reads configuration from environment variables (or a `.env` file at
28
+ the project root). Copy `.env.example` to `.env` to start:
29
+
30
+ ```bash
31
+ cp .env.example .env
32
+ ```
33
+
34
+ | Variable | Purpose |
35
+ |------------------------------------|---------------------------------------------------------------|
36
+ | `OPENAI_API_KEY` | Default provider key |
37
+ | `ANTHROPIC_API_KEY` | Optional, used when `--provider anthropic` |
38
+ | `GOOGLE_API_KEY` | Optional, used when `--provider google` |
39
+ | `PAPERHUB_PROVIDER` | Override default provider (default: openai) |
40
+ | `PAPERHUB_MODEL` | Optional global model override |
41
+ | `PAPERHUB_OPENAI_MODEL` | OpenAI default model (default: gpt-5.4-mini) |
42
+ | `PAPERHUB_OPENAI_REASONING_EFFORT` | OpenAI reasoning effort (default: xhigh) |
43
+ | `PAPERHUB_ANTHROPIC_MODEL` | Anthropic default model (default: claude-haiku-4-5-20251001) |
44
+ | `PAPERHUB_GOOGLE_MODEL` | Google default model (default: gemini-3-flash-preview) |
45
+ | `PAPERHUB_CONCURRENCY` | Max concurrent paper agents (default: 5) |
46
+ | `PAPERHUB_MAX_PDF_CHARS` | Truncation cap for PDF text (default: 60000) |
47
+ | `PAPERHUB_CACHE_DIR` | Override the on-disk cache location |
48
+
49
+ ## Terminal CLI (Primary)
50
+
51
+ Start the interactive launcher:
52
+
53
+ ```bash
54
+ paperhub
55
+ ```
56
+
57
+ The launcher opens a REPL with a status dashboard showing the current provider,
58
+ model, API key state, date range, and top paper count. Use commands to configure
59
+ and run:
60
+
61
+ ```text
62
+ /provider
63
+ /provider openai
64
+ /model
65
+ /model gpt-5.4-mini
66
+ /model default
67
+ /language
68
+ /date 2026-05
69
+ /date 2026-05-15
70
+ /date 2026-W18
71
+ /date 2026-05-01 2026-05-31
72
+ /top 5
73
+ /metadata
74
+ /run
75
+ /api-keys
76
+ /quit
77
+ ```
78
+
79
+ ### Date formats for `/date`
80
+
81
+ | Example | Period | Description |
82
+ |-------------------------------|----------|-----------------------|
83
+ | `/date 2026-05` | month | May 2026 |
84
+ | `/date 2026` | year | Full year 2026 |
85
+ | `/date 2026-05-15` | day | Single day |
86
+ | `/date 2026-W18` | week | ISO week 18 of 2026 |
87
+ | `/date 2026-05-01 2026-05-31` | custom | Inclusive date range |
88
+
89
+ `/metadata` fetches HuggingFace paper metadata only and does not call an LLM.
90
+ If the selected provider key is missing, `/run` prints setup guidance and the
91
+ launcher can render `docs/API_KEYS.md` with `/api-keys`.
92
+
93
+ You can also pass startup flags:
94
+
95
+ ```bash
96
+ paperhub --provider anthropic
97
+ paperhub --model claude-haiku-4-5-20251001
98
+ paperhub --top-n 10
99
+ ```
100
+
101
+ ## Python / Jupyter API
102
+
103
+ ```python
104
+ from datetime import date
105
+ from paperhub import PaperHub
106
+
107
+ hub = PaperHub(provider="openai")
108
+
109
+ # Month
110
+ hub.run(period="month", year=2026, month=5, top_n=10)
111
+
112
+ # Single day
113
+ hub.run(period="day", year=2026, month=5, day=1, top_n=5)
114
+
115
+ # ISO week
116
+ hub.run(period="week", year=2026, week=18, top_n=5)
117
+
118
+ # Full year
119
+ hub.run(period="year", year=2026, top_n=20)
120
+
121
+ # Custom range
122
+ hub.run(period="custom", start=date(2026, 4, 15), end=date(2026, 4, 30), top_n=15)
123
+ ```
124
+
125
+ `run` returns a `list[PaperSummary]`; in non-Jupyter contexts pass
126
+ `display=False` and call `render_plain` yourself if you do not need the
127
+ Markdown side effect.
128
+
129
+ For a step-by-step notebook, open `examples/03_jupyter_quickstart.ipynb`.
130
+
131
+ ## Provider Selection
132
+
133
+ ```python
134
+ PaperHub(provider="openai") # OpenAI default model
135
+ PaperHub(provider="openai", model="gpt-5.4-mini")
136
+ PaperHub(provider="anthropic") # Anthropic default model
137
+ PaperHub(model="claude-haiku-4-5-20251001", provider="anthropic")
138
+ PaperHub(model="gemini-3-flash-preview", provider="google")
139
+ ```
140
+
141
+ If `model` is omitted, PaperHub picks the selected provider's default model.
142
+ Provider-specific `.env` values such as `PAPERHUB_OPENAI_MODEL` override those
143
+ defaults. `PAPERHUB_MODEL` remains available as a global override. OpenAI uses
144
+ `PAPERHUB_OPENAI_REASONING_EFFORT=xhigh` by default; set it to an empty value
145
+ to let the OpenAI API choose its model default.
146
+
147
+ Provider SDKs are imported lazily — installing `paperhub` includes OpenAI by
148
+ default, and does not require Anthropic or Google packages unless you use those
149
+ providers.
150
+
151
+ ## Caching
152
+
153
+ PaperHub caches metadata, PDF text, and summaries in
154
+ `~/.cache/paperhub/paperhub.sqlite` (override with `PAPERHUB_CACHE_DIR`).
155
+ Summary entries are keyed by `(arxiv_id, model, language)`, so swapping models
156
+ or output language gives you a clean re-run while keeping the PDF download
157
+ free.
158
+
159
+ A second invocation with the same papers and model:
160
+
161
+ - Reuses the cached PDF text (no arXiv hit, no extraction).
162
+ - Reuses the cached summary (no LLM call).
163
+
164
+ ## Tests, Lint, Typecheck, Build
165
+
166
+ ```bash
167
+ python3 -m pytest # unit tests, no live network or LLM keys needed
168
+ python3 -m ruff check .
169
+ python3 -m ruff format --check .
170
+ python3 -m mypy src tests
171
+ python3 -m build # build wheel + sdist
172
+ ```
173
+
174
+ The unit tests use a fake LLM client and `httpx.MockTransport`; no real
175
+ provider keys are required.
176
+
177
+ ## Project Layout
178
+
179
+ ```
180
+ src/paperhub/
181
+ __init__.py # PaperHub public API
182
+ config.py # Settings (pydantic-settings)
183
+ models.py # PaperMeta, PaperSummary, RunRequest
184
+ dates.py # period → (start, end)
185
+ fetchers/ # HF JSON API (default) + HTML fallback
186
+ pdf/ # arXiv download + text extraction
187
+ agents/ # LLMClient protocol + provider clients + PaperAgent
188
+ orchestrator.py # asyncio.Semaphore parallelism
189
+ cache.py # SQLite cache
190
+ formatter.py # Markdown / plain-text rendering
191
+ interactive_cli.py # `paperhub` interactive launcher
192
+ tests/ # pytest suite, mocked HTTP and fake LLM
193
+ docs/ARCHITECTURE.md
194
+ docs/HOW_TO_START.md
195
+ docs/API_KEYS.md
196
+ examples/README.md
197
+ examples/03_jupyter_quickstart.ipynb
198
+ ```
199
+
200
+ ## Troubleshooting
201
+
202
+ - *"No papers found"*: HuggingFace may not yet have published Daily Papers
203
+ for that date. Use `/metadata` in the interactive launcher to check the
204
+ fetcher without an LLM call.
205
+ - *PDF text comes back tiny*: some arXiv PDFs use unusual layouts. PaperHub
206
+ falls back to `pdfplumber`; if both extractors are short, the agent will
207
+ pass through the abstract as the input text instead of failing.
@@ -0,0 +1,67 @@
1
+ # PaperHub API Keys
2
+
3
+ PaperHub only needs an API key for the provider you choose for summarization.
4
+ Metadata-only checks do not require any LLM key.
5
+
6
+ ## Environment Variables
7
+
8
+ | Provider | Environment variable | Extra install |
9
+ |----------|----------------------|---------------|
10
+ | OpenAI | `OPENAI_API_KEY` | included by default |
11
+ | Anthropic | `ANTHROPIC_API_KEY` | `python3 -m pip install -e ".[anthropic]"` |
12
+ | Google Gemini | `GOOGLE_API_KEY` | `python3 -m pip install -e ".[google]"` |
13
+
14
+ ## Recommended `.env` Setup
15
+
16
+ From the repository root:
17
+
18
+ ```bash
19
+ cp .env.example .env
20
+ ```
21
+
22
+ Edit `.env`:
23
+
24
+ ```bash
25
+ OPENAI_API_KEY=sk-...
26
+ ANTHROPIC_API_KEY=sk-ant-...
27
+ GOOGLE_API_KEY=...
28
+
29
+ PAPERHUB_PROVIDER=openai
30
+ PAPERHUB_CONCURRENCY=2
31
+ PAPERHUB_MAX_PDF_CHARS=60000
32
+ ```
33
+
34
+ Do not commit `.env`; the repository `.gitignore` excludes it.
35
+
36
+ ## Provider Selection
37
+
38
+ Use the launcher:
39
+
40
+ ```text
41
+ /provider
42
+ /provider openai
43
+ /provider anthropic
44
+ /provider google
45
+ ```
46
+
47
+ ## Missing Key Behavior
48
+
49
+ If the selected provider key is missing, PaperHub will stop before making an
50
+ LLM call and print setup guidance. You can still check the fetch pipeline:
51
+
52
+ ```text
53
+ /metadata
54
+ ```
55
+
56
+ In the interactive launcher, use:
57
+
58
+ ```text
59
+ /status
60
+ /provider
61
+ /api-keys
62
+ /metadata
63
+ ```
64
+
65
+ `/status` shows the selected provider key state. `/provider` opens the full
66
+ provider/API-key availability selector. `/api-keys` prints this guide in the
67
+ terminal.