@companion-ai/feynman 0.5.3 → 0.5.5

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "feynman",
4
4
  "vars": {
5
5
  "ink": "#d3c6aa",
package/.nvmrc CHANGED
@@ -1 +1 @@
1
- 24.20.0
1
+ 24.21.0
package/README.md CHANGED
@@ -25,34 +25,22 @@ curl -fsSL https://feynman.is/install | bash
25
25
  irm https://feynman.is/install.ps1 | iex
26
26
  ```
27
27
 
28
- The one-line installer fetches the latest tagged release. To pin a version, pass it explicitly, for example `curl -fsSL https://feynman.is/install | bash -s -- 0.2.35`.
28
+ The one-line installer fetches the latest tagged release as a standalone bundle with its own Node.js runtime and verifies its SHA-256 before installing. To pin a version, pass it explicitly, for example `curl -fsSL https://feynman.is/install | bash -s -- 0.5.3`. Rerun the installer to upgrade; `feynman update` only updates optional Pi packages you installed.
29
29
 
30
- The installer downloads a standalone native bundle with its own pinned Node.js runtime and verifies the release SHA-256 before replacing an existing installation.
31
-
32
- To upgrade the standalone app later, rerun the installer. `feynman update` only refreshes optional Pi packages you installed; Pi and the core packages update with Feynman itself.
33
-
34
- To uninstall the standalone app, remove the launcher and runtime bundle, then optionally remove `~/.feynman` if you also want to delete settings, sessions, and installed package state. If you also want to delete alphaXiv login state, remove `~/.ahub`. See the installation guide for platform-specific paths.
35
-
36
- **npm alternative** (uses your local Node.js runtime):
30
+ **npm alternative** (uses your local Node.js `>=22.22.0`):
37
31
 
38
32
  ```bash
39
33
  npm install -g @companion-ai/feynman
40
34
  ```
41
35
 
42
- To update an npm installation, run `npm install -g @companion-ai/feynman@latest`.
43
-
44
- If you installed the interim `@advaitpaliwal/feynman` package (0.3.48), migrate once:
36
+ If you installed the interim `@advaitpaliwal/feynman` package, migrate once:
45
37
 
46
38
  ```bash
47
39
  npm uninstall -g @advaitpaliwal/feynman
48
40
  npm install -g @companion-ai/feynman
49
41
  ```
50
42
 
51
- The command remains `feynman`; the native install commands above are unchanged. See the [installation guide](https://feynman.is/docs/getting-started/installation) for Node.js requirements and uninstall instructions.
52
-
53
- Local models are supported through the setup flow. For LM Studio, run `feynman setup`, choose `LM Studio`, and keep the default `http://localhost:1234/v1` unless you changed the server port. For LiteLLM, choose `LiteLLM Proxy` and keep the default `http://localhost:4000/v1`. For Ollama or vLLM, choose `Custom provider (baseUrl + API key)`, use `openai-completions`, and point it at the local `/v1` endpoint.
54
-
55
- To authenticate another hosted provider, run `feynman model login <provider>`. GitHub Copilot sign-in retries model discovery once when GitHub rate-limits the request. OpenRouter login opens an OAuth page and listens for a local callback; over SSH or in another headless environment, paste the browser's final redirect URL or authorization code into Feynman's prompt, or set `OPENROUTER_API_KEY` before launch to use API-key authentication without OAuth.
43
+ Then run `feynman setup` to sign in to a model provider. To use Feynman in an ACP editor such as Zed, run it through [pi-acp](https://github.com/svkozak/pi-acp): `"agent_servers": { "Feynman": { "command": "npx", "args": ["-y", "pi-acp"], "env": { "PI_ACP_PI_COMMAND": "feynman" } } }`. See the [installation guide](https://feynman.is/docs/getting-started/installation) for uninstalling and the [setup guide](https://feynman.is/docs/getting-started/setup) for local models (LM Studio, LiteLLM, Ollama, vLLM) and Amazon Bedrock.
56
44
 
57
45
  ### Skills Only
58
46
 
@@ -70,52 +58,18 @@ curl -fsSL https://feynman.is/install-skills | bash
70
58
  irm https://feynman.is/install-skills.ps1 | iex
71
59
  ```
72
60
 
73
- That installs the skill library into `~/.codex/skills/feynman` for Codex. You can also name the Codex target explicitly:
74
-
75
- **macOS / Linux:**
76
-
77
- ```bash
78
- curl -fsSL https://feynman.is/install-skills | bash -s -- --codex
79
- ```
80
-
81
- **Windows (PowerShell):**
82
-
83
- ```powershell
84
- & ([scriptblock]::Create((irm https://feynman.is/install-skills.ps1))) -Scope Codex
85
- ```
86
-
87
- For a repo-local Claude/agent install instead:
88
-
89
- **macOS / Linux:**
90
-
91
- ```bash
92
- curl -fsSL https://feynman.is/install-skills | bash -s -- --repo
93
- ```
94
-
95
- **Windows (PowerShell):**
96
-
97
- ```powershell
98
- & ([scriptblock]::Create((irm https://feynman.is/install-skills.ps1))) -Scope Repo
99
- ```
100
-
101
- That installs into `.agents/skills/feynman` under the current repository.
102
-
103
- For an OpenCode project-local install instead:
104
-
105
- **macOS / Linux:**
61
+ That installs the skill library into `~/.codex/skills/feynman` for Codex. For other targets, pass a scope:
106
62
 
107
63
  ```bash
108
- curl -fsSL https://feynman.is/install-skills | bash -s -- --opencode
64
+ curl -fsSL https://feynman.is/install-skills | bash -s -- --codex # ~/.codex/skills/feynman (default)
65
+ curl -fsSL https://feynman.is/install-skills | bash -s -- --repo # .agents/skills/feynman in the current repo
66
+ curl -fsSL https://feynman.is/install-skills | bash -s -- --opencode # .opencode/skills/feynman in the current repo
109
67
  ```
110
68
 
111
- **Windows (PowerShell):**
112
-
113
69
  ```powershell
114
- & ([scriptblock]::Create((irm https://feynman.is/install-skills.ps1))) -Scope OpenCode
70
+ & ([scriptblock]::Create((irm https://feynman.is/install-skills.ps1))) -Scope Codex # or -Scope Repo, -Scope OpenCode
115
71
  ```
116
72
 
117
- That installs into `.opencode/skills/feynman` under the current repository.
118
-
119
73
  These installers download the bundled `skills/` and `prompts/` trees plus the repo guidance files referenced by those skills. They do not install the Feynman terminal, bundled Node runtime, auth storage, or Pi packages.
120
74
 
121
75
  ---
@@ -124,16 +78,10 @@ These installers download the bundled `skills/` and `prompts/` trees plus the re
124
78
 
125
79
  ```
126
80
  $ feynman "what do we know about scaling laws"
127
- → Searches papers and web, produces a cited research brief
128
-
129
- $ feynman -- "- summarize the strongest evidence first"
130
- → Preserves a research prompt that begins with a dash instead of parsing it as a CLI option
131
-
132
- $ feynman --prompt="- summarize the strongest evidence first"
133
- → Runs a dash-leading research prompt once and exits
81
+ → Searches papers and the web, answers with cited sources
134
82
 
135
83
  $ feynman deepresearch "mechanistic interpretability"
136
- → Multi-agent investigation with parallel researchers, synthesis, verification
84
+ → Plan-first investigation with parallel researchers, synthesis, and citation verification
137
85
 
138
86
  $ feynman lit "RLHF alternatives"
139
87
  → Literature review with consensus, disagreements, open questions, and lab/PI corpus mode when the input names a research group
@@ -165,6 +113,7 @@ Ask naturally or use slash commands as shortcuts.
165
113
  | `/compare <topic>` | Source comparison matrix |
166
114
  | `/draft <topic>` | Paper-style draft from research findings |
167
115
  | `/autoresearch <idea>` | Bounded experiment loop with benchmark evidence |
116
+ | `/summarize <source>` | Summarize a paper, report, repo, or PDF without loading it raw into context |
168
117
  | `/btw <question>` | Side conversation while the main research agent is busy, with optional handoff back into the main thread |
169
118
  | `/outputs` | Browse all research artifacts |
170
119
 
@@ -183,19 +132,18 @@ Four bundled research agents, invoked by workflow prompts when decomposition hel
183
132
 
184
133
  ### Skills & Tools
185
134
 
186
- - **[AlphaXiv](https://www.alphaxiv.org/)** — paper search, Q&A, code reading, annotations (via Feynman's `alpha` tools and `feynman alpha` command)
187
- - **Literature databases** — read-only Semantic Scholar (citation-sorted search that surfaces seminal papers), OpenAlex (keyword and semantic search, citation graphs, authors, venues, OA status), arXiv ID lookup, PubMed (metadata, PMID/PMCID/DOI conversion, related articles, citation matching, copyright checks, PMC full-text routing), Europe PMC open-access full-text sections, bioRxiv/medRxiv preprints, and Crossref DOI metadata, with stable identifiers and endpoint provenance. Set the free `OPENALEX_API_KEY` ([create one](https://openalex.org/settings/api)) and optionally `SEMANTIC_SCHOLAR_API_KEY` ([request one](https://www.semanticscholar.org/product/api#api-key-form)) so searches use your own rate limits
135
+ - **[alphaXiv](https://www.alphaxiv.org/)** — paper search, Q&A, code reading, and annotations (via Feynman's `alpha` tools and `feynman alpha` command)
136
+ - **Literature databases** — read-only Semantic Scholar, OpenAlex, arXiv ID lookup, PubMed, Europe PMC full text, bioRxiv/medRxiv, and Crossref, with stable identifiers. Set the free `OPENALEX_API_KEY` ([create one](https://openalex.org/settings/api)) and optionally `SEMANTIC_SCHOLAR_API_KEY` ([request one](https://www.semanticscholar.org/product/api#api-key-form)) to use your own rate limits
188
137
  - **[Hugging Face Hub](https://huggingface.co/docs/hub/api)** — dataset metadata, split/schema inspection, and small file reads from model, dataset, and Space repos
189
- - **Web research** — multi-provider search, explicit proxy routing, bounded GitHub issue/PR documents, raw or question-grounded page retrieval, direct images, external fetched-content caching, stored-page passage lookup, and auditable source text; tools, commands, images, PDFs, and browser cookies remain independently gated
190
- - **Session search** — indexed recall across prior research sessions
191
- - **Observability** — opt-out PostHog usage metadata for CLI commands, research workflows, tools, and model calls (see [Telemetry](#telemetry))
192
- - **Research execution options** — Docker, plus Modal or RunPod when their CLIs are installed, for explicitly chosen replication, benchmark, or dataset-heavy experiment runs; not service deployment or generic cloud administration
138
+ - **Web research** — search, page fetching, and PDF extraction through [pi-web-access](https://github.com/nicobailon/pi-web-access); Exa works without a key, and `feynman search set` configures Perplexity, Exa, or Gemini
139
+ - **Documents** — local PDF and office-document parsing through [pi-docparser](https://github.com/maxedapps/pi-docparser)
140
+ - **Compute** — Docker, plus Modal or RunPod when their CLIs are installed, for replication and experiment runs you explicitly approve
193
141
 
194
142
  ---
195
143
 
196
144
  ### How it works
197
145
 
198
- Built on [Pi](https://github.com/badlogic/pi-mono) for the agent runtime, [alphaXiv](https://www.alphaxiv.org/) for paper search and analysis, and CLI tools for compute and execution. Runtime resources follow Pi's documented package model for [packages](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/packages.md), [extensions](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/extensions.md), and [skills](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/skills.md). Hugging Face inspection uses the public [Hub API endpoints](https://huggingface.co/docs/hub/api) and `HF_TOKEN` / `HUGGINGFACE_HUB_TOKEN` environment variables documented by [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/environment_variables). The ML recipe workflow was informed by the open-source [Hugging Face `ml-intern`](https://github.com/huggingface/ml-intern) research-agent repo, but is implemented as native Feynman prompts, skills, and read-only tools. Research outputs are source-grounded — research claims link to papers, docs, or repos with direct URLs.
146
+ Feynman runs on stock [Pi](https://github.com/earendil-works/pi) (`@earendil-works/pi-coding-agent`). Its prompts, skills, agents, and research tools load as a Pi [package](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/packages.md) alongside the bundled `pi-subagents`, `pi-web-access`, `pi-docparser`, and `pi-btw` packages. Paper search and analysis use [alphaXiv](https://www.alphaxiv.org/). Research claims link to papers, docs, or repos with direct URLs.
199
147
 
200
148
  ---
201
149
 
@@ -217,7 +165,7 @@ Feynman sends anonymous usage telemetry to PostHog by default and prints a one-t
217
165
 
218
166
  ---
219
167
 
220
- The bundled research runtime is updated as a coordinated set, including Pi, Alpha Hub's `alpha-mcp`, document parsing, web research, and subagents. See the [package stack](https://feynman.is/docs/reference/package-stack) and [release notes](https://feynman.is/docs/reference/releases) for versions and upgrade details.
168
+ The bundled Pi packages are pinned and update with Feynman, not through `feynman update`. See the [package stack](https://feynman.is/docs/reference/package-stack) and [release notes](https://feynman.is/docs/reference/releases).
221
169
 
222
170
  ### Contributing
223
171
 
package/RELEASES.md CHANGED
@@ -6,6 +6,42 @@ GitHub release notes are generated from the matching `## vX.Y.Z` section in this
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## v0.5.5 - 2026-09-24
10
+
11
+ ### Node.js 26
12
+
13
+ - Feynman now runs on Node.js 26, the current release. The upper version limit is gone: Feynman needs Node.js 22.22.0 or newer, like Pi itself. Tests run on Node 22, 24, and 26.
14
+ - The standalone installers bundle Node.js 24.21.0, the latest LTS release.
15
+
16
+ ### alphaXiv
17
+
18
+ - When an alphaXiv call fails, the tool error now points the agent to `feynman_science_database_search` (arXiv or Semantic Scholar) or `fetch_content`, so a research run continues on another source instead of retrying a broken tool. A "not logged in" error names `feynman alpha login`.
19
+ - The alphaXiv docs explain signing in from a machine without a browser (SSH, Docker, WSL): open the printed URL anywhere and paste the final `127.0.0.1:9876/callback` URL back into the terminal.
20
+
21
+ ### Other
22
+
23
+ - The setup docs explain the most common reason local models write no files: a small context window. They show how to raise Ollama's context and set `contextWindow` and `maxTokens` in `models.json`.
24
+ - feynman.is/privacy and feynman.is/telemetry go to the telemetry section, which lists what is collected and how to opt out.
25
+ - Updated dependencies: pi-btw 0.6.1, posthog-node 5.53, @clack/prompts 1.8.1, and the website toolchain (Astro 7.3, @astrojs/react 7). CI uses actions/checkout and actions/setup-node v7 and wrangler 4.139.
26
+
27
+ ## v0.5.4 - 2026-09-24
28
+
29
+ ### Use Feynman from ACP editors
30
+
31
+ - `feynman --mode rpc` now accepts `--no-themes`, the Pi flag the [pi-acp](https://github.com/svkozak/pi-acp) adapter passes, so Feynman runs in ACP editors such as Zed. Point pi-acp at Feynman with `PI_ACP_PI_COMMAND=feynman`; the setup guide has the Zed settings.
32
+
33
+ ### Removed what did not work
34
+
35
+ - The optional `session-search` package preset is gone. It indexes `~/.pi/agent/sessions` and never saw Feynman's sessions in `~/.feynman/sessions`, and its `/search` collided with pi-web-access's. Search past sessions with `grep` or `rg` over `~/.feynman/sessions`; the session-search skill now shows how.
36
+ - `/preview` is no longer listed in `/help`: no bundled or optional package provides it. `feynman setup preview` still installs pandoc, and the preview docs show how to render artifacts to HTML or PDF.
37
+ - `/help` lists pi-web-access's real `/websearch` and `/curator` commands instead of `/web-results`, which pi-web-access 0.31 no longer registers.
38
+ - The autoresearch and alpha skills no longer mention tools and patches that do not exist.
39
+
40
+ ### Docs match the code
41
+
42
+ - Every docs page, the landing page, and the README were checked against the CLI, prompts, agents, and package code. Corrections include the setup flow (model access, optional packages, alphaXiv login, pandoc), where keys are stored (plain text in `~/.feynman/agent/auth.json` with user-only permissions, not encrypted), the verifier, reviewer, and writer roles and which workflows use them, workflow steps and output files, the web-search tools and commands, and dead Pi links (now `earendil-works/pi`).
43
+ - The landing page adds a PowerShell install command and drops cards for features that do not ship.
44
+
9
45
  ## v0.5.3 - 2026-09-24
10
46
 
11
47
  ### Leaner prompts, same research quality
package/bin/feynman.js CHANGED
@@ -3,7 +3,6 @@ import { resolve } from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
4
 
5
5
  const MIN_NODE_VERSION = "22.22.0";
6
- const MAX_NODE_MAJOR = 25;
7
6
  const PREFERRED_NODE_MAJOR = 24;
8
7
 
9
8
  function parseNodeVersion(version) {
@@ -21,15 +20,12 @@ function compareNodeVersions(left, right) {
21
20
  return left.patch - right.patch;
22
21
  }
23
22
 
24
- const parsedNodeVersion = parseNodeVersion(process.versions.node);
25
- if (compareNodeVersions(parsedNodeVersion, parseNodeVersion(MIN_NODE_VERSION)) < 0 || parsedNodeVersion.major > MAX_NODE_MAJOR) {
23
+ if (compareNodeVersions(parseNodeVersion(process.versions.node), parseNodeVersion(MIN_NODE_VERSION)) < 0) {
26
24
  const isWindows = process.platform === "win32";
27
- console.error(`feynman supports Node.js ${MIN_NODE_VERSION} through ${MAX_NODE_MAJOR}.x (detected ${process.versions.node}).`);
28
- console.error(parsedNodeVersion.major > MAX_NODE_MAJOR
29
- ? "This newer Node release is not supported yet."
30
- : isWindows
31
- ? "Install a supported Node.js release from https://nodejs.org, or use the standalone installer:"
32
- : `Switch to a supported Node release with \`nvm install ${PREFERRED_NODE_MAJOR} && nvm use ${PREFERRED_NODE_MAJOR}\`, or use the standalone installer:`);
25
+ console.error(`feynman requires Node.js ${MIN_NODE_VERSION} or newer (detected ${process.versions.node}).`);
26
+ console.error(isWindows
27
+ ? "Install a supported Node.js release from https://nodejs.org, or use the standalone installer:"
28
+ : `Switch to a supported Node release with \`nvm install ${PREFERRED_NODE_MAJOR} && nvm use ${PREFERRED_NODE_MAJOR}\`, or use the standalone installer:`);
33
29
  console.error(isWindows
34
30
  ? "irm https://feynman.is/install.ps1 | iex"
35
31
  : "curl -fsSL https://feynman.is/install | bash");
package/dist/cli.js CHANGED
@@ -18,7 +18,7 @@ import { verifyAlphaAuthStatus } from "./alpha-auth-status.js";
18
18
  import { ensureFeynmanAgentDir } from "./bootstrap/home.js";
19
19
  import { ensureFeynmanHome, getDefaultSessionDir, getFeynmanAgentDir, getFeynmanHome } from "./config/paths.js";
20
20
  import { launchPiChat, runPi } from "./pi/launch.js";
21
- import { installPiPackage, isOptionalPackagePresetSupported, listOptionalPackagePresets, MAX_NATIVE_PACKAGE_NODE_MAJOR, normalizeOptionalPackagePresetName, resolvePackageSource, updatePiPackages, } from "./pi/packages.js";
21
+ import { installPiPackage, listOptionalPackagePresets, normalizeOptionalPackagePresetName, resolvePackageSource, updatePiPackages, } from "./pi/packages.js";
22
22
  import { canonicalizeModelSpec, ensureFeynmanSettings, normalizeThinkingLevel, readJson, } from "./pi/settings.js";
23
23
  import { BUNDLED_PI_PACKAGES, buildPiEnv } from "./pi/runtime.js";
24
24
  import { getConfiguredServiceTier, normalizeServiceTier, setConfiguredServiceTier } from "./model/service-tier.js";
@@ -266,11 +266,6 @@ async function handlePackagesCommand(subcommand, args, piOptions) {
266
266
  if (!presetName) {
267
267
  throw new Error(`Unknown package preset: ${target}`);
268
268
  }
269
- if (!isOptionalPackagePresetSupported(presetName)) {
270
- console.log(`${presetName} is not available on this runtime.`);
271
- console.log(`Its sqlite-backed dependency is only supported through Node ${MAX_NATIVE_PACKAGE_NODE_MAJOR}.x.`);
272
- return;
273
- }
274
269
  const source = resolvePackageSource(presetName);
275
270
  if (configuredSources.has(source)) {
276
271
  console.log(`${source} already installed`);
@@ -448,6 +443,7 @@ async function runMain(input) {
448
443
  model: { type: "string" },
449
444
  "new-session": { type: "boolean" },
450
445
  "no-session": { type: "boolean" },
446
+ "no-themes": { type: "boolean" },
451
447
  prompt: { type: "string" },
452
448
  resume: { type: "boolean", short: "r" },
453
449
  "service-tier": { type: "string" },
@@ -668,7 +664,8 @@ async function runMain(input) {
668
664
  thinkingLevel: launchThinkingLevel,
669
665
  explicitModelSpec,
670
666
  resumeRecentSession,
671
- piArgs,
667
+ // ACP adapters such as pi-acp pass --no-themes with --mode rpc.
668
+ piArgs: values["no-themes"] ? [...piArgs, "--no-themes"] : piArgs,
672
669
  preLaunchNotice,
673
670
  ...promptOptions,
674
671
  });
@@ -1,6 +1,5 @@
1
1
  import { runPi } from "./launch.js";
2
2
  import { buildPiEnv } from "./runtime.js";
3
- export const MAX_NATIVE_PACKAGE_NODE_MAJOR = 22;
4
3
  export const OPTIONAL_PACKAGE_PRESETS = {
5
4
  memory: {
6
5
  description: "Research-session preference and correction memory.",
@@ -10,29 +9,13 @@ export const OPTIONAL_PACKAGE_PRESETS = {
10
9
  description: "Hindsight-backed research continuity memory.",
11
10
  source: "npm:@luxusai/pi-hindsight",
12
11
  },
13
- "session-search": {
14
- description: "Indexed recall for prior research session transcripts.",
15
- source: "npm:@kaiserlich-dev/pi-session-search",
16
- maxNodeMajor: MAX_NATIVE_PACKAGE_NODE_MAJOR,
17
- },
18
12
  };
19
- function parseNodeMajor(version) {
20
- return Number.parseInt(version.replace(/^v/, "").split(".")[0] ?? "0", 10) || 0;
21
- }
22
- export function supportsNativePackageSources(version = process.versions.node) {
23
- return parseNodeMajor(version) <= MAX_NATIVE_PACKAGE_NODE_MAJOR;
24
- }
25
13
  export function normalizeOptionalPackagePresetName(name) {
26
14
  const normalized = name.trim().toLowerCase();
27
15
  return normalized in OPTIONAL_PACKAGE_PRESETS ? normalized : undefined;
28
16
  }
29
- export function isOptionalPackagePresetSupported(name, version = process.versions.node) {
30
- const preset = OPTIONAL_PACKAGE_PRESETS[name];
31
- return !preset.maxNodeMajor || parseNodeMajor(version) <= preset.maxNodeMajor;
32
- }
33
- export function listOptionalPackagePresets(version = process.versions.node) {
17
+ export function listOptionalPackagePresets() {
34
18
  return Object.keys(OPTIONAL_PACKAGE_PRESETS)
35
- .filter((name) => isOptionalPackagePresetSupported(name, version))
36
19
  .map((name) => ({ name, ...OPTIONAL_PACKAGE_PRESETS[name] }));
37
20
  }
38
21
  export function resolvePackageSource(name) {
@@ -1,5 +1,4 @@
1
1
  export const MIN_NODE_VERSION = "22.22.0";
2
- export const MAX_NODE_MAJOR = 25;
3
2
  export const PREFERRED_NODE_MAJOR = 24;
4
3
  function parseNodeVersion(version) {
5
4
  const [major = "0", minor = "0", patch = "0"] = version.replace(/^v/, "").split(".");
@@ -17,20 +16,15 @@ function compareNodeVersions(left, right) {
17
16
  return left.patch - right.patch;
18
17
  }
19
18
  export function isSupportedNodeVersion(version = process.versions.node) {
20
- const parsed = parseNodeVersion(version);
21
- return compareNodeVersions(parsed, parseNodeVersion(MIN_NODE_VERSION)) >= 0 && parsed.major <= MAX_NODE_MAJOR;
19
+ return compareNodeVersions(parseNodeVersion(version), parseNodeVersion(MIN_NODE_VERSION)) >= 0;
22
20
  }
23
21
  export function getUnsupportedNodeVersionLines(version = process.versions.node) {
24
22
  const isWindows = process.platform === "win32";
25
- const parsed = parseNodeVersion(version);
26
- const rangeText = `Node.js ${MIN_NODE_VERSION} through ${MAX_NODE_MAJOR}.x`;
27
23
  return [
28
- `feynman supports ${rangeText} (detected ${version}).`,
29
- parsed.major > MAX_NODE_MAJOR
30
- ? "This newer Node release is not supported yet."
31
- : isWindows
32
- ? "Install a supported Node.js release from https://nodejs.org, or use the standalone installer:"
33
- : `Switch to a supported Node release with \`nvm install ${PREFERRED_NODE_MAJOR} && nvm use ${PREFERRED_NODE_MAJOR}\`, or use the standalone installer:`,
24
+ `feynman requires Node.js ${MIN_NODE_VERSION} or newer (detected ${version}).`,
25
+ isWindows
26
+ ? "Install a supported Node.js release from https://nodejs.org, or use the standalone installer:"
27
+ : `Switch to a supported Node release with \`nvm install ${PREFERRED_NODE_MAJOR} && nvm use ${PREFERRED_NODE_MAJOR}\`, or use the standalone installer:`,
34
28
  isWindows
35
29
  ? "irm https://feynman.is/install.ps1 | iex"
36
30
  : "curl -fsSL https://feynman.is/install | bash",
@@ -18,6 +18,19 @@ function formatText(value: unknown): string {
18
18
  return JSON.stringify(value, null, 2);
19
19
  }
20
20
 
21
+ // alphaXiv's API has changed without notice before; when a call fails, point
22
+ // the model at the other paper sources instead of leaving it on a broken tool.
23
+ async function withPaperFallback<T>(run: () => Promise<T>): Promise<T> {
24
+ try {
25
+ return await run();
26
+ } catch (error) {
27
+ const message = (error instanceof Error ? error.message : String(error)).replace("`alpha login`", "`feynman alpha login`");
28
+ throw new Error(
29
+ `${message}\nalphaXiv did not answer this call. Use feynman_science_database_search (source "arxiv" or "semanticscholar") or fetch_content on https://arxiv.org/abs/<id> instead.`,
30
+ );
31
+ }
32
+ }
33
+
21
34
  // Pi converts Type.Array inputs before validating them, which would turn null into ["null"].
22
35
  // Preserve the JSON Schema array contract without the Type.Array conversion marker.
23
36
  const paperSectionsSchema = Type.Unsafe<string[]>({
@@ -47,7 +60,7 @@ export function registerAlphaTools(pi: ExtensionAPI): void {
47
60
  ),
48
61
  }),
49
62
  async execute(_toolCallId, params) {
50
- const result = await searchPapers(params.query, params.mode?.trim() || "semantic");
63
+ const result = await withPaperFallback(() => searchPapers(params.query, params.mode?.trim() || "semantic"));
51
64
  return { content: [{ type: "text", text: formatText(result) }], details: result };
52
65
  },
53
66
  });
@@ -69,7 +82,7 @@ export function registerAlphaTools(pi: ExtensionAPI): void {
69
82
  sections: Type.Optional(paperSectionsSchema),
70
83
  }),
71
84
  async execute(_toolCallId, params) {
72
- const result = await getPaper(params.paper, { fullText: params.fullText });
85
+ const result = await withPaperFallback(() => getPaper(params.paper, { fullText: params.fullText }));
73
86
  const extracted = extractPaperSections(result.content, params.section, params.sections);
74
87
  const filteredResult = extracted.requested.length
75
88
  ? {
@@ -92,7 +105,7 @@ export function registerAlphaTools(pi: ExtensionAPI): void {
92
105
  question: Type.String({ description: "Question about the paper." }),
93
106
  }),
94
107
  async execute(_toolCallId, params) {
95
- const result = await askPaper(params.paper, params.question);
108
+ const result = await withPaperFallback(() => askPaper(params.paper, params.question));
96
109
  return { content: [{ type: "text", text: formatText(result) }], details: result };
97
110
  },
98
111
  });
@@ -54,8 +54,8 @@ export const livePackageCommandGroups = [
54
54
  title: "Live Package Commands",
55
55
  commands: [
56
56
  { name: "search", usage: "/search" },
57
- { name: "web-results", usage: "/web-results" },
58
- { name: "preview", usage: "/preview" },
57
+ { name: "websearch", usage: "/websearch" },
58
+ { name: "curator", usage: "/curator" },
59
59
  { name: "hotkeys", usage: "/hotkeys" },
60
60
  { name: "new", usage: "/new" },
61
61
  { name: "quit", usage: "/quit" },
@@ -161,6 +161,7 @@ export const legacyFlags = [
161
161
  { usage: "--session <path|id>", description: "Open a specific session." },
162
162
  { usage: "--fork <path|id>", description: "Fork a session into a new one." },
163
163
  { usage: "--no-session", description: "Use an in-memory session that is not persisted." },
164
+ { usage: "--no-themes", description: "Skip theme loading (passed by ACP adapters such as pi-acp)." },
164
165
  { usage: "--export <session.jsonl> [out.html]", description: "Export a session file to HTML and exit." },
165
166
  { usage: "--doctor", description: "Alias for `feynman doctor`." },
166
167
  { usage: "--setup-preview", description: "Alias for `feynman setup preview`." },
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@companion-ai/feynman",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "Research-first CLI agent built on Pi and alphaXiv",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "engines": {
8
- "node": ">=22.22.0 <26"
8
+ "node": ">=22.22.0"
9
9
  },
10
10
  "bin": {
11
11
  "feynman": "bin/feynman.js"
@@ -77,16 +77,16 @@
77
77
  }
78
78
  },
79
79
  "dependencies": {
80
- "@clack/prompts": "^1.7.0",
80
+ "@clack/prompts": "^1.8.1",
81
81
  "@companion-ai/alpha-hub": "0.1.6",
82
82
  "@earendil-works/pi-ai": "*",
83
83
  "@earendil-works/pi-coding-agent": "*",
84
84
  "fast-xml-parser": "5.11.1",
85
- "pi-btw": "0.6.0",
85
+ "pi-btw": "0.6.1",
86
86
  "pi-docparser": "4.0.0",
87
87
  "pi-subagents": "0.71.0",
88
88
  "pi-web-access": "0.31.0",
89
- "posthog-node": "^5.51.6"
89
+ "posthog-node": "^5.53.0"
90
90
  },
91
91
  "peerDependencies": {
92
92
  "@earendil-works/pi-ai": "*",
@@ -95,10 +95,10 @@
95
95
  "typebox": "*"
96
96
  },
97
97
  "devDependencies": {
98
- "@types/node": "^26.4.1",
99
- "tsx": "^4.23.13",
98
+ "@types/node": "^26.6.2",
99
+ "tsx": "^4.23.15",
100
100
  "typescript": "^7.0.2",
101
- "yaml": "2.9.0"
101
+ "yaml": "2.9.1"
102
102
  },
103
103
  "repository": {
104
104
  "type": "git",
@@ -1,5 +1,4 @@
1
1
  const MIN_NODE_VERSION = "22.22.0";
2
- const MAX_NODE_MAJOR = 25;
3
2
  const PREFERRED_NODE_MAJOR = 24;
4
3
 
5
4
  function parseNodeVersion(version) {
@@ -18,20 +17,16 @@ function compareNodeVersions(left, right) {
18
17
  }
19
18
 
20
19
  function isSupportedNodeVersion(version = process.versions.node) {
21
- const parsed = parseNodeVersion(version);
22
- return compareNodeVersions(parsed, parseNodeVersion(MIN_NODE_VERSION)) >= 0 && parsed.major <= MAX_NODE_MAJOR;
20
+ return compareNodeVersions(parseNodeVersion(version), parseNodeVersion(MIN_NODE_VERSION)) >= 0;
23
21
  }
24
22
 
25
23
  function getUnsupportedNodeVersionLines(version = process.versions.node) {
26
24
  const isWindows = process.platform === "win32";
27
- const parsed = parseNodeVersion(version);
28
25
  return [
29
- `feynman supports Node.js ${MIN_NODE_VERSION} through ${MAX_NODE_MAJOR}.x (detected ${version}).`,
30
- parsed.major > MAX_NODE_MAJOR
31
- ? "This newer Node release is not supported yet."
32
- : isWindows
33
- ? "Install a supported Node.js release from https://nodejs.org, or use the standalone installer:"
34
- : `Switch to a supported Node release with \`nvm install ${PREFERRED_NODE_MAJOR} && nvm use ${PREFERRED_NODE_MAJOR}\`, or use the standalone installer:`,
26
+ `feynman requires Node.js ${MIN_NODE_VERSION} or newer (detected ${version}).`,
27
+ isWindows
28
+ ? "Install a supported Node.js release from https://nodejs.org, or use the standalone installer:"
29
+ : `Switch to a supported Node release with \`nvm install ${PREFERRED_NODE_MAJOR} && nvm use ${PREFERRED_NODE_MAJOR}\`, or use the standalone installer:`,
35
30
  isWindows
36
31
  ? "irm https://feynman.is/install.ps1 | iex"
37
32
  : "curl -fsSL https://feynman.is/install | bash",
@@ -42,11 +37,5 @@ if (!isSupportedNodeVersion()) {
42
37
  for (const line of getUnsupportedNodeVersionLines()) {
43
38
  console.error(line);
44
39
  }
45
- // Too-new Node must not abort the install: failing preinstall makes npm roll
46
- // back to the previously installed version, which pins users to a release that
47
- // predates the fix they are trying to get (issue #177). The launcher in
48
- // bin/feynman.js enforces the supported range at runtime with the same message.
49
- if (parseNodeVersion(process.versions.node).major <= MAX_NODE_MAJOR) {
50
- process.exit(1);
51
- }
40
+ process.exit(1);
52
41
  }
@@ -12,7 +12,8 @@ const appRoot = realpathSync(resolve(feynmanBin, "..", ".."));
12
12
  const home = mkdtempSync(join(tmpdir(), "feynman-rpc-"));
13
13
  const env = { ...process.env, FEYNMAN_HOME: home, HOME: home, USERPROFILE: home, FEYNMAN_TELEMETRY: "0", PI_OFFLINE: "1" };
14
14
 
15
- const child = spawn(process.execPath, [feynmanBin, "--mode", "rpc", "--no-session"], { cwd: home, env });
15
+ // --no-themes is what ACP adapters such as pi-acp pass; Feynman must accept it.
16
+ const child = spawn(process.execPath, [feynmanBin, "--mode", "rpc", "--no-session", "--no-themes"], { cwd: home, env });
16
17
  let stdout = "";
17
18
  let stderr = "";
18
19
  child.stderr.on("data", (chunk) => { stderr += chunk; });
@@ -5,7 +5,7 @@ description: Search, read, and query research papers via Feynman's alphaXiv-back
5
5
 
6
6
  # Alpha Research CLI
7
7
 
8
- Use visible Feynman alpha tools when they are available. For shell commands, use `feynman alpha ...`; do not call the user's bare global `alpha` binary because it can be stale or unpatched.
8
+ Use visible Feynman alpha tools when they are available. For shell commands, use `feynman alpha ...`; do not call the user's bare global `alpha` binary because it can be stale.
9
9
 
10
10
  ## Commands
11
11
 
@@ -7,6 +7,6 @@ description: Bounded research experiment loop that tries hypotheses, measures be
7
7
 
8
8
  Run the `/autoresearch` workflow. The slash command expands the full workflow instructions in the active session; do not try to read a relative prompt-template path from the installed skill directory.
9
9
 
10
- Optional tools used when visible: `init_experiment`, `run_experiment`, `log_experiment`. Without those tools, run the benchmark through the available shell/tooling and record benchmark result, evidence, and decision in the session files.
10
+ Run the benchmark through the shell and record each result, its evidence, and the keep/revert decision in the session files.
11
11
 
12
12
  Session files: `autoresearch.md`, `autoresearch.sh`, `autoresearch.jsonl`
@@ -1,29 +1,16 @@
1
1
  ---
2
2
  name: preview
3
- description: Preview Markdown, LaTeX, PDF, or code artifacts when preview commands are visible, or fall back to shell/browser tools. Use when the user wants to review a written artifact, export a report, or view a rendered document.
3
+ description: Render Markdown or LaTeX research artifacts to HTML or PDF with pandoc. Use when the user wants to review a written artifact, export a report, or view a rendered document.
4
4
  ---
5
5
 
6
6
  # Preview
7
7
 
8
- Use `/preview` only when that command is visible in the active session. If preview commands are unavailable, render or open artifacts with shell/browser tools and report that the preview package is not installed.
9
-
10
- ## Commands
11
-
12
- | Command | Description |
13
- |---------|-------------|
14
- | `/preview` | Preview the most recent artifact in the browser, when available |
15
- | `/preview --file <path>` | Preview a specific file, when available |
16
- | `/preview-browser` | Force browser preview, when available |
17
- | `/preview-pdf` | Export to PDF via pandoc + LaTeX, when available |
18
- | `/preview-clear-cache` | Clear rendered preview cache, when available |
19
-
20
- ## Fallback
21
-
22
- If the preview commands are not available, use bash:
8
+ Render Markdown or LaTeX artifacts with pandoc through the shell. `feynman setup preview` checks for pandoc, and `feynman doctor` reports whether it is available.
23
9
 
24
10
  ```bash
25
- open <file.md> # macOS — opens in default app
26
- open <file.pdf> # macOS — opens in Preview
27
- pandoc input.md -o output.html
28
- pandoc input.md -o output.pdf
11
+ pandoc outputs/<slug>.md -s -o outputs/<slug>.html # HTML
12
+ pandoc outputs/<slug>.md -o outputs/<slug>.pdf # PDF (needs a LaTeX engine)
13
+ open outputs/<slug>.html # macOS; xdg-open on Linux
29
14
  ```
15
+
16
+ Rendered HTML and PDF files are previews; the Markdown artifact stays canonical. If pandoc or a LaTeX engine is missing, say so and leave the Markdown artifact as the deliverable.
@@ -1,26 +1,15 @@
1
1
  ---
2
2
  name: session-search
3
- description: Recover prior Feynman work from session transcripts. Use the optional /search command only when it is installed and visible; otherwise search local session JSONL files directly.
3
+ description: Search prior Feynman session transcripts on disk. Use when the user asks about earlier research sessions, past findings, or wants to resume a prior session.
4
4
  ---
5
5
 
6
6
  # Session Search
7
7
 
8
- Use the `/search` command to search prior Feynman sessions interactively only when the optional session-search package is installed and the command is visible. Otherwise, search session JSONL files directly via bash.
9
-
10
- ## Interactive search
11
-
12
- ```
13
- /search <query>
14
- ```
15
-
16
- Opens the session search UI when the optional package is loaded. Supports `resume <sessionPath>` to continue a found session.
17
-
18
- ## Direct file search
19
-
20
- Session transcripts are stored as JSONL files in `~/.feynman/sessions/`. Each line is a JSON record with `type` (session, message, model_change) and `message.content` fields.
8
+ Feynman stores session transcripts as JSONL files under `~/.feynman/sessions/` (or `$FEYNMAN_HOME/.feynman/sessions/`). Each line is a JSON record with a `type` (session, message, model_change) and, for messages, `message.content`.
21
9
 
22
10
  ```bash
23
- grep -ril "scaling laws" ~/.feynman/sessions/
11
+ grep -ril "scaling laws" ~/.feynman/sessions/ # sessions that mention a topic
12
+ grep -il "scaling laws" -r ~/.feynman/sessions/ | xargs ls -t # newest first
24
13
  ```
25
14
 
26
- For structured search across sessions, use the interactive `/search` command when it is visible. If it is unavailable, direct file search is the supported fallback.
15
+ To continue a session you found, run `feynman --session <path>` or pick it with `feynman --resume`.