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.
- package/.env.example +31 -3
- package/README-sc.md +151 -36
- package/README.md +150 -27
- package/dist/cli.js +21 -0
- package/dist/cli.js.map +1 -1
- package/dist/config/ConfigService.d.ts +1 -1
- package/dist/config/ConfigService.d.ts.map +1 -1
- package/dist/config/ConfigService.js +6 -1
- package/dist/config/ConfigService.js.map +1 -1
- package/dist/config/constants.d.ts +6 -0
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +4 -1
- package/dist/config/constants.js.map +1 -1
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/diagnostics.js +54 -12
- package/dist/core/diagnostics.js.map +1 -1
- package/dist/core/handleToolCall.d.ts.map +1 -1
- package/dist/core/handleToolCall.js +77 -7
- package/dist/core/handleToolCall.js.map +1 -1
- package/dist/core/platformMetadata.d.ts +28 -0
- package/dist/core/platformMetadata.d.ts.map +1 -0
- package/dist/core/platformMetadata.js +258 -0
- package/dist/core/platformMetadata.js.map +1 -0
- package/dist/core/schemas.d.ts +134 -74
- package/dist/core/schemas.d.ts.map +1 -1
- package/dist/core/schemas.js +42 -38
- package/dist/core/schemas.js.map +1 -1
- package/dist/core/searchers.d.ts +11 -0
- package/dist/core/searchers.d.ts.map +1 -1
- package/dist/core/searchers.js +17 -1
- package/dist/core/searchers.js.map +1 -1
- package/dist/core/tools.d.ts.map +1 -1
- package/dist/core/tools.js +82 -30
- package/dist/core/tools.js.map +1 -1
- package/dist/platforms/ACMSearcher.d.ts +16 -0
- package/dist/platforms/ACMSearcher.d.ts.map +1 -0
- package/dist/platforms/ACMSearcher.js +125 -0
- package/dist/platforms/ACMSearcher.js.map +1 -0
- package/dist/platforms/ArxivSearcher.d.ts.map +1 -1
- package/dist/platforms/ArxivSearcher.js +10 -2
- package/dist/platforms/ArxivSearcher.js.map +1 -1
- package/dist/platforms/DBLPSearcher.d.ts +16 -0
- package/dist/platforms/DBLPSearcher.d.ts.map +1 -0
- package/dist/platforms/DBLPSearcher.js +116 -0
- package/dist/platforms/DBLPSearcher.js.map +1 -0
- package/dist/platforms/IEEESearcher.d.ts +15 -0
- package/dist/platforms/IEEESearcher.d.ts.map +1 -0
- package/dist/platforms/IEEESearcher.js +123 -0
- package/dist/platforms/IEEESearcher.js.map +1 -0
- package/dist/platforms/OpenAIRESearcher.d.ts.map +1 -1
- package/dist/platforms/OpenAIRESearcher.js +9 -1
- package/dist/platforms/OpenAIRESearcher.js.map +1 -1
- package/dist/platforms/OpenReviewSearcher.d.ts +19 -0
- package/dist/platforms/OpenReviewSearcher.d.ts.map +1 -0
- package/dist/platforms/OpenReviewSearcher.js +141 -0
- package/dist/platforms/OpenReviewSearcher.js.map +1 -0
- package/dist/platforms/PaperSource.d.ts +6 -0
- package/dist/platforms/PaperSource.d.ts.map +1 -1
- package/dist/platforms/PaperSource.js.map +1 -1
- package/dist/platforms/PubMedSearcher.d.ts.map +1 -1
- package/dist/platforms/PubMedSearcher.js +8 -0
- package/dist/platforms/PubMedSearcher.js.map +1 -1
- package/dist/platforms/USENIXSearcher.d.ts +14 -0
- package/dist/platforms/USENIXSearcher.d.ts.map +1 -0
- package/dist/platforms/USENIXSearcher.js +75 -0
- package/dist/platforms/USENIXSearcher.js.map +1 -0
- package/dist/services/JournalMetricsService.d.ts +38 -0
- package/dist/services/JournalMetricsService.d.ts.map +1 -0
- package/dist/services/JournalMetricsService.js +142 -0
- package/dist/services/JournalMetricsService.js.map +1 -0
- package/dist/services/MultiSourceSearchService.d.ts.map +1 -1
- package/dist/services/MultiSourceSearchService.js +8 -34
- package/dist/services/MultiSourceSearchService.js.map +1 -1
- package/dist/services/OpenAccessFallbackService.d.ts +1 -0
- package/dist/services/OpenAccessFallbackService.d.ts.map +1 -1
- package/dist/services/OpenAccessFallbackService.js +2 -2
- package/dist/services/OpenAccessFallbackService.js.map +1 -1
- package/dist/utils/HttpClient.d.ts +6 -0
- package/dist/utils/HttpClient.d.ts.map +1 -0
- package/dist/utils/HttpClient.js +30 -0
- package/dist/utils/HttpClient.js.map +1 -0
- package/dist/utils/PdfDownload.d.ts.map +1 -1
- package/dist/utils/PdfDownload.js +106 -16
- package/dist/utils/PdfDownload.js.map +1 -1
- package/package.json +3 -1
- 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":"
|
|
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: '
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAM9D,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,QAAQ,GAAG,OAAO;IAC5D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IACvF,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,WAAW,GAAG,EAAE;IAC1D,OAAO,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,MAAM,CAAC;AAClG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAc,EACd,QAAgB,EAChB,YAAoB,EACpB,UAA8B,EAAE;IAEhC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,2DAA2D,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAE5E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,
|
|
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.
|
|
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
|
-
|
|
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"
|
|
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
|
-
|
|
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 分区或中科院分区查询;遇到这类请求时说明能力边界,除非用户另行指定本地私有工具。
|