paper-search-cli 0.1.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 (166) hide show
  1. package/.env.example +165 -0
  2. package/LICENSE +21 -0
  3. package/README-sc.md +642 -0
  4. package/README.md +642 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +637 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/config/ConfigService.d.ts +26 -0
  10. package/dist/config/ConfigService.d.ts.map +1 -0
  11. package/dist/config/ConfigService.js +145 -0
  12. package/dist/config/ConfigService.js.map +1 -0
  13. package/dist/config/constants.d.ts +140 -0
  14. package/dist/config/constants.d.ts.map +1 -0
  15. package/dist/config/constants.js +93 -0
  16. package/dist/config/constants.js.map +1 -0
  17. package/dist/core/diagnostics.d.ts +43 -0
  18. package/dist/core/diagnostics.d.ts.map +1 -0
  19. package/dist/core/diagnostics.js +544 -0
  20. package/dist/core/diagnostics.js.map +1 -0
  21. package/dist/core/handleToolCall.d.ts +8 -0
  22. package/dist/core/handleToolCall.d.ts.map +1 -0
  23. package/dist/core/handleToolCall.js +440 -0
  24. package/dist/core/handleToolCall.js.map +1 -0
  25. package/dist/core/schemas.d.ts +454 -0
  26. package/dist/core/schemas.d.ts.map +1 -0
  27. package/dist/core/schemas.js +322 -0
  28. package/dist/core/schemas.js.map +1 -0
  29. package/dist/core/searchers.d.ts +45 -0
  30. package/dist/core/searchers.d.ts.map +1 -0
  31. package/dist/core/searchers.js +73 -0
  32. package/dist/core/searchers.js.map +1 -0
  33. package/dist/core/tools.d.ts +7 -0
  34. package/dist/core/tools.d.ts.map +1 -0
  35. package/dist/core/tools.js +640 -0
  36. package/dist/core/tools.js.map +1 -0
  37. package/dist/models/Paper.d.ts +64 -0
  38. package/dist/models/Paper.d.ts.map +1 -0
  39. package/dist/models/Paper.js +70 -0
  40. package/dist/models/Paper.js.map +1 -0
  41. package/dist/platforms/ArxivSearcher.d.ts +64 -0
  42. package/dist/platforms/ArxivSearcher.d.ts.map +1 -0
  43. package/dist/platforms/ArxivSearcher.js +531 -0
  44. package/dist/platforms/ArxivSearcher.js.map +1 -0
  45. package/dist/platforms/BioRxivSearcher.d.ts +47 -0
  46. package/dist/platforms/BioRxivSearcher.d.ts.map +1 -0
  47. package/dist/platforms/BioRxivSearcher.js +196 -0
  48. package/dist/platforms/BioRxivSearcher.js.map +1 -0
  49. package/dist/platforms/CORESearcher.d.ts +16 -0
  50. package/dist/platforms/CORESearcher.d.ts.map +1 -0
  51. package/dist/platforms/CORESearcher.js +148 -0
  52. package/dist/platforms/CORESearcher.js.map +1 -0
  53. package/dist/platforms/CrossrefSearcher.d.ts +34 -0
  54. package/dist/platforms/CrossrefSearcher.d.ts.map +1 -0
  55. package/dist/platforms/CrossrefSearcher.js +339 -0
  56. package/dist/platforms/CrossrefSearcher.js.map +1 -0
  57. package/dist/platforms/EuropePMCSearcher.d.ts +20 -0
  58. package/dist/platforms/EuropePMCSearcher.d.ts.map +1 -0
  59. package/dist/platforms/EuropePMCSearcher.js +173 -0
  60. package/dist/platforms/EuropePMCSearcher.js.map +1 -0
  61. package/dist/platforms/GoogleScholarSearcher.d.ts +77 -0
  62. package/dist/platforms/GoogleScholarSearcher.d.ts.map +1 -0
  63. package/dist/platforms/GoogleScholarSearcher.js +262 -0
  64. package/dist/platforms/GoogleScholarSearcher.js.map +1 -0
  65. package/dist/platforms/IACRSearcher.d.ts +51 -0
  66. package/dist/platforms/IACRSearcher.d.ts.map +1 -0
  67. package/dist/platforms/IACRSearcher.js +339 -0
  68. package/dist/platforms/IACRSearcher.js.map +1 -0
  69. package/dist/platforms/OpenAIRESearcher.d.ts +22 -0
  70. package/dist/platforms/OpenAIRESearcher.d.ts.map +1 -0
  71. package/dist/platforms/OpenAIRESearcher.js +223 -0
  72. package/dist/platforms/OpenAIRESearcher.js.map +1 -0
  73. package/dist/platforms/OpenAlexSearcher.d.ts +14 -0
  74. package/dist/platforms/OpenAlexSearcher.d.ts.map +1 -0
  75. package/dist/platforms/OpenAlexSearcher.js +114 -0
  76. package/dist/platforms/OpenAlexSearcher.js.map +1 -0
  77. package/dist/platforms/PMCSearcher.d.ts +20 -0
  78. package/dist/platforms/PMCSearcher.d.ts.map +1 -0
  79. package/dist/platforms/PMCSearcher.js +177 -0
  80. package/dist/platforms/PMCSearcher.js.map +1 -0
  81. package/dist/platforms/PaperSource.d.ts +143 -0
  82. package/dist/platforms/PaperSource.d.ts.map +1 -0
  83. package/dist/platforms/PaperSource.js +125 -0
  84. package/dist/platforms/PaperSource.js.map +1 -0
  85. package/dist/platforms/PubMedSearcher.d.ts +104 -0
  86. package/dist/platforms/PubMedSearcher.d.ts.map +1 -0
  87. package/dist/platforms/PubMedSearcher.js +422 -0
  88. package/dist/platforms/PubMedSearcher.js.map +1 -0
  89. package/dist/platforms/SciHubSearcher.d.ts +66 -0
  90. package/dist/platforms/SciHubSearcher.d.ts.map +1 -0
  91. package/dist/platforms/SciHubSearcher.js +398 -0
  92. package/dist/platforms/SciHubSearcher.js.map +1 -0
  93. package/dist/platforms/ScienceDirectSearcher.d.ts +42 -0
  94. package/dist/platforms/ScienceDirectSearcher.d.ts.map +1 -0
  95. package/dist/platforms/ScienceDirectSearcher.js +326 -0
  96. package/dist/platforms/ScienceDirectSearcher.js.map +1 -0
  97. package/dist/platforms/ScopusSearcher.d.ts +43 -0
  98. package/dist/platforms/ScopusSearcher.d.ts.map +1 -0
  99. package/dist/platforms/ScopusSearcher.js +364 -0
  100. package/dist/platforms/ScopusSearcher.js.map +1 -0
  101. package/dist/platforms/SemanticScholarSearcher.d.ts +96 -0
  102. package/dist/platforms/SemanticScholarSearcher.d.ts.map +1 -0
  103. package/dist/platforms/SemanticScholarSearcher.js +419 -0
  104. package/dist/platforms/SemanticScholarSearcher.js.map +1 -0
  105. package/dist/platforms/SpringerSearcher.d.ts +54 -0
  106. package/dist/platforms/SpringerSearcher.d.ts.map +1 -0
  107. package/dist/platforms/SpringerSearcher.js +407 -0
  108. package/dist/platforms/SpringerSearcher.js.map +1 -0
  109. package/dist/platforms/UnpaywallSearcher.d.ts +18 -0
  110. package/dist/platforms/UnpaywallSearcher.d.ts.map +1 -0
  111. package/dist/platforms/UnpaywallSearcher.js +115 -0
  112. package/dist/platforms/UnpaywallSearcher.js.map +1 -0
  113. package/dist/platforms/WebOfScienceSearcher.d.ts +111 -0
  114. package/dist/platforms/WebOfScienceSearcher.d.ts.map +1 -0
  115. package/dist/platforms/WebOfScienceSearcher.js +500 -0
  116. package/dist/platforms/WebOfScienceSearcher.js.map +1 -0
  117. package/dist/platforms/WileySearcher.d.ts +44 -0
  118. package/dist/platforms/WileySearcher.d.ts.map +1 -0
  119. package/dist/platforms/WileySearcher.js +148 -0
  120. package/dist/platforms/WileySearcher.js.map +1 -0
  121. package/dist/services/CitationService.d.ts +66 -0
  122. package/dist/services/CitationService.d.ts.map +1 -0
  123. package/dist/services/CitationService.js +237 -0
  124. package/dist/services/CitationService.js.map +1 -0
  125. package/dist/services/MultiSourceSearchService.d.ts +19 -0
  126. package/dist/services/MultiSourceSearchService.d.ts.map +1 -0
  127. package/dist/services/MultiSourceSearchService.js +96 -0
  128. package/dist/services/MultiSourceSearchService.js.map +1 -0
  129. package/dist/services/OpenAccessFallbackService.d.ts +20 -0
  130. package/dist/services/OpenAccessFallbackService.d.ts.map +1 -0
  131. package/dist/services/OpenAccessFallbackService.js +124 -0
  132. package/dist/services/OpenAccessFallbackService.js.map +1 -0
  133. package/dist/utils/ErrorHandler.d.ts +99 -0
  134. package/dist/utils/ErrorHandler.d.ts.map +1 -0
  135. package/dist/utils/ErrorHandler.js +266 -0
  136. package/dist/utils/ErrorHandler.js.map +1 -0
  137. package/dist/utils/Logger.d.ts +6 -0
  138. package/dist/utils/Logger.d.ts.map +1 -0
  139. package/dist/utils/Logger.js +26 -0
  140. package/dist/utils/Logger.js.map +1 -0
  141. package/dist/utils/PDFExtractor.d.ts +34 -0
  142. package/dist/utils/PDFExtractor.d.ts.map +1 -0
  143. package/dist/utils/PDFExtractor.js +130 -0
  144. package/dist/utils/PDFExtractor.js.map +1 -0
  145. package/dist/utils/PdfDownload.d.ts +7 -0
  146. package/dist/utils/PdfDownload.d.ts.map +1 -0
  147. package/dist/utils/PdfDownload.js +52 -0
  148. package/dist/utils/PdfDownload.js.map +1 -0
  149. package/dist/utils/QuotaManager.d.ts +32 -0
  150. package/dist/utils/QuotaManager.d.ts.map +1 -0
  151. package/dist/utils/QuotaManager.js +95 -0
  152. package/dist/utils/QuotaManager.js.map +1 -0
  153. package/dist/utils/RateLimiter.d.ts +50 -0
  154. package/dist/utils/RateLimiter.d.ts.map +1 -0
  155. package/dist/utils/RateLimiter.js +121 -0
  156. package/dist/utils/RateLimiter.js.map +1 -0
  157. package/dist/utils/RequestCache.d.ts +26 -0
  158. package/dist/utils/RequestCache.d.ts.map +1 -0
  159. package/dist/utils/RequestCache.js +66 -0
  160. package/dist/utils/RequestCache.js.map +1 -0
  161. package/dist/utils/SecurityUtils.d.ts +80 -0
  162. package/dist/utils/SecurityUtils.d.ts.map +1 -0
  163. package/dist/utils/SecurityUtils.js +357 -0
  164. package/dist/utils/SecurityUtils.js.map +1 -0
  165. package/package.json +111 -0
  166. package/skills/paper-search/SKILL.md +192 -0
@@ -0,0 +1,419 @@
1
+ /**
2
+ * Semantic Scholar API集成模块
3
+ * 支持免费API和付费API密钥
4
+ */
5
+ import axios from 'axios';
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import { PaperFactory } from '../models/Paper.js';
9
+ import { PaperSource } from './PaperSource.js';
10
+ import { RateLimiter } from '../utils/RateLimiter.js';
11
+ import { ErrorHandler } from '../utils/ErrorHandler.js';
12
+ import { RequestCache } from '../utils/RequestCache.js';
13
+ import { sanitizeDoi } from '../utils/SecurityUtils.js';
14
+ import { TIMEOUTS, USER_AGENT } from '../config/constants.js';
15
+ import { logDebug } from '../utils/Logger.js';
16
+ import { downloadPdfFromUrl, safeFilename } from '../utils/PdfDownload.js';
17
+ export class SemanticScholarSearcher extends PaperSource {
18
+ rateLimiter;
19
+ cache;
20
+ baseApiUrl;
21
+ constructor(apiKey) {
22
+ super('semantic', 'https://api.semanticscholar.org/graph/v1', apiKey);
23
+ this.baseApiUrl = this.baseUrl;
24
+ // Semantic Scholar免费API限制:100 requests per 5 minutes
25
+ // 付费API: 1000 requests per 5 minutes
26
+ // 更保守的速率限制以避免被封
27
+ const requestsPerMinute = apiKey ? 180 : 18; // 有API密钥时更宽松
28
+ this.rateLimiter = new RateLimiter({
29
+ requestsPerSecond: requestsPerMinute / 60,
30
+ burstCapacity: Math.max(3, Math.floor(requestsPerMinute / 20)), // 降低突发容量
31
+ debug: process.env.NODE_ENV === 'development'
32
+ });
33
+ this.cache = new RequestCache({
34
+ maxSize: 100,
35
+ ttlMs: 3600000 // 1 hour
36
+ });
37
+ }
38
+ getCapabilities() {
39
+ return {
40
+ search: true,
41
+ download: true, // 部分论文有开放获取PDF
42
+ fullText: false, // 只有部分PDF
43
+ citations: true, // 提供引用统计
44
+ requiresApiKey: false, // 免费API可用,但有限制
45
+ supportedOptions: ['maxResults', 'year', 'fieldsOfStudy', 'sortBy']
46
+ };
47
+ }
48
+ /**
49
+ * 搜索Semantic Scholar论文
50
+ */
51
+ async search(query, options = {}) {
52
+ const customOptions = options;
53
+ const forceRefresh = customOptions.forceRefresh === true;
54
+ // Check cache first
55
+ if (!forceRefresh) {
56
+ const cacheKey = this.cache.generateKey('semantic', query, options);
57
+ const cached = this.cache.get(cacheKey);
58
+ if (cached) {
59
+ return cached;
60
+ }
61
+ }
62
+ await this.rateLimiter.waitForPermission();
63
+ try {
64
+ const params = {
65
+ query: query,
66
+ limit: Math.min(options.maxResults || 10, 100), // API限制最大100
67
+ fields: [
68
+ 'paperId', 'title', 'abstract', 'venue', 'year',
69
+ 'referenceCount', 'citationCount', 'influentialCitationCount',
70
+ 'isOpenAccess', 'openAccessPdf', 'fieldsOfStudy', 's2FieldsOfStudy',
71
+ 'publicationTypes', 'publicationDate', 'journal', 'authors',
72
+ 'externalIds', 'url'
73
+ ].join(',')
74
+ };
75
+ // 添加年份过滤
76
+ if (options.year) {
77
+ params.year = options.year;
78
+ }
79
+ // 添加研究领域过滤
80
+ if (options.fieldsOfStudy && options.fieldsOfStudy.length > 0) {
81
+ params.fieldsOfStudy = options.fieldsOfStudy.join(',');
82
+ }
83
+ const url = `${this.baseApiUrl}/paper/search`;
84
+ const headers = {
85
+ 'User-Agent': USER_AGENT,
86
+ 'Accept': 'application/json',
87
+ 'Accept-Language': 'en-US,en;q=0.9'
88
+ };
89
+ // 添加API密钥(如果有)- 根据官方文档推荐的方式
90
+ if (this.apiKey) {
91
+ headers['x-api-key'] = this.apiKey;
92
+ }
93
+ logDebug(`Semantic Scholar API Request: GET ${url}`);
94
+ logDebug('Semantic Scholar Request params:', params);
95
+ const response = await ErrorHandler.retryWithBackoff(() => axios.get(url, {
96
+ params,
97
+ headers,
98
+ timeout: TIMEOUTS.DEFAULT,
99
+ maxRedirects: 5,
100
+ validateStatus: (status) => status < 500
101
+ }), { context: 'Semantic Scholar search' });
102
+ logDebug(`Semantic Scholar API Response: ${response.status} ${response.statusText}`);
103
+ // 处理可能的错误响应
104
+ if (response.status >= 400) {
105
+ // Convert non-throwing 4xx response to unified error handling
106
+ this.handleHttpError({ response, config: response.config }, 'search');
107
+ }
108
+ const papers = this.parseSearchResponse(response.data);
109
+ logDebug(`Semantic Scholar Parsed ${papers.length} papers`);
110
+ // Cache results
111
+ const cacheKey = this.cache.generateKey('semantic', query, options);
112
+ this.cache.set(cacheKey, papers);
113
+ return papers;
114
+ }
115
+ catch (error) {
116
+ logDebug('Semantic Scholar Search Error:', error.message);
117
+ // 处理速率限制错误
118
+ if (error.response?.status === 429) {
119
+ const retryAfter = error.response.headers['retry-after'];
120
+ logDebug(`Rate limited by Semantic Scholar API. ${retryAfter ? `Retry after ${retryAfter} seconds.` : 'Please wait before making more requests.'}`);
121
+ }
122
+ // 处理API限制错误
123
+ if (error.response?.status === 403) {
124
+ logDebug('Access denied. Please check your API key or ensure you are within the free tier limits.');
125
+ }
126
+ this.handleHttpError(error, 'search');
127
+ }
128
+ }
129
+ /**
130
+ * 获取论文详细信息
131
+ */
132
+ async getPaperDetails(paperId) {
133
+ await this.rateLimiter.waitForPermission();
134
+ try {
135
+ const params = {
136
+ fields: [
137
+ 'paperId', 'title', 'abstract', 'venue', 'year',
138
+ 'referenceCount', 'citationCount', 'influentialCitationCount',
139
+ 'isOpenAccess', 'openAccessPdf', 'fieldsOfStudy', 's2FieldsOfStudy',
140
+ 'publicationTypes', 'publicationDate', 'journal', 'authors',
141
+ 'externalIds', 'url'
142
+ ].join(',')
143
+ };
144
+ const url = `${this.baseApiUrl}/paper/${paperId}`;
145
+ const headers = {
146
+ 'User-Agent': USER_AGENT,
147
+ 'Accept': 'application/json'
148
+ };
149
+ if (this.apiKey) {
150
+ headers['x-api-key'] = this.apiKey;
151
+ }
152
+ const response = await ErrorHandler.retryWithBackoff(() => axios.get(url, {
153
+ params,
154
+ headers,
155
+ timeout: TIMEOUTS.DEFAULT,
156
+ maxRedirects: 5,
157
+ validateStatus: (status) => status < 500
158
+ }), { context: 'Semantic Scholar paper details' });
159
+ return this.parseSemanticPaper(response.data);
160
+ }
161
+ catch (error) {
162
+ logDebug('Error getting paper details from Semantic Scholar:', error.message);
163
+ return null;
164
+ }
165
+ }
166
+ async searchSnippets(options) {
167
+ if (!this.apiKey) {
168
+ throw new Error('search_semantic_snippets requires SEMANTIC_SCHOLAR_API_KEY.');
169
+ }
170
+ await this.rateLimiter.waitForPermission();
171
+ try {
172
+ const params = {
173
+ query: options.query,
174
+ limit: Math.min(options.limit || 5, 1000)
175
+ };
176
+ const paperIds = this.listParam(options.paperIds);
177
+ const authors = this.listParam(options.authors);
178
+ const venue = this.listParam(options.venue);
179
+ const fieldsOfStudy = this.listParam(options.fieldsOfStudy);
180
+ const fields = this.listParam(options.fields);
181
+ if (paperIds.length > 0)
182
+ params.paperIds = paperIds.join(',');
183
+ if (authors.length > 0)
184
+ params.authors = authors.join(',');
185
+ if (venue.length > 0)
186
+ params.venue = venue.join(',');
187
+ if (fieldsOfStudy.length > 0)
188
+ params.fieldsOfStudy = fieldsOfStudy.join(',');
189
+ if (fields.length > 0)
190
+ params.fields = fields.join(',');
191
+ if (options.year)
192
+ params.year = options.year;
193
+ if (options.minCitationCount)
194
+ params.minCitationCount = options.minCitationCount;
195
+ if (options.publicationDateOrYear)
196
+ params.publicationDateOrYear = options.publicationDateOrYear;
197
+ const url = `${this.baseApiUrl}/snippet/search`;
198
+ const response = await ErrorHandler.retryWithBackoff(() => axios.get(url, {
199
+ params,
200
+ headers: {
201
+ 'User-Agent': USER_AGENT,
202
+ Accept: 'application/json',
203
+ 'x-api-key': this.apiKey
204
+ },
205
+ timeout: TIMEOUTS.DEFAULT,
206
+ maxRedirects: 5,
207
+ validateStatus: status => status < 500
208
+ }), { context: 'Semantic Scholar snippet search' });
209
+ if (response.status >= 400) {
210
+ this.handleHttpError({ response, config: response.config }, 'snippet search');
211
+ }
212
+ const data = Array.isArray(response.data?.data) ? response.data.data : [];
213
+ return data.map(item => this.parseSnippet(item));
214
+ }
215
+ catch (error) {
216
+ this.handleHttpError(error, 'snippet search');
217
+ }
218
+ }
219
+ /**
220
+ * 下载PDF文件
221
+ */
222
+ async downloadPdf(paperId, options = {}) {
223
+ try {
224
+ // 首先获取论文详细信息以获取PDF URL
225
+ const paper = await this.getPaperDetails(paperId);
226
+ if (!paper?.pdfUrl) {
227
+ throw new Error(`No PDF URL available for paper ${paperId}`);
228
+ }
229
+ const savePath = options.savePath || './downloads';
230
+ return await downloadPdfFromUrl(paper.pdfUrl, savePath, `semantic_${safeFilename(paperId)}`, {
231
+ headers: {
232
+ Referer: paper.url || 'https://www.semanticscholar.org/',
233
+ 'User-Agent': USER_AGENT
234
+ }
235
+ });
236
+ }
237
+ catch (error) {
238
+ this.handleHttpError(error, 'download PDF');
239
+ }
240
+ }
241
+ /**
242
+ * 读取论文全文内容
243
+ */
244
+ async readPaper(paperId, options = {}) {
245
+ try {
246
+ const savePath = options.savePath || './downloads';
247
+ const filename = `semantic_${paperId.replace(/[/\\:*?"<>|]/g, '_')}.pdf`;
248
+ const filePath = path.join(savePath, filename);
249
+ // 如果PDF不存在,先下载
250
+ if (!fs.existsSync(filePath)) {
251
+ await this.downloadPdf(paperId, options);
252
+ }
253
+ return `PDF file downloaded at: ${filePath}. Full text extraction requires additional PDF parsing implementation.`;
254
+ }
255
+ catch (error) {
256
+ this.handleHttpError(error, 'read paper');
257
+ }
258
+ }
259
+ /**
260
+ * 根据DOI获取论文信息
261
+ */
262
+ async getPaperByDoi(doi) {
263
+ // Clean and validate DOI
264
+ const doiResult = sanitizeDoi(doi);
265
+ if (!doiResult.valid) {
266
+ logDebug('Invalid DOI format:', doiResult.error);
267
+ return null;
268
+ }
269
+ try {
270
+ return await this.getPaperDetails(`DOI:${doiResult.sanitized}`);
271
+ }
272
+ catch (error) {
273
+ logDebug('Error getting paper by DOI from Semantic Scholar:', error);
274
+ return null;
275
+ }
276
+ }
277
+ /**
278
+ * 解析搜索响应
279
+ */
280
+ parseSearchResponse(data) {
281
+ if (!data.data || !Array.isArray(data.data)) {
282
+ return [];
283
+ }
284
+ return data.data.map(item => this.parseSemanticPaper(item))
285
+ .filter(paper => paper !== null);
286
+ }
287
+ /**
288
+ * 解析单个Semantic Scholar论文
289
+ */
290
+ parseSemanticPaper(item) {
291
+ try {
292
+ // 提取作者
293
+ const authors = item.authors?.map(author => author.name) || [];
294
+ // 提取发表日期
295
+ const publishedDate = item.publicationDate ?
296
+ this.parseDate(item.publicationDate) :
297
+ (item.year ? new Date(item.year, 0, 1) : null);
298
+ // 提取PDF URL
299
+ let pdfUrl = '';
300
+ if (item.openAccessPdf?.url) {
301
+ pdfUrl = this.normalizePdfUrl(item.openAccessPdf.url);
302
+ }
303
+ else if (item.openAccessPdf?.disclaimer) {
304
+ // 尝试从disclaimer中提取URL
305
+ const urlMatch = item.openAccessPdf.disclaimer.match(/https?:\/\/[^\s,)]+/);
306
+ if (urlMatch) {
307
+ pdfUrl = this.normalizePdfUrl(urlMatch[0]);
308
+ }
309
+ }
310
+ // 提取DOI
311
+ const doi = item.externalIds?.DOI || '';
312
+ // 提取分类
313
+ const fieldsOfStudy = item.fieldsOfStudy || [];
314
+ const s2Fields = item.s2FieldsOfStudy?.map(field => field.category) || [];
315
+ const categories = [...fieldsOfStudy, ...s2Fields];
316
+ // 构建URL
317
+ const url = item.url || `https://www.semanticscholar.org/paper/${item.paperId}`;
318
+ return PaperFactory.create({
319
+ paperId: item.paperId,
320
+ title: this.cleanText(item.title),
321
+ authors: authors,
322
+ abstract: this.cleanText(item.abstract || ''),
323
+ doi: doi,
324
+ publishedDate: publishedDate,
325
+ pdfUrl: pdfUrl,
326
+ url: url,
327
+ source: 'semantic',
328
+ categories: [...new Set(categories)], // 去重
329
+ keywords: [],
330
+ citationCount: item.citationCount || 0,
331
+ journal: item.venue || item.journal?.name || '',
332
+ volume: item.journal?.volume || undefined,
333
+ pages: item.journal?.pages || undefined,
334
+ year: item.year,
335
+ extra: {
336
+ semanticScholarId: item.paperId,
337
+ referenceCount: item.referenceCount || 0,
338
+ influentialCitationCount: item.influentialCitationCount || 0,
339
+ isOpenAccess: item.isOpenAccess || false,
340
+ publicationTypes: item.publicationTypes || [],
341
+ externalIds: item.externalIds || {}
342
+ }
343
+ });
344
+ }
345
+ catch (error) {
346
+ logDebug('Error parsing Semantic Scholar paper:', error);
347
+ return null;
348
+ }
349
+ }
350
+ normalizePdfUrl(url) {
351
+ const clean = url.trim();
352
+ const arxivAbs = clean.match(/^https?:\/\/arxiv\.org\/abs\/([^?#]+)(?:[?#].*)?$/i);
353
+ if (arxivAbs) {
354
+ return `https://arxiv.org/pdf/${arxivAbs[1]}`;
355
+ }
356
+ if (/^https?:\/\/api\.unpaywall\.org\//i.test(clean) || /^https?:\/\/(?:dx\.)?doi\.org\//i.test(clean)) {
357
+ return '';
358
+ }
359
+ return clean;
360
+ }
361
+ parseSnippet(item) {
362
+ const paper = item?.paper || {};
363
+ const snippet = item?.snippet || {};
364
+ const corpusId = paper.corpusId ?? paper.corpus_id ?? '';
365
+ return {
366
+ score: typeof item?.score === 'number' ? item.score : null,
367
+ paper: {
368
+ corpusId: corpusId ? String(corpusId) : '',
369
+ title: this.cleanText(paper.title || ''),
370
+ authors: this.listParam(paper.authors),
371
+ openAccessInfo: paper.openAccessInfo || {},
372
+ url: corpusId ? `https://www.semanticscholar.org/paper/CorpusId:${corpusId}` : ''
373
+ },
374
+ snippet: {
375
+ text: this.cleanText(snippet.text || item?.text || ''),
376
+ snippetKind: snippet.snippetKind || snippet.kind || '',
377
+ section: snippet.section || '',
378
+ snippetOffset: snippet.snippetOffset || {},
379
+ annotations: snippet.annotations || {}
380
+ },
381
+ text: this.cleanText(snippet.text || item?.text || '')
382
+ };
383
+ }
384
+ listParam(value) {
385
+ if (!value)
386
+ return [];
387
+ if (Array.isArray(value))
388
+ return value.map(item => String(item).trim()).filter(Boolean);
389
+ return String(value)
390
+ .split(',')
391
+ .map(item => item.trim())
392
+ .filter(Boolean);
393
+ }
394
+ /**
395
+ * 获取速率限制器状态
396
+ */
397
+ getRateLimiterStatus() {
398
+ return this.rateLimiter.getStatus();
399
+ }
400
+ /**
401
+ * 验证API密钥(如果提供)
402
+ */
403
+ async validateApiKey() {
404
+ if (!this.apiKey) {
405
+ return true; // 无API密钥时使用免费限制
406
+ }
407
+ try {
408
+ await this.search('test', { maxResults: 1 });
409
+ return true;
410
+ }
411
+ catch (error) {
412
+ if (error.response?.status === 401 || error.response?.status === 403) {
413
+ return false;
414
+ }
415
+ return true; // 其他错误可能是网络问题
416
+ }
417
+ }
418
+ }
419
+ //# sourceMappingURL=SemanticScholarSearcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SemanticScholarSearcher.js","sourceRoot":"","sources":["../../src/platforms/SemanticScholarSearcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Springer Nature Searcher
3
+ *
4
+ * Documentation: https://dev.springernature.com/
5
+ * API Endpoints:
6
+ * - Metadata API v2: https://api.springernature.com/meta/v2/json
7
+ * - OpenAccess API: https://api.springernature.com/openaccess/json (if available with your key)
8
+ *
9
+ * Required API Key: Yes (api_key parameter)
10
+ * Get API key from: https://dev.springernature.com/signup
11
+ *
12
+ * Note: Meta API v2 is the primary API. OpenAccess API may require special access.
13
+ */
14
+ import { PaperSource, SearchOptions, DownloadOptions, PlatformCapabilities } from './PaperSource.js';
15
+ import { Paper } from '../models/Paper.js';
16
+ export declare class SpringerSearcher extends PaperSource {
17
+ private metadataClient;
18
+ private openAccessClient;
19
+ private rateLimiter;
20
+ private quotaManager;
21
+ private hasOpenAccessAPI;
22
+ private openAccessApiKey?;
23
+ private testingPromise;
24
+ constructor(apiKey?: string, openAccessApiKey?: string);
25
+ search(query: string, options?: SearchOptions): Promise<Paper[]>;
26
+ private parseResult;
27
+ downloadPdf(doi: string, options?: {
28
+ savePath?: string;
29
+ }): Promise<string>;
30
+ getCapabilities(): PlatformCapabilities;
31
+ /**
32
+ * 获取引用此论文的文献列表(通过Crossref/OpenCitations)
33
+ */
34
+ getCitations(doi: string): Promise<Paper[]>;
35
+ /**
36
+ * 获取论文的参考文献列表(通过Crossref)
37
+ */
38
+ getReferences(doi: string): Promise<Paper[]>;
39
+ /**
40
+ * 清理和转义查询参数中的特殊字符
41
+ */
42
+ private sanitizeQueryValue;
43
+ /**
44
+ * Test if OpenAccess API is available for this API key
45
+ * Uses promise caching to prevent race conditions with concurrent requests
46
+ */
47
+ private testOpenAccessAPI;
48
+ /**
49
+ * Perform the actual OpenAccess API test
50
+ */
51
+ private performOpenAccessTest;
52
+ readPaper(paperId: string, options?: DownloadOptions): Promise<string>;
53
+ }
54
+ //# sourceMappingURL=SpringerSearcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpringerSearcher.d.ts","sourceRoot":"","sources":["../../src/platforms/SpringerSearcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,KAAK,EAAgB,MAAM,oBAAoB,CAAC;AA6CzD,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,OAAO,CAAC,cAAc,CAA8B;gBAExC,MAAM,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM;IA0ChD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA0I1E,OAAO,CAAC,WAAW;IA8Db,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAoDpF,eAAe,IAAI,oBAAoB;IAWvC;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA6BjD;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA6BlD;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;;OAGG;YACW,iBAAiB;IAqB/B;;OAEG;YACW,qBAAqB;IAwB7B,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;CAOjF"}