@companion-ai/feynman 0.5.45 → 0.5.47
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/RELEASES.md
CHANGED
|
@@ -6,6 +6,15 @@ GitHub release notes are generated from the matching `## vX.Y.Z` section in this
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## v0.5.47 - 2026-10-15
|
|
10
|
+
|
|
11
|
+
- **pi-web-access 0.41.0.** Sites that turn away AI fetchers can be read by setting your own User-Agent: add `"fetchContent": { "userAgent": "..." }` to `~/.feynman/agent/web-search.json`. A SearXNG instance on your own machine now works without opening every local service to page fetches.
|
|
12
|
+
|
|
13
|
+
## v0.5.46 - 2026-10-13
|
|
14
|
+
|
|
15
|
+
- **Recent arXiv papers resolve by DOI.** OpenAlex adds new arXiv preprints days late, so looking up an arXiv DOI (`10.48550/arXiv.<id>`) it doesn't have yet failed. It is now looked up on arXiv itself, with a note.
|
|
16
|
+
- When a topic sent to the arXiv source is written in arXiv's own query syntax (`search_query=all:...`, `submittedDate:[...]`), only the search words are passed on to OpenAlex.
|
|
17
|
+
|
|
9
18
|
## v0.5.45 - 2026-10-13
|
|
10
19
|
|
|
11
20
|
- **Paper lookups recover instead of failing.**
|
|
@@ -159,6 +159,19 @@ function arxivFeedEntries(feed: Record<string, unknown>): Record<string, unknown
|
|
|
159
159
|
return entries;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
// Plain search words from a query written in arXiv's API syntax
|
|
163
|
+
// (search_query=all:..., AND submittedDate:[...], &max_results=...).
|
|
164
|
+
export function arxivTopicText(query: string): string {
|
|
165
|
+
return query
|
|
166
|
+
.replace(/&?\b(?:max_results|start|sortBy|sortOrder)=[^&\s]*/gi, " ")
|
|
167
|
+
.replace(/\b(?:AND|OR|ANDNOT)\s+submittedDate:\[[^\]]*\]/gi, " ")
|
|
168
|
+
.replace(/\bsearch_query[=_:]+/gi, " ")
|
|
169
|
+
.replace(/\b(?:all|ti|abs|au|cat|co|jr):/gi, " ")
|
|
170
|
+
.replace(/[&"()]/g, " ")
|
|
171
|
+
.replace(/\s+/g, " ")
|
|
172
|
+
.trim();
|
|
173
|
+
}
|
|
174
|
+
|
|
162
175
|
async function getArxivPapers(query: string): Promise<Record<string, unknown>> {
|
|
163
176
|
const parsed = parseToolKeyValueQuery(stripGetPapersCommand(query));
|
|
164
177
|
const requested = (parsed.flags.ids ?? parsed.text).split(/[,\s]+/).map((id) => id.trim()).filter(Boolean).slice(0, MAX_ARXIV_EXACT_RESULTS);
|
|
@@ -173,7 +186,7 @@ async function getArxivPapers(query: string): Promise<Record<string, unknown>> {
|
|
|
173
186
|
if (!ids.length) {
|
|
174
187
|
throw new ArxivTopicQueryError(
|
|
175
188
|
`No arXiv IDs found in "${query}". The arxiv source only looks up papers by ID; search topics with source semanticscholar or openalex.`,
|
|
176
|
-
parsed.text || stripGetPapersCommand(query),
|
|
189
|
+
arxivTopicText(parsed.text || stripGetPapersCommand(query)),
|
|
177
190
|
);
|
|
178
191
|
}
|
|
179
192
|
const rows: Record<string, unknown>[] = [];
|
|
@@ -461,6 +461,22 @@ async function searchArxivWithFallback(params: ScienceDatabaseSearchParams): Pro
|
|
|
461
461
|
}
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
+
// OpenAlex indexes new arXiv preprints days late; arXiv itself answers for its
|
|
465
|
+
// own DOIs (10.48550/arXiv.<id>).
|
|
466
|
+
async function withArxivDoiFallback(
|
|
467
|
+
params: ScienceDatabaseSearchParams,
|
|
468
|
+
run: () => Promise<Record<string, unknown>>,
|
|
469
|
+
): Promise<Record<string, unknown>> {
|
|
470
|
+
try {
|
|
471
|
+
return await run();
|
|
472
|
+
} catch (error) {
|
|
473
|
+
const arxivId = error instanceof Error ? /^OpenAlex has no work for doi:10\.48550\/arxiv\.(.+)$/i.exec(error.message)?.[1] : undefined;
|
|
474
|
+
if (!arxivId) throw error;
|
|
475
|
+
const result = await searchArxivWithFallback({ ...params, source: "arxiv", query: arxivId });
|
|
476
|
+
return { fallbackNote: `OpenAlex has no record of this arXiv DOI yet, so it was looked up on arXiv (${arxivId}).`, ...result };
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
464
480
|
async function scienceDatabaseSearch(params: ScienceDatabaseSearchParams): Promise<Record<string, unknown>> {
|
|
465
481
|
if (params.source === "arxiv") return searchArxivWithFallback(params);
|
|
466
482
|
if (params.source === "biorxiv") return searchPreprints(params, "biorxiv");
|
|
@@ -473,11 +489,11 @@ async function scienceDatabaseSearch(params: ScienceDatabaseSearchParams): Promi
|
|
|
473
489
|
return withIndexFallback(semanticScholar, openAlex, (reason) => `Semantic Scholar was unavailable (${reason}); these results are from OpenAlex.`);
|
|
474
490
|
}
|
|
475
491
|
if (params.source === "openalex") {
|
|
476
|
-
return withIndexFallback(
|
|
492
|
+
return withArxivDoiFallback(params, () => withIndexFallback(
|
|
477
493
|
openAlex,
|
|
478
494
|
OPENALEX_LOOKUP_QUERY.test(params.query.trim()) ? undefined : semanticScholar,
|
|
479
495
|
(reason) => `OpenAlex was unavailable (${reason}); these results are from Semantic Scholar.`,
|
|
480
|
-
);
|
|
496
|
+
));
|
|
481
497
|
}
|
|
482
498
|
return searchEuropePmc(params);
|
|
483
499
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@companion-ai/feynman",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.47",
|
|
4
4
|
"description": "The open source AI research agent.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"pi-btw": "0.8.0",
|
|
87
87
|
"pi-docparser": "4.0.0",
|
|
88
88
|
"pi-subagents": "0.78.0",
|
|
89
|
-
"pi-web-access": "0.
|
|
89
|
+
"pi-web-access": "0.41.0",
|
|
90
90
|
"posthog-node": "^5.53.0"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|