@companion-ai/feynman 0.5.23 → 0.5.25

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,16 @@ GitHub release notes are generated from the matching `## vX.Y.Z` section in this
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## v0.5.25 - 2026-10-05
10
+
11
+ - **Pi 1.0.2 and pi-subagents 0.76.0.** Pi now uses the patched brace-expansion 5.0.12 (GHSA-q2hr-2g5m-vwhr, GHSA-qhr7-859c-m2p7, GHSA-6j4f-fj2g-mc7p), so Feynman's npm audit has no exceptions left, and an npm install pulls about 120 fewer packages. Pi also retries "model at capacity" errors instead of ending the turn, and Sign in with ChatGPT reports a busy callback port instead of "OAuth state mismatch". pi-subagents frees async slots held by abandoned workflows.
12
+ - **A timed-out paper search no longer ends a research step.** A Semantic Scholar or OpenAlex topic search that hits the 25 s timeout is answered from the other index, and other sources say which one did not respond instead of "This operation was aborted".
13
+ - **arXiv batch versions.** Looking up a bare arXiv ID alongside an older version now returns the latest version for the bare ID regardless of feed order. An unavailable explicit version is reported in `not_found` instead of resolving to a different version. Thanks to @Kunyanli230 (#322).
14
+
15
+ ## v0.5.24 - 2026-10-03
16
+
17
+ - **Pi 1.0.** Feynman now runs on Pi 1.0.0, with pi-subagents 0.75.0 (background subagents start on Pi 1.0) and pi-btw 0.7.1 (allows Pi 1.x). The terminal UI is fullscreen by default and keeps its own scrollback; run `feynman --tui-mode regular`, or set `"tuiMode": "regular"` in `~/.feynman/agent/settings.json`, to use the terminal's normal scrollback. Launch warnings show inside the fullscreen UI. Pi 1.0 also adds MCP OAuth hardening, a copy-code Anthropic login for headless machines, and lower codemode token use.
18
+
9
19
  ## v0.5.23 - 2026-10-02
10
20
 
11
21
  - **arXiv and PubMed rate limits.** arXiv asks for one request every three seconds, and parallel lookups got `429`; arXiv requests now run at that pace and a 429 is retried once. A PubMed `429`, which a subagent in another process or a shared IP can still trigger, is retried once after a pause.
package/dist/cli.js CHANGED
@@ -467,6 +467,7 @@ async function runMain(input) {
467
467
  "new-session": { type: "boolean" },
468
468
  "no-session": { type: "boolean" },
469
469
  "no-themes": { type: "boolean" },
470
+ "tui-mode": { type: "string" },
470
471
  prompt: { type: "string" },
471
472
  resume: { type: "boolean", short: "r" },
472
473
  "service-tier": { type: "string" },
@@ -694,7 +695,11 @@ async function runMain(input) {
694
695
  explicitModelSpec,
695
696
  resumeRecentSession,
696
697
  // ACP adapters such as pi-acp pass --no-themes with --mode rpc.
697
- piArgs: values["no-themes"] ? [...piArgs, "--no-themes"] : piArgs,
698
+ piArgs: [
699
+ ...piArgs,
700
+ ...(values["no-themes"] ? ["--no-themes"] : []),
701
+ ...(values["tui-mode"] ? ["--tui-mode", values["tui-mode"]] : []),
702
+ ],
698
703
  preLaunchNotice,
699
704
  ...promptOptions,
700
705
  });
@@ -167,13 +167,16 @@ async function getArxivPapers(query: string): Promise<Record<string, unknown>> {
167
167
  const feed = recordValue(xmlParser.parse(xml).feed);
168
168
  const byId = new Map<string, Record<string, unknown>>();
169
169
  for (const row of arxivFeedEntries(feed).map(parseArxivEntry).filter((item): item is Record<string, unknown> => Boolean(item))) {
170
- if (row.arxiv_id) byId.set(String(row.arxiv_id), row);
170
+ if (row.arxiv_id) {
171
+ const bare = String(row.arxiv_id);
172
+ const latest = byId.get(bare);
173
+ if (!latest || Number(row.version) >= Number(latest.version)) byId.set(bare, row);
174
+ }
171
175
  if (row.id_versioned) byId.set(String(row.id_versioned), row);
172
176
  }
173
177
  const seen = new Map<Record<string, unknown>, string>();
174
178
  for (const id of ids) {
175
- const bare = id.replace(/v\d+$/i, "");
176
- const row = byId.get(id) ?? byId.get(bare);
179
+ const row = byId.get(id);
177
180
  if (!row) notFound.push(id);
178
181
  else if (seen.has(row)) duplicates.push({ requested: id, resolved_as: seen.get(row) });
179
182
  else {
@@ -385,7 +385,14 @@ async function searchSemanticScholar(params: ScienceDatabaseSearchParams): Promi
385
385
  const OPENALEX_LOOKUP_QUERY =
386
386
  /^(?:openalex_\w+|rate-limit|authors?|author-search|sources?|venues?|citations?|references?|work|detail)(?::|\s|$)|^(?:W\d+|doi:\s*10\.|10\.\S+\/)/i;
387
387
 
388
+ // Each request aborts after REQUEST_TIMEOUT_MS, which fetch reports as a bare
389
+ // "This operation was aborted".
390
+ function isTimeout(error: unknown): boolean {
391
+ return error instanceof Error && error.name === "AbortError";
392
+ }
393
+
388
394
  function isIndexUnavailable(error: unknown): boolean {
395
+ if (isTimeout(error)) return true;
389
396
  if (error instanceof ScienceDatabaseRequestError) return error.status === 429 || error.status >= 500;
390
397
  return error instanceof Error && /^OpenAlex request failed: (?:429|5\d\d)\b/.test(error.message);
391
398
  }
@@ -469,7 +476,13 @@ export function registerScienceDatabaseTools(pi: ExtensionAPI): void {
469
476
  ], { description: "PubMed sort order. For semanticscholar, prefer the default citation-count sort; use pub_date (newest first) only when recency matters. relevance falls back to the default when the anonymous pool is rate-limited. Ignored for other sources." })),
470
477
  }),
471
478
  async execute(_toolCallId, params) {
472
- const result = await scienceDatabaseSearch(params as ScienceDatabaseSearchParams);
479
+ let result: Record<string, unknown>;
480
+ try {
481
+ result = await scienceDatabaseSearch(params as ScienceDatabaseSearchParams);
482
+ } catch (error) {
483
+ if (!isTimeout(error)) throw error;
484
+ throw new Error(`${params.source} did not respond within ${REQUEST_TIMEOUT_MS / 1000} s. Retry, or search another source.`);
485
+ }
473
486
  return {
474
487
  content: [{ type: "text", text: formatText(result) }],
475
488
  details: result,
@@ -157,6 +157,7 @@ export const legacyFlags = [
157
157
  { usage: "--cwd <path>", description: "Set the working directory for tools." },
158
158
  { usage: "--session-dir <path>", description: "Set the session storage directory." },
159
159
  { usage: "--new-session", description: "Start a new persisted session." },
160
+ { usage: "--tui-mode <fullscreen|regular>", description: "Run the terminal UI fullscreen (default) or in the normal scrollback." },
160
161
  { usage: "--continue, -c", description: "Continue the most recent session (default for an interactive launch)." },
161
162
  { usage: "--resume, -r", description: "Pick a previous session to resume." },
162
163
  { usage: "--session <path|id>", description: "Open a specific session." },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@companion-ai/feynman",
3
- "version": "0.5.23",
3
+ "version": "0.5.25",
4
4
  "description": "Research-first CLI agent built on Pi and alphaXiv",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -80,15 +80,15 @@
80
80
  "@clack/prompts": "^1.8.1",
81
81
  "@companion-ai/alpha-hub": "0.1.6",
82
82
  "fast-xml-parser": "5.11.1",
83
- "pi-btw": "0.7.0",
83
+ "pi-btw": "0.7.1",
84
84
  "pi-docparser": "4.0.0",
85
- "pi-subagents": "0.74.0",
85
+ "pi-subagents": "0.76.0",
86
86
  "pi-web-access": "0.35.0",
87
87
  "posthog-node": "^5.53.0"
88
88
  },
89
89
  "peerDependencies": {
90
- "@earendil-works/pi-ai": "0.99.2",
91
- "@earendil-works/pi-coding-agent": "0.99.2",
90
+ "@earendil-works/pi-ai": "1.0.2",
91
+ "@earendil-works/pi-coding-agent": "1.0.2",
92
92
  "@earendil-works/pi-tui": "*",
93
93
  "typebox": "*"
94
94
  },