@wentorai/research-plugins 1.4.0 → 1.4.3
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/README.en.md +143 -0
- package/README.md +98 -131
- package/curated/literature/README.md +2 -2
- package/curated/writing/README.md +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/literature/discovery/SKILL.md +1 -1
- package/skills/literature/discovery/citation-alert-guide/SKILL.md +2 -2
- package/skills/literature/discovery/conference-proceedings-guide/SKILL.md +2 -2
- package/skills/literature/discovery/literature-mapping-guide/SKILL.md +1 -1
- package/skills/literature/discovery/paper-recommendation-guide/SKILL.md +8 -14
- package/skills/literature/discovery/rss-paper-feeds/SKILL.md +20 -14
- package/skills/literature/discovery/semantic-paper-radar/SKILL.md +8 -8
- package/skills/literature/discovery/semantic-scholar-recs-guide/SKILL.md +103 -86
- package/skills/literature/fulltext/open-access-guide/SKILL.md +1 -1
- package/skills/literature/fulltext/open-access-mining-guide/SKILL.md +5 -5
- package/skills/literature/metadata/citation-network-guide/SKILL.md +3 -3
- package/skills/literature/metadata/h-index-guide/SKILL.md +0 -27
- package/skills/literature/search/SKILL.md +1 -1
- package/skills/literature/search/citation-chaining-guide/SKILL.md +42 -32
- package/skills/literature/search/database-comparison-guide/SKILL.md +1 -1
- package/skills/literature/search/semantic-scholar-api/SKILL.md +56 -53
- package/skills/research/automation/paper-to-agent-guide/SKILL.md +1 -1
- package/skills/research/deep-research/in-depth-research-guide/SKILL.md +1 -1
- package/skills/research/deep-research/kosmos-scientist-guide/SKILL.md +3 -3
- package/skills/research/deep-research/llm-scientific-discovery-guide/SKILL.md +1 -1
- package/skills/research/deep-research/local-deep-research-guide/SKILL.md +6 -6
- package/skills/research/deep-research/open-researcher-guide/SKILL.md +3 -3
- package/skills/research/deep-research/tongyi-deep-research-guide/SKILL.md +4 -4
- package/skills/research/methodology/grad-school-guide/SKILL.md +1 -1
- package/skills/research/paper-review/automated-review-guide/SKILL.md +1 -1
- package/skills/tools/diagram/excalidraw-diagram-guide/SKILL.md +1 -1
- package/skills/tools/diagram/mermaid-architect-guide/SKILL.md +1 -1
- package/skills/tools/diagram/plantuml-guide/SKILL.md +1 -1
- package/skills/tools/document/grobid-pdf-parsing/SKILL.md +1 -1
- package/skills/tools/document/paper-parse-guide/SKILL.md +2 -2
- package/skills/tools/knowledge-graph/citation-network-builder/SKILL.md +5 -5
- package/skills/tools/knowledge-graph/knowledge-graph-construction/SKILL.md +1 -1
- package/skills/tools/scraping/academic-web-scraping/SKILL.md +1 -2
- package/skills/tools/scraping/google-scholar-scraper/SKILL.md +7 -7
- package/skills/writing/citation/SKILL.md +1 -1
- package/skills/writing/citation/academic-citation-manager/SKILL.md +20 -17
- package/skills/writing/citation/citation-assistant-skill/SKILL.md +72 -58
- package/skills/writing/citation/onecite-reference-guide/SKILL.md +1 -1
- package/skills/writing/citation/zotero-reference-guide/SKILL.md +1 -1
- package/skills/writing/citation/zotero-scholar-guide/SKILL.md +1 -1
- package/src/tools/arxiv.ts +13 -3
- package/src/tools/biorxiv.ts +21 -5
- package/src/tools/crossref.ts +13 -6
- package/src/tools/datacite.ts +7 -3
- package/src/tools/doaj.ts +3 -2
- package/src/tools/europe-pmc.ts +4 -3
- package/src/tools/hal.ts +6 -4
- package/src/tools/inspire-hep.ts +3 -2
- package/src/tools/openaire.ts +11 -6
- package/src/tools/openalex.ts +17 -2
- package/src/tools/opencitations.ts +9 -0
- package/src/tools/orcid.ts +3 -0
- package/src/tools/osf-preprints.ts +3 -2
- package/src/tools/pubmed.ts +12 -5
- package/src/tools/unpaywall.ts +3 -0
- package/src/tools/util.ts +33 -0
- package/src/tools/zenodo.ts +10 -4
package/src/tools/orcid.ts
CHANGED
|
@@ -72,6 +72,9 @@ export function createOrcidTools(
|
|
|
72
72
|
}),
|
|
73
73
|
}),
|
|
74
74
|
execute: async (input: { orcid: string }) => {
|
|
75
|
+
if (!input?.orcid) {
|
|
76
|
+
return toolResult({ error: 'orcid parameter is required (e.g., "0000-0002-1825-0097")' });
|
|
77
|
+
}
|
|
75
78
|
const orcid = input.orcid.replace(/^https?:\/\/orcid\.org\//, "");
|
|
76
79
|
|
|
77
80
|
const result = await trackedFetch(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
3
|
-
import { toolResult, trackedFetch, isTrackedError } from "./util.js";
|
|
3
|
+
import { toolResult, trackedFetch, isTrackedError, validParam } from "./util.js";
|
|
4
4
|
|
|
5
5
|
const BASE = "https://api.osf.io/v2";
|
|
6
6
|
|
|
@@ -36,7 +36,8 @@ export function createOsfPreprintsTools(
|
|
|
36
36
|
const params = new URLSearchParams({
|
|
37
37
|
"page[size]": String(Math.min(input.size ?? 10, 100)),
|
|
38
38
|
});
|
|
39
|
-
|
|
39
|
+
const provider = validParam(input.provider);
|
|
40
|
+
if (provider) params.set("filter[provider]", provider);
|
|
40
41
|
if (input.page) params.set("page", String(input.page));
|
|
41
42
|
|
|
42
43
|
const result = await trackedFetch(
|
package/src/tools/pubmed.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
3
|
-
import { toolResult, trackedFetch, isTrackedError } from "./util.js";
|
|
3
|
+
import { toolResult, trackedFetch, isTrackedError, validParam, validEnum } from "./util.js";
|
|
4
4
|
|
|
5
5
|
const EUTILS = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils";
|
|
6
6
|
|
|
@@ -41,17 +41,21 @@ export function createPubMedTools(
|
|
|
41
41
|
min_date?: string;
|
|
42
42
|
max_date?: string;
|
|
43
43
|
}) => {
|
|
44
|
+
const sort = validEnum(input.sort, ["relevance", "pub_date"] as const, "relevance");
|
|
45
|
+
const minDate = validParam(input.min_date);
|
|
46
|
+
const maxDate = validParam(input.max_date);
|
|
47
|
+
|
|
44
48
|
const searchParams = new URLSearchParams({
|
|
45
49
|
db: "pubmed",
|
|
46
50
|
term: input.query,
|
|
47
51
|
retmax: String(Math.min(input.max_results ?? 10, 100)),
|
|
48
52
|
retmode: "json",
|
|
49
|
-
sort
|
|
53
|
+
sort,
|
|
50
54
|
usehistory: "y",
|
|
51
55
|
});
|
|
52
|
-
if (
|
|
53
|
-
if (
|
|
54
|
-
if (
|
|
56
|
+
if (minDate) searchParams.set("mindate", minDate);
|
|
57
|
+
if (maxDate) searchParams.set("maxdate", maxDate);
|
|
58
|
+
if (minDate || maxDate) searchParams.set("datetype", "pdat");
|
|
55
59
|
|
|
56
60
|
const searchTracked = await trackedFetch("pubmed", `${EUTILS}/esearch.fcgi?${searchParams}`);
|
|
57
61
|
if (isTrackedError(searchTracked)) return searchTracked;
|
|
@@ -109,6 +113,9 @@ export function createPubMedTools(
|
|
|
109
113
|
pmid: Type.String({ description: "PubMed ID (numeric string)" }),
|
|
110
114
|
}),
|
|
111
115
|
execute: async (input: { pmid: string }) => {
|
|
116
|
+
if (!input?.pmid) {
|
|
117
|
+
return toolResult({ error: 'pmid parameter is required (numeric PubMed ID, e.g., "33116299")' });
|
|
118
|
+
}
|
|
112
119
|
const params = new URLSearchParams({
|
|
113
120
|
db: "pubmed",
|
|
114
121
|
id: input.pmid,
|
package/src/tools/unpaywall.ts
CHANGED
|
@@ -22,6 +22,9 @@ export function createUnpaywallTools(
|
|
|
22
22
|
}),
|
|
23
23
|
}),
|
|
24
24
|
execute: async (input: { doi: string }) => {
|
|
25
|
+
if (!input?.doi) {
|
|
26
|
+
return toolResult({ error: 'doi parameter is required (e.g., "10.1038/nature12373")' });
|
|
27
|
+
}
|
|
25
28
|
const doi = input.doi.replace(/^https?:\/\/doi\.org\//, "");
|
|
26
29
|
const tracked = await trackedFetch(
|
|
27
30
|
"unpaywall",
|
package/src/tools/util.ts
CHANGED
|
@@ -150,3 +150,36 @@ export function isTrackedError(
|
|
|
150
150
|
): result is ReturnType<typeof toolResult> {
|
|
151
151
|
return "content" in result && "details" in result;
|
|
152
152
|
}
|
|
153
|
+
|
|
154
|
+
// ── LLM Input Sanitization ──────────────────────────────────────────────
|
|
155
|
+
|
|
156
|
+
const INVALID_PARAM_VALUES = new Set(["undefined", "null", "none", "None", ""]);
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Sanitize an optional string parameter from LLM tool calls.
|
|
160
|
+
*
|
|
161
|
+
* LLMs (especially weaker models) sometimes pass the literal string "undefined"
|
|
162
|
+
* or "null" instead of omitting the parameter. The nullish coalescing operator
|
|
163
|
+
* (`??`) does NOT catch these because they are truthy strings.
|
|
164
|
+
*
|
|
165
|
+
* Returns the value if valid, or `undefined` if it's a known non-value.
|
|
166
|
+
*/
|
|
167
|
+
export function validParam(value: string | undefined | null): string | undefined {
|
|
168
|
+
if (value == null) return undefined;
|
|
169
|
+
if (INVALID_PARAM_VALUES.has(value.trim())) return undefined;
|
|
170
|
+
return value;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Validate a string parameter against a whitelist of allowed values.
|
|
175
|
+
* Returns the value if it matches, or the fallback otherwise.
|
|
176
|
+
*/
|
|
177
|
+
export function validEnum<T extends string>(
|
|
178
|
+
value: string | undefined | null,
|
|
179
|
+
allowed: readonly T[],
|
|
180
|
+
fallback: T,
|
|
181
|
+
): T {
|
|
182
|
+
const clean = validParam(value);
|
|
183
|
+
if (clean && (allowed as readonly string[]).includes(clean)) return clean as T;
|
|
184
|
+
return fallback;
|
|
185
|
+
}
|
package/src/tools/zenodo.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import type { OpenClawPluginApi, OpenClawPluginToolContext } from "openclaw/plugin-sdk";
|
|
3
|
-
import { toolResult, trackedFetch, isTrackedError } from "./util.js";
|
|
3
|
+
import { toolResult, trackedFetch, isTrackedError, validParam } from "./util.js";
|
|
4
4
|
|
|
5
5
|
const BASE = "https://zenodo.org/api";
|
|
6
6
|
|
|
@@ -48,9 +48,12 @@ export function createZenodoTools(
|
|
|
48
48
|
q: input.query,
|
|
49
49
|
size: String(Math.min(input.size ?? 10, 100)),
|
|
50
50
|
});
|
|
51
|
-
|
|
52
|
-
if (
|
|
53
|
-
|
|
51
|
+
const type = validParam(input.type);
|
|
52
|
+
if (type) params.set("type", type);
|
|
53
|
+
const sort = validParam(input.sort);
|
|
54
|
+
if (sort) params.set("sort", sort);
|
|
55
|
+
const accessRight = validParam(input.access_right);
|
|
56
|
+
if (accessRight) params.set("access_right", accessRight);
|
|
54
57
|
|
|
55
58
|
const result = await trackedFetch("zenodo", `${BASE}/records?${params}`, undefined, 10_000);
|
|
56
59
|
if (isTrackedError(result)) return result;
|
|
@@ -103,6 +106,9 @@ export function createZenodoTools(
|
|
|
103
106
|
}),
|
|
104
107
|
}),
|
|
105
108
|
execute: async (input: { record_id: string }) => {
|
|
109
|
+
if (!input?.record_id) {
|
|
110
|
+
return toolResult({ error: 'record_id parameter is required (e.g., "1234567")' });
|
|
111
|
+
}
|
|
106
112
|
const id = input.record_id.replace(/\D/g, "");
|
|
107
113
|
const result = await trackedFetch("zenodo", `${BASE}/records/${id}`, undefined, 10_000);
|
|
108
114
|
if (isTrackedError(result)) return result;
|