papersearch 0.4.0 → 0.4.2

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.
package/README.md CHANGED
@@ -8,7 +8,7 @@ It is the open version by default: once installed it searches and downloads open
8
8
 
9
9
  ![Node.js](https://img.shields.io/badge/node.js->=18.0.0-green.svg)
10
10
  ![License](https://img.shields.io/badge/license-MIT-blue.svg)
11
- ![Version](https://img.shields.io/badge/version-0.4.0-blue.svg)
11
+ ![Version](https://img.shields.io/badge/version-0.4.2-blue.svg)
12
12
  [![LinuxDo](https://img.shields.io/badge/LinuxDo-community-1f6feb)](https://linux.do)
13
13
 
14
14
  [How it works](#how-it-works) | [Quick start](#quick-start) | [Two ways to download](#two-ways-to-download) | [Search sources](#search-sources) | [Configuration](#configuration) | [Agent Skill](#agent-skill) | [Commands](#commands) | [Troubleshooting](#troubleshooting)
@@ -102,6 +102,7 @@ paper-search carsi status --format text
102
102
 
103
103
  - Installing asks for your school (a CARSI member school, by Chinese name, English name or domain) and downloads the dedicated Camoufox browser, about 3 GB in all; on macOS, `--browser ego` uses ego lite instead, about 0.5 GB. `--skip-school` leaves the school for later.
104
104
  - Schools sign in through CARSI (the Chinese university identity federation). When a publisher's institution list has no CARSI or no entry for your school, the program says so at once; download on campus or through your school's VPN instead.
105
+ - Downloads show a progress window: skip this paper, mark the journal or publisher as no access, stop the whole task, or change how long waits last (the gear at the top right). On the school's login page a paper waits up to 3 minutes by default; anywhere else (human checks, publisher pages, ...) it ends after 1 minute.
105
106
  - `paper-search carsi update` updates the extension after a PaperSearch upgrade; `paper-search carsi uninstall` removes it (keeping the browser and the school settings by default).
106
107
  - Windows: if PowerShell blocks `npm.ps1`, use `npm.cmd` or Command Prompt; downloads must run in a desktop session, as a browser window cannot open from SSH or a system service.
107
108
 
@@ -204,7 +205,9 @@ Some sources are subject to platform terms, institutional subscriptions or local
204
205
 
205
206
  ## Origins
206
207
 
207
- Thanks to the [LinuxDo](https://linux.do) community, where the command-plus-Skill approach and workflow improvements came from discussion and open sharing. The project draws on ideas from [openags/paper-search-mcp](https://github.com/openags/paper-search-mcp), reworked into a standalone command; the institutional download backend was carved out of scansci-pdf, see `carsi/NOTICE`.
208
+ - Thanks to the [LinuxDo](https://linux.do) community, where the command-plus-Skill approach and workflow improvements came from discussion and open sharing.
209
+ - [openags/paper-search-mcp](https://github.com/openags/paper-search-mcp): the project draws on its ideas, reworked into a standalone command.
210
+ - [Rimagination/scansci-pdf](https://github.com/Rimagination/scansci-pdf) (MIT): the institutional download backend (`carsi/`) was carved out of it, keeping only the institutional access part (CARSI and other federation sign-in, publisher site capture, session reuse, PDF capture), with publisher rules added one by one since; its copyright notice is kept in `carsi/NOTICE`.
208
211
 
209
212
  ## License
210
213
 
package/README.zh.md CHANGED
@@ -8,7 +8,7 @@ PaperSearch 是给 AI 工具和终端用的学术文献命令 `paper-search`,
8
8
 
9
9
  ![Node.js](https://img.shields.io/badge/node.js->=18.0.0-green.svg)
10
10
  ![License](https://img.shields.io/badge/license-MIT-blue.svg)
11
- ![Version](https://img.shields.io/badge/version-0.4.0-blue.svg)
11
+ ![Version](https://img.shields.io/badge/version-0.4.2-blue.svg)
12
12
  [![LinuxDo](https://img.shields.io/badge/LinuxDo-community-1f6feb)](https://linux.do)
13
13
 
14
14
  [整体逻辑](#整体逻辑) | [快速开始](#快速开始) | [两种下载方式](#两种下载方式) | [检索来源](#检索来源) | [配置](#配置) | [Agent Skill](#agent-skill) | [命令](#命令) | [排障](#排障)
@@ -102,6 +102,7 @@ paper-search carsi status --format text
102
102
 
103
103
  - 安装时会问你的学校(CARSI 成员学校,中文名、英文名或域名都可以),并下载专用浏览器 Camoufox,共约 3 GB;macOS 上 `--browser ego` 改用 ego lite,约 0.5 GB。`--skip-school` 可以以后再选学校。
104
104
  - 目前用 CARSI(中国高校身份联盟)登录学校;出版社的机构列表里没有 CARSI 或你的学校时,程序会立即说明,建议在校园网或学校 VPN 下下载。
105
+ - 下载时会出现进度窗口:可以跳过本篇、标记本刊或出版社无权限、终止整个任务,右上角齿轮可以调整等待时间。停在学校登录页默认最多等 3 分钟,停在其他页面(人机验证、出版社页面等)默认 1 分钟后结束这一篇。
105
106
  - `paper-search carsi update` 在 PaperSearch 升级后更新扩展,`paper-search carsi uninstall` 卸载(默认保留浏览器和学校配置)。
106
107
  - Windows:PowerShell 拦住 `npm.ps1` 时改用 `npm.cmd` 或命令提示符;下载要在桌面会话里运行,经 SSH 或系统服务启动时浏览器窗口打不开。
107
108
 
@@ -204,7 +205,9 @@ paper-search skills update --targets claude
204
205
 
205
206
  ## 项目来源
206
207
 
207
- 感谢 [LinuxDo](https://linux.do) 社区,命令 + Skill 的路线和工作流改进来自社区交流与开源分享。本项目参考了 [openags/paper-search-mcp](https://github.com/openags/paper-search-mcp) 的思路,并改成独立的命令行工具;机构下载后端从 scansci-pdf 裁出,见 `carsi/NOTICE`。
208
+ - 感谢 [LinuxDo](https://linux.do) 社区:命令 + Skill 的路线和工作流改进来自社区交流与开源分享。
209
+ - [openags/paper-search-mcp](https://github.com/openags/paper-search-mcp):本项目参考了它的思路,并改成独立的命令行工具。
210
+ - [Rimagination/scansci-pdf](https://github.com/Rimagination/scansci-pdf)(MIT):机构下载后端(`carsi/`)由它裁出,只保留机构访问这一段(CARSI 等联盟登录、出版社网站抓取、会话复用、PDF 捕获),再逐家补充出版社规则;原项目的版权声明保留在 `carsi/NOTICE`。
208
211
 
209
212
  ## License
210
213
 
package/carsi/README.md CHANGED
@@ -23,7 +23,7 @@ python3 -m venv .venv
23
23
 
24
24
  ## 使用
25
25
 
26
- 等待用户操作(学校登录、人机验证)每篇累计最多 5 分钟,从第一次等待算起(配置键 `browser_login_timeout`,秒,默认 300)。超时后结果为 `login_timeout`(学校登录)或 `download_timeout`(人机验证)。工具参数 `user_wait: "short"`(PaperSearch 批量里有一篇等满时限后传给后面的篇目)表示用户多半不在:每次等待最多 60 秒,登录页 60 秒没有变化也结束,登录框里有人输入则照常等。
26
+ 等待用户操作:停在学校登录页(以及没配置学校时的选校页)每篇最多 3 分钟(配置键 `browser_login_timeout`,秒,默认 180);停在其他页面(人机验证、出版社页面、选机构页、取 PDF 时等待处理)连续超过 1 分钟就结束这一篇(`browser_page_wait_timeout`,默认 60)。两项和每家出版社每小时最多下载篇数都能在进度窗口右上角的设置(齿轮)里改。浏览器某一步 90 秒没有响应时,这一篇以 `browser_unresponsive` 结束。进度窗口的按钮:跳过本篇、本刊无权限、出版社无权限、终止任务(整批停下,剩余篇目记为 `batch_stopped`)、⚑ 报告问题。
27
27
 
28
28
  浏览器调用超过 4 分钟没有返回时,后端会取消它并把这一篇记为 `browser_unresponsive`(日志里记下是哪个调用、从哪里调用),批量继续下一篇。后端一直停着不动(CPU 为 0、进度不再更新)时,`kill -USR1 <后端进程号>` 会把它所有线程的 Python 调用栈追加到 `<数据目录>/logs/stacks-<日期>.txt`,用来看它在等哪个浏览器调用;进程不会因此退出。
29
29
 
@@ -28,9 +28,9 @@ from typing import Any
28
28
 
29
29
  log = logging.getLogger(__name__)
30
30
 
31
- # The longest legitimate call is a page load or PDF wait (60-90 s); waits for
32
- # the user are made of short calls.
33
- LIMIT_SEC = 240
31
+ # The longest legitimate call is a page load (60 s, the engine's longest
32
+ # timeout); waits for the user are made of short calls.
33
+ LIMIT_SEC = 90
34
34
 
35
35
  _inflight: dict[int, tuple[float, str, list[str], Any, Any]] = {}
36
36
  _installed = False
@@ -100,8 +100,11 @@ DEFAULT_CONFIG: dict[str, Any] = {
100
100
  "fast_retry_delay_sec": 15,
101
101
  # 任务启动时自动弹出悬浮进度条(独立进程,已有实例则不重复弹出)。
102
102
  "progress_bar_auto": True,
103
- # 每篇文章等待用户操作(学校登录、人机验证)的总时长上限,秒;从第一次等待算起。
103
+ # 每篇文章在学校登录页等待用户输入的总时长上限,秒;从第一次等待算起。
104
104
  "browser_login_timeout": 180,
105
+ # 不在学校登录页时(出版社页面、选机构页、人机验证、取 PDF 时等待处理)最多等多久,秒;
106
+ # 连续超过就结束这一篇。进度窗口里可以改。
107
+ "browser_page_wait_timeout": 60,
105
108
  # 每个出版社每小时最多打开的文章数,防止学校因下载过多被出版社暂停访问;0 = 不限。
106
109
  "publisher_hourly_limit": 100,
107
110
  # Turnstile 交互门(如 sci-hub.vg):无头会话下无法点击,默认跳过并冷却。
@@ -86,7 +86,7 @@ from .batch_pdf_urls import PdfUrlsMixin
86
86
  from .batch_runs import RunsMixin
87
87
  from .batch_diagnostics import DiagnosticsMixin
88
88
  from .batch_user import PdfFoundWhileWaiting, UserProvidedPdf, UserRequestsMixin
89
- from ..entitlements import UserSkippedArticle
89
+ from ..entitlements import UserSkippedArticle, UserStoppedBatch
90
90
 
91
91
 
92
92
  class PublisherBatchDownloader(
@@ -153,6 +153,7 @@ class PublisherBatchDownloader(
153
153
  from . import supplements
154
154
 
155
155
  self._phase(result, "supplements")
156
+ progress_reporter.update(part="supplements", supplements_saved=0, supplements_total=None)
156
157
  try:
157
158
  page = context.new_page()
158
159
  except Exception as exc:
@@ -185,8 +186,10 @@ class PublisherBatchDownloader(
185
186
  if links or url in own_page:
186
187
  break
187
188
  self._event(result, "supplements_found", str(len(links)))
189
+ progress_reporter.update(supplements_total=len(links))
188
190
  files = supplements.collect(page.context.request, links, Path(output_dir), doi,
189
- download=lambda url: self._download_in_new_tab(page, url))
191
+ download=lambda url: self._download_in_new_tab(page, url),
192
+ progress=lambda saved: progress_reporter.update(supplements_saved=saved))
190
193
  saved = sum(1 for f in files if f.get("status") == "saved")
191
194
  self._event(result, "supplements_saved", f"{saved}/{len(files)}")
192
195
  return files
@@ -346,6 +349,7 @@ class PublisherBatchDownloader(
346
349
  from ..browser import watchdog
347
350
 
348
351
  self._phase(result, "open")
352
+ progress_reporter.update(part="main", supplements_saved=0, supplements_total=None)
349
353
  self._run_dir = run_dir
350
354
  watchdog.on_slow_call = lambda name, seconds, ended, where: self._event(
351
355
  result, "wait", f"browser call {name}: {seconds:.0f} s, ended: {ended} ({where})")
@@ -512,6 +516,12 @@ class PublisherBatchDownloader(
512
516
  self._event(result, "pdf_found_while_waiting" if isinstance(provided, PdfFoundWhileWaiting)
513
517
  else "pdf_from_user_report", provided.url)
514
518
  return self._save_captured_pdf(page, record, result, run_dir, provided.body, provided.url)
519
+ except UserStoppedBatch as decision:
520
+ watchdog.clear_interrupt()
521
+ result.reason = result.state = "batch_stopped"
522
+ self._event(result, "batch_stopped", str(decision))
523
+ self._write_diagnostic(page, result, run_dir)
524
+ return result
515
525
  except UserSkippedArticle as decision:
516
526
  watchdog.clear_interrupt()
517
527
  result.reason = result.state = "user_skipped"
@@ -1256,7 +1256,7 @@ class CaptureMixin:
1256
1256
  # Human verification gets its own budget: the user's time must
1257
1257
  # not use up the PDF step, and once the check clears the PDF
1258
1258
  # gets its full time again.
1259
- challenge_deadline = time.time() + max(self.SUSPECT_BLOCK_WAIT_SEC, timeout_sec)
1259
+ challenge_deadline = time.time() + max(self.page_wait_sec, timeout_sec)
1260
1260
  if not self._wait_for_challenge_with_deadline(page, result, challenge_deadline):
1261
1261
  return None, str(getattr(page, "url", "") or "")
1262
1262
  deadline = time.time() + timeout_sec
@@ -260,6 +260,7 @@ class LoginMixin:
260
260
  last_auto_action_at = 0.0
261
261
  visited_idp = False
262
262
  page_since, page_inputs = time.time(), ()
263
+ outside_since = time.time() # last seen on the user's own login step
263
264
  article_returns = 0
264
265
  session_returns = 0
265
266
  away_from_publisher = False # on an IdP, federation or chooser page since the last probe
@@ -273,6 +274,14 @@ class LoginMixin:
273
274
  result.reason = "institution_federation_unavailable"
274
275
  self._event(result, result.reason, "the school is not in the publisher's institution list")
275
276
  return False
277
+ over, outside_since = self._page_wait_over(page, outside_since)
278
+ if over:
279
+ # Off the school's login page for a whole page wait (a publisher
280
+ # page, a chooser, a redirect that goes nowhere): nobody is typing.
281
+ self._event(result, "page_wait_ended",
282
+ f"{self._login_wait_page(page)} after {self.page_wait_sec:.0f} s")
283
+ self._wait_ran_out(result)
284
+ return False
276
285
  marker = f"{self._title(page)} | {getattr(page, 'url', '')[:160]}"
277
286
  here = urlparse(str(getattr(page, "url", "") or ""))
278
287
  on_publisher = self._on_publisher_host(here.geturl())
@@ -1143,6 +1152,26 @@ class LoginMixin:
1143
1152
  return True
1144
1153
  return self.adapter.is_article_page_url(url) is True
1145
1154
 
1155
+ def _page_wait_over(self, page: Any, outside_since: float) -> tuple[bool, float]:
1156
+ """Whether a login wait has been off the user's own login step for a whole
1157
+ page wait, and when that step was last seen (now, when on it)."""
1158
+ now = time.time()
1159
+ if self._users_login_step(page):
1160
+ return False, now
1161
+ return now - outside_since >= self.page_wait_sec, outside_since
1162
+
1163
+ def _users_login_step(self, page: Any) -> bool:
1164
+ """The user's own step of the login, which may take the long wait
1165
+ (``login_timeout_sec``): the school's login page (a password field, or the
1166
+ school's identity provider), or a school chooser when no school is
1167
+ configured or the user chooses by hand. Any other page off the publisher's
1168
+ site is not: Atypon's iam.atypon.com hub, where AHA's login stopped on
1169
+ 2026-11-03, was taken for the school's page and waited three minutes."""
1170
+ url = str(getattr(page, "url", "") or "")
1171
+ if self._school_password_box(page, url) or self._is_idp_host(urlparse(url).netloc):
1172
+ return True
1173
+ return self._is_auth_page(url) and (not self.institution_query or bool(getattr(self, "_manual_school", False)))
1174
+
1146
1175
  def _login_wait_page(self, page: Any) -> str:
1147
1176
  """Where a login that waited on the user ended (ADR 0012):
1148
1177
 
@@ -1155,7 +1184,9 @@ class LoginMixin:
1155
1184
  if page.is_closed() is True:
1156
1185
  return "closed"
1157
1186
  url = str(getattr(page, "url", "") or "")
1158
- if self._is_human_login_page(page):
1187
+ # The school's own page, by the same test as the long wait: a publisher's
1188
+ # SSO hub (iam.atypon.com) is no school login (2026-11-03).
1189
+ if self._school_password_box(page, url) or self._is_idp_host(urlparse(url).netloc):
1159
1190
  return "school_login"
1160
1191
  if self._is_auth_page(url):
1161
1192
  return "institution_chooser" if self.institution_query else "school_choice"
@@ -1165,13 +1196,17 @@ class LoginMixin:
1165
1196
  current_url = str(getattr(page, "url", "") or "")
1166
1197
  host = (urlparse(current_url).netloc or "").lower()
1167
1198
  if self.config.get("publisher_institution_federation") == "carsi":
1168
- if (page.locator('input[type="password"]:visible, input[autocomplete="one-time-code"]:visible').count()
1169
- and not self._personal_login_box(page, current_url)):
1199
+ if self._school_password_box(page, current_url):
1170
1200
  return True
1171
1201
  if not self._on_publisher_host(current_url):
1172
1202
  return not self._is_federation_chooser(current_url)
1173
1203
  return self._is_idp_host(host)
1174
1204
 
1205
+ def _school_password_box(self, page: Any, url: str) -> bool:
1206
+ """A password or one-time-code field that is not a personal account's box on the publisher's site."""
1207
+ return bool(page.locator('input[type="password"]:visible, input[autocomplete="one-time-code"]:visible').count()
1208
+ and not self._personal_login_box(page, url))
1209
+
1175
1210
  def _personal_login_box(self, page: Any, url: str) -> bool:
1176
1211
  """The password field is a personal account's login box on the publisher's
1177
1212
  own article page, nobody typing in it: BMJ shows one next to "Log in via
@@ -35,7 +35,16 @@ class UserWaitMixin:
35
35
  return self._wait_for_challenge(page, result, deadline=deadline)
36
36
  return self._wait_for_challenge(page, result)
37
37
 
38
- SUSPECT_BLOCK_WAIT_SEC = 180
38
+ # A wait off the school's login page (verification, the publisher's pages and
39
+ # choosers, the PDF step): config ``browser_page_wait_timeout``, else this.
40
+ PAGE_WAIT_SEC = 60
41
+
42
+ @property
43
+ def page_wait_sec(self) -> float:
44
+ """How long a wait that is not the user's own login step may last; the
45
+ school's login page has ``login_timeout_sec`` (user's choice, 2026-11-03)."""
46
+ value = (getattr(self, "config", None) or {}).get("browser_page_wait_timeout")
47
+ return self.PAGE_WAIT_SEC if value is None else max(10.0, float(value))
39
48
 
40
49
  @staticmethod
41
50
  def _visible_text_excerpt(body: str | bytes | None, limit: int = 600) -> str:
@@ -103,7 +112,7 @@ class UserWaitMixin:
103
112
 
104
113
  def _wait_out_suspect_block(self, page: Any, result: DownloadResult, captured: dict[str, Any], suspect: str,
105
114
  suspect_host: str, started: float) -> bool:
106
- deadline = started + min(max(self.login_timeout_sec, 30), self.SUSPECT_BLOCK_WAIT_SEC)
115
+ deadline = started + self.page_wait_sec
107
116
  reporter = None
108
117
  attention_key = f"pdf-step:{id(self)}:{result.doi}"
109
118
  try:
@@ -302,9 +311,10 @@ class UserWaitMixin:
302
311
  return deadline
303
312
 
304
313
  def _wait_deadline(self, result: DownloadResult, deadline: float | None = None) -> float:
305
- """End of a wait on the user that starts now: the caller's bound, the
306
- article's total, and when the user seems away the short wait."""
307
- bounds = [self._user_wait_deadline(result)]
314
+ """End of a wait on the user that starts now, off the school's login page
315
+ (verification pages): the caller's bound, the article's total, the page
316
+ wait, and when the user seems away the short wait."""
317
+ bounds = [self._user_wait_deadline(result), time.time() + self.page_wait_sec]
308
318
  if deadline is not None:
309
319
  bounds.append(deadline)
310
320
  if self._user_away:
@@ -45,6 +45,7 @@ _FAILURE_KINDS = {
45
45
  "unexpected_error": ("source_exception", ""),
46
46
  "user_marked_no_entitlement": ("no_entitlement", "skipped_by_user"),
47
47
  "user_skipped": ("user_skipped", "skipped_by_user"),
48
+ "batch_stopped": ("batch_stopped", "stopped_by_user"),
48
49
  "pdf_wrong_article": ("pdf_wrong_article", "review_browser"),
49
50
  "supplements_only": ("supplements_only", "supplements_only"),
50
51
  # The DOI resolves to no site to sign in on (publishers/site.py): no driver can run.
@@ -87,12 +87,14 @@ def _get(request: Any, url: str, entry: dict[str, Any], sleep) -> Any:
87
87
 
88
88
  def collect(request: Any, links: Iterable[SupplementLink], output_dir: Path, doi: str, *,
89
89
  clock=time.monotonic, sleep=time.sleep,
90
- download: Callable[[str], tuple[bytes, str]] | None = None) -> list[dict[str, Any]]:
90
+ download: Callable[[str], tuple[bytes, str]] | None = None,
91
+ progress: Callable[[int], None] | None = None) -> list[dict[str, Any]]:
91
92
  """Fetch ``links`` with ``request`` (a Playwright APIRequestContext). A file
92
93
  refused with 403 is taken through ``download`` when given: the browser
93
94
  opens it and downloads it itself (Taylor & Francis behind Cloudflare
94
95
  refused every scripted request with ego, the page's own fetch included,
95
- and let the browser's own navigation through, 2026-11-01)."""
96
+ and let the browser's own navigation through, 2026-11-01). ``progress`` is
97
+ told how many files are saved after each one (the progress window)."""
96
98
  unique: list[SupplementLink] = []
97
99
  for link in links:
98
100
  if link.url and link.url not in {u.url for u in unique}:
@@ -139,6 +141,8 @@ def collect(request: Any, links: Iterable[SupplementLink], output_dir: Path, doi
139
141
  except Exception as exc:
140
142
  entry.update(status="failed", reason=f"{type(exc).__name__}: {str(exc)[:160]}")
141
143
  files.append(entry)
144
+ if progress is not None:
145
+ progress(sum(1 for f in files if f.get("status") == "saved"))
142
146
  (target / "manifest.json").write_text(
143
147
  json.dumps({"doi": doi, "files": files}, ensure_ascii=False, indent=2), encoding="utf-8")
144
148
  return files
@@ -34,6 +34,14 @@ class UserSkippedArticle(UserMarkedNoEntitlement):
34
34
  """The user pressed "skip this paper": it ends, nothing is remembered."""
35
35
 
36
36
 
37
+ class UserStoppedBatch(UserMarkedNoEntitlement):
38
+ """The user pressed "stop the task": this paper ends and the batch stops."""
39
+
40
+
41
+ # Not an entitlement decision: nothing is recorded, the batch ends.
42
+ STOP_BATCH = "stop_batch"
43
+
44
+
37
45
  SKIP = "skip"
38
46
  ALLOW = "allow"
39
47
  _ACTIONS = {
@@ -183,7 +191,7 @@ def clear(key: str) -> bool:
183
191
 
184
192
  def request_action(current: str, action: str, run_id: str = "") -> None:
185
193
  """Written by the progress window when the user presses a button."""
186
- if action not in _ACTIONS:
194
+ if action not in _ACTIONS and action != STOP_BATCH:
187
195
  raise ValueError("unknown action")
188
196
  _write_json(control_path(), {"current": current, "action": action, "run_id": run_id, "at": time.time()})
189
197
 
@@ -204,7 +212,7 @@ def take_action(doi: str, since: float) -> str | None:
204
212
  except OSError:
205
213
  pass
206
214
  action = data.get("action")
207
- return action if action in _ACTIONS else None
215
+ return action if action in _ACTIONS or action == STOP_BATCH else None
208
216
 
209
217
 
210
218
  def apply_user_decision(doi: str, publisher: str, since: float) -> str | None:
@@ -212,6 +220,8 @@ def apply_user_decision(doi: str, publisher: str, since: float) -> str | None:
212
220
  action = take_action(doi, since)
213
221
  if not action:
214
222
  return None
223
+ if action == STOP_BATCH:
224
+ raise UserStoppedBatch(action)
215
225
  if action == "skip_item":
216
226
  raise UserSkippedArticle(action)
217
227
  try:
@@ -29,6 +29,7 @@ from typing import Any
29
29
  import os as _os
30
30
  import sys as _sys
31
31
 
32
+ from . import user_settings
32
33
  from .progress_reporter import read_state
33
34
 
34
35
  # --- Win32 / DWM constants -------------------------------------------------
@@ -43,6 +44,13 @@ DWMSBT_MAINWINDOW = 2 # light Mica
43
44
 
44
45
  # Palettes: (light, dark). Picked once at start from the OS appearance.
45
46
  CONTENT_LABELS = {"main": "正文", "supplements": "附录", "both": "正文+附录"}
47
+ # The step of the main text, as the status line says it ("正文 · 正在获取 PDF").
48
+ STAGE_TEXT = {
49
+ "starting": "准备中", "opening_article": "正在打开文章", "checking_access": "正在检查访问权限",
50
+ "waiting_login": "等待机构登录", "waiting_verification": "等待人机验证", "fetching_pdf": "正在获取 PDF",
51
+ "pdf_captured": "已读到 PDF,正在核对", "saved_pending_verification": "已保存",
52
+ "route_failed": "这条路没走通,正在换路",
53
+ }
46
54
 
47
55
  PALETTES = {
48
56
  "light": {
@@ -232,6 +240,8 @@ class ProgressWindow:
232
240
  self._flash: tuple[str, float, str] | None = None # (text, until, doi)
233
241
  self._chosen: tuple[str, str] | None = None # (doi, action) pressed for the current paper
234
242
  self._hover = "" # the button under the mouse; kept across redraws
243
+ self._settings: tk.Toplevel | None = None # the settings dialog, when open
244
+ self._last_current = "" # the paper shown, for a message after the dialog closes
235
245
  self.root.after(400, self._tick)
236
246
 
237
247
  # --- window plumbing ---------------------------------------------------
@@ -294,6 +304,7 @@ class ProgressWindow:
294
304
  self.f_count = tkfont.Font(family=ui, size=px(14), weight="bold")
295
305
  self.f_body = tkfont.Font(family=ui, size=px(12))
296
306
  self.f_small = tkfont.Font(family=ui, size=px(11))
307
+ self.f_gear = tkfont.Font(family=ui, size=px(15))
297
308
  self.f_mono = tkfont.Font(family=mono, size=px(11))
298
309
 
299
310
  def _anchor_x(self) -> int:
@@ -351,6 +362,21 @@ class ProgressWindow:
351
362
  return _fmt_elapsed((end - started).total_seconds())
352
363
  return _fmt_elapsed((datetime.now() - started).total_seconds())
353
364
 
365
+ @staticmethod
366
+ def _status_text(state: dict[str, Any], running: bool) -> str:
367
+ """The status line: which part of the paper is being fetched and how far,
368
+ "正文 · 正在获取 PDF" or "附录 · 已保存 2/5"; between papers, the phase."""
369
+ phase = str(state.get("phase") or ("处理中" if running else ""))
370
+ part = str(state.get("part") or "")
371
+ if not running or state.get("awaiting_next") or part not in ("main", "supplements"):
372
+ return phase
373
+ if part == "supplements":
374
+ total = state.get("supplements_total")
375
+ if not isinstance(total, int):
376
+ return "附录 · 正在查找附录文件"
377
+ return f"附录 · 已保存 {int(state.get('supplements_saved') or 0)}/{total}"
378
+ return "正文 · " + STAGE_TEXT.get(str(state.get("stage") or ""), phase)
379
+
354
380
  @staticmethod
355
381
  def _attention_items(state: dict[str, Any]) -> list[dict[str, Any]]:
356
382
  attention = state.get("attention")
@@ -370,7 +396,9 @@ class ProgressWindow:
370
396
  Hl = max(self.H, c.winfo_height())
371
397
  u = lambda n: int(round(n * s))
372
398
 
399
+ gear_left = self._draw_gear(Wl - P, P + u(9))
373
400
  if not state:
401
+ self._last_current = ""
374
402
  c.create_text(Wl // 2, Hl // 2 - u(8), text="PaperSearch", fill=col["text"], font=self.f_title)
375
403
  c.create_text(Wl // 2, Hl // 2 + u(14), text="暂无下载任务", fill=col["dim"], font=self.f_small)
376
404
  return
@@ -401,8 +429,8 @@ class ProgressWindow:
401
429
  dot = u(8)
402
430
  c.create_oval(P, y1 - dot // 2, P + dot, y1 + dot // 2, fill=tone, outline=tone)
403
431
  count = f"{done} / {total}" if total else f"{done}"
404
- c.create_text(Wl - P, y1, text=count, fill=col["text"], font=self.f_count, anchor="e")
405
- count_w = self.f_count.measure(count)
432
+ c.create_text(gear_left - u(8), y1, text=count, fill=col["text"], font=self.f_count, anchor="e")
433
+ count_w = self.f_count.measure(count) + (Wl - P - gear_left) + u(8)
406
434
  # What this download fetches, as a small label left of the count.
407
435
  content = CONTENT_LABELS.get(str(state.get("content") or "main"), CONTENT_LABELS["main"])
408
436
  chip_h = u(18)
@@ -440,13 +468,14 @@ class ProgressWindow:
440
468
  self._pill(P - u(2), y2 - u(11), P + self.f_body.measure(text) + u(14), y2 + u(11), col["warn_bg"])
441
469
  c.create_text(P + u(6), y2, text=text, fill=col["warn"], font=self.f_body, anchor="w")
442
470
  else:
443
- phase = str(state.get("phase") or ("处理中" if running else ""))
471
+ phase = self._status_text(state, running)
444
472
  c.create_text(P, y2, anchor="w", fill=col["dim"], font=self.f_body,
445
473
  text=_elide(self.f_body, phase, phase_room))
446
474
 
447
475
  # Row 3: the paper being worked on
448
476
  y3 = y2 + u(22)
449
477
  current = str((attention[-1].get("current") if attention else "") or state.get("current") or "")
478
+ self._last_current = current
450
479
  if current:
451
480
  c.create_text(P, y3, anchor="w", fill=col["text"] if running else col["dim"], font=self.f_mono,
452
481
  text=_elide(self.f_mono, current, Wl - 2 * P))
@@ -484,7 +513,7 @@ class ProgressWindow:
484
513
  x = P
485
514
  chosen = self._chosen[1] if self._chosen and self._chosen[0] == current else ""
486
515
  for key, label in (("skip_item", "跳过本篇"), ("skip_journal", "本刊无权限"),
487
- ("skip_publisher", "出版社无权限")):
516
+ ("skip_publisher", "出版社无权限"), ("stop_batch", "终止任务")):
488
517
  pressed = key == chosen
489
518
  text = ("✓ " + label) if pressed else label
490
519
  w = self.f_small.measure(text) + u(18)
@@ -492,7 +521,8 @@ class ProgressWindow:
492
521
  self._pill(x, y6 - u(11), x + w, y6 + u(11), col["warn"] if pressed else col["track"], tags=(tag,))
493
522
  fill = col["bg"] if pressed else (col["text"] if self._hover == key else col["btn"])
494
523
  label_id = c.create_text(x + w / 2, y6, text=text, fill=fill, font=self.f_small, tags=(tag,))
495
- c.tag_bind(tag, "<Button-1>", lambda e, k=key, d=current, s=state: self._decide(k, d, s))
524
+ c.tag_bind(tag, "<Button-1>", lambda e, k=key, d=current, s=state: (
525
+ self._stop(d, s) if k == "stop_batch" else self._decide(k, d, s)))
496
526
  if not pressed:
497
527
  c.tag_bind(tag, "<Enter>", lambda e, k=key, i=label_id: self._hover_button(k, i))
498
528
  c.tag_bind(tag, "<Leave>", lambda e, i=label_id: self._hover_button("", i))
@@ -516,7 +546,8 @@ class ProgressWindow:
516
546
  from .entitlements import request_action
517
547
 
518
548
  request_action(doi, action, str(state.get("run_id") or ""))
519
- text = {"skip_item": "已跳过本篇,进入下一篇",
549
+ text = {"stop_batch": "已终止任务:这一篇结束,剩下的不再下载",
550
+ "skip_item": "已跳过本篇,进入下一篇",
520
551
  "skip_journal": "已记住:本刊无权限,以后自动跳过(可用 entitlements 撤销)",
521
552
  "skip_publisher": "已记住:该出版社无权限,以后自动跳过"}[action]
522
553
  except Exception as exc:
@@ -525,6 +556,98 @@ class ProgressWindow:
525
556
  self._chosen = (doi, action)
526
557
  self._draw(state)
527
558
 
559
+ def _stop(self, doi: str, state: dict[str, Any]) -> None:
560
+ """Stop the whole task, after asking: this paper ends, the rest are not downloaded."""
561
+ from tkinter import messagebox
562
+
563
+ left = max(0, int(state.get("total", 0) or 0) - int(state.get("done", 0) or 0) - 1)
564
+ question = "终止整个下载任务?这一篇立即结束" + (f",剩下的 {left} 篇不再下载。" if left else "。")
565
+ if messagebox.askyesno("终止任务", question, parent=self.root):
566
+ self._decide("stop_batch", doi, state)
567
+
568
+ def _draw_gear(self, right: int, y: int) -> int:
569
+ """The settings button at the top right, a round button like the others'
570
+ colours; returns its left edge."""
571
+ c, col = self.canvas, self.c
572
+ d = int(round(24 * self.s))
573
+ x0, y0 = right - d, y - d // 2
574
+ c.create_oval(x0, y0, right, y0 + d, fill=col["track"], outline=col["track"], tags=("settings",))
575
+ item = c.create_text(right - d / 2, y, text="\u2699", fill=col["btn"], font=self.f_gear, tags=("settings",))
576
+ c.tag_bind("settings", "<Button-1>", lambda e: self._open_settings())
577
+ c.tag_bind("settings", "<Enter>", lambda e: c.itemconfigure(item, fill=col["text"]))
578
+ c.tag_bind("settings", "<Leave>", lambda e: c.itemconfigure(item, fill=col["btn"]))
579
+ return x0
580
+
581
+ def _open_settings(self) -> None:
582
+ """The settings dialog: each value typed in and checked; saved values
583
+ apply from the next paper."""
584
+ if self._settings is not None and self._settings.winfo_exists():
585
+ self._settings.lift()
586
+ return
587
+ col, pad = self.c, int(round(14 * self.s))
588
+ top = self._settings = tk.Toplevel(self.root, bg=col["bg"])
589
+ top.title("设置")
590
+ top.resizable(False, False)
591
+ top.attributes("-topmost", True)
592
+ top.transient(self.root)
593
+ frame = tk.Frame(top, bg=col["bg"], padx=pad, pady=pad)
594
+ frame.pack(fill="both", expand=True)
595
+ tk.Label(frame, text="设置", bg=col["bg"], fg=col["text"], font=self.f_title).grid(
596
+ row=0, column=0, columnspan=3, sticky="w", pady=(0, pad // 2))
597
+ values = user_settings.current()
598
+ entries: dict[str, tk.Entry] = {}
599
+ errors: dict[str, tk.Label] = {}
600
+ for i, field in enumerate(user_settings.FIELDS):
601
+ row = 1 + 2 * i
602
+ tk.Label(frame, text=field.label, bg=col["bg"], fg=col["text"], font=self.f_body).grid(
603
+ row=row, column=0, sticky="w", padx=(0, pad))
604
+ entry = tk.Entry(frame, width=6, justify="right", font=self.f_body)
605
+ entry.insert(0, str(values[field.name]))
606
+ entry.grid(row=row, column=1, pady=3)
607
+ tk.Label(frame, text=field.unit, bg=col["bg"], fg=col["dim"], font=self.f_body).grid(
608
+ row=row, column=2, sticky="w", padx=(6, 0))
609
+ error = tk.Label(frame, text="", bg=col["bg"], fg=col["bad"], font=self.f_small)
610
+ error.grid(row=row + 1, column=0, columnspan=3, sticky="w")
611
+ error.grid_remove()
612
+ entries[field.name], errors[field.name] = entry, error
613
+
614
+ def reset() -> None:
615
+ for field in user_settings.FIELDS:
616
+ entries[field.name].delete(0, "end")
617
+ entries[field.name].insert(0, str(field.default))
618
+ errors[field.name].grid_remove()
619
+
620
+ def save() -> None:
621
+ chosen: dict[str, int] = {}
622
+ for field in user_settings.FIELDS:
623
+ value, problem = user_settings.check(field, entries[field.name].get())
624
+ if problem:
625
+ errors[field.name].configure(text=problem)
626
+ errors[field.name].grid()
627
+ else:
628
+ errors[field.name].grid_remove()
629
+ chosen[field.name] = int(value)
630
+ if len(chosen) < len(user_settings.FIELDS):
631
+ return
632
+ try:
633
+ user_settings.save(chosen)
634
+ text = "设置已保存,从下一篇起生效"
635
+ except Exception as exc:
636
+ text = f"保存失败:{type(exc).__name__}"
637
+ top.destroy()
638
+ self._flash = (text, time.time() + 6, self._last_current)
639
+
640
+ buttons = tk.Frame(frame, bg=col["bg"])
641
+ buttons.grid(row=1 + 2 * len(user_settings.FIELDS), column=0, columnspan=3, sticky="e", pady=(pad // 2, 0))
642
+ for text, command in (("恢复默认", reset), ("取消", top.destroy), ("保存", save)):
643
+ tk.Button(buttons, text=text, command=command, font=self.f_small).pack(side="left", padx=(6, 0))
644
+ top.bind("<Return>", lambda e: save())
645
+ top.bind("<Escape>", lambda e: top.destroy())
646
+ top.update_idletasks()
647
+ x = self.root.winfo_rootx()
648
+ y = max(0, self.root.winfo_rooty() - top.winfo_height() - 8)
649
+ top.geometry(f"+{x}+{y}")
650
+
528
651
  def _hover_button(self, key: str, label_id: int) -> None:
529
652
  self._hover = key
530
653
  self.canvas.itemconfigure(label_id, fill=self.c["text"] if key else self.c["btn"])
@@ -0,0 +1,55 @@
1
+ """The settings the progress window lets the user type in: how long a download
2
+ waits on the school's login page and elsewhere, and how many papers each
3
+ publisher may open per hour. They apply from the next paper."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from dataclasses import dataclass
8
+
9
+ from . import config as _config
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class Field:
14
+ name: str
15
+ label: str
16
+ key: str # the backend's config key
17
+ default: int
18
+ low: int
19
+ high: int
20
+ unit: str
21
+
22
+
23
+ FIELDS = (
24
+ Field("login", "学校登录页最多等", "browser_login_timeout", 180, 30, 1800, "秒"),
25
+ Field("page", "其他页面最多等", "browser_page_wait_timeout", 60, 10, 600, "秒"),
26
+ Field("hourly", "每家出版社每小时最多", "publisher_hourly_limit", 100, 0, 1000, "篇"),
27
+ )
28
+
29
+
30
+ def current() -> dict[str, int]:
31
+ """The values now set, by field name."""
32
+ config = _config.load_config()
33
+ return {field.name: int(config.get(field.key, field.default)) for field in FIELDS}
34
+
35
+
36
+ def check(field: Field, text: str) -> tuple[int | None, str]:
37
+ """A typed value, or why it cannot be saved."""
38
+ try:
39
+ value = int(str(text).strip())
40
+ except ValueError:
41
+ value = None
42
+ if value is None or not field.low <= value <= field.high:
43
+ return None, f"请输入 {field.low} 到 {field.high} 之间的整数"
44
+ return value, ""
45
+
46
+
47
+ def save(values: dict[str, int]) -> None:
48
+ """Save values by field name; each is checked again first."""
49
+ for field in FIELDS:
50
+ if field.name not in values:
51
+ continue
52
+ value, problem = check(field, str(values[field.name]))
53
+ if problem:
54
+ raise ValueError(f"{field.key}: {problem}")
55
+ _config.update_config(field.key, str(value))
@@ -1 +1 @@
1
- {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../../src/capabilities/pdf-discovery/batch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../../src/capabilities/pdf-discovery/batch.ts"],"names":[],"mappings":"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"}
@@ -121,6 +121,15 @@ async function pastHourlyLimit(run, log, pause) {
121
121
  /** The journal's site blocked the current network (state L): a protection page,
122
122
  * or the school paused for downloading too much. The backend answers the
123
123
  * journal's later items at once; every other item goes on (the user, 2026-11-02). */
124
+ /** The user pressed "终止任务" in the progress window: the batch ends after this item. */
125
+ function stoppedByUser(result) {
126
+ return result.attempts.some((attempt) => attempt.code === "batch_stopped");
127
+ }
128
+ const STOP_NOTICE = "[批量] 已在进度窗口终止任务,剩下的篇目不再下载";
129
+ /** The attempt recorded for an item the batch did not reach because the user stopped it. */
130
+ function notReached() {
131
+ return { stage: "entitled_access", status: "skipped", message: "已终止任务,未下载", code: "batch_stopped" };
132
+ }
124
133
  function publisherBlocked(result) {
125
134
  return (result.status !== "ok" &&
126
135
  result.attempts.some((a) => a.stage === "entitled_access" && a.code === "access_blocked"));
@@ -244,11 +253,24 @@ async function downloadPerItem(searchers, options, backend, log, createTiers, pa
244
253
  log(AWAY_NOTICE);
245
254
  }
246
255
  const finished = itemResult(result, index, request);
247
- await supplementsForOpenItem(finished, recorded(request, ledger, entry), backend);
256
+ if (!stoppedByUser(result))
257
+ await supplementsForOpenItem(finished, recorded(request, ledger, entry), backend);
248
258
  ledger?.item(entry, finished);
249
259
  items.push(finished);
250
260
  if (publisherBlocked(result))
251
261
  log(blockedNotice(request.doi || request.paperId));
262
+ if (stoppedByUser(result)) {
263
+ for (const [rest, restItem] of options.items.entries()) {
264
+ if (rest <= offset)
265
+ continue;
266
+ const restRequest = itemOptions(restItem, options);
267
+ const restFinished = itemResult({ status: "error", attempts: [notReached()] }, rest + 1, restRequest);
268
+ ledger?.item(runItem(rest + 1, restRequest), restFinished);
269
+ items.push(restFinished);
270
+ }
271
+ log(STOP_NOTICE);
272
+ break;
273
+ }
252
274
  }
253
275
  ledger?.close();
254
276
  return summary("per_item", batchId, items, {
@@ -294,6 +316,7 @@ async function downloadTwoPhase(searchers, options, backend, log, createTiers, m
294
316
  let succeeded = 0;
295
317
  let failed = 0;
296
318
  let away = false;
319
+ let stopped = false;
297
320
  for (const [step, offset] of pending.entries()) {
298
321
  const request = requests[offset];
299
322
  log(`[批量] 机构下载 ${step + 1}/${remaining}:${request.doi || request.paperId}`);
@@ -316,9 +339,18 @@ async function downloadTwoPhase(searchers, options, backend, log, createTiers, m
316
339
  ledger?.item(entries[offset], items[offset]);
317
340
  if (publisherBlocked(result))
318
341
  log(blockedNotice(request.doi || request.paperId));
342
+ if (stoppedByUser(result)) {
343
+ stopped = true;
344
+ for (const rest of pending.slice(step + 1)) {
345
+ items[rest] = itemResult({ ...items[rest], status: "error", attempts: [...items[rest].attempts, notReached()] }, rest + 1, requests[rest]);
346
+ ledger?.item(entries[rest], items[rest]);
347
+ }
348
+ log(STOP_NOTICE);
349
+ break;
350
+ }
319
351
  }
320
352
  // Phase 3: supplementary files for the items the open stages already got.
321
- if (options.content === "both") {
353
+ if (options.content === "both" && !stopped) {
322
354
  const open = requests.map((_, offset) => offset).filter((offset) => !pending.includes(offset));
323
355
  if (open.length)
324
356
  ledger?.phase(`补充材料 ${open.length} 篇`);
@@ -1 +1 @@
1
- {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../../src/capabilities/pdf-discovery/batch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"batch.js","sourceRoot":"","sources":["../../../src/capabilities/pdf-discovery/batch.ts"],"names":[],"mappings":"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"}
@@ -16,7 +16,7 @@ export const CARSI_DOWNLOAD_TIMEOUT_MS = 1_200_000;
16
16
  export const CARSI_CLEANUP_TIMEOUT_MS = 5_000;
17
17
  const CARSI_BACKEND_SOURCE = "carsi";
18
18
  // MCP clientInfo is informational only; keep in step with package.json on release.
19
- const PAPER_SEARCH_MCP_CLIENT_VERSION = "0.4.0";
19
+ const PAPER_SEARCH_MCP_CLIENT_VERSION = "0.4.2";
20
20
  const NO_BATCH_SUPPORT = {
21
21
  downloadFields: false,
22
22
  supplementsField: false,
@@ -5,7 +5,10 @@ const { Worker, parentPort, workerData } = require("node:worker_threads");
5
5
  const { readFileSync } = require("node:fs");
6
6
  if (workerData?.paperSearchPdfFirstPage === true) {
7
7
  const parse = require("pdf-parse/lib/pdf-parse.js");
8
- parse(readFileSync(workerData.filePath), { max: workerData.maxPages || 1 })
8
+ // A plain Uint8Array, not the Buffer: in a worker on Node 24 pdf-parse fails on
9
+ // a Buffer ("bad XRef entry"), and every PDF would read as unreadable.
10
+ const file = readFileSync(workerData.filePath);
11
+ parse(new Uint8Array(file.buffer, file.byteOffset, file.byteLength), { max: workerData.maxPages || 1 })
9
12
  .then((result) => {
10
13
  const text = typeof result.text === "string"
11
14
  ? result.text.slice(0, (workerData.maxPages || 1) > 1 ? 400000 : 50000)
@@ -1 +1 @@
1
- {"version":3,"file":"PdfFirstPage.cjs","sourceRoot":"","sources":["../../../src/infrastructure/pdf/PdfFirstPage.cjs"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PdfFirstPage.cjs","sourceRoot":"","sources":["../../../src/infrastructure/pdf/PdfFirstPage.cjs"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PdfFirstPage.d.cts","sourceRoot":"","sources":["../../../src/infrastructure/pdf/PdfFirstPage.cjs"],"names":[],"mappings":"AA4DA;;;;GAIG;AACH,+CAFW,MAAM,GAAqB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAIvF;AAED;;;;GAIG;AACH,uCAFW,MAAM,YAAmB,MAAM,GAAqB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIpF"}
1
+ {"version":3,"file":"PdfFirstPage.d.cts","sourceRoot":"","sources":["../../../src/infrastructure/pdf/PdfFirstPage.cjs"],"names":[],"mappings":"AA+DA;;;;GAIG;AACH,+CAFW,MAAM,GAAqB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAIvF;AAED;;;;GAIG;AACH,uCAFW,MAAM,YAAmB,MAAM,GAAqB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIpF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "papersearch",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "PaperSearch: an agent-friendly command for searching and downloading academic papers from multiple sources.",
5
5
  "main": "dist/cli.js",
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
 
17
17
  - 只用开放来源和学校权限(不用 Sci-Hub):`download_with_fallback` / `download_batch` 设 `useSciHub=false`。只测学校权限这一步:`download_batch` 设 `"mode":"entitled_only"`。
18
18
  - 同一个数据目录同时只跑一个下载。命令没结束时,不因窗口看似停住而重新下载或登录。
19
- - 批量按顺序逐篇进行。遇到学校登录或人机验证时停在这一篇,提醒用户到下载浏览器操作;每篇最多等 3 分钟(后端配置 `browser_login_timeout`,秒)。学校统一认证登录一次后,其余篇目通常自动通过。一篇等满时限后(日志写“这一篇等你登录或验证已到时限”),后面每篇只等 60 秒;用户在登录框输入时照常等。
19
+ - 批量按顺序逐篇进行。遇到学校登录或人机验证时停在这一篇,提醒用户到下载浏览器操作。等待时限:停在学校登录页(以及没配置学校、要用户自己选学校的页面)最多 3 分钟(后端配置 `browser_login_timeout`,秒);停在其他页面(人机验证、出版社页面、选机构页、取 PDF 时等待处理)连续超过 1 分钟就结束这一篇(`browser_page_wait_timeout`)。两项都能在进度窗口右上角的设置(齿轮)里改,从下一篇起生效。学校统一认证登录一次后,其余篇目通常自动通过。一篇等满时限后(日志写“这一篇等你登录或验证已到时限”),后面每篇只等 60 秒;用户在登录框输入时照常等。
20
20
  - 每个出版社每小时最多打开 100 篇(后端配置 `publisher_hourly_limit`,0 为不限)。到上限时批量等到可以继续再下这一篇(日志写明时间);单篇返回 `rate_limited`,稍后再试。
21
21
  - 出版社网站拦截了当前网络(`access_blocked`,如 Cloudflare 拦截页)时这一篇结束;同一期刊 30 分钟内的其他文章直接跳过(`journal_blocked_earlier`),其他期刊照常继续。告诉用户可能是当前网络被网站防护拦截,也可能是下载过多被暂停:可换网络或稍后再试,后者请联系学校图书馆。
22
22
  - 登录和人机验证只由用户在下载浏览器里完成;不索取账号、密码、验证码,不代替用户通过验证。
@@ -26,6 +26,9 @@
26
26
 
27
27
  ## 进度窗口和问题报告
28
28
 
29
+ - “终止任务”:确认后当前这一篇立即结束,整批停下,剩下的篇目记为 `batch_stopped`(未下载)。用户想停下整批时让他点这个,不要另外中止命令。
30
+ - 第二行写明正在下哪部分:“正文 · 正在获取 PDF”“附录 · 已保存 2/5”。
31
+ - 右上角齿轮(设置):手动输入学校登录页、其他页面的最长等待(秒)和每家出版社每小时最多下载篇数,保存后从下一篇起生效。
29
32
  - “跳过本篇”:只结束当前这一篇。“本刊无权限”“出版社无权限”:结束这一篇并记住,以后自动跳过;查看或撤销用 `paper-search-carsi entitlements`(`list` / `clear <key>`)。点击后 1–2 秒内生效。
30
33
  - ⚑ 报告问题:用户选择看到的问题后,后端截下页面并处理(读取已打开的 PDF、回到文章、刷新、停止自动选校),窗口显示处理结果。
31
34
  - 发起机构下载时同时监听用户的报告(与下载相同的 `CARSI_DATA_DIR`):