paper-search-cli 0.1.2 → 0.2.0

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 (86) hide show
  1. package/.env.example +31 -3
  2. package/README-sc.md +151 -36
  3. package/README.md +150 -27
  4. package/dist/cli.js +21 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/config/ConfigService.d.ts +1 -1
  7. package/dist/config/ConfigService.d.ts.map +1 -1
  8. package/dist/config/ConfigService.js +6 -1
  9. package/dist/config/ConfigService.js.map +1 -1
  10. package/dist/config/constants.d.ts +6 -0
  11. package/dist/config/constants.d.ts.map +1 -1
  12. package/dist/config/constants.js +4 -1
  13. package/dist/config/constants.js.map +1 -1
  14. package/dist/core/diagnostics.d.ts.map +1 -1
  15. package/dist/core/diagnostics.js +54 -12
  16. package/dist/core/diagnostics.js.map +1 -1
  17. package/dist/core/handleToolCall.d.ts.map +1 -1
  18. package/dist/core/handleToolCall.js +77 -7
  19. package/dist/core/handleToolCall.js.map +1 -1
  20. package/dist/core/platformMetadata.d.ts +28 -0
  21. package/dist/core/platformMetadata.d.ts.map +1 -0
  22. package/dist/core/platformMetadata.js +258 -0
  23. package/dist/core/platformMetadata.js.map +1 -0
  24. package/dist/core/schemas.d.ts +134 -74
  25. package/dist/core/schemas.d.ts.map +1 -1
  26. package/dist/core/schemas.js +42 -38
  27. package/dist/core/schemas.js.map +1 -1
  28. package/dist/core/searchers.d.ts +11 -0
  29. package/dist/core/searchers.d.ts.map +1 -1
  30. package/dist/core/searchers.js +17 -1
  31. package/dist/core/searchers.js.map +1 -1
  32. package/dist/core/tools.d.ts.map +1 -1
  33. package/dist/core/tools.js +82 -30
  34. package/dist/core/tools.js.map +1 -1
  35. package/dist/platforms/ACMSearcher.d.ts +16 -0
  36. package/dist/platforms/ACMSearcher.d.ts.map +1 -0
  37. package/dist/platforms/ACMSearcher.js +125 -0
  38. package/dist/platforms/ACMSearcher.js.map +1 -0
  39. package/dist/platforms/ArxivSearcher.d.ts.map +1 -1
  40. package/dist/platforms/ArxivSearcher.js +10 -2
  41. package/dist/platforms/ArxivSearcher.js.map +1 -1
  42. package/dist/platforms/DBLPSearcher.d.ts +16 -0
  43. package/dist/platforms/DBLPSearcher.d.ts.map +1 -0
  44. package/dist/platforms/DBLPSearcher.js +116 -0
  45. package/dist/platforms/DBLPSearcher.js.map +1 -0
  46. package/dist/platforms/IEEESearcher.d.ts +15 -0
  47. package/dist/platforms/IEEESearcher.d.ts.map +1 -0
  48. package/dist/platforms/IEEESearcher.js +123 -0
  49. package/dist/platforms/IEEESearcher.js.map +1 -0
  50. package/dist/platforms/OpenAIRESearcher.d.ts.map +1 -1
  51. package/dist/platforms/OpenAIRESearcher.js +9 -1
  52. package/dist/platforms/OpenAIRESearcher.js.map +1 -1
  53. package/dist/platforms/OpenReviewSearcher.d.ts +19 -0
  54. package/dist/platforms/OpenReviewSearcher.d.ts.map +1 -0
  55. package/dist/platforms/OpenReviewSearcher.js +141 -0
  56. package/dist/platforms/OpenReviewSearcher.js.map +1 -0
  57. package/dist/platforms/PaperSource.d.ts +6 -0
  58. package/dist/platforms/PaperSource.d.ts.map +1 -1
  59. package/dist/platforms/PaperSource.js.map +1 -1
  60. package/dist/platforms/PubMedSearcher.d.ts.map +1 -1
  61. package/dist/platforms/PubMedSearcher.js +8 -0
  62. package/dist/platforms/PubMedSearcher.js.map +1 -1
  63. package/dist/platforms/USENIXSearcher.d.ts +14 -0
  64. package/dist/platforms/USENIXSearcher.d.ts.map +1 -0
  65. package/dist/platforms/USENIXSearcher.js +75 -0
  66. package/dist/platforms/USENIXSearcher.js.map +1 -0
  67. package/dist/services/JournalMetricsService.d.ts +38 -0
  68. package/dist/services/JournalMetricsService.d.ts.map +1 -0
  69. package/dist/services/JournalMetricsService.js +142 -0
  70. package/dist/services/JournalMetricsService.js.map +1 -0
  71. package/dist/services/MultiSourceSearchService.d.ts.map +1 -1
  72. package/dist/services/MultiSourceSearchService.js +8 -34
  73. package/dist/services/MultiSourceSearchService.js.map +1 -1
  74. package/dist/services/OpenAccessFallbackService.d.ts +1 -0
  75. package/dist/services/OpenAccessFallbackService.d.ts.map +1 -1
  76. package/dist/services/OpenAccessFallbackService.js +2 -2
  77. package/dist/services/OpenAccessFallbackService.js.map +1 -1
  78. package/dist/utils/HttpClient.d.ts +6 -0
  79. package/dist/utils/HttpClient.d.ts.map +1 -0
  80. package/dist/utils/HttpClient.js +30 -0
  81. package/dist/utils/HttpClient.js.map +1 -0
  82. package/dist/utils/PdfDownload.d.ts.map +1 -1
  83. package/dist/utils/PdfDownload.js +106 -16
  84. package/dist/utils/PdfDownload.js.map +1 -1
  85. package/package.json +3 -1
  86. package/skills/paper-search/SKILL.md +38 -8
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClient.d.ts","sourceRoot":"","sources":["../../src/utils/HttpClient.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAuBvC"}
@@ -0,0 +1,30 @@
1
+ import axios from 'axios';
2
+ import { HttpsProxyAgent } from 'https-proxy-agent';
3
+ import { SocksProxyAgent } from 'socks-proxy-agent';
4
+ import { logDebug } from './Logger.js';
5
+ /**
6
+ * Initializes global HTTP/HTTPS and SOCKS proxy agents for Axios
7
+ * based on standard proxy environment variables.
8
+ */
9
+ export function setupGlobalProxy() {
10
+ const proxy = process.env.HTTPS_PROXY ||
11
+ process.env.HTTP_PROXY ||
12
+ process.env.https_proxy ||
13
+ process.env.http_proxy;
14
+ if (!proxy) {
15
+ return;
16
+ }
17
+ try {
18
+ logDebug(`Configuring global HTTP/HTTPS proxy: ${proxy}`);
19
+ const agent = proxy.startsWith('socks')
20
+ ? new SocksProxyAgent(proxy)
21
+ : new HttpsProxyAgent(proxy);
22
+ // Inject agent as default for both http and https protocols
23
+ axios.defaults.httpAgent = agent;
24
+ axios.defaults.httpsAgent = agent;
25
+ }
26
+ catch (error) {
27
+ logDebug(`Failed to initialize global proxy agent: ${error.message}`);
28
+ }
29
+ }
30
+ //# sourceMappingURL=HttpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClient.js","sourceRoot":"","sources":["../../src/utils/HttpClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GACT,OAAO,CAAC,GAAG,CAAC,WAAW;QACvB,OAAO,CAAC,GAAG,CAAC,UAAU;QACtB,OAAO,CAAC,GAAG,CAAC,WAAW;QACvB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;IAEzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,QAAQ,CAAC,wCAAwC,KAAK,EAAE,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;YACrC,CAAC,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC;YAC5B,CAAC,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;QAE/B,4DAA4D;QAC5D,KAAK,CAAC,QAAQ,CAAC,SAAS,GAAG,KAAK,CAAC;QACjC,KAAK,CAAC,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC;IACpC,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,QAAQ,CAAC,4CAA4C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PdfDownload.d.ts","sourceRoot":"","sources":["../../src/utils/PdfDownload.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAU,GAAG,MAAM,CAGtE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,SAAK,GAAG,OAAO,CAErE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,CAAC,CA4CjB"}
1
+ {"version":3,"file":"PdfDownload.d.ts","sourceRoot":"","sources":["../../src/utils/PdfDownload.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAU,GAAG,MAAM,CAGtE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,SAAK,GAAG,OAAO,CAErE;AAiCD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,CAAC,CA4GjB"}
@@ -1,6 +1,7 @@
1
1
  import axios from 'axios';
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
+ import { Readable } from 'stream';
4
5
  import { TIMEOUTS, USER_AGENT } from '../config/constants.js';
5
6
  export function safeFilename(value, fallback = 'paper') {
6
7
  const safe = value.replace(/[^a-zA-Z0-9._-]+/g, '_').replace(/^[_\-.]+|[_\-.]+$/g, '');
@@ -9,6 +10,36 @@ export function safeFilename(value, fallback = 'paper') {
9
10
  export function isPdfBuffer(buffer, contentType = '') {
10
11
  return contentType.toLowerCase().includes('pdf') || buffer.subarray(0, 4).toString() === '%PDF';
11
12
  }
13
+ async function getStreamSnippet(stream, maxBytes = 240) {
14
+ return new Promise((resolve) => {
15
+ let buffer = Buffer.alloc(0);
16
+ const onData = (chunk) => {
17
+ buffer = Buffer.concat([buffer, chunk]);
18
+ if (buffer.length >= maxBytes) {
19
+ cleanup();
20
+ stream.destroy?.();
21
+ }
22
+ };
23
+ const cleanup = () => {
24
+ if (typeof stream.off === 'function') {
25
+ stream.off('data', onData);
26
+ }
27
+ };
28
+ stream.on('data', onData);
29
+ stream.on('end', () => {
30
+ cleanup();
31
+ resolve(buffer.subarray(0, maxBytes).toString('utf8').replace(/\s+/g, ' ').trim());
32
+ });
33
+ stream.on('close', () => {
34
+ cleanup();
35
+ resolve(buffer.subarray(0, maxBytes).toString('utf8').replace(/\s+/g, ' ').trim());
36
+ });
37
+ stream.on('error', () => {
38
+ cleanup();
39
+ resolve(buffer.subarray(0, maxBytes).toString('utf8').replace(/\s+/g, ' ').trim());
40
+ });
41
+ });
42
+ }
12
43
  export async function downloadPdfFromUrl(pdfUrl, savePath, filenameHint, options = {}) {
13
44
  if (!pdfUrl) {
14
45
  throw new Error('Missing PDF URL');
@@ -19,7 +50,7 @@ export async function downloadPdfFromUrl(pdfUrl, savePath, filenameHint, options
19
50
  fs.mkdirSync(savePath, { recursive: true });
20
51
  const outputPath = path.join(savePath, `${safeFilename(filenameHint)}.pdf`);
21
52
  const response = await axios.get(pdfUrl, {
22
- responseType: 'arraybuffer',
53
+ responseType: 'stream',
23
54
  timeout: TIMEOUTS.DOWNLOAD,
24
55
  maxRedirects: 5,
25
56
  headers: {
@@ -30,23 +61,82 @@ export async function downloadPdfFromUrl(pdfUrl, savePath, filenameHint, options
30
61
  validateStatus: status => status < 500
31
62
  });
32
63
  if (response.status >= 400) {
33
- const errorBuffer = Buffer.from(response.data || []);
34
- const snippet = errorBuffer.subarray(0, 240).toString('utf8').replace(/\s+/g, ' ').trim();
35
- const challenge = response.headers['cf-mitigated'] || /cloudflare|challenge|just a moment/i.test(snippet);
64
+ let errStream = response.data;
65
+ if (!(errStream instanceof Readable) && !(errStream && typeof errStream.on === 'function')) {
66
+ errStream = Readable.from(Buffer.isBuffer(errStream) ? errStream : Buffer.from(errStream || ''));
67
+ }
68
+ const errorSnippet = await getStreamSnippet(errStream);
69
+ const cfHeader = response.headers['cf-mitigated'];
70
+ const challenge = !!cfHeader || /cloudflare|challenge|just a moment/i.test(errorSnippet);
36
71
  const reason = challenge ? 'provider returned an HTML anti-bot challenge instead of a PDF' : 'provider refused the request';
37
72
  throw new Error(`PDF download failed with HTTP ${response.status}: ${reason}`);
38
73
  }
39
- const buffer = Buffer.from(response.data);
40
- const contentType = String(response.headers['content-type'] || '').toLowerCase();
41
- if (!isPdfBuffer(buffer, contentType)) {
42
- const snippet = buffer.subarray(0, 240).toString('utf8').replace(/\s+/g, ' ').trim();
43
- const challenge = response.headers['cf-mitigated'] || /cloudflare|challenge|preparing to download|proof-of-work/i.test(snippet);
44
- const reason = challenge
45
- ? 'the provider returned an HTML challenge page instead of a PDF'
46
- : `content-type was ${contentType || 'unknown'}`;
47
- throw new Error(`Resolved URL did not return a PDF (${reason}): ${pdfUrl}`);
48
- }
49
- fs.writeFileSync(outputPath, buffer);
50
- return outputPath;
74
+ return new Promise((resolve, reject) => {
75
+ const writer = fs.createWriteStream(outputPath);
76
+ let reader = response.data;
77
+ if (!(reader instanceof Readable) && !(reader && typeof reader.on === 'function')) {
78
+ reader = Readable.from(Buffer.isBuffer(reader) ? reader : Buffer.from(reader || ''));
79
+ }
80
+ let checked = false;
81
+ let totalBytes = 0;
82
+ const contentLengthHeader = response.headers['content-length'];
83
+ const expectedLength = contentLengthHeader ? parseInt(String(contentLengthHeader), 10) : 0;
84
+ writer.on('error', (err) => {
85
+ if (typeof reader.destroy === 'function')
86
+ reader.destroy();
87
+ fs.unlink(outputPath, () => { });
88
+ reject(err);
89
+ });
90
+ reader.on('data', (chunk) => {
91
+ totalBytes += chunk.length;
92
+ if (!checked) {
93
+ checked = true;
94
+ const contentType = String(response.headers['content-type'] || '').toLowerCase();
95
+ const isPdf = contentType.includes('pdf') || chunk.subarray(0, 4).toString() === '%PDF';
96
+ if (!isPdf) {
97
+ const snippet = chunk.subarray(0, 240).toString('utf8').replace(/\s+/g, ' ').trim();
98
+ const cfHeader = response.headers['cf-mitigated'];
99
+ const challenge = !!cfHeader || /cloudflare|challenge|preparing to download|proof-of-work|<!doctype html/i.test(snippet);
100
+ const reason = challenge
101
+ ? 'the provider returned an HTML challenge page instead of a PDF'
102
+ : `content-type was ${contentType || 'unknown'}`;
103
+ if (typeof reader.destroy === 'function')
104
+ reader.destroy();
105
+ writer.destroy();
106
+ fs.unlink(outputPath, () => { });
107
+ reject(new Error(`Resolved URL did not return a PDF (${reason}): ${pdfUrl}`));
108
+ return;
109
+ }
110
+ }
111
+ if (!writer.write(chunk)) {
112
+ if (typeof reader.pause === 'function')
113
+ reader.pause();
114
+ }
115
+ });
116
+ writer.on('drain', () => {
117
+ if (typeof reader.resume === 'function')
118
+ reader.resume();
119
+ });
120
+ reader.on('end', () => {
121
+ writer.end();
122
+ });
123
+ reader.on('close', () => {
124
+ if (typeof reader.destroy === 'function')
125
+ reader.destroy();
126
+ });
127
+ writer.on('finish', () => {
128
+ if (expectedLength && totalBytes !== expectedLength) {
129
+ fs.unlink(outputPath, () => { });
130
+ reject(new Error(`PDF download incomplete: received ${totalBytes} bytes, expected ${expectedLength} bytes`));
131
+ return;
132
+ }
133
+ resolve(outputPath);
134
+ });
135
+ reader.on('error', (err) => {
136
+ writer.destroy();
137
+ fs.unlink(outputPath, () => { });
138
+ reject(err);
139
+ });
140
+ });
51
141
  }
52
142
  //# sourceMappingURL=PdfDownload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PdfDownload.js","sourceRoot":"","sources":["../../src/utils/PdfDownload.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PdfDownload.js","sourceRoot":"","sources":["../../src/utils/PdfDownload.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paper-search-cli",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Agent-friendly CLI for searching and downloading academic papers from multiple sources.",
5
5
  "main": "dist/cli.js",
6
6
  "type": "module",
@@ -43,8 +43,10 @@
43
43
  "axios": "^1.7.2",
44
44
  "cheerio": "^1.1.2",
45
45
  "dotenv": "^16.4.5",
46
+ "https-proxy-agent": "^7.0.0",
46
47
  "lru-cache": "^11.2.5",
47
48
  "pdf-parse": "^1.1.4",
49
+ "socks-proxy-agent": "^8.0.0",
48
50
  "xml2js": "^0.6.2",
49
51
  "zod": "^3.23.8"
50
52
  },
@@ -3,12 +3,14 @@ name: paper-search
3
3
  description: |
4
4
  学术文献检索与论文获取调度器,基于 paper-search CLI,而不是 MCP server。
5
5
  用于:搜索论文、查找相似研究、做文献综述初筛、验证 PMID/DOI、下载论文 PDF、
6
- 调用 Crossref/OpenAlex/PubMed/PMC/Europe PMC/arXiv/bioRxiv/medRxiv/Semantic Scholar/CORE/OpenAIRE/IACR 等来源,
7
- 以及使用 Semantic Scholar Open Access snippet 索引检索论文正文片段中的方法学细节。
6
+ 调用 Crossref/OpenAlex/PubMed/PMC/Europe PMC/arXiv/bioRxiv/medRxiv/Semantic Scholar/CORE/OpenAIRE/DBLP/ACM/USENIX/OpenReview/IACR 等来源,
7
+ 使用 Semantic Scholar Open Access snippet 索引检索论文正文片段中的方法学细节,
8
+ 以及通过 EasyScholar 查询期刊影响因子、JCR/SSCI 分区、中科院分区、JCI、ESI、预警和等级指标。
8
9
  当用户提到“搜文献”“找论文”“文献检索”“search papers”“find papers”“literature search”
9
10
  “查一下有没有相关研究”“帮我找几篇参考文献”“看看别人怎么做的”“下载论文 PDF”
10
11
  “验证 PMID”“验证 DOI”“正文片段检索”“snippet search”“Methods 里怎么做的”
11
- “方法学细节检索”等任务时使用。
12
+ “方法学细节检索”“影响因子”“IF”“JCR 分区”“中科院分区”“期刊分区”
13
+ “期刊等级”“目标期刊指标”“journal metrics”等任务时使用。
12
14
  此 skill 只负责指导 agent 调用 paper-search CLI;API key 必须通过 paper-search setup、
13
15
  paper-search config、.env 或环境变量配置,绝不要写入 Skill 文件。
14
16
  ---
@@ -26,7 +28,7 @@ command -v paper-search
26
28
  paper-search status --pretty
27
29
  ```
28
30
 
29
- 如果涉及 Semantic Scholar 正文片段、CORE、Unpaywall、Web of Science、Scopus、ScienceDirect、Springer 或 Wiley 等需要 key/邮箱的能力,再运行:
31
+ 如果涉及 Semantic Scholar 正文片段、EasyScholar 期刊指标、CORE、Unpaywall、Web of Science、IEEE Xplore、Scopus、ScienceDirect、Springer/SpringerLink 或 Wiley 等需要 key/邮箱的能力,再运行:
30
32
 
31
33
  ```bash
32
34
  paper-search config doctor --pretty
@@ -37,6 +39,7 @@ paper-search config doctor --pretty
37
39
  ```bash
38
40
  paper-search setup
39
41
  paper-search config set SEMANTIC_SCHOLAR_API_KEY your_key
42
+ paper-search setup EASYSCHOLAR_KEY
40
43
  paper-search config doctor --pretty
41
44
  ```
42
45
 
@@ -65,6 +68,8 @@ paper-search status --pretty
65
68
  paper-search search "machine learning" --platform crossref --max-results 5 --pretty
66
69
  paper-search search "osteoarthritis occupational exposure" --platform pubmed --max-results 10 --pretty
67
70
  paper-search search "transformer attention mechanism" --sources arxiv,semantic,crossref --max-results 5 --pretty
71
+ paper-search search "graph neural networks" --platform dblp --max-results 5 --pretty
72
+ paper-search search "large language models" --platform openreview --max-results 5 --pretty
68
73
  ```
69
74
 
70
75
  `--platform all` 或 `--sources all` 只用于需要广覆盖召回时。精确任务优先指定平台或 `--sources`。
@@ -74,6 +79,8 @@ paper-search search "transformer attention mechanism" --sources arxiv,semantic,c
74
79
  ```bash
75
80
  paper-search run search_pubmed --arg query="osteoarthritis occupational exposure" --arg maxResults=10 --pretty
76
81
  paper-search run search_openalex --arg query="causal inference target trial emulation" --arg maxResults=5 --pretty
82
+ paper-search run search_acm --arg query="software testing" --arg maxResults=5 --pretty
83
+ paper-search run search_usenix --arg query="file systems" --arg maxResults=5 --pretty
77
84
  paper-search run get_paper_by_doi --arg doi="10.xxxx/xxxxx" --pretty
78
85
  ```
79
86
 
@@ -83,15 +90,29 @@ paper-search run get_paper_by_doi --arg doi="10.xxxx/xxxxx" --pretty
83
90
  paper-search run search_semantic_scholar --json-args '{"query":"graph neural network medicine","maxResults":5,"year":"2020-2025"}' --pretty
84
91
  ```
85
92
 
93
+ ### 期刊指标查询
94
+
95
+ 当用户询问影响因子、JCR/SSCI 分区、中科院分区、JCI、ESI、预警、北大核心、南大核心、CSCD、A&HCI、CCF、EI 或目标期刊等级时,使用 EasyScholar 原生 CLI 工具,而不是通用论文检索。
96
+
97
+ ```bash
98
+ paper-search journal-metrics "Nature" "BMJ" --pretty
99
+ paper-search journal-metrics --file journals.txt --include-raw --pretty
100
+ paper-search run query_journal_metrics --json-args '{"journals":["Nature"],"includeRaw":true}' --pretty
101
+ ```
102
+
103
+ 返回时优先解释标准化的 `core` 字段:`impact_factor`、`impact_factor_5y`、`jcr_quartile`、`ssci_quartile`、`jci`、`cas_base`、`cas_upgraded`、`cas_small`、`cas_top`、`cas_zone`、`esi`、`warning`、`pku`、`cssci`、`cscd`、`ahci`、`ccf`、`ei`、`china_st_core`。如果需要完整字段,使用 `--include-raw` 并检查 `official_all`、`official_select`、`custom_rank`。
104
+
105
+ EasyScholar 文档要求每秒最多 2 次请求;批量查询时不要并发调用。
106
+
86
107
  ### 下载 PDF
87
108
 
88
109
  ```bash
89
110
  paper-search download 2301.12345 --platform arxiv --save-path ./downloads --pretty
90
111
  paper-search run download_paper --arg paperId="10.xxxx/xxxxx" --arg platform=springer --arg savePath="./downloads" --pretty
91
- paper-search run download_with_fallback --json-args '{"doi":"10.xxxx/xxxxx","title":"Paper title","savePath":"./downloads","useSciHub":false}' --pretty
112
+ paper-search run download_with_fallback --json-args '{"source":"crossref","paperId":"10.xxxx/xxxxx","doi":"10.xxxx/xxxxx","title":"Paper title","savePath":"./downloads"}' --pretty
92
113
  ```
93
114
 
94
- 默认不要启用 Sci-Hub;只有用户明确要求并承担相应访问边界时,才把 `useSciHub` 设为 `true`。
115
+ 下载漏斗默认包含 Sci-Hub 作为最后兜底;只有用户明确要求关闭该阶段时,才把 `useSciHub` 设为 `false`。
95
116
 
96
117
  ## 平台选择
97
118
 
@@ -100,11 +121,19 @@ paper-search run download_with_fallback --json-args '{"doi":"10.xxxx/xxxxx","tit
100
121
  | 生物医学、临床、药学、公卫 | `pubmed` | `pmc`, `europepmc`, `semantic`, `crossref` |
101
122
  | 正文方法学片段 | `search_semantic_snippets` | 先用 `pubmed`/`semantic` 找题名和同义词 |
102
123
  | 计算机、AI、数学、物理 | `arxiv` | `semantic`, `crossref`, `openalex` |
124
+ | 计算机文献目录/会议元数据 | `dblp` | `acm`, `usenix`, `openreview`, `ieee` 需要 key |
103
125
  | 跨学科广覆盖 | `crossref` | `openalex`, `semantic` |
104
126
  | 开放获取全文发现 | `pmc`, `europepmc`, `core`, `openaire`, `unpaywall` | `download_with_fallback` |
127
+ | 期刊影响因子/分区/等级 | `journal-metrics` | `query_journal_metrics` |
105
128
  | 密码学 | `iacr` | `arxiv` |
106
129
  | 引用统计排序 | `semantic`, `crossref`, `openalex` | `webofscience`, `scopus` 需要 key |
107
- | 出版商/付费数据库 | `webofscience`, `scopus`, `sciencedirect`, `springer`, `wiley` | 仅在 key 已配置时使用 |
130
+ | 出版商/付费数据库 | `webofscience`, `ieee`, `scopus`, `sciencedirect`, `springer`/`springerlink`, `wiley` | 仅在 key 已配置时使用 |
131
+
132
+ 平台边界:
133
+
134
+ - `acm` 通过 Crossref 的 ACM DOI 前缀检索元数据,不抓取 ACM Digital Library 页面。
135
+ - `usenix` 通过 DBLP 返回 USENIX 相关会议/期刊元数据,不抓取 USENIX 搜索页。
136
+ - `springerlink` 是 `springer` 的别名,仍需要 Springer API key。
108
137
 
109
138
  查询构建规则:
110
139
 
@@ -179,7 +208,9 @@ paper-search run search_crossref --arg query="full paper title" --arg maxResults
179
208
  |---|---|
180
209
  | CLI 不存在 | 提示安装 `npm install -g paper-search-cli` |
181
210
  | API key 缺失 | 提示运行 `paper-search setup`;不要索要或保存 key |
211
+ | EasyScholar key 缺失 | 提示运行 `paper-search setup EASYSCHOLAR_KEY`;不要让用户在聊天中发送 SecretKey |
182
212
  | 429 限流 | 降低 `--max-results`,换平台,或提示配置可选 key |
213
+ | EasyScholar 批量查询 | 控制在每秒最多 2 次请求;优先使用单次 `journal-metrics` 多期刊输入,不要并发 |
183
214
  | 0 结果 | 放宽关键词,换英文同义词,换平台,或用 `--sources` 扩展 |
184
215
  | 下载失败 | 优先开放获取来源和 `download_with_fallback`,报告失败原因 |
185
216
  | 用户要求完整正文 | 先下载 PDF;再交给当前环境可用的 PDF/MinerU 解析流程 |
@@ -189,4 +220,3 @@ paper-search run search_crossref --arg query="full paper title" --arg maxResults
189
220
  - 不管理 Zotero、Obsidian 或其他文献库。
190
221
  - 不写论文正文,不做语言润色。
191
222
  - 不把 API key、token、cookie 写入 Skill、README 或回复。
192
- - 当前公开 CLI 不提供期刊 IF、JCR 分区或中科院分区查询;遇到这类请求时说明能力边界,除非用户另行指定本地私有工具。