@wentorai/research-plugins 1.0.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/LICENSE +21 -0
- package/README.md +204 -0
- package/curated/analysis/README.md +64 -0
- package/curated/domains/README.md +104 -0
- package/curated/literature/README.md +53 -0
- package/curated/research/README.md +62 -0
- package/curated/tools/README.md +87 -0
- package/curated/writing/README.md +61 -0
- package/index.ts +39 -0
- package/mcp-configs/academic-db/ChatSpatial.json +17 -0
- package/mcp-configs/academic-db/academia-mcp.json +17 -0
- package/mcp-configs/academic-db/academic-paper-explorer.json +17 -0
- package/mcp-configs/academic-db/academic-search-mcp-server.json +17 -0
- package/mcp-configs/academic-db/agentinterviews-mcp.json +17 -0
- package/mcp-configs/academic-db/all-in-mcp.json +17 -0
- package/mcp-configs/academic-db/apple-health-mcp.json +17 -0
- package/mcp-configs/academic-db/arxiv-latex-mcp.json +17 -0
- package/mcp-configs/academic-db/arxiv-mcp-server.json +17 -0
- package/mcp-configs/academic-db/bgpt-mcp.json +17 -0
- package/mcp-configs/academic-db/biomcp.json +17 -0
- package/mcp-configs/academic-db/biothings-mcp.json +17 -0
- package/mcp-configs/academic-db/catalysishub-mcp-server.json +17 -0
- package/mcp-configs/academic-db/clinicaltrialsgov-mcp-server.json +17 -0
- package/mcp-configs/academic-db/deep-research-mcp.json +17 -0
- package/mcp-configs/academic-db/dicom-mcp.json +17 -0
- package/mcp-configs/academic-db/enrichr-mcp-server.json +17 -0
- package/mcp-configs/academic-db/fec-mcp-server.json +17 -0
- package/mcp-configs/academic-db/fhir-mcp-server-themomentum.json +17 -0
- package/mcp-configs/academic-db/fhir-mcp.json +19 -0
- package/mcp-configs/academic-db/gget-mcp.json +17 -0
- package/mcp-configs/academic-db/google-researcher-mcp.json +17 -0
- package/mcp-configs/academic-db/idea-reality-mcp.json +17 -0
- package/mcp-configs/academic-db/legiscan-mcp.json +19 -0
- package/mcp-configs/academic-db/lex.json +17 -0
- package/mcp-configs/ai-platform/Adaptive-Graph-of-Thoughts-MCP-server.json +17 -0
- package/mcp-configs/ai-platform/ai-counsel.json +17 -0
- package/mcp-configs/ai-platform/atlas-mcp-server.json +17 -0
- package/mcp-configs/ai-platform/counsel-mcp.json +17 -0
- package/mcp-configs/ai-platform/cross-llm-mcp.json +17 -0
- package/mcp-configs/ai-platform/gptr-mcp.json +17 -0
- package/mcp-configs/browser/decipher-research-agent.json +17 -0
- package/mcp-configs/browser/deep-research.json +17 -0
- package/mcp-configs/browser/everything-claude-code.json +17 -0
- package/mcp-configs/browser/gpt-researcher.json +17 -0
- package/mcp-configs/browser/heurist-agent-framework.json +17 -0
- package/mcp-configs/data-platform/4everland-hosting-mcp.json +17 -0
- package/mcp-configs/data-platform/context-keeper.json +17 -0
- package/mcp-configs/data-platform/context7.json +19 -0
- package/mcp-configs/data-platform/contextstream-mcp.json +17 -0
- package/mcp-configs/data-platform/email-mcp.json +17 -0
- package/mcp-configs/note-knowledge/ApeRAG.json +17 -0
- package/mcp-configs/note-knowledge/In-Memoria.json +17 -0
- package/mcp-configs/note-knowledge/agent-memory.json +17 -0
- package/mcp-configs/note-knowledge/aimemo.json +17 -0
- package/mcp-configs/note-knowledge/biel-mcp.json +19 -0
- package/mcp-configs/note-knowledge/cognee.json +17 -0
- package/mcp-configs/note-knowledge/context-awesome.json +17 -0
- package/mcp-configs/note-knowledge/context-mcp.json +17 -0
- package/mcp-configs/note-knowledge/conversation-handoff-mcp.json +17 -0
- package/mcp-configs/note-knowledge/cortex.json +17 -0
- package/mcp-configs/note-knowledge/devrag.json +17 -0
- package/mcp-configs/note-knowledge/easy-obsidian-mcp.json +17 -0
- package/mcp-configs/note-knowledge/engram.json +17 -0
- package/mcp-configs/note-knowledge/gnosis-mcp.json +17 -0
- package/mcp-configs/note-knowledge/graphlit-mcp-server.json +19 -0
- package/mcp-configs/reference-mgr/arxiv-cli.json +17 -0
- package/mcp-configs/reference-mgr/arxiv-search-mcp.json +17 -0
- package/mcp-configs/reference-mgr/chiken.json +17 -0
- package/mcp-configs/reference-mgr/claude-scholar.json +17 -0
- package/mcp-configs/reference-mgr/devonthink-mcp.json +17 -0
- package/mcp-configs/registry.json +447 -0
- package/openclaw.plugin.json +21 -0
- package/package.json +61 -0
- package/skills/analysis/dataviz/color-accessibility-guide/SKILL.md +230 -0
- package/skills/analysis/dataviz/geospatial-viz-guide/SKILL.md +218 -0
- package/skills/analysis/dataviz/interactive-viz-guide/SKILL.md +287 -0
- package/skills/analysis/dataviz/network-visualization-guide/SKILL.md +195 -0
- package/skills/analysis/dataviz/publication-figures-guide/SKILL.md +238 -0
- package/skills/analysis/dataviz/python-dataviz-guide/SKILL.md +195 -0
- package/skills/analysis/econometrics/causal-inference-guide/SKILL.md +197 -0
- package/skills/analysis/econometrics/iv-regression-guide/SKILL.md +198 -0
- package/skills/analysis/econometrics/panel-data-guide/SKILL.md +274 -0
- package/skills/analysis/econometrics/robustness-checks/SKILL.md +250 -0
- package/skills/analysis/econometrics/stata-regression/SKILL.md +117 -0
- package/skills/analysis/econometrics/time-series-guide/SKILL.md +235 -0
- package/skills/analysis/statistics/bayesian-statistics-guide/SKILL.md +221 -0
- package/skills/analysis/statistics/hypothesis-testing-guide/SKILL.md +210 -0
- package/skills/analysis/statistics/meta-analysis-guide/SKILL.md +206 -0
- package/skills/analysis/statistics/nonparametric-tests-guide/SKILL.md +221 -0
- package/skills/analysis/statistics/power-analysis-guide/SKILL.md +240 -0
- package/skills/analysis/statistics/sem-guide/SKILL.md +231 -0
- package/skills/analysis/statistics/survival-analysis-guide/SKILL.md +195 -0
- package/skills/analysis/wrangling/missing-data-handling/SKILL.md +224 -0
- package/skills/analysis/wrangling/pandas-data-wrangling/SKILL.md +242 -0
- package/skills/analysis/wrangling/questionnaire-design-guide/SKILL.md +234 -0
- package/skills/analysis/wrangling/text-mining-guide/SKILL.md +225 -0
- package/skills/domains/ai-ml/computer-vision-guide/SKILL.md +213 -0
- package/skills/domains/ai-ml/deep-learning-papers-guide/SKILL.md +200 -0
- package/skills/domains/ai-ml/llm-evaluation-guide/SKILL.md +194 -0
- package/skills/domains/ai-ml/prompt-engineering-research/SKILL.md +233 -0
- package/skills/domains/ai-ml/reinforcement-learning-guide/SKILL.md +254 -0
- package/skills/domains/ai-ml/transformer-architecture-guide/SKILL.md +233 -0
- package/skills/domains/biomedical/clinical-research-guide/SKILL.md +232 -0
- package/skills/domains/biomedical/clinicaltrials-api/SKILL.md +177 -0
- package/skills/domains/biomedical/epidemiology-guide/SKILL.md +200 -0
- package/skills/domains/biomedical/genomics-analysis-guide/SKILL.md +270 -0
- package/skills/domains/business/market-analysis-guide/SKILL.md +112 -0
- package/skills/domains/business/strategic-management-guide/SKILL.md +154 -0
- package/skills/domains/chemistry/computational-chemistry-guide/SKILL.md +266 -0
- package/skills/domains/chemistry/retrosynthesis-guide/SKILL.md +215 -0
- package/skills/domains/cs/algorithms-complexity-guide/SKILL.md +194 -0
- package/skills/domains/cs/dblp-api/SKILL.md +129 -0
- package/skills/domains/cs/software-engineering-research/SKILL.md +218 -0
- package/skills/domains/ecology/biodiversity-data-guide/SKILL.md +296 -0
- package/skills/domains/ecology/conservation-biology-guide/SKILL.md +198 -0
- package/skills/domains/ecology/gbif-api/SKILL.md +158 -0
- package/skills/domains/ecology/inaturalist-api/SKILL.md +173 -0
- package/skills/domains/economics/behavioral-economics-guide/SKILL.md +239 -0
- package/skills/domains/economics/development-economics-guide/SKILL.md +181 -0
- package/skills/domains/economics/fred-api/SKILL.md +189 -0
- package/skills/domains/education/curriculum-design-guide/SKILL.md +144 -0
- package/skills/domains/education/learning-science-guide/SKILL.md +150 -0
- package/skills/domains/finance/financial-data-analysis/SKILL.md +152 -0
- package/skills/domains/finance/quantitative-finance-guide/SKILL.md +151 -0
- package/skills/domains/geoscience/climate-science-guide/SKILL.md +158 -0
- package/skills/domains/geoscience/gis-remote-sensing-guide/SKILL.md +129 -0
- package/skills/domains/humanities/digital-humanities-guide/SKILL.md +181 -0
- package/skills/domains/humanities/philosophy-research-guide/SKILL.md +148 -0
- package/skills/domains/law/courtlistener-api/SKILL.md +213 -0
- package/skills/domains/law/legal-research-guide/SKILL.md +250 -0
- package/skills/domains/math/linear-algebra-applications/SKILL.md +227 -0
- package/skills/domains/math/numerical-methods-guide/SKILL.md +236 -0
- package/skills/domains/math/oeis-api/SKILL.md +158 -0
- package/skills/domains/pharma/clinical-pharmacology-guide/SKILL.md +165 -0
- package/skills/domains/pharma/drug-development-guide/SKILL.md +177 -0
- package/skills/domains/physics/computational-physics-guide/SKILL.md +300 -0
- package/skills/domains/physics/nasa-ads-api/SKILL.md +150 -0
- package/skills/domains/physics/quantum-computing-guide/SKILL.md +234 -0
- package/skills/domains/social-science/social-research-methods/SKILL.md +194 -0
- package/skills/domains/social-science/survey-research-guide/SKILL.md +182 -0
- package/skills/literature/discovery/citation-alert-guide/SKILL.md +154 -0
- package/skills/literature/discovery/conference-proceedings-guide/SKILL.md +142 -0
- package/skills/literature/discovery/literature-mapping-guide/SKILL.md +175 -0
- package/skills/literature/discovery/paper-tracking-guide/SKILL.md +211 -0
- package/skills/literature/discovery/rss-paper-feeds/SKILL.md +214 -0
- package/skills/literature/discovery/semantic-scholar-recs-guide/SKILL.md +164 -0
- package/skills/literature/fulltext/doaj-api/SKILL.md +120 -0
- package/skills/literature/fulltext/interlibrary-loan-guide/SKILL.md +163 -0
- package/skills/literature/fulltext/open-access-guide/SKILL.md +183 -0
- package/skills/literature/fulltext/pmc-oai-api/SKILL.md +184 -0
- package/skills/literature/fulltext/preprint-servers-guide/SKILL.md +128 -0
- package/skills/literature/fulltext/repository-harvesting-guide/SKILL.md +207 -0
- package/skills/literature/fulltext/unpaywall-api/SKILL.md +113 -0
- package/skills/literature/metadata/altmetrics-guide/SKILL.md +132 -0
- package/skills/literature/metadata/citation-network-guide/SKILL.md +236 -0
- package/skills/literature/metadata/crossref-api/SKILL.md +133 -0
- package/skills/literature/metadata/datacite-api/SKILL.md +126 -0
- package/skills/literature/metadata/doi-resolution-guide/SKILL.md +168 -0
- package/skills/literature/metadata/h-index-guide/SKILL.md +183 -0
- package/skills/literature/metadata/journal-metrics-guide/SKILL.md +188 -0
- package/skills/literature/metadata/opencitations-api/SKILL.md +128 -0
- package/skills/literature/metadata/orcid-api/SKILL.md +136 -0
- package/skills/literature/metadata/orcid-integration-guide/SKILL.md +178 -0
- package/skills/literature/search/arxiv-api/SKILL.md +95 -0
- package/skills/literature/search/biorxiv-api/SKILL.md +123 -0
- package/skills/literature/search/boolean-search-guide/SKILL.md +199 -0
- package/skills/literature/search/citation-chaining-guide/SKILL.md +148 -0
- package/skills/literature/search/database-comparison-guide/SKILL.md +100 -0
- package/skills/literature/search/europe-pmc-api/SKILL.md +120 -0
- package/skills/literature/search/google-scholar-guide/SKILL.md +182 -0
- package/skills/literature/search/mesh-terms-guide/SKILL.md +164 -0
- package/skills/literature/search/openalex-api/SKILL.md +134 -0
- package/skills/literature/search/pubmed-api/SKILL.md +130 -0
- package/skills/literature/search/scientify-literature-survey/SKILL.md +203 -0
- package/skills/literature/search/semantic-scholar-api/SKILL.md +134 -0
- package/skills/literature/search/systematic-search-strategy/SKILL.md +214 -0
- package/skills/research/automation/ai-scientist-guide/SKILL.md +228 -0
- package/skills/research/automation/data-collection-automation/SKILL.md +248 -0
- package/skills/research/automation/research-workflow-automation/SKILL.md +266 -0
- package/skills/research/deep-research/meta-synthesis-guide/SKILL.md +174 -0
- package/skills/research/deep-research/research-cog/SKILL.md +153 -0
- package/skills/research/deep-research/scoping-review-guide/SKILL.md +217 -0
- package/skills/research/deep-research/systematic-review-guide/SKILL.md +250 -0
- package/skills/research/funding/figshare-api/SKILL.md +163 -0
- package/skills/research/funding/grant-writing-guide/SKILL.md +233 -0
- package/skills/research/funding/nsf-grant-guide/SKILL.md +206 -0
- package/skills/research/funding/open-science-guide/SKILL.md +255 -0
- package/skills/research/funding/zenodo-api/SKILL.md +174 -0
- package/skills/research/methodology/action-research-guide/SKILL.md +201 -0
- package/skills/research/methodology/experimental-design-guide/SKILL.md +236 -0
- package/skills/research/methodology/grad-school-guide/SKILL.md +182 -0
- package/skills/research/methodology/grounded-theory-guide/SKILL.md +171 -0
- package/skills/research/methodology/mixed-methods-guide/SKILL.md +208 -0
- package/skills/research/methodology/qualitative-research-guide/SKILL.md +234 -0
- package/skills/research/methodology/scientify-idea-generation/SKILL.md +222 -0
- package/skills/research/paper-review/paper-reading-assistant/SKILL.md +266 -0
- package/skills/research/paper-review/peer-review-guide/SKILL.md +227 -0
- package/skills/research/paper-review/rebuttal-writing-guide/SKILL.md +185 -0
- package/skills/research/paper-review/scientify-write-review-paper/SKILL.md +209 -0
- package/skills/tools/code-exec/jupyter-notebook-guide/SKILL.md +178 -0
- package/skills/tools/code-exec/python-reproducibility-guide/SKILL.md +341 -0
- package/skills/tools/code-exec/r-reproducibility-guide/SKILL.md +236 -0
- package/skills/tools/code-exec/sandbox-execution-guide/SKILL.md +221 -0
- package/skills/tools/diagram/mermaid-diagram-guide/SKILL.md +269 -0
- package/skills/tools/diagram/plantuml-guide/SKILL.md +397 -0
- package/skills/tools/diagram/scientific-illustration-guide/SKILL.md +225 -0
- package/skills/tools/document/anystyle-api/SKILL.md +199 -0
- package/skills/tools/document/grobid-pdf-parsing/SKILL.md +294 -0
- package/skills/tools/document/markdown-academic-guide/SKILL.md +217 -0
- package/skills/tools/document/pdf-extraction-guide/SKILL.md +321 -0
- package/skills/tools/knowledge-graph/knowledge-graph-construction/SKILL.md +306 -0
- package/skills/tools/knowledge-graph/ontology-design-guide/SKILL.md +214 -0
- package/skills/tools/knowledge-graph/rag-methodology-guide/SKILL.md +325 -0
- package/skills/tools/ocr-translate/formula-recognition-guide/SKILL.md +367 -0
- package/skills/tools/ocr-translate/handwriting-recognition-guide/SKILL.md +211 -0
- package/skills/tools/ocr-translate/latex-ocr-guide/SKILL.md +204 -0
- package/skills/tools/ocr-translate/multilingual-research-guide/SKILL.md +234 -0
- package/skills/tools/scraping/academic-web-scraping/SKILL.md +326 -0
- package/skills/tools/scraping/api-data-collection-guide/SKILL.md +301 -0
- package/skills/tools/scraping/web-scraping-ethics-guide/SKILL.md +250 -0
- package/skills/writing/citation/bibtex-management-guide/SKILL.md +246 -0
- package/skills/writing/citation/citation-style-guide/SKILL.md +248 -0
- package/skills/writing/citation/reference-manager-comparison/SKILL.md +208 -0
- package/skills/writing/citation/zotero-api/SKILL.md +188 -0
- package/skills/writing/composition/abstract-writing-guide/SKILL.md +188 -0
- package/skills/writing/composition/discussion-writing-guide/SKILL.md +194 -0
- package/skills/writing/composition/introduction-writing-guide/SKILL.md +194 -0
- package/skills/writing/composition/literature-review-writing/SKILL.md +196 -0
- package/skills/writing/composition/methods-section-guide/SKILL.md +185 -0
- package/skills/writing/composition/response-to-reviewers/SKILL.md +215 -0
- package/skills/writing/composition/scientific-writing-guide/SKILL.md +152 -0
- package/skills/writing/latex/bibliography-management-guide/SKILL.md +206 -0
- package/skills/writing/latex/latex-drawing-guide/SKILL.md +234 -0
- package/skills/writing/latex/latex-ecosystem-guide/SKILL.md +240 -0
- package/skills/writing/latex/math-typesetting-guide/SKILL.md +231 -0
- package/skills/writing/latex/overleaf-collaboration-guide/SKILL.md +211 -0
- package/skills/writing/latex/tikz-diagrams-guide/SKILL.md +211 -0
- package/skills/writing/polish/academic-translation-guide/SKILL.md +175 -0
- package/skills/writing/polish/academic-writing-refiner/SKILL.md +143 -0
- package/skills/writing/polish/ai-writing-humanizer/SKILL.md +178 -0
- package/skills/writing/polish/grammar-checker-guide/SKILL.md +184 -0
- package/skills/writing/polish/plagiarism-detection-guide/SKILL.md +167 -0
- package/skills/writing/templates/beamer-presentation-guide/SKILL.md +263 -0
- package/skills/writing/templates/conference-paper-template/SKILL.md +219 -0
- package/skills/writing/templates/thesis-template-guide/SKILL.md +200 -0
- package/skills/writing/templates/thesis-writing-guide/SKILL.md +220 -0
- package/src/tools/arxiv.ts +131 -0
- package/src/tools/crossref.ts +112 -0
- package/src/tools/openalex.ts +174 -0
- package/src/tools/pubmed.ts +166 -0
- package/src/tools/semantic-scholar.ts +108 -0
- package/src/tools/unpaywall.ts +58 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
3
|
+
|
|
4
|
+
const EUTILS = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils";
|
|
5
|
+
|
|
6
|
+
export function createPubMedTools(
|
|
7
|
+
_ctx: OpenClawPluginToolContext,
|
|
8
|
+
_api: OpenClawPluginApi,
|
|
9
|
+
) {
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
name: "search_pubmed",
|
|
13
|
+
description:
|
|
14
|
+
"Search PubMed biomedical literature database. Covers 36M+ citations from MEDLINE, life science journals, and online books.",
|
|
15
|
+
inputSchema: Type.Object({
|
|
16
|
+
query: Type.String({
|
|
17
|
+
description:
|
|
18
|
+
"PubMed search query. Supports MeSH terms and field tags, e.g. 'CRISPR[Title] AND 2024[PDAT]'",
|
|
19
|
+
}),
|
|
20
|
+
max_results: Type.Optional(
|
|
21
|
+
Type.Number({ description: "Max results (default 10, max 100)" }),
|
|
22
|
+
),
|
|
23
|
+
sort: Type.Optional(
|
|
24
|
+
Type.String({
|
|
25
|
+
description: "Sort by: 'relevance' or 'pub_date'",
|
|
26
|
+
}),
|
|
27
|
+
),
|
|
28
|
+
min_date: Type.Optional(
|
|
29
|
+
Type.String({ description: "Min publication date (YYYY/MM/DD)" }),
|
|
30
|
+
),
|
|
31
|
+
max_date: Type.Optional(
|
|
32
|
+
Type.String({ description: "Max publication date (YYYY/MM/DD)" }),
|
|
33
|
+
),
|
|
34
|
+
}),
|
|
35
|
+
handler: async (input: {
|
|
36
|
+
query: string;
|
|
37
|
+
max_results?: number;
|
|
38
|
+
sort?: string;
|
|
39
|
+
min_date?: string;
|
|
40
|
+
max_date?: string;
|
|
41
|
+
}) => {
|
|
42
|
+
const searchParams = new URLSearchParams({
|
|
43
|
+
db: "pubmed",
|
|
44
|
+
term: input.query,
|
|
45
|
+
retmax: String(Math.min(input.max_results ?? 10, 100)),
|
|
46
|
+
retmode: "json",
|
|
47
|
+
sort: input.sort ?? "relevance",
|
|
48
|
+
usehistory: "y",
|
|
49
|
+
});
|
|
50
|
+
if (input.min_date) searchParams.set("mindate", input.min_date);
|
|
51
|
+
if (input.max_date) searchParams.set("maxdate", input.max_date);
|
|
52
|
+
if (input.min_date || input.max_date) searchParams.set("datetype", "pdat");
|
|
53
|
+
|
|
54
|
+
const searchRes = await fetch(`${EUTILS}/esearch.fcgi?${searchParams}`);
|
|
55
|
+
if (!searchRes.ok)
|
|
56
|
+
return { error: `Search error: ${searchRes.status} ${searchRes.statusText}` };
|
|
57
|
+
const searchData = await searchRes.json();
|
|
58
|
+
const ids: string[] = searchData.esearchresult?.idlist ?? [];
|
|
59
|
+
|
|
60
|
+
if (ids.length === 0) return { total_count: searchData.esearchresult?.count ?? 0, articles: [] };
|
|
61
|
+
|
|
62
|
+
const summaryParams = new URLSearchParams({
|
|
63
|
+
db: "pubmed",
|
|
64
|
+
id: ids.join(","),
|
|
65
|
+
retmode: "json",
|
|
66
|
+
});
|
|
67
|
+
const summaryRes = await fetch(`${EUTILS}/esummary.fcgi?${summaryParams}`);
|
|
68
|
+
if (!summaryRes.ok)
|
|
69
|
+
return { error: `Summary error: ${summaryRes.status} ${summaryRes.statusText}` };
|
|
70
|
+
const summaryData = await summaryRes.json();
|
|
71
|
+
|
|
72
|
+
const articles = ids.map((id) => {
|
|
73
|
+
const doc = summaryData.result?.[id];
|
|
74
|
+
if (!doc) return { pmid: id };
|
|
75
|
+
return {
|
|
76
|
+
pmid: id,
|
|
77
|
+
title: doc.title,
|
|
78
|
+
authors: doc.authors
|
|
79
|
+
?.slice(0, 5)
|
|
80
|
+
.map((a: Record<string, string>) => a.name),
|
|
81
|
+
source: doc.source,
|
|
82
|
+
pub_date: doc.pubdate,
|
|
83
|
+
doi: doc.elocationid?.replace("doi: ", ""),
|
|
84
|
+
pmc: doc.articleids?.find(
|
|
85
|
+
(a: Record<string, string>) => a.idtype === "pmc",
|
|
86
|
+
)?.value,
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
total_count: parseInt(searchData.esearchresult?.count ?? "0", 10),
|
|
92
|
+
articles,
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "get_article",
|
|
98
|
+
description:
|
|
99
|
+
"Get detailed article metadata from PubMed by PMID, including abstract.",
|
|
100
|
+
inputSchema: Type.Object({
|
|
101
|
+
pmid: Type.String({ description: "PubMed ID (numeric string)" }),
|
|
102
|
+
}),
|
|
103
|
+
handler: async (input: { pmid: string }) => {
|
|
104
|
+
const params = new URLSearchParams({
|
|
105
|
+
db: "pubmed",
|
|
106
|
+
id: input.pmid,
|
|
107
|
+
retmode: "xml",
|
|
108
|
+
});
|
|
109
|
+
const res = await fetch(`${EUTILS}/efetch.fcgi?${params}`);
|
|
110
|
+
if (!res.ok) return { error: `API error: ${res.status} ${res.statusText}` };
|
|
111
|
+
const xml = await res.text();
|
|
112
|
+
|
|
113
|
+
const getText = (tag: string) => {
|
|
114
|
+
const m = xml.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
115
|
+
return m ? m[1].trim() : "";
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const getAbstract = () => {
|
|
119
|
+
const m = xml.match(/<AbstractText[^>]*>([\s\S]*?)<\/AbstractText>/g);
|
|
120
|
+
if (!m) return "";
|
|
121
|
+
return m
|
|
122
|
+
.map((s) => s.replace(/<\/?AbstractText[^>]*>/g, "").trim())
|
|
123
|
+
.join(" ");
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const getAuthors = () => {
|
|
127
|
+
const authors: string[] = [];
|
|
128
|
+
const re = /<Author[^>]*>[\s\S]*?<LastName>([\s\S]*?)<\/LastName>[\s\S]*?<ForeName>([\s\S]*?)<\/ForeName>[\s\S]*?<\/Author>/g;
|
|
129
|
+
let m;
|
|
130
|
+
while ((m = re.exec(xml)) !== null) {
|
|
131
|
+
authors.push(`${m[2].trim()} ${m[1].trim()}`);
|
|
132
|
+
}
|
|
133
|
+
return authors;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const getMesh = () => {
|
|
137
|
+
const terms: string[] = [];
|
|
138
|
+
const re = /<DescriptorName[^>]*>([\s\S]*?)<\/DescriptorName>/g;
|
|
139
|
+
let m;
|
|
140
|
+
while ((m = re.exec(xml)) !== null) terms.push(m[1].trim());
|
|
141
|
+
return terms;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const doi =
|
|
145
|
+
xml.match(/<ArticleId IdType="doi">([\s\S]*?)<\/ArticleId>/)?.[1]?.trim() ??
|
|
146
|
+
"";
|
|
147
|
+
const pmc =
|
|
148
|
+
xml.match(/<ArticleId IdType="pmc">([\s\S]*?)<\/ArticleId>/)?.[1]?.trim() ??
|
|
149
|
+
"";
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
pmid: input.pmid,
|
|
153
|
+
title: getText("ArticleTitle"),
|
|
154
|
+
abstract: getAbstract(),
|
|
155
|
+
authors: getAuthors(),
|
|
156
|
+
journal: getText("Title"),
|
|
157
|
+
pub_date: `${getText("Year")}-${getText("Month")}`,
|
|
158
|
+
doi,
|
|
159
|
+
pmc,
|
|
160
|
+
mesh_terms: getMesh(),
|
|
161
|
+
url: `https://pubmed.ncbi.nlm.nih.gov/${input.pmid}/`,
|
|
162
|
+
};
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
3
|
+
|
|
4
|
+
const BASE = "https://api.semanticscholar.org/graph/v1";
|
|
5
|
+
|
|
6
|
+
export function createSemanticScholarTools(
|
|
7
|
+
ctx: OpenClawPluginToolContext,
|
|
8
|
+
api: OpenClawPluginApi,
|
|
9
|
+
) {
|
|
10
|
+
const apiKey =
|
|
11
|
+
ctx.config?.get?.("plugins.entries.research-plugins.semanticScholarApiKey") ?? "";
|
|
12
|
+
|
|
13
|
+
const headers: Record<string, string> = apiKey ? { "x-api-key": apiKey } : {};
|
|
14
|
+
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
name: "search_papers",
|
|
18
|
+
description:
|
|
19
|
+
"Search academic papers on Semantic Scholar. Returns titles, abstracts, authors, citation counts.",
|
|
20
|
+
inputSchema: Type.Object({
|
|
21
|
+
query: Type.String({ description: "Search query keywords" }),
|
|
22
|
+
limit: Type.Optional(
|
|
23
|
+
Type.Number({ description: "Max results to return (default 10, max 100)" }),
|
|
24
|
+
),
|
|
25
|
+
year: Type.Optional(
|
|
26
|
+
Type.String({ description: "Year filter, e.g. '2024' or '2020-2024'" }),
|
|
27
|
+
),
|
|
28
|
+
fields_of_study: Type.Optional(
|
|
29
|
+
Type.String({
|
|
30
|
+
description:
|
|
31
|
+
"Comma-separated fields, e.g. 'Computer Science,Mathematics'",
|
|
32
|
+
}),
|
|
33
|
+
),
|
|
34
|
+
open_access_only: Type.Optional(
|
|
35
|
+
Type.Boolean({ description: "Only return open access papers" }),
|
|
36
|
+
),
|
|
37
|
+
}),
|
|
38
|
+
handler: async (input: {
|
|
39
|
+
query: string;
|
|
40
|
+
limit?: number;
|
|
41
|
+
year?: string;
|
|
42
|
+
fields_of_study?: string;
|
|
43
|
+
open_access_only?: boolean;
|
|
44
|
+
}) => {
|
|
45
|
+
const params = new URLSearchParams({
|
|
46
|
+
query: input.query,
|
|
47
|
+
limit: String(Math.min(input.limit ?? 10, 100)),
|
|
48
|
+
fields:
|
|
49
|
+
"title,abstract,authors,year,citationCount,referenceCount,url,isOpenAccess,openAccessPdf",
|
|
50
|
+
});
|
|
51
|
+
if (input.year) params.set("year", input.year);
|
|
52
|
+
if (input.fields_of_study)
|
|
53
|
+
params.set("fieldsOfStudy", input.fields_of_study);
|
|
54
|
+
if (input.open_access_only) params.set("openAccessPdf", "");
|
|
55
|
+
|
|
56
|
+
const res = await fetch(`${BASE}/paper/search?${params}`, { headers });
|
|
57
|
+
if (!res.ok) return { error: `API error: ${res.status} ${res.statusText}` };
|
|
58
|
+
return res.json();
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "get_paper",
|
|
63
|
+
description:
|
|
64
|
+
"Get detailed information about a specific paper by its Semantic Scholar ID, DOI, or ArXiv ID.",
|
|
65
|
+
inputSchema: Type.Object({
|
|
66
|
+
paper_id: Type.String({
|
|
67
|
+
description:
|
|
68
|
+
"Paper identifier: Semantic Scholar ID, DOI (e.g. '10.1234/...'), or ArXiv ID (e.g. 'arXiv:2301.00001')",
|
|
69
|
+
}),
|
|
70
|
+
}),
|
|
71
|
+
handler: async (input: { paper_id: string }) => {
|
|
72
|
+
const fields =
|
|
73
|
+
"title,abstract,authors,year,citationCount,referenceCount,tldr,url,venue,isOpenAccess,openAccessPdf,fieldsOfStudy,publicationDate";
|
|
74
|
+
const res = await fetch(
|
|
75
|
+
`${BASE}/paper/${encodeURIComponent(input.paper_id)}?fields=${fields}`,
|
|
76
|
+
{ headers },
|
|
77
|
+
);
|
|
78
|
+
if (!res.ok) return { error: `API error: ${res.status} ${res.statusText}` };
|
|
79
|
+
return res.json();
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "get_citations",
|
|
84
|
+
description:
|
|
85
|
+
"Get papers that cite a given paper. Useful for forward citation tracking.",
|
|
86
|
+
inputSchema: Type.Object({
|
|
87
|
+
paper_id: Type.String({ description: "Paper identifier (S2 ID, DOI, or ArXiv ID)" }),
|
|
88
|
+
limit: Type.Optional(
|
|
89
|
+
Type.Number({ description: "Max citations to return (default 20, max 100)" }),
|
|
90
|
+
),
|
|
91
|
+
offset: Type.Optional(
|
|
92
|
+
Type.Number({ description: "Pagination offset" }),
|
|
93
|
+
),
|
|
94
|
+
}),
|
|
95
|
+
handler: async (input: { paper_id: string; limit?: number; offset?: number }) => {
|
|
96
|
+
const fields = "title,authors,year,citationCount,url,abstract";
|
|
97
|
+
const limit = Math.min(input.limit ?? 20, 100);
|
|
98
|
+
const offset = input.offset ?? 0;
|
|
99
|
+
const res = await fetch(
|
|
100
|
+
`${BASE}/paper/${encodeURIComponent(input.paper_id)}/citations?fields=${fields}&limit=${limit}&offset=${offset}`,
|
|
101
|
+
{ headers },
|
|
102
|
+
);
|
|
103
|
+
if (!res.ok) return { error: `API error: ${res.status} ${res.statusText}` };
|
|
104
|
+
return res.json();
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
3
|
+
|
|
4
|
+
const BASE = "https://api.unpaywall.org/v2";
|
|
5
|
+
|
|
6
|
+
export function createUnpaywallTools(
|
|
7
|
+
_ctx: OpenClawPluginToolContext,
|
|
8
|
+
_api: OpenClawPluginApi,
|
|
9
|
+
) {
|
|
10
|
+
const email = "research-plugins@wentor.ai";
|
|
11
|
+
|
|
12
|
+
return [
|
|
13
|
+
{
|
|
14
|
+
name: "find_oa_version",
|
|
15
|
+
description:
|
|
16
|
+
"Find open access versions of a paper by DOI using Unpaywall. Returns free PDF links from repositories, preprint servers, and publisher OA pages.",
|
|
17
|
+
inputSchema: Type.Object({
|
|
18
|
+
doi: Type.String({
|
|
19
|
+
description: "DOI of the paper, e.g. '10.1038/nature12373'",
|
|
20
|
+
}),
|
|
21
|
+
}),
|
|
22
|
+
handler: async (input: { doi: string }) => {
|
|
23
|
+
const doi = input.doi.replace(/^https?:\/\/doi\.org\//, "");
|
|
24
|
+
const res = await fetch(
|
|
25
|
+
`${BASE}/${encodeURIComponent(doi)}?email=${email}`,
|
|
26
|
+
);
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
if (res.status === 404) return { error: "DOI not found in Unpaywall" };
|
|
29
|
+
return { error: `API error: ${res.status} ${res.statusText}` };
|
|
30
|
+
}
|
|
31
|
+
const data = await res.json();
|
|
32
|
+
|
|
33
|
+
const oaLocations = (
|
|
34
|
+
data.oa_locations as Record<string, unknown>[] | undefined
|
|
35
|
+
)?.map((loc) => ({
|
|
36
|
+
url: loc.url,
|
|
37
|
+
url_for_pdf: loc.url_for_pdf,
|
|
38
|
+
host_type: loc.host_type,
|
|
39
|
+
license: loc.license,
|
|
40
|
+
version: loc.version,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
doi: data.doi,
|
|
45
|
+
title: data.title,
|
|
46
|
+
is_oa: data.is_oa,
|
|
47
|
+
oa_status: data.oa_status,
|
|
48
|
+
best_oa_url: data.best_oa_location?.url,
|
|
49
|
+
best_oa_pdf: data.best_oa_location?.url_for_pdf,
|
|
50
|
+
journal: data.journal_name,
|
|
51
|
+
publisher: data.publisher,
|
|
52
|
+
published_date: data.published_date,
|
|
53
|
+
oa_locations: oaLocations,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
}
|