@gonzih/research-rabbit 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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +330 -0
  3. package/SKILL.md +109 -0
  4. package/dist/analysis.d.ts +12 -0
  5. package/dist/analysis.d.ts.map +1 -0
  6. package/dist/analysis.js +217 -0
  7. package/dist/analysis.js.map +1 -0
  8. package/dist/citations.d.ts +3 -0
  9. package/dist/citations.d.ts.map +1 -0
  10. package/dist/citations.js +52 -0
  11. package/dist/citations.js.map +1 -0
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +187 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/search.d.ts +3 -0
  17. package/dist/search.d.ts.map +1 -0
  18. package/dist/search.js +61 -0
  19. package/dist/search.js.map +1 -0
  20. package/dist/sources/arxiv.d.ts +3 -0
  21. package/dist/sources/arxiv.d.ts.map +1 -0
  22. package/dist/sources/arxiv.js +51 -0
  23. package/dist/sources/arxiv.js.map +1 -0
  24. package/dist/sources/openalex.d.ts +3 -0
  25. package/dist/sources/openalex.d.ts.map +1 -0
  26. package/dist/sources/openalex.js +47 -0
  27. package/dist/sources/openalex.js.map +1 -0
  28. package/dist/sources/pubmed.d.ts +3 -0
  29. package/dist/sources/pubmed.d.ts.map +1 -0
  30. package/dist/sources/pubmed.js +68 -0
  31. package/dist/sources/pubmed.js.map +1 -0
  32. package/dist/sources/semantic_scholar.d.ts +3 -0
  33. package/dist/sources/semantic_scholar.d.ts.map +1 -0
  34. package/dist/sources/semantic_scholar.js +38 -0
  35. package/dist/sources/semantic_scholar.js.map +1 -0
  36. package/dist/types.d.ts +51 -0
  37. package/dist/types.d.ts.map +1 -0
  38. package/dist/types.js +2 -0
  39. package/dist/types.js.map +1 -0
  40. package/llms.txt +18 -0
  41. package/package.json +37 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../src/analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Paper, CitationStyle } from './types.js';
2
+ export declare function formatCitation(paper: Paper, style: CitationStyle): string;
3
+ //# sourceMappingURL=citations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citations.d.ts","sourceRoot":"","sources":["../src/citations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAyBvD,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,CA4BzE"}
@@ -0,0 +1,52 @@
1
+ function formatAuthorsApa(authors) {
2
+ if (authors.length === 0)
3
+ return 'Unknown Author';
4
+ if (authors.length === 1)
5
+ return formatNameApa(authors[0]);
6
+ if (authors.length <= 20)
7
+ return authors.map(formatNameApa).join(', ');
8
+ return authors.slice(0, 19).map(formatNameApa).join(', ') + ', ... ' + formatNameApa(authors[authors.length - 1]);
9
+ }
10
+ function formatNameApa(name) {
11
+ const parts = name.trim().split(/\s+/);
12
+ if (parts.length === 1)
13
+ return parts[0];
14
+ const last = parts[parts.length - 1];
15
+ const initials = parts.slice(0, -1).map(p => p[0] + '.').join(' ');
16
+ return `${last}, ${initials}`;
17
+ }
18
+ function formatNameMla(name) {
19
+ const parts = name.trim().split(/\s+/);
20
+ if (parts.length === 1)
21
+ return parts[0];
22
+ const last = parts[parts.length - 1];
23
+ const first = parts.slice(0, -1).join(' ');
24
+ return `${last}, ${first}`;
25
+ }
26
+ export function formatCitation(paper, style) {
27
+ const authors = paper.authors.length > 0 ? paper.authors : ['Unknown Author'];
28
+ const year = paper.year > 0 ? paper.year.toString() : 'n.d.';
29
+ const title = paper.title;
30
+ const url = paper.doi ? `https://doi.org/${paper.doi}` : paper.url;
31
+ const source = paper.source.replace('_', ' ').split(' ').map(w => w[0].toUpperCase() + w.slice(1)).join(' ');
32
+ switch (style) {
33
+ case 'apa': {
34
+ const formattedAuthors = formatAuthorsApa(authors);
35
+ return `${formattedAuthors} (${year}). ${title}. ${source}. ${url}`;
36
+ }
37
+ case 'mla': {
38
+ const firstAuthor = formatNameMla(authors[0]);
39
+ const otherAuthors = authors.length > 1
40
+ ? (authors.length === 2 ? ` and ${authors[1]}` : ', et al.')
41
+ : '';
42
+ return `${firstAuthor}${otherAuthors}. "${title}." ${source}, ${year}. ${url}`;
43
+ }
44
+ case 'chicago': {
45
+ const formattedAuthors = authors.length <= 3
46
+ ? authors.join(', ')
47
+ : authors.slice(0, 3).join(', ') + ', et al.';
48
+ return `${formattedAuthors}. "${title}." ${source} (${year}). ${url}.`;
49
+ }
50
+ }
51
+ }
52
+ //# sourceMappingURL=citations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citations.js","sourceRoot":"","sources":["../src/citations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { z } from 'zod';
5
+ import { searchPapers } from './search.js';
6
+ import { summarizePaper, mapLiterature, findGaps, buildArgument } from './analysis.js';
7
+ import { formatCitation } from './citations.js';
8
+ const server = new McpServer({
9
+ name: 'research-rabbit',
10
+ version: '0.1.0',
11
+ });
12
+ // ─── Tool: search_papers ─────────────────────────────────────────────────────
13
+ server.tool('search_papers', 'Search academic databases (ArXiv, Semantic Scholar, OpenAlex, PubMed) for real papers. Returns verified paper metadata — no hallucinated citations.', {
14
+ query: z.string().describe('Search query (e.g., "mental health effects social media teenagers")'),
15
+ sources: z.array(z.enum(['arxiv', 'semantic_scholar', 'openalex', 'pubmed'])).optional().describe('Which databases to search (default: all)'),
16
+ limit: z.number().min(1).max(25).optional().default(10).describe('Number of papers to return (default: 10, max: 25)'),
17
+ yearFrom: z.number().optional().describe('Earliest publication year to include'),
18
+ }, async ({ query, sources, limit, yearFrom }) => {
19
+ const papers = await searchPapers(query, sources ?? ['arxiv', 'semantic_scholar', 'openalex', 'pubmed'], limit ?? 10, yearFrom);
20
+ return {
21
+ content: [{
22
+ type: 'text',
23
+ text: JSON.stringify({
24
+ count: papers.length,
25
+ query,
26
+ sources: sources ?? ['arxiv', 'semantic_scholar', 'openalex', 'pubmed'],
27
+ papers,
28
+ }, null, 2),
29
+ }],
30
+ };
31
+ });
32
+ // ─── Tool: summarize_paper ───────────────────────────────────────────────────
33
+ server.tool('summarize_paper', 'Generate a structured summary of an academic paper from its abstract. Extracts main claim, methodology, key evidence, limitations, and topic relevance.', {
34
+ paperId: z.string().describe('Paper ID (from search_papers results)'),
35
+ title: z.string().describe('Paper title'),
36
+ abstract: z.string().describe('Paper abstract text'),
37
+ topic: z.string().describe('The research topic the student is working on'),
38
+ }, async ({ paperId, title, abstract, topic }) => {
39
+ const summary = await summarizePaper(paperId, title, abstract, topic);
40
+ return {
41
+ content: [{ type: 'text', text: JSON.stringify(summary, null, 2) }],
42
+ };
43
+ });
44
+ // ─── Tool: map_literature ────────────────────────────────────────────────────
45
+ server.tool('map_literature', 'Analyze a set of papers to map the state of the literature: consensus, active debates, methodological tensions, and temporal trends.', {
46
+ papers: z.array(z.object({
47
+ id: z.string(),
48
+ source: z.enum(['arxiv', 'semantic_scholar', 'openalex', 'pubmed', 'crossref']),
49
+ title: z.string(),
50
+ authors: z.array(z.string()),
51
+ year: z.number(),
52
+ abstract: z.string(),
53
+ citationCount: z.number().optional(),
54
+ doi: z.string().optional(),
55
+ url: z.string(),
56
+ openAccessPdfUrl: z.string().optional(),
57
+ })).min(2).max(20).describe('Array of Paper objects (from search_papers)'),
58
+ topic: z.string().describe('The research topic'),
59
+ }, async ({ papers, topic }) => {
60
+ const map = await mapLiterature(papers, topic);
61
+ return {
62
+ content: [{ type: 'text', text: JSON.stringify(map, null, 2) }],
63
+ };
64
+ });
65
+ // ─── Tool: find_gaps ─────────────────────────────────────────────────────────
66
+ server.tool('find_gaps', 'Identify research gaps and original contribution angles from a set of papers. This is the KEY tool for helping students find where their work can be novel.', {
67
+ papers: z.array(z.object({
68
+ id: z.string(),
69
+ source: z.enum(['arxiv', 'semantic_scholar', 'openalex', 'pubmed', 'crossref']),
70
+ title: z.string(),
71
+ authors: z.array(z.string()),
72
+ year: z.number(),
73
+ abstract: z.string(),
74
+ citationCount: z.number().optional(),
75
+ doi: z.string().optional(),
76
+ url: z.string(),
77
+ openAccessPdfUrl: z.string().optional(),
78
+ })).min(2).max(20).describe('Array of Paper objects'),
79
+ topic: z.string().describe('The research topic'),
80
+ }, async ({ papers, topic }) => {
81
+ const gaps = await findGaps(papers, topic);
82
+ return {
83
+ content: [{ type: 'text', text: JSON.stringify(gaps, null, 2) }],
84
+ };
85
+ });
86
+ // ─── Tool: build_argument ────────────────────────────────────────────────────
87
+ server.tool('build_argument', 'Build a structured argument scaffold for a research paper, with evidence assignments from real papers. Identifies missing evidence the student still needs to find.', {
88
+ topic: z.string().describe('The research topic'),
89
+ thesis: z.string().describe("The student's thesis statement or argument"),
90
+ papers: z.array(z.object({
91
+ id: z.string(),
92
+ source: z.enum(['arxiv', 'semantic_scholar', 'openalex', 'pubmed', 'crossref']),
93
+ title: z.string(),
94
+ authors: z.array(z.string()),
95
+ year: z.number(),
96
+ abstract: z.string(),
97
+ citationCount: z.number().optional(),
98
+ doi: z.string().optional(),
99
+ url: z.string(),
100
+ openAccessPdfUrl: z.string().optional(),
101
+ })).min(1).describe('Available papers to draw from'),
102
+ }, async ({ topic, thesis, papers }) => {
103
+ const result = await buildArgument(topic, thesis, papers);
104
+ return {
105
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
106
+ };
107
+ });
108
+ // ─── Tool: format_citation ───────────────────────────────────────────────────
109
+ server.tool('format_citation', 'Format a paper citation in APA, MLA, or Chicago style. Only formats papers from real API results — never hallucinated.', {
110
+ paper: z.object({
111
+ id: z.string(),
112
+ source: z.enum(['arxiv', 'semantic_scholar', 'openalex', 'pubmed', 'crossref']),
113
+ title: z.string(),
114
+ authors: z.array(z.string()),
115
+ year: z.number(),
116
+ abstract: z.string(),
117
+ citationCount: z.number().optional(),
118
+ doi: z.string().optional(),
119
+ url: z.string(),
120
+ openAccessPdfUrl: z.string().optional(),
121
+ }).describe('Paper object from search_papers results'),
122
+ style: z.enum(['apa', 'mla', 'chicago']).describe('Citation style'),
123
+ }, async ({ paper, style }) => {
124
+ const citation = formatCitation(paper, style);
125
+ return {
126
+ content: [{ type: 'text', text: citation }],
127
+ };
128
+ });
129
+ // ─── Tool: search_and_summarize ──────────────────────────────────────────────
130
+ server.tool('search_and_summarize', 'All-in-one research assistant: searches all databases, summarizes top papers, maps the literature, and finds research gaps. The fastest way to go deep on a topic.', {
131
+ query: z.string().describe('Research topic or question'),
132
+ depth: z.enum(['quick', 'thorough']).optional().default('quick').describe('"quick" returns top 5 papers with fast analysis; "thorough" returns top 10 with full gap analysis'),
133
+ }, async ({ query, depth }) => {
134
+ const limit = depth === 'thorough' ? 10 : 5;
135
+ // Search all sources
136
+ const papers = await searchPapers(query, ['arxiv', 'semantic_scholar', 'openalex', 'pubmed'], limit);
137
+ if (papers.length === 0) {
138
+ return {
139
+ content: [{
140
+ type: 'text',
141
+ text: JSON.stringify({
142
+ query,
143
+ papers: [],
144
+ message: 'No papers found. Try different keywords or check your internet connection.',
145
+ }, null, 2),
146
+ }],
147
+ };
148
+ }
149
+ // Summarize all papers (in parallel, with a limit)
150
+ const papersWithAbstracts = papers.filter(p => p.abstract.length > 50);
151
+ const summaries = await Promise.all(papersWithAbstracts.slice(0, depth === 'thorough' ? 8 : 5).map(p => summarizePaper(p.id, p.title, p.abstract, query).catch(e => ({
152
+ paperId: p.id,
153
+ title: p.title,
154
+ mainClaim: `Summarization failed: ${e instanceof Error ? e.message : String(e)}`,
155
+ methodology: 'Unknown',
156
+ keyEvidence: [],
157
+ limitations: [],
158
+ relevanceToTopic: 'Could not assess',
159
+ }))));
160
+ // Map literature
161
+ const literatureMap = papers.length >= 2
162
+ ? await mapLiterature(papers, query).catch(() => ({ consensus: [], debates: [], methodologicalTensions: [], temporalTrends: [] }))
163
+ : { consensus: [], debates: [], methodologicalTensions: [], temporalTrends: [] };
164
+ // Find gaps (thorough mode only or if enough papers)
165
+ const gaps = (depth === 'thorough' || papers.length >= 5)
166
+ ? await findGaps(papers, query).catch(() => ({ gaps: [], originalContributionAngles: [] }))
167
+ : { gaps: [], originalContributionAngles: [] };
168
+ return {
169
+ content: [{
170
+ type: 'text',
171
+ text: JSON.stringify({
172
+ query,
173
+ depth,
174
+ paperCount: papers.length,
175
+ papers,
176
+ summaries,
177
+ literatureMap,
178
+ gaps,
179
+ }, null, 2),
180
+ }],
181
+ };
182
+ });
183
+ // ─── Start server ─────────────────────────────────────────────────────────────
184
+ const transport = new StdioServerTransport();
185
+ await server.connect(transport);
186
+ console.error('Research Rabbit MCP server running on stdio');
187
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Paper, SearchSource } from './types.js';
2
+ export declare function searchPapers(query: string, sources?: SearchSource[], limit?: number, yearFrom?: number): Promise<Paper[]>;
3
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAwCtD,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,YAAY,EAAwD,EAC7E,KAAK,GAAE,MAAW,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,KAAK,EAAE,CAAC,CA+BlB"}
package/dist/search.js ADDED
@@ -0,0 +1,61 @@
1
+ import { searchArxiv } from './sources/arxiv.js';
2
+ import { searchSemanticScholar } from './sources/semantic_scholar.js';
3
+ import { searchOpenAlex } from './sources/openalex.js';
4
+ import { searchPubMed } from './sources/pubmed.js';
5
+ function normalizeTitle(title) {
6
+ return title.toLowerCase().replace(/[^a-z0-9]/g, '').substring(0, 50);
7
+ }
8
+ function deduplicatePapers(papers) {
9
+ const seen = new Map();
10
+ for (const paper of papers) {
11
+ const key = normalizeTitle(paper.title);
12
+ if (!seen.has(key)) {
13
+ seen.set(key, paper);
14
+ }
15
+ else {
16
+ // Prefer paper with more data (citation count, abstract)
17
+ const existing = seen.get(key);
18
+ if ((paper.citationCount ?? 0) > (existing.citationCount ?? 0) ||
19
+ (paper.abstract.length > existing.abstract.length)) {
20
+ seen.set(key, { ...paper, id: existing.id }); // keep original id
21
+ }
22
+ }
23
+ }
24
+ return Array.from(seen.values());
25
+ }
26
+ function rankPapers(papers) {
27
+ return papers.sort((a, b) => {
28
+ // Score: citation count (normalized) + recency bonus
29
+ const currentYear = new Date().getFullYear();
30
+ const scoreA = (a.citationCount ?? 0) * 0.001 + Math.max(0, a.year - (currentYear - 10));
31
+ const scoreB = (b.citationCount ?? 0) * 0.001 + Math.max(0, b.year - (currentYear - 10));
32
+ return scoreB - scoreA;
33
+ });
34
+ }
35
+ export async function searchPapers(query, sources = ['arxiv', 'semantic_scholar', 'openalex', 'pubmed'], limit = 10, yearFrom) {
36
+ const perSourceLimit = Math.ceil(limit * 1.5); // fetch extra to account for dedup
37
+ const searchPromises = [];
38
+ if (sources.includes('arxiv')) {
39
+ searchPromises.push(searchArxiv(query, perSourceLimit, yearFrom));
40
+ }
41
+ if (sources.includes('semantic_scholar')) {
42
+ searchPromises.push(searchSemanticScholar(query, perSourceLimit, yearFrom));
43
+ }
44
+ if (sources.includes('openalex')) {
45
+ searchPromises.push(searchOpenAlex(query, perSourceLimit, yearFrom));
46
+ }
47
+ if (sources.includes('pubmed')) {
48
+ searchPromises.push(searchPubMed(query, perSourceLimit, yearFrom));
49
+ }
50
+ const results = await Promise.allSettled(searchPromises);
51
+ const allPapers = [];
52
+ for (const result of results) {
53
+ if (result.status === 'fulfilled') {
54
+ allPapers.push(...result.value);
55
+ }
56
+ }
57
+ const deduplicated = deduplicatePapers(allPapers);
58
+ const ranked = rankPapers(deduplicated);
59
+ return ranked.slice(0, limit);
60
+ }
61
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Paper } from '../types.js';
2
+ export declare function searchArxiv(query: string, limit?: number, yearFrom?: number): Promise<Paper[]>;
3
+ //# sourceMappingURL=arxiv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arxiv.d.ts","sourceRoot":"","sources":["../../src/sources/arxiv.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAyCzC,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAqBxG"}
@@ -0,0 +1,51 @@
1
+ function parseArxivXml(xml) {
2
+ const papers = [];
3
+ // Extract entries using regex (avoid XML parser dependency)
4
+ const entryMatches = xml.matchAll(/<entry>([\s\S]*?)<\/entry>/g);
5
+ for (const match of entryMatches) {
6
+ const entry = match[1];
7
+ const titleMatch = entry.match(/<title>([\s\S]*?)<\/title>/);
8
+ const abstractMatch = entry.match(/<summary>([\s\S]*?)<\/summary>/);
9
+ const publishedMatch = entry.match(/<published>([\s\S]*?)<\/published>/);
10
+ const idMatch = entry.match(/<id>([\s\S]*?)<\/id>/);
11
+ const authorMatches = [...entry.matchAll(/<name>([\s\S]*?)<\/name>/g)];
12
+ if (!titleMatch || !idMatch)
13
+ continue;
14
+ const arxivId = idMatch[1].trim().replace('http://arxiv.org/abs/', '');
15
+ const year = publishedMatch ? parseInt(publishedMatch[1].substring(0, 4)) : 0;
16
+ // Find PDF link
17
+ const pdfLinkMatch = entry.match(/href="(https?:\/\/arxiv\.org\/pdf\/[^"]+)"/);
18
+ papers.push({
19
+ id: `arxiv:${arxivId}`,
20
+ source: 'arxiv',
21
+ title: titleMatch[1].trim().replace(/\s+/g, ' '),
22
+ authors: authorMatches.map(m => m[1].trim()),
23
+ year,
24
+ abstract: abstractMatch ? abstractMatch[1].trim().replace(/\s+/g, ' ') : '',
25
+ url: `https://arxiv.org/abs/${arxivId}`,
26
+ openAccessPdfUrl: pdfLinkMatch ? pdfLinkMatch[1] : `https://arxiv.org/pdf/${arxivId}`,
27
+ });
28
+ }
29
+ return papers;
30
+ }
31
+ export async function searchArxiv(query, limit = 10, yearFrom) {
32
+ const searchQuery = yearFrom
33
+ ? `${query} AND submittedDate:[${yearFrom}0101 TO 99991231]`
34
+ : query;
35
+ const url = `http://export.arxiv.org/api/query?search_query=all:${encodeURIComponent(searchQuery)}&max_results=${limit}&sortBy=relevance`;
36
+ try {
37
+ const response = await fetch(url, {
38
+ headers: { 'User-Agent': 'research-rabbit/0.1.0 (academic research tool)' },
39
+ signal: AbortSignal.timeout(15000),
40
+ });
41
+ if (!response.ok)
42
+ throw new Error(`ArXiv API error: ${response.status}`);
43
+ const xml = await response.text();
44
+ return parseArxivXml(xml);
45
+ }
46
+ catch (error) {
47
+ console.error('ArXiv search failed:', error instanceof Error ? error.message : error);
48
+ return [];
49
+ }
50
+ }
51
+ //# sourceMappingURL=arxiv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arxiv.js","sourceRoot":"","sources":["../../src/sources/arxiv.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Paper } from '../types.js';
2
+ export declare function searchOpenAlex(query: string, limit?: number, yearFrom?: number): Promise<Paper[]>;
3
+ //# sourceMappingURL=openalex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openalex.d.ts","sourceRoot":"","sources":["../../src/sources/openalex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAuBzC,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAmC3G"}
@@ -0,0 +1,47 @@
1
+ function reconstructAbstract(invertedIndex) {
2
+ if (!invertedIndex)
3
+ return '';
4
+ const words = [];
5
+ for (const [word, positions] of Object.entries(invertedIndex)) {
6
+ for (const pos of positions)
7
+ words.push([word, pos]);
8
+ }
9
+ words.sort((a, b) => a[1] - b[1]);
10
+ return words.map(w => w[0]).join(' ');
11
+ }
12
+ export async function searchOpenAlex(query, limit = 10, yearFrom) {
13
+ let url = `https://api.openalex.org/works?search=${encodeURIComponent(query)}&per-page=${limit}&select=id,title,authorships,publication_year,abstract_inverted_index,cited_by_count,doi,best_oa_location`;
14
+ if (yearFrom)
15
+ url += `&filter=publication_year:>${yearFrom - 1}`;
16
+ try {
17
+ const response = await fetch(url, {
18
+ headers: {
19
+ 'User-Agent': 'research-rabbit/0.1.0 (academic research tool; mailto:research@example.com)',
20
+ },
21
+ signal: AbortSignal.timeout(15000),
22
+ });
23
+ if (!response.ok)
24
+ throw new Error(`OpenAlex API error: ${response.status}`);
25
+ const data = await response.json();
26
+ return (data.results || []).map(w => {
27
+ const openAlexId = w.id.replace('https://openalex.org/', '');
28
+ return {
29
+ id: `openalex:${openAlexId}`,
30
+ source: 'openalex',
31
+ title: w.title || '',
32
+ authors: (w.authorships || []).map(a => a.author.display_name),
33
+ year: w.publication_year || 0,
34
+ abstract: reconstructAbstract(w.abstract_inverted_index),
35
+ citationCount: w.cited_by_count,
36
+ doi: w.doi?.replace('https://doi.org/', ''),
37
+ url: w.doi ? `https://doi.org/${w.doi.replace('https://doi.org/', '')}` : `https://openalex.org/${openAlexId}`,
38
+ openAccessPdfUrl: w.best_oa_location?.pdf_url ?? undefined,
39
+ };
40
+ });
41
+ }
42
+ catch (error) {
43
+ console.error('OpenAlex search failed:', error instanceof Error ? error.message : error);
44
+ return [];
45
+ }
46
+ }
47
+ //# sourceMappingURL=openalex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openalex.js","sourceRoot":"","sources":["../../src/sources/openalex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Paper } from '../types.js';
2
+ export declare function searchPubMed(query: string, limit?: number, yearFrom?: number): Promise<Paper[]>;
3
+ //# sourceMappingURL=pubmed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubmed.d.ts","sourceRoot":"","sources":["../../src/sources/pubmed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAiFzG"}
@@ -0,0 +1,68 @@
1
+ export async function searchPubMed(query, limit = 10, yearFrom) {
2
+ const searchTerm = yearFrom ? `${query} AND ${yearFrom}:3000[pdat]` : query;
3
+ // Step 1: Search for IDs
4
+ const searchUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=${encodeURIComponent(searchTerm)}&retmax=${limit}&retmode=json`;
5
+ try {
6
+ const searchResp = await fetch(searchUrl, {
7
+ headers: { 'User-Agent': 'research-rabbit/0.1.0 (academic research tool)' },
8
+ signal: AbortSignal.timeout(15000),
9
+ });
10
+ if (!searchResp.ok)
11
+ throw new Error(`PubMed search error: ${searchResp.status}`);
12
+ const searchData = await searchResp.json();
13
+ const ids = searchData.esearchresult?.idlist || [];
14
+ if (ids.length === 0)
15
+ return [];
16
+ // Step 2: Fetch summaries
17
+ const summaryUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=pubmed&id=${ids.join(',')}&retmode=json`;
18
+ const summaryResp = await fetch(summaryUrl, {
19
+ headers: { 'User-Agent': 'research-rabbit/0.1.0 (academic research tool)' },
20
+ signal: AbortSignal.timeout(15000),
21
+ });
22
+ if (!summaryResp.ok)
23
+ throw new Error(`PubMed summary error: ${summaryResp.status}`);
24
+ const summaryData = await summaryResp.json();
25
+ // Step 3: Fetch abstracts (efetch)
26
+ const fetchUrl = `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=${ids.join(',')}&retmode=xml&rettype=abstract`;
27
+ const fetchResp = await fetch(fetchUrl, {
28
+ headers: { 'User-Agent': 'research-rabbit/0.1.0 (academic research tool)' },
29
+ signal: AbortSignal.timeout(15000),
30
+ });
31
+ const abstractXml = fetchResp.ok ? await fetchResp.text() : '';
32
+ // Parse abstracts from XML
33
+ const abstracts = {};
34
+ const articleMatches = [...abstractXml.matchAll(/<PubmedArticle>([\s\S]*?)<\/PubmedArticle>/g)];
35
+ for (const articleMatch of articleMatches) {
36
+ const articleXml = articleMatch[1];
37
+ const pmidMatch = articleXml.match(/<PMID[^>]*>(\d+)<\/PMID>/);
38
+ const abstractMatch = articleXml.match(/<AbstractText[^>]*>([\s\S]*?)<\/AbstractText>/);
39
+ if (pmidMatch && abstractMatch) {
40
+ abstracts[pmidMatch[1]] = abstractMatch[1].replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
41
+ }
42
+ }
43
+ const papers = [];
44
+ for (const id of ids) {
45
+ const summary = summaryData.result?.[id];
46
+ if (!summary || id === 'uids')
47
+ continue;
48
+ const doi = summary.articleids?.find(a => a.idtype === 'doi')?.value;
49
+ const year = parseInt(summary.pubdate?.split(' ')[0] || '0') || 0;
50
+ papers.push({
51
+ id: `pubmed:${id}`,
52
+ source: 'pubmed',
53
+ title: summary.title || '',
54
+ authors: (summary.authors || []).map(a => a.name),
55
+ year,
56
+ abstract: abstracts[id] || '',
57
+ doi,
58
+ url: `https://pubmed.ncbi.nlm.nih.gov/${id}/`,
59
+ });
60
+ }
61
+ return papers;
62
+ }
63
+ catch (error) {
64
+ console.error('PubMed search failed:', error instanceof Error ? error.message : error);
65
+ return [];
66
+ }
67
+ }
68
+ //# sourceMappingURL=pubmed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubmed.js","sourceRoot":"","sources":["../../src/sources/pubmed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Paper } from '../types.js';
2
+ export declare function searchSemanticScholar(query: string, limit?: number, yearFrom?: number): Promise<Paper[]>;
3
+ //# sourceMappingURL=semantic_scholar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic_scholar.d.ts","sourceRoot":"","sources":["../../src/sources/semantic_scholar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAazC,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAqClH"}