orbitr 0.1.1__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.
- orbitr-0.1.1/.env.example +33 -0
- orbitr-0.1.1/.envrc +1 -0
- orbitr-0.1.1/.github/workflows/ci.yml +95 -0
- orbitr-0.1.1/.gitignore +23 -0
- orbitr-0.1.1/AGENTS.md +114 -0
- orbitr-0.1.1/CHANGELOG.md +108 -0
- orbitr-0.1.1/LICENSE +21 -0
- orbitr-0.1.1/PKG-INFO +735 -0
- orbitr-0.1.1/README.md +701 -0
- orbitr-0.1.1/flake.lock +61 -0
- orbitr-0.1.1/flake.nix +44 -0
- orbitr-0.1.1/justfile +122 -0
- orbitr-0.1.1/pyproject.toml +75 -0
- orbitr-0.1.1/specs/implementation.md +475 -0
- orbitr-0.1.1/specs/planning.md +190 -0
- orbitr-0.1.1/specs/progress.md +276 -0
- orbitr-0.1.1/src/orbitr/__init__.py +3 -0
- orbitr-0.1.1/src/orbitr/_async.py +27 -0
- orbitr-0.1.1/src/orbitr/cli.py +132 -0
- orbitr-0.1.1/src/orbitr/clients/__init__.py +1 -0
- orbitr-0.1.1/src/orbitr/clients/arxiv.py +151 -0
- orbitr-0.1.1/src/orbitr/clients/base.py +228 -0
- orbitr-0.1.1/src/orbitr/clients/semantic_scholar.py +258 -0
- orbitr-0.1.1/src/orbitr/commands/__init__.py +1 -0
- orbitr-0.1.1/src/orbitr/commands/author.py +146 -0
- orbitr-0.1.1/src/orbitr/commands/cache.py +147 -0
- orbitr-0.1.1/src/orbitr/commands/doctor.py +128 -0
- orbitr-0.1.1/src/orbitr/commands/export.py +176 -0
- orbitr-0.1.1/src/orbitr/commands/init.py +196 -0
- orbitr-0.1.1/src/orbitr/commands/paper.py +350 -0
- orbitr-0.1.1/src/orbitr/commands/query.py +202 -0
- orbitr-0.1.1/src/orbitr/commands/recommend.py +172 -0
- orbitr-0.1.1/src/orbitr/commands/search.py +360 -0
- orbitr-0.1.1/src/orbitr/commands/zotero.py +266 -0
- orbitr-0.1.1/src/orbitr/config.py +173 -0
- orbitr-0.1.1/src/orbitr/core/__init__.py +1 -0
- orbitr-0.1.1/src/orbitr/core/cache.py +221 -0
- orbitr-0.1.1/src/orbitr/core/deduplication.py +184 -0
- orbitr-0.1.1/src/orbitr/core/export.py +223 -0
- orbitr-0.1.1/src/orbitr/core/models.py +57 -0
- orbitr-0.1.1/src/orbitr/core/query.py +214 -0
- orbitr-0.1.1/src/orbitr/core/ranking.py +157 -0
- orbitr-0.1.1/src/orbitr/display/__init__.py +119 -0
- orbitr-0.1.1/src/orbitr/display/detail.py +140 -0
- orbitr-0.1.1/src/orbitr/display/json_fmt.py +24 -0
- orbitr-0.1.1/src/orbitr/display/panels.py +91 -0
- orbitr-0.1.1/src/orbitr/display/table.py +76 -0
- orbitr-0.1.1/src/orbitr/exceptions.py +35 -0
- orbitr-0.1.1/src/orbitr/zotero/__init__.py +1 -0
- orbitr-0.1.1/src/orbitr/zotero/client.py +134 -0
- orbitr-0.1.1/tests/__init__.py +0 -0
- orbitr-0.1.1/tests/conftest.py +31 -0
- orbitr-0.1.1/tests/fixtures/.gitkeep +0 -0
- orbitr-0.1.1/tests/fixtures/arxiv_get_by_id.xml +47 -0
- orbitr-0.1.1/tests/fixtures/arxiv_search.xml +100 -0
- orbitr-0.1.1/tests/fixtures/ss_citations.json +145 -0
- orbitr-0.1.1/tests/fixtures/ss_get_by_id.json +56 -0
- orbitr-0.1.1/tests/fixtures/ss_recommendations.json +3 -0
- orbitr-0.1.1/tests/fixtures/ss_search.json +111 -0
- orbitr-0.1.1/tests/smoke_test.sh +257 -0
- orbitr-0.1.1/tests/test_arxiv.py +305 -0
- orbitr-0.1.1/tests/test_author.py +153 -0
- orbitr-0.1.1/tests/test_base_client.py +203 -0
- orbitr-0.1.1/tests/test_cache.py +212 -0
- orbitr-0.1.1/tests/test_cache_cmd.py +200 -0
- orbitr-0.1.1/tests/test_deduplication.py +293 -0
- orbitr-0.1.1/tests/test_display_phase4.py +265 -0
- orbitr-0.1.1/tests/test_doctor.py +209 -0
- orbitr-0.1.1/tests/test_export.py +281 -0
- orbitr-0.1.1/tests/test_init.py +344 -0
- orbitr-0.1.1/tests/test_models.py +152 -0
- orbitr-0.1.1/tests/test_paper.py +334 -0
- orbitr-0.1.1/tests/test_query.py +204 -0
- orbitr-0.1.1/tests/test_ranking.py +169 -0
- orbitr-0.1.1/tests/test_recommend.py +150 -0
- orbitr-0.1.1/tests/test_search.py +441 -0
- orbitr-0.1.1/tests/test_semantic_scholar.py +250 -0
- orbitr-0.1.1/tests/test_zotero.py +274 -0
- orbitr-0.1.1/uv.lock +1011 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# lumen environment variables
|
|
2
|
+
# Copy to .env and fill in values, or run `lumen init` for guided setup.
|
|
3
|
+
# These override settings in ~/.config/lumen/config.toml.
|
|
4
|
+
|
|
5
|
+
# Semantic Scholar API key (optional — increases rate limits)
|
|
6
|
+
# Get one at: https://www.semanticscholar.org/product/api
|
|
7
|
+
SEMANTIC_SCHOLAR_API_KEY=
|
|
8
|
+
|
|
9
|
+
# Zotero credentials (required for `lumen zotero` commands)
|
|
10
|
+
# Get your User ID and API key at: https://www.zotero.org/settings/keys
|
|
11
|
+
ZOTERO_USER_ID=
|
|
12
|
+
ZOTERO_API_KEY=
|
|
13
|
+
|
|
14
|
+
# Override default search sources (comma-separated)
|
|
15
|
+
# LUMEN_SOURCES=arxiv,semantic_scholar
|
|
16
|
+
|
|
17
|
+
# Override default max results
|
|
18
|
+
# LUMEN_MAX_RESULTS=10
|
|
19
|
+
|
|
20
|
+
# Override default output format (table, list, json)
|
|
21
|
+
# LUMEN_FORMAT=table
|
|
22
|
+
|
|
23
|
+
# Override cache directory
|
|
24
|
+
# LUMEN_CACHE_DIR=~/.cache/lumen
|
|
25
|
+
|
|
26
|
+
# Disable caching entirely
|
|
27
|
+
# LUMEN_NO_CACHE=1
|
|
28
|
+
|
|
29
|
+
# Disable pager for long output
|
|
30
|
+
# LUMEN_NO_PAGER=1
|
|
31
|
+
|
|
32
|
+
# Disable all color output (also respected: NO_COLOR=1)
|
|
33
|
+
# NO_COLOR=1
|
orbitr-0.1.1/.envrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
use flake .
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
name: Lint
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: astral-sh/setup-uv@v5
|
|
18
|
+
with:
|
|
19
|
+
enable-cache: true
|
|
20
|
+
- run: uv sync --group dev
|
|
21
|
+
- run: uv run ruff format --check src/ tests/
|
|
22
|
+
- run: uv run ruff check src/ tests/
|
|
23
|
+
|
|
24
|
+
typecheck:
|
|
25
|
+
name: Type check
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
- uses: astral-sh/setup-uv@v5
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: true
|
|
32
|
+
- run: uv sync --group dev
|
|
33
|
+
- run: uv run pyright src/
|
|
34
|
+
|
|
35
|
+
test:
|
|
36
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
strategy:
|
|
39
|
+
fail-fast: false
|
|
40
|
+
matrix:
|
|
41
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
- uses: astral-sh/setup-uv@v5
|
|
45
|
+
with:
|
|
46
|
+
enable-cache: true
|
|
47
|
+
python-version: ${{ matrix.python-version }}
|
|
48
|
+
- run: uv sync --group dev
|
|
49
|
+
- run: uv run pytest --tb=short -q
|
|
50
|
+
|
|
51
|
+
coverage:
|
|
52
|
+
name: Coverage
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
steps:
|
|
55
|
+
- uses: actions/checkout@v4
|
|
56
|
+
- uses: astral-sh/setup-uv@v5
|
|
57
|
+
with:
|
|
58
|
+
enable-cache: true
|
|
59
|
+
- run: uv sync --group dev
|
|
60
|
+
- run: uv run pytest --cov=orbitr --cov-report=term-missing --cov-fail-under=80 -q
|
|
61
|
+
|
|
62
|
+
build:
|
|
63
|
+
name: Build
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
needs: [lint, typecheck, test]
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v4
|
|
68
|
+
- uses: astral-sh/setup-uv@v5
|
|
69
|
+
with:
|
|
70
|
+
enable-cache: true
|
|
71
|
+
- run: uv build
|
|
72
|
+
- name: Check wheel installs and --version works
|
|
73
|
+
run: |
|
|
74
|
+
uv tool install dist/*.whl
|
|
75
|
+
orbitr --version
|
|
76
|
+
- uses: actions/upload-artifact@v4
|
|
77
|
+
with:
|
|
78
|
+
name: dist
|
|
79
|
+
path: dist/
|
|
80
|
+
|
|
81
|
+
publish:
|
|
82
|
+
name: Publish to PyPI
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
needs: [build]
|
|
85
|
+
if: github.event_name == 'release'
|
|
86
|
+
environment: pypi
|
|
87
|
+
permissions:
|
|
88
|
+
id-token: write
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/download-artifact@v4
|
|
91
|
+
with:
|
|
92
|
+
name: dist
|
|
93
|
+
path: dist/
|
|
94
|
+
- uses: astral-sh/setup-uv@v5
|
|
95
|
+
- run: uv publish --trusted-publishing always
|
orbitr-0.1.1/.gitignore
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
dist/
|
|
2
|
+
build/
|
|
3
|
+
*.egg-info/
|
|
4
|
+
__pycache__/
|
|
5
|
+
.venv/
|
|
6
|
+
.env
|
|
7
|
+
.env.local
|
|
8
|
+
*.pem
|
|
9
|
+
credentials.json
|
|
10
|
+
.DS_Store
|
|
11
|
+
.idea/
|
|
12
|
+
.vscode/
|
|
13
|
+
*.swp
|
|
14
|
+
*.pyc
|
|
15
|
+
*.pyo
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.pyright/
|
|
19
|
+
htmlcov/
|
|
20
|
+
.coverage
|
|
21
|
+
coverage.xml
|
|
22
|
+
.direnv/
|
|
23
|
+
.aider*
|
orbitr-0.1.1/AGENTS.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# orbitr — Agent Project Context
|
|
2
|
+
|
|
3
|
+
## Software Purpose
|
|
4
|
+
|
|
5
|
+
`orbitr` is a Python CLI tool for academic literature search and reference management. It queries arXiv, Semantic Scholar, and Google Scholar concurrently, deduplicates and ranks results, and integrates with the Zotero reference manager. Target users: researchers, academics, and students who prefer terminal-based workflows.
|
|
6
|
+
|
|
7
|
+
## Architecture Overview
|
|
8
|
+
|
|
9
|
+
CLI pipeline: command dispatch → concurrent async API clients → core processing (dedup, ranking, cache) → display layer (Rich or JSON).
|
|
10
|
+
|
|
11
|
+
**Key components:**
|
|
12
|
+
|
|
13
|
+
- `src/orbitr/cli.py` — Typer root app; global flags; injects config into context
|
|
14
|
+
- `src/orbitr/config.py` — layered config: CLI flags > env vars > `~/.config/orbitr/config.toml` > defaults
|
|
15
|
+
- `src/orbitr/commands/` — one module per command (`search`, `paper`, `cite`, `author`, `recommend`, `export`, `query`, `zotero`, `cache`, `init`, `doctor`)
|
|
16
|
+
- `src/orbitr/clients/` — async httpx clients: `arxiv.py`, `semantic_scholar.py`; all extend `base.py` (retry, rate limiting, circuit break); Google Scholar deferred to v1.1
|
|
17
|
+
- `src/orbitr/core/` — `models.py` (Pydantic), `deduplication.py`, `ranking.py`, `cache.py` (SQLite), `export.py` (BibTeX/RIS/CSL-JSON)
|
|
18
|
+
- `src/orbitr/zotero/client.py` — pyzotero wrapper
|
|
19
|
+
- `src/orbitr/display/` — `table.py`, `list.py`, `detail.py`, `json_fmt.py`
|
|
20
|
+
|
|
21
|
+
## Dev Environment
|
|
22
|
+
|
|
23
|
+
The project uses a **Nix flake** to pin the dev environment (Python 3.12, uv, ruff,
|
|
24
|
+
pyright) and **direnv** to activate it automatically on `cd`. A **justfile** provides
|
|
25
|
+
all common workflow recipes.
|
|
26
|
+
|
|
27
|
+
Entry point:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cd orbitr # direnv runs `use flake .` — activates pinned shell
|
|
31
|
+
just setup # uv sync inside the flake environment
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Without direnv: `nix develop` then `just setup`.
|
|
35
|
+
|
|
36
|
+
## Build, Test, and Run
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
just setup # uv sync — install deps and editable package
|
|
40
|
+
just run -- --help # run orbitr via uv run
|
|
41
|
+
just build # uv build — produces dist/ wheel + sdist
|
|
42
|
+
|
|
43
|
+
just fmt # ruff format src/ tests/
|
|
44
|
+
just lint # ruff check --fix src/ tests/
|
|
45
|
+
just check # fmt + lint, no writes (use in CI)
|
|
46
|
+
just types # pyright src/
|
|
47
|
+
just qa # check + types
|
|
48
|
+
|
|
49
|
+
just test # pytest — full suite
|
|
50
|
+
just test-unit # pytest -m "not integration"
|
|
51
|
+
just cov # pytest --cov with term-missing report
|
|
52
|
+
just test-mod core/test_deduplication # single module
|
|
53
|
+
|
|
54
|
+
just clean # remove build artifacts and caches
|
|
55
|
+
just reset # wipe .venv and reinstall from scratch
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Run `just` with no arguments to list all recipes.
|
|
59
|
+
|
|
60
|
+
## Language and Stack
|
|
61
|
+
|
|
62
|
+
- **Python** ≥ 3.10; `uv` for deps and packaging; `hatchling` build backend
|
|
63
|
+
- **CLI:** Typer + Click
|
|
64
|
+
- **Terminal output:** Rich
|
|
65
|
+
- **HTTP:** httpx (async)
|
|
66
|
+
- **Models:** Pydantic v2
|
|
67
|
+
- **Cache:** SQLite (stdlib `sqlite3`)
|
|
68
|
+
- **Zotero:** pyzotero
|
|
69
|
+
- **Code style:** `ruff format` (88 chars), `ruff check` (rules: E, F, UP, B, SIM, I), `pyright` basic
|
|
70
|
+
|
|
71
|
+
## Directory Structure
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
orbitr/
|
|
75
|
+
├── pyproject.toml
|
|
76
|
+
├── flake.nix
|
|
77
|
+
├── CLAUDE.md
|
|
78
|
+
├── README.md
|
|
79
|
+
├── .env.example
|
|
80
|
+
├── specs/ # planning.md, progress.md, implementation.md
|
|
81
|
+
├── logs/ # session and weekly review logs
|
|
82
|
+
├── src/orbitr/ # source package
|
|
83
|
+
├── tests/ # pytest suite + fixtures/
|
|
84
|
+
└── .gitignore
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Development Workflow
|
|
88
|
+
|
|
89
|
+
- Conventional commits: `type(scope): message` (feat, fix, chore, docs, test, refactor)
|
|
90
|
+
- All commands must have complete `--help` text with a usage example before merging
|
|
91
|
+
- Errors go to stderr; data goes to stdout — enforce at every command boundary
|
|
92
|
+
- All new commands: add entry to `cli.py`, stub in `commands/`, unit test in `tests/test_<command>.py`
|
|
93
|
+
- Run `just check` before committing; run `just qa` before opening a PR
|
|
94
|
+
- Check `specs/planning.md` for the current phase and open tasks
|
|
95
|
+
- Update `specs/progress.md` after completing a milestone or feature
|
|
96
|
+
|
|
97
|
+
## Key Conventions
|
|
98
|
+
|
|
99
|
+
- **Exit codes:** 0 success, 1 general error, 2 usage error, 3 config error, 4 no results
|
|
100
|
+
- **Config path:** `~/.config/orbitr/config.toml` (XDG); cache at `~/.cache/orbitr/`
|
|
101
|
+
- **Credentials file permissions:** `0600` — enforced in `orbitr init`
|
|
102
|
+
- **TTY detection:** when stdout is not a TTY, default `--format` to `json` automatically
|
|
103
|
+
- **`NO_COLOR`** env var disables all Rich color; `--no-color` flag does the same
|
|
104
|
+
- **Async in Typer:** wrap async work in `asyncio.run()` at the command level; no persistent event loop
|
|
105
|
+
- **Google Scholar:** deferred to v1.1 — do not implement in v1
|
|
106
|
+
- **Deduplication threshold:** 85% fuzzy title similarity (configurable internally)
|
|
107
|
+
|
|
108
|
+
## How to Use Claude Effectively Here
|
|
109
|
+
|
|
110
|
+
- **Before implementing a command:** read `specs/implementation.md` for the module structure and key interfaces; check `specs/progress.md` for current status
|
|
111
|
+
- **Error messages:** always include what failed, why, and a fix suggestion — see `specs/implementation.md` § Error Handling for the pattern
|
|
112
|
+
- **Adding a new command:** follow the pattern in existing `commands/` modules; register in `cli.py`; add `--help` text with a real example
|
|
113
|
+
- **Tests:** use `tests/fixtures/` for API responses; mock with `respx`; never make live API calls in tests
|
|
114
|
+
- **Display:** add new renderers in `display/`; always accept `format: Literal["table","list","detail","json"]` and honor `NO_COLOR`
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here.
|
|
4
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
5
|
+
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## [0.1.0] — 2026-04-06
|
|
10
|
+
|
|
11
|
+
Initial release.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
**Core pipeline**
|
|
16
|
+
|
|
17
|
+
- Multi-source concurrent search across arXiv (Atom feed) and Semantic Scholar
|
|
18
|
+
(Graph API v1) via `orbitr search`
|
|
19
|
+
- Intelligent deduplication: exact DOI match → exact arXiv ID match → fuzzy
|
|
20
|
+
title similarity (rapidfuzz, 85% threshold) with author-overlap gating
|
|
21
|
+
- Five ranking criteria: `relevance` (TF-IDF), `citations` (log-scaled),
|
|
22
|
+
`date` (recency), `impact` (citations × date), `combined` (weighted blend)
|
|
23
|
+
- SQLite TTL cache with three independent tiers:
|
|
24
|
+
`search` (1 h), `paper` (24 h), `citations` (6 h)
|
|
25
|
+
|
|
26
|
+
**Commands**
|
|
27
|
+
|
|
28
|
+
- `orbitr search` — keyword + `field:value` syntax, field flags (`--title`,
|
|
29
|
+
`--author`, `--venue`), year range (`--from`, `--to`), sort, format
|
|
30
|
+
- `orbitr paper` — fetch by arXiv ID, DOI, or Semantic Scholar ID; auto-detects
|
|
31
|
+
ID type; accepts `arxiv:`, `abs/`, URL, and bare ID forms
|
|
32
|
+
- `orbitr cite` — citing papers via Semantic Scholar
|
|
33
|
+
- `orbitr author` — author search via Semantic Scholar two-step (search → papers)
|
|
34
|
+
- `orbitr recommend` — content/citation/hybrid recommendations via SS
|
|
35
|
+
- `orbitr export` — BibTeX, RIS, CSL-JSON; reads ndjson from stdin or `--query`
|
|
36
|
+
- `orbitr query` — heuristic NL-to-query translator with `--run` flag
|
|
37
|
+
- `orbitr zotero add/collections/new` — Zotero Web API integration via pyzotero
|
|
38
|
+
- `orbitr cache stats/clean/clear` — cache inspection and management
|
|
39
|
+
- `orbitr init` — interactive credential and defaults setup (writes `config.toml`
|
|
40
|
+
with mode `0600`)
|
|
41
|
+
- `orbitr doctor` — async connectivity checks for arXiv, SS, and Zotero
|
|
42
|
+
|
|
43
|
+
**Display layer**
|
|
44
|
+
|
|
45
|
+
- Four output formats: `table` (Rich Table), `list` (Rich Panels), `detail`
|
|
46
|
+
(full single-paper layout with abstract, metadata, links), `json` (ndjson)
|
|
47
|
+
- TTY auto-detection: `--format` defaults to `json` when stdout is not a TTY
|
|
48
|
+
- Pager integration: long output routed through `$PAGER` (`less -R`) on TTY;
|
|
49
|
+
disabled with `LUMEN_NO_PAGER=1`
|
|
50
|
+
|
|
51
|
+
**Error handling**
|
|
52
|
+
|
|
53
|
+
- `LumenError` hierarchy with exit codes: 1 (source), 2 (usage), 3 (config),
|
|
54
|
+
4 (no results)
|
|
55
|
+
- HTTP errors converted to clean `SourceError` in `BaseClient._get`; no raw
|
|
56
|
+
httpx messages surface to users
|
|
57
|
+
- 5xx errors retried up to 3× with exponential backoff; 403 directs to
|
|
58
|
+
`orbitr init` for API key setup
|
|
59
|
+
- Dim suggestion lines on all error messages
|
|
60
|
+
|
|
61
|
+
**Infrastructure**
|
|
62
|
+
|
|
63
|
+
- Layered config: CLI flags > env vars > `~/.config/orbitr/config.toml` > defaults
|
|
64
|
+
- Nix flake dev environment (Python 3.12, uv, ruff, pyright)
|
|
65
|
+
- `justfile` with test, lint, format, coverage, build, and install recipes
|
|
66
|
+
- GitHub Actions CI: lint, typecheck, test (Python 3.10–3.12), coverage, build,
|
|
67
|
+
publish-on-release
|
|
68
|
+
|
|
69
|
+
### Test coverage
|
|
70
|
+
|
|
71
|
+
- 343 tests; `core/` at 100%, `display/` at 97% overall
|
|
72
|
+
- Offline API tests via `respx` fixtures (no live network calls in CI)
|
|
73
|
+
- Smoke test script (`tests/smoke_test.sh`) for pre-release live-API validation
|
|
74
|
+
|
|
75
|
+
### Known limitations
|
|
76
|
+
|
|
77
|
+
- Google Scholar support deferred to v1.1 (scraping fragility)
|
|
78
|
+
- `orbitr recommend --method` flag is accepted but all methods use the same
|
|
79
|
+
SS endpoint; method distinctions planned for v1.1
|
|
80
|
+
- `display/detail.py` falls back to list view for multi-paper input in some
|
|
81
|
+
edge cases
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## [0.1.1] — 2026-04-06
|
|
86
|
+
|
|
87
|
+
### Fixed
|
|
88
|
+
|
|
89
|
+
- **`orbitr init` — env-var credential protection** (`commands/init.py`, `config.py`):
|
|
90
|
+
- Credentials supplied via `SEMANTIC_SCHOLAR_API_KEY`, `ZOTERO_USER_ID`, or
|
|
91
|
+
`ZOTERO_API_KEY` environment variables are now detected at init time.
|
|
92
|
+
- A clear dim note is shown for each active env var: *"Already set via
|
|
93
|
+
ENV_VAR — leave blank to keep using the env var."*
|
|
94
|
+
- Prompts for env-var-sourced credentials default to blank instead of
|
|
95
|
+
pre-filling with the resolved (env) value, preventing accidental plain-text
|
|
96
|
+
exposure in `config.toml`.
|
|
97
|
+
- If the user leaves a credential blank and an env var is active, the
|
|
98
|
+
existing `config.toml` value for that field is preserved rather than
|
|
99
|
+
overwritten with an empty string.
|
|
100
|
+
- Entering a new value at the prompt always writes it to `config.toml`,
|
|
101
|
+
regardless of whether an env var is also set.
|
|
102
|
+
- Config loading (`load_config`) was already correct (env vars take
|
|
103
|
+
precedence over `config.toml` at runtime); this fix closes the init-time
|
|
104
|
+
loophole.
|
|
105
|
+
|
|
106
|
+
## Unreleased
|
|
107
|
+
|
|
108
|
+
_Nothing yet._
|
orbitr-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jerid Francom
|
|
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.
|