@mantra-ai/core 0.1.6 → 0.3.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 (31) hide show
  1. package/dist/discovery/ranking.d.ts +31 -0
  2. package/dist/discovery/ranking.d.ts.map +1 -0
  3. package/dist/discovery/ranking.js +214 -0
  4. package/dist/discovery/ranking.js.map +1 -0
  5. package/dist/discovery/registry.d.ts +32 -0
  6. package/dist/discovery/registry.d.ts.map +1 -0
  7. package/dist/discovery/registry.js +90 -0
  8. package/dist/discovery/registry.js.map +1 -0
  9. package/dist/discovery/types.d.ts +103 -0
  10. package/dist/discovery/types.d.ts.map +1 -0
  11. package/dist/discovery/types.js +8 -0
  12. package/dist/discovery/types.js.map +1 -0
  13. package/dist/index.d.ts +8 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +6 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/sources/semantic-scholar/citation-graph-provider.d.ts +19 -0
  18. package/dist/sources/semantic-scholar/citation-graph-provider.d.ts.map +1 -0
  19. package/dist/sources/semantic-scholar/citation-graph-provider.js +91 -0
  20. package/dist/sources/semantic-scholar/citation-graph-provider.js.map +1 -0
  21. package/dist/sources/semantic-scholar/client.d.ts +97 -0
  22. package/dist/sources/semantic-scholar/client.d.ts.map +1 -0
  23. package/dist/sources/semantic-scholar/client.js +195 -0
  24. package/dist/sources/semantic-scholar/client.js.map +1 -0
  25. package/dist/sources/semantic-scholar/provider.d.ts +22 -0
  26. package/dist/sources/semantic-scholar/provider.d.ts.map +1 -0
  27. package/dist/sources/semantic-scholar/provider.js +63 -0
  28. package/dist/sources/semantic-scholar/provider.js.map +1 -0
  29. package/dist/types/version.d.ts +84 -84
  30. package/dist/types/work.d.ts +216 -216
  31. package/package.json +1 -1
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Semantic Scholar citation-graph discovery provider.
3
+ *
4
+ * Expands from a set of seed DOIs by fetching their references (bibliography)
5
+ * and citations (downstream work), then returns deduplicated candidates.
6
+ */
7
+ import { getPaperReferences, getPaperCitations, } from "./client";
8
+ import { s2PaperToCandidate } from "./provider";
9
+ /** Max concurrent seed expansions to avoid rate-limit bursts. */
10
+ const MAX_CONCURRENCY = 3;
11
+ /** Max results per direction per seed. */
12
+ const PER_SEED_LIMIT = 50;
13
+ export class SemanticScholarCitationGraphProvider {
14
+ name = "Semantic Scholar Citation Graph";
15
+ sourceKind = "semantic-scholar-citation-graph";
16
+ capabilities = ["search"];
17
+ isLocal = false;
18
+ clientOpts;
19
+ seedDois;
20
+ constructor(seedDois, clientOpts) {
21
+ this.seedDois = seedDois;
22
+ this.clientOpts = clientOpts ?? {};
23
+ }
24
+ async search(_query, opts) {
25
+ if (this.seedDois.length === 0)
26
+ return [];
27
+ const limit = opts?.limit ?? 20;
28
+ // Fan out across seeds with bounded concurrency, tagging each result
29
+ const allTagged = [];
30
+ const seedDoiSet = new Set(this.seedDois.map((d) => d.toLowerCase()));
31
+ for (let i = 0; i < this.seedDois.length; i += MAX_CONCURRENCY) {
32
+ const batch = this.seedDois.slice(i, i + MAX_CONCURRENCY);
33
+ // Build tagged request pairs: [refs-doi1, cites-doi1, refs-doi2, ...]
34
+ const requests = [];
35
+ for (const doi of batch) {
36
+ requests.push({
37
+ doi,
38
+ relation: "references",
39
+ promise: getPaperReferences(`DOI:${doi}`, { ...this.clientOpts, limit: PER_SEED_LIMIT }),
40
+ });
41
+ requests.push({
42
+ doi,
43
+ relation: "cited-by",
44
+ promise: getPaperCitations(`DOI:${doi}`, { ...this.clientOpts, limit: PER_SEED_LIMIT }),
45
+ });
46
+ }
47
+ const results = await Promise.allSettled(requests.map((r) => r.promise));
48
+ for (let j = 0; j < results.length; j++) {
49
+ const result = results[j];
50
+ const req = requests[j];
51
+ if (result.status === "fulfilled" && result.value.ok) {
52
+ for (const paper of result.value.data) {
53
+ allTagged.push({ paper, seedDoi: req.doi, relation: req.relation });
54
+ }
55
+ }
56
+ }
57
+ }
58
+ // Deduplicate by S2 paperId, collecting seed origins per paper
59
+ const paperMap = new Map();
60
+ for (const { paper, seedDoi, relation } of allTagged) {
61
+ // Exclude seed papers from results
62
+ const paperDoi = paper.externalIds?.DOI?.toLowerCase();
63
+ if (paperDoi && seedDoiSet.has(paperDoi))
64
+ continue;
65
+ const existing = paperMap.get(paper.paperId);
66
+ if (existing) {
67
+ // Add this origin if not already tracked
68
+ const originKey = `${seedDoi.toLowerCase()}:${relation}`;
69
+ if (!existing.origins.some((o) => `${o.doi.toLowerCase()}:${o.relation}` === originKey)) {
70
+ existing.origins.push({ doi: seedDoi, relation });
71
+ }
72
+ }
73
+ else {
74
+ paperMap.set(paper.paperId, {
75
+ paper,
76
+ origins: [{ doi: seedDoi, relation }],
77
+ });
78
+ }
79
+ }
80
+ // Map to candidates, scored by position (will be re-ranked by core)
81
+ const entries = [...paperMap.values()].slice(0, limit);
82
+ const candidates = entries.map(({ paper, origins }, i) => {
83
+ const c = s2PaperToCandidate(paper, i);
84
+ c.sources = ["semantic-scholar-citation-graph"];
85
+ c.seedOrigins = origins;
86
+ return c;
87
+ });
88
+ return candidates;
89
+ }
90
+ }
91
+ //# sourceMappingURL=citation-graph-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-graph-provider.js","sourceRoot":"","sources":["../../../src/sources/semantic-scholar/citation-graph-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Typed client for the Semantic Scholar Academic Graph API.
3
+ *
4
+ * Unauthenticated: 100 requests per 5 minutes.
5
+ * Authenticated (x-api-key header): higher limits.
6
+ *
7
+ * @see https://api.semanticscholar.org/api-docs/graph
8
+ */
9
+ import type { AdapterResult } from "../../works/types";
10
+ export interface S2Author {
11
+ authorId: string | null;
12
+ name: string | null;
13
+ }
14
+ export interface S2ExternalIds {
15
+ DOI?: string | null;
16
+ ArXiv?: string | null;
17
+ PubMed?: string | null;
18
+ PMCID?: string | null;
19
+ MAG?: string | null;
20
+ CorpusId?: number | null;
21
+ }
22
+ export interface S2Paper {
23
+ paperId: string;
24
+ title: string | null;
25
+ abstract: string | null;
26
+ year: number | null;
27
+ authors: S2Author[];
28
+ citationCount: number | null;
29
+ influentialCitationCount: number | null;
30
+ venue: string | null;
31
+ externalIds: S2ExternalIds | null;
32
+ url: string | null;
33
+ referenceCount?: number | null;
34
+ isOpenAccess?: boolean | null;
35
+ openAccessPdf?: {
36
+ url: string;
37
+ } | null;
38
+ publicationDate?: string | null;
39
+ journal?: {
40
+ name: string | null;
41
+ } | null;
42
+ }
43
+ export interface S2SearchResponse {
44
+ total: number;
45
+ offset: number;
46
+ next?: number;
47
+ data: S2Paper[];
48
+ }
49
+ /** A single edge in a citation graph response. */
50
+ export interface S2CitationEdge {
51
+ citingPaper?: S2Paper;
52
+ citedPaper?: S2Paper;
53
+ }
54
+ export interface S2CitationResponse {
55
+ offset: number;
56
+ next?: number;
57
+ data: S2CitationEdge[];
58
+ }
59
+ export interface S2ClientOpts {
60
+ apiKey?: string;
61
+ }
62
+ /**
63
+ * Search for papers by keyword query.
64
+ *
65
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/post_graph_get_papers_search
66
+ */
67
+ export declare function searchPapers(query: string, opts?: S2ClientOpts & {
68
+ limit?: number;
69
+ offset?: number;
70
+ }): Promise<AdapterResult<S2SearchResponse>>;
71
+ /**
72
+ * Get detailed information about a single paper.
73
+ *
74
+ * Accepts S2 paper ID, DOI (prefixed with "DOI:"), ArXiv ID ("ARXIV:"), etc.
75
+ *
76
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/post_graph_get_paper
77
+ */
78
+ export declare function getPaperDetails(paperId: string, opts?: S2ClientOpts): Promise<AdapterResult<S2Paper>>;
79
+ /**
80
+ * Get papers referenced by a given paper (its bibliography).
81
+ *
82
+ * Returns up to `limit` cited papers.
83
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/get_graph_get_paper_references
84
+ */
85
+ export declare function getPaperReferences(paperId: string, opts?: S2ClientOpts & {
86
+ limit?: number;
87
+ }): Promise<AdapterResult<S2Paper[]>>;
88
+ /**
89
+ * Get papers that cite a given paper.
90
+ *
91
+ * Returns up to `limit` citing papers.
92
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/get_graph_get_paper_citations
93
+ */
94
+ export declare function getPaperCitations(paperId: string, opts?: S2ClientOpts & {
95
+ limit?: number;
96
+ }): Promise<AdapterResult<S2Paper[]>>;
97
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/sources/semantic-scholar/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Typed client for the Semantic Scholar Academic Graph API.
3
+ *
4
+ * Unauthenticated: 100 requests per 5 minutes.
5
+ * Authenticated (x-api-key header): higher limits.
6
+ *
7
+ * @see https://api.semanticscholar.org/api-docs/graph
8
+ */
9
+ const BASE_URL = "https://api.semanticscholar.org/graph/v1";
10
+ const SEARCH_FIELDS = [
11
+ "paperId",
12
+ "title",
13
+ "abstract",
14
+ "year",
15
+ "authors",
16
+ "citationCount",
17
+ "influentialCitationCount",
18
+ "venue",
19
+ "externalIds",
20
+ "url",
21
+ ].join(",");
22
+ const DETAIL_FIELDS = [
23
+ ...SEARCH_FIELDS.split(","),
24
+ "referenceCount",
25
+ "isOpenAccess",
26
+ "openAccessPdf",
27
+ "publicationDate",
28
+ "journal",
29
+ ].join(",");
30
+ /** Max retries on 429 / 5xx before giving up. */
31
+ const MAX_RETRIES = 2;
32
+ /** Request timeout in ms. */
33
+ const REQUEST_TIMEOUT_MS = 10_000;
34
+ // ── Helpers ──────────────────────────────────────────────────────────
35
+ function buildHeaders(apiKey) {
36
+ const headers = {
37
+ Accept: "application/json",
38
+ };
39
+ if (apiKey) {
40
+ headers["x-api-key"] = apiKey;
41
+ }
42
+ return headers;
43
+ }
44
+ async function fetchWithRetry(url, headers) {
45
+ let lastError;
46
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
47
+ try {
48
+ const res = await fetch(url, {
49
+ headers,
50
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
51
+ });
52
+ // Retry on 429 or 5xx
53
+ if ((res.status === 429 || res.status >= 500) && attempt < MAX_RETRIES) {
54
+ // Exponential backoff: 1s, 2s
55
+ await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));
56
+ continue;
57
+ }
58
+ return res;
59
+ }
60
+ catch (e) {
61
+ lastError = e;
62
+ if (attempt < MAX_RETRIES) {
63
+ await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));
64
+ continue;
65
+ }
66
+ }
67
+ }
68
+ throw lastError ?? new Error("fetchWithRetry exhausted");
69
+ }
70
+ // ── Public API ───────────────────────────────────────────────────────
71
+ /**
72
+ * Search for papers by keyword query.
73
+ *
74
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/post_graph_get_papers_search
75
+ */
76
+ export async function searchPapers(query, opts) {
77
+ const limit = Math.min(opts?.limit ?? 20, 100);
78
+ const offset = opts?.offset ?? 0;
79
+ const params = new URLSearchParams({
80
+ query,
81
+ fields: SEARCH_FIELDS,
82
+ limit: String(limit),
83
+ offset: String(offset),
84
+ });
85
+ const url = `${BASE_URL}/paper/search?${params}`;
86
+ try {
87
+ const res = await fetchWithRetry(url, buildHeaders(opts?.apiKey));
88
+ if (!res.ok) {
89
+ const status = res.status;
90
+ if (status === 400)
91
+ return { ok: false, status, reason: "not_found" };
92
+ if (status === 429)
93
+ return { ok: false, status, reason: "rate_limited" };
94
+ return { ok: false, status, reason: "upstream_error" };
95
+ }
96
+ const data = (await res.json());
97
+ return { ok: true, data };
98
+ }
99
+ catch {
100
+ return { ok: false, reason: "network_error" };
101
+ }
102
+ }
103
+ /**
104
+ * Get detailed information about a single paper.
105
+ *
106
+ * Accepts S2 paper ID, DOI (prefixed with "DOI:"), ArXiv ID ("ARXIV:"), etc.
107
+ *
108
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/post_graph_get_paper
109
+ */
110
+ export async function getPaperDetails(paperId, opts) {
111
+ const url = `${BASE_URL}/paper/${encodeURIComponent(paperId)}?fields=${DETAIL_FIELDS}`;
112
+ try {
113
+ const res = await fetchWithRetry(url, buildHeaders(opts?.apiKey));
114
+ if (!res.ok) {
115
+ const status = res.status;
116
+ if (status === 404)
117
+ return { ok: false, status, reason: "not_found" };
118
+ if (status === 429)
119
+ return { ok: false, status, reason: "rate_limited" };
120
+ return { ok: false, status, reason: "upstream_error" };
121
+ }
122
+ const data = (await res.json());
123
+ return { ok: true, data };
124
+ }
125
+ catch {
126
+ return { ok: false, reason: "network_error" };
127
+ }
128
+ }
129
+ /**
130
+ * Get papers referenced by a given paper (its bibliography).
131
+ *
132
+ * Returns up to `limit` cited papers.
133
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/get_graph_get_paper_references
134
+ */
135
+ export async function getPaperReferences(paperId, opts) {
136
+ const limit = Math.min(opts?.limit ?? 100, 1000);
137
+ const params = new URLSearchParams({
138
+ fields: SEARCH_FIELDS,
139
+ limit: String(limit),
140
+ });
141
+ const url = `${BASE_URL}/paper/${encodeURIComponent(paperId)}/references?${params}`;
142
+ try {
143
+ const res = await fetchWithRetry(url, buildHeaders(opts?.apiKey));
144
+ if (!res.ok) {
145
+ const status = res.status;
146
+ if (status === 404)
147
+ return { ok: false, status, reason: "not_found" };
148
+ if (status === 429)
149
+ return { ok: false, status, reason: "rate_limited" };
150
+ return { ok: false, status, reason: "upstream_error" };
151
+ }
152
+ const body = (await res.json());
153
+ const papers = body.data
154
+ .map((edge) => edge.citedPaper)
155
+ .filter((p) => p != null && p.paperId != null);
156
+ return { ok: true, data: papers };
157
+ }
158
+ catch {
159
+ return { ok: false, reason: "network_error" };
160
+ }
161
+ }
162
+ /**
163
+ * Get papers that cite a given paper.
164
+ *
165
+ * Returns up to `limit` citing papers.
166
+ * @see https://api.semanticscholar.org/api-docs/graph#tag/Paper-Data/operation/get_graph_get_paper_citations
167
+ */
168
+ export async function getPaperCitations(paperId, opts) {
169
+ const limit = Math.min(opts?.limit ?? 100, 1000);
170
+ const params = new URLSearchParams({
171
+ fields: SEARCH_FIELDS,
172
+ limit: String(limit),
173
+ });
174
+ const url = `${BASE_URL}/paper/${encodeURIComponent(paperId)}/citations?${params}`;
175
+ try {
176
+ const res = await fetchWithRetry(url, buildHeaders(opts?.apiKey));
177
+ if (!res.ok) {
178
+ const status = res.status;
179
+ if (status === 404)
180
+ return { ok: false, status, reason: "not_found" };
181
+ if (status === 429)
182
+ return { ok: false, status, reason: "rate_limited" };
183
+ return { ok: false, status, reason: "upstream_error" };
184
+ }
185
+ const body = (await res.json());
186
+ const papers = body.data
187
+ .map((edge) => edge.citingPaper)
188
+ .filter((p) => p != null && p.paperId != null);
189
+ return { ok: true, data: papers };
190
+ }
191
+ catch {
192
+ return { ok: false, reason: "network_error" };
193
+ }
194
+ }
195
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/sources/semantic-scholar/client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,QAAQ,GAAG,0CAA0C,CAAC;AAE5D,MAAM,aAAa,GAAG;IACpB,SAAS;IACT,OAAO;IACP,UAAU;IACV,MAAM;IACN,SAAS;IACT,eAAe;IACf,0BAA0B;IAC1B,OAAO;IACP,aAAa;IACb,KAAK;CACN,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,MAAM,aAAa,GAAG;IACpB,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC;IAC3B,gBAAgB;IAChB,cAAc;IACd,eAAe;IACf,iBAAiB;IACjB,SAAS;CACV,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ,iDAAiD;AACjD,MAAM,WAAW,GAAG,CAAC,CAAC;AAEtB,6BAA6B;AAC7B,MAAM,kBAAkB,GAAG,MAAM,CAAC;AA4DlC,wEAAwE;AAExE,SAAS,YAAY,CAAC,MAAe;IACnC,MAAM,OAAO,GAA2B;QACtC,MAAM,EAAE,kBAAkB;KAC3B,CAAC;IACF,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;IAChC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,GAAW,EACX,OAA+B;IAE/B,IAAI,SAAkB,CAAC;IAEvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,OAAO;gBACP,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC;aAChD,CAAC,CAAC;YAEH,sBAAsB;YACtB,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;gBACvE,8BAA8B;gBAC9B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9D,SAAS;YACX,CAAC;YAED,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,SAAS,GAAG,CAAC,CAAC;YACd,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;gBAC1B,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC9D,SAAS;YACX,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;AAC3D,CAAC;AAED,wEAAwE;AAExE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAa,EACb,IAAyD;IAEzD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC;IAEjC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,KAAK;QACL,MAAM,EAAE,aAAa;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;KACvB,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,GAAG,QAAQ,iBAAiB,MAAM,EAAE,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAElE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1B,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YACtE,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YACzE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAqB,CAAC;QACpD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAe,EACf,IAAmB;IAEnB,MAAM,GAAG,GAAG,GAAG,QAAQ,UAAU,kBAAkB,CAAC,OAAO,CAAC,WAAW,aAAa,EAAE,CAAC;IAEvF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAElE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1B,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YACtE,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YACzE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAY,CAAC;QAC3C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAe,EACf,IAAwC;IAExC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,EAAE,IAAI,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,MAAM,EAAE,aAAa;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;KACrB,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,GAAG,QAAQ,UAAU,kBAAkB,CAAC,OAAO,CAAC,eAAe,MAAM,EAAE,CAAC;IAEpF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAElE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1B,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YACtE,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YACzE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI;aACrB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC;aAC9B,MAAM,CAAC,CAAC,CAAC,EAAgB,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QAC/D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAe,EACf,IAAwC;IAExC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,IAAI,GAAG,EAAE,IAAI,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,MAAM,EAAE,aAAa;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;KACrB,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,GAAG,QAAQ,UAAU,kBAAkB,CAAC,OAAO,CAAC,cAAc,MAAM,EAAE,CAAC;IAEnF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAElE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YAC1B,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YACtE,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YACzE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;QACzD,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuB,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI;aACrB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;aAC/B,MAAM,CAAC,CAAC,CAAC,EAAgB,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;QAC/D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAChD,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Semantic Scholar discovery provider.
3
+ *
4
+ * Adapts the S2 API client to the DiscoverProvider interface.
5
+ */
6
+ import type { DiscoverCandidateCore, DiscoverProvider, DiscoverSearchOpts } from "../../discovery/types";
7
+ import { type S2Paper, type S2ClientOpts } from "./client";
8
+ /**
9
+ * Map an S2Paper to a DiscoverCandidateCore.
10
+ * Handles sparse records gracefully — every field may be null.
11
+ */
12
+ export declare function s2PaperToCandidate(paper: S2Paper, position: number): DiscoverCandidateCore;
13
+ export declare class SemanticScholarProvider implements DiscoverProvider {
14
+ readonly name = "Semantic Scholar";
15
+ readonly sourceKind: "semantic-scholar";
16
+ readonly capabilities: readonly ["search"];
17
+ readonly isLocal = false;
18
+ private opts;
19
+ constructor(opts?: S2ClientOpts);
20
+ search(query: string, opts?: DiscoverSearchOpts): Promise<DiscoverCandidateCore[]>;
21
+ }
22
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/sources/semantic-scholar/provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAgB,KAAK,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAEzE;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,qBAAqB,CA+BvB;AAED,qBAAa,uBAAwB,YAAW,gBAAgB;IAC9D,QAAQ,CAAC,IAAI,sBAAsB;IACnC,QAAQ,CAAC,UAAU,EAAG,kBAAkB,CAAU;IAClD,QAAQ,CAAC,YAAY,sBAAuB;IAC5C,QAAQ,CAAC,OAAO,SAAS;IAEzB,OAAO,CAAC,IAAI,CAAe;gBAEf,IAAI,CAAC,EAAE,YAAY;IAIzB,MAAM,CACV,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,kBAAkB,GACxB,OAAO,CAAC,qBAAqB,EAAE,CAAC;CAkBpC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Semantic Scholar discovery provider.
3
+ *
4
+ * Adapts the S2 API client to the DiscoverProvider interface.
5
+ */
6
+ import { searchPapers } from "./client";
7
+ /**
8
+ * Map an S2Paper to a DiscoverCandidateCore.
9
+ * Handles sparse records gracefully — every field may be null.
10
+ */
11
+ export function s2PaperToCandidate(paper, position) {
12
+ const doi = paper.externalIds?.DOI ?? null;
13
+ const authors = paper.authors
14
+ ?.map((a) => a.name)
15
+ .filter(Boolean)
16
+ .join(", ") || null;
17
+ // Truncate abstract to ~200 chars for snippet
18
+ let abstractSnippet = null;
19
+ if (paper.abstract) {
20
+ abstractSnippet =
21
+ paper.abstract.length > 200
22
+ ? paper.abstract.slice(0, 197) + "..."
23
+ : paper.abstract;
24
+ }
25
+ return {
26
+ doi,
27
+ title: paper.title,
28
+ authors,
29
+ year: paper.year,
30
+ sources: ["semantic-scholar"],
31
+ score: position, // position-based; normalizeScore handles conversion to 0–1
32
+ semanticScholarId: paper.paperId,
33
+ citationCount: paper.citationCount,
34
+ influentialCitationCount: paper.influentialCitationCount,
35
+ abstractSnippet,
36
+ venue: paper.venue || null,
37
+ url: paper.url,
38
+ };
39
+ }
40
+ export class SemanticScholarProvider {
41
+ name = "Semantic Scholar";
42
+ sourceKind = "semantic-scholar";
43
+ capabilities = ["search"];
44
+ isLocal = false;
45
+ opts;
46
+ constructor(opts) {
47
+ this.opts = opts ?? {};
48
+ }
49
+ async search(query, opts) {
50
+ const limit = opts?.limit ?? 20;
51
+ const result = await searchPapers(query, {
52
+ ...this.opts,
53
+ limit,
54
+ });
55
+ if (!result.ok) {
56
+ // Throw so the registry captures it as a provider error
57
+ // and the other providers continue working.
58
+ throw new Error(`Semantic Scholar search failed: ${result.reason}${result.status ? ` (${result.status})` : ""}`);
59
+ }
60
+ return result.data.data.map((paper, i) => s2PaperToCandidate(paper, i));
61
+ }
62
+ }
63
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/sources/semantic-scholar/provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAE,YAAY,EAAmC,MAAM,UAAU,CAAC;AAEzE;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAc,EACd,QAAgB;IAEhB,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,GAAG,IAAI,IAAI,CAAC;IAE3C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO;QAC3B,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SACnB,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAEtB,8CAA8C;IAC9C,IAAI,eAAe,GAAkB,IAAI,CAAC;IAC1C,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,eAAe;YACb,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,GAAG;gBACzB,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;gBACtC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,OAAO;QACL,GAAG;QACH,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,OAAO;QACP,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,CAAC,kBAAkB,CAAC;QAC7B,KAAK,EAAE,QAAQ,EAAE,2DAA2D;QAC5E,iBAAiB,EAAE,KAAK,CAAC,OAAO;QAChC,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;QACxD,eAAe;QACf,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI;QAC1B,GAAG,EAAE,KAAK,CAAC,GAAG;KACf,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,uBAAuB;IACzB,IAAI,GAAG,kBAAkB,CAAC;IAC1B,UAAU,GAAG,kBAA2B,CAAC;IACzC,YAAY,GAAG,CAAC,QAAQ,CAAU,CAAC;IACnC,OAAO,GAAG,KAAK,CAAC;IAEjB,IAAI,CAAe;IAE3B,YAAY,IAAmB;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAa,EACb,IAAyB;QAEzB,MAAM,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QAEhC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,EAAE;YACvC,GAAG,IAAI,CAAC,IAAI;YACZ,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,wDAAwD;YACxD,4CAA4C;YAC5C,MAAM,IAAI,KAAK,CACb,mCAAmC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAChG,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC;CACF"}