fix(npm): use latest entry points without install scripts
This commit is contained in:
parent
81ed68f67d
commit
34252f55e9
|
|
@ -8,7 +8,6 @@ REA development requires Node.js 24.18.x and npm 11.16.x. Real-Hopper verificati
|
|||
|
||||
```bash
|
||||
npm ci
|
||||
npm run rebuild:native # only when the packaged PTY binary is incompatible
|
||||
npm test
|
||||
```
|
||||
|
||||
|
|
@ -78,8 +77,8 @@ npm publish --access public
|
|||
After npm registry propagation, verify the published CLI and connect the client SDK version pinned in `package.json` to the published server to confirm the canonical tool catalog:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents --help
|
||||
npx -y rea-agents doctor
|
||||
npx -y rea-agents setup --yes
|
||||
npx -y rea-agents mcp
|
||||
npx -y rea-agents@latest --help
|
||||
npx -y rea-agents@latest doctor
|
||||
npx -y rea-agents@latest setup --yes
|
||||
npx -y rea-agents@latest mcp
|
||||
```
|
||||
|
|
|
|||
45
README.md
45
README.md
|
|
@ -117,9 +117,9 @@ Review the setup plan, approve it if appropriate, then describe the app or featu
|
|||
### From Terminal — no installation
|
||||
|
||||
```bash
|
||||
npx -y rea-agents setup
|
||||
npx -y rea-agents doctor
|
||||
npx -y rea-agents analyze /Applications/Notes.app
|
||||
npx -y rea-agents@latest setup
|
||||
npx -y rea-agents@latest doctor
|
||||
npx -y rea-agents@latest analyze /Applications/Notes.app
|
||||
```
|
||||
|
||||
Review the setup plan before confirming it. Restart a configured agent so it loads REA.
|
||||
|
|
@ -146,6 +146,11 @@ an unrelated global package.
|
|||
|
||||
Choose either the no-install commands or the global installation. You do not need both.
|
||||
|
||||
`npm install rea-agents` without `--global` installs `rea` only into the
|
||||
current project's `node_modules/.bin`; it does not add `rea` to your shell
|
||||
`PATH`. Use the `npx` commands above for one-off runs or `--global` when you
|
||||
want a shell-visible `rea` command.
|
||||
|
||||
### Requirements
|
||||
|
||||
- macOS 12 or newer
|
||||
|
|
@ -159,7 +164,7 @@ Deep binary operations use [Hopper](https://www.hopperapp.com/), a separate desk
|
|||
If something is not working, run:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents doctor
|
||||
npx -y rea-agents@latest doctor
|
||||
```
|
||||
|
||||
`rea doctor --json` is read-only and distinguishes unsupported hosts, missing dependencies, a missing local analysis engine, configuration drift, and healthy checks. Paid-license activation is optional: on Linux, REA runs the supported Hopper demo build on a private Xvfb display and selects Hopper's offered demo mode for each analysis session.
|
||||
|
|
@ -432,7 +437,7 @@ Setup detects Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf,
|
|||
"mcpServers": {
|
||||
"rea": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "rea-agents", "mcp"]
|
||||
"args": ["-y", "rea-agents@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -473,20 +478,20 @@ The CLI and MCP server use the same application workflows and evidence contracts
|
|||
The agent workflow above is the easiest way to use REA. For a one-off overview from the Terminal:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents analyze /Applications/Notes.app
|
||||
npx -y rea-agents inspect /Applications/Notes.app
|
||||
npx -y rea-agents inspect /Applications/Notes.app --detail detailed --limit 20
|
||||
npx -y rea-agents search /Applications/Notes.app "offline"
|
||||
npx -y rea-agents function /Applications/Notes.app 0x1000
|
||||
npx -y rea-agents xrefs /Applications/Notes.app 0x1000
|
||||
npx -y rea-agents trace /Applications/Notes.app "offline"
|
||||
npx -y rea-agents compare /absolute/path/to/left-evidence.json /absolute/path/to/right-evidence.json
|
||||
npx -y rea-agents investigate-versions /path/to/v1 /path/to/v2 /absolute/path/to/evidence/releases.json --yes
|
||||
npx -y rea-agents capabilities
|
||||
npx -y rea-agents providers
|
||||
npx -y rea-agents@latest analyze /Applications/Notes.app
|
||||
npx -y rea-agents@latest inspect /Applications/Notes.app
|
||||
npx -y rea-agents@latest inspect /Applications/Notes.app --detail detailed --limit 20
|
||||
npx -y rea-agents@latest search /Applications/Notes.app "offline"
|
||||
npx -y rea-agents@latest function /Applications/Notes.app 0x1000
|
||||
npx -y rea-agents@latest xrefs /Applications/Notes.app 0x1000
|
||||
npx -y rea-agents@latest trace /Applications/Notes.app "offline"
|
||||
npx -y rea-agents@latest compare /absolute/path/to/left-evidence.json /absolute/path/to/right-evidence.json
|
||||
npx -y rea-agents@latest investigate-versions /path/to/v1 /path/to/v2 /absolute/path/to/evidence/releases.json --yes
|
||||
npx -y rea-agents@latest capabilities
|
||||
npx -y rea-agents@latest providers
|
||||
```
|
||||
|
||||
Run `npx -y rea-agents --help` for direct decompilation, bounded search and
|
||||
Run `npx -y rea-agents@latest --help` for direct decompilation, bounded search and
|
||||
other options. `analyze` and `inspect` share the same overview workflow;
|
||||
`function`, `xrefs`, and `trace` return the same Evidence v2 envelopes as MCP.
|
||||
|
||||
|
|
@ -588,9 +593,9 @@ first terminal, interaction, exit, filesystem, protocol, process, or shim
|
|||
divergence. See [Process Capture v4](docs/process-capture.md) for scenario
|
||||
fields, command-shim replay, checkpoint triggers, limits, and safety behavior.
|
||||
|
||||
If the native PTY backend is unavailable, install Xcode command-line tools and
|
||||
run `npm run rebuild:native`. Linux source builds require Python, `make`, and a
|
||||
C++ toolchain. Compatible packaged binaries do not require this rebuild.
|
||||
REA installs a prebuilt PTY backend for supported macOS, Linux, and Windows
|
||||
architectures. If the capability check reports that the backend is unavailable,
|
||||
reinstall REA for the current platform and architecture.
|
||||
|
||||
ASAR inventory verifies Electron integrity metadata for both archive entries
|
||||
and `.asar.unpacked` companion files. Integrity failures identify the logical
|
||||
|
|
|
|||
12
README_ar.md
12
README_ar.md
|
|
@ -90,7 +90,7 @@ npx skills add morluto/rea
|
|||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
|
||||
npx -y rea-agents setup
|
||||
npx -y rea-agents@latest setup
|
||||
```
|
||||
|
||||
إذا طلب macOS أو برنامج التثبيت تأكيدًا، فأكمل الخطوة ثم شغّل الأمر نفسه مرة أخرى.
|
||||
|
|
@ -111,7 +111,7 @@ npx -y rea-agents setup
|
|||
إذا واجهت مشكلة، فشغّل:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents doctor
|
||||
npx -y rea-agents@latest doctor
|
||||
rea uninstall
|
||||
rea uninstall --purge-data
|
||||
```
|
||||
|
|
@ -180,7 +180,7 @@ rea uninstall --purge-data
|
|||
"mcpServers": {
|
||||
"rea": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "rea-agents", "mcp"]
|
||||
"args": ["-y", "rea-agents@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -206,11 +206,11 @@ flowchart LR
|
|||
سير عمل الوكيل أعلاه هو أسهل طريقة لاستخدام REA. للحصول على نظرة سريعة على تطبيق من الطرفية:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents analyze /Applications/Notes.app
|
||||
npx -y rea-agents compare /absolute/path/to/left-evidence.json /absolute/path/to/right-evidence.json
|
||||
npx -y rea-agents@latest analyze /Applications/Notes.app
|
||||
npx -y rea-agents@latest compare /absolute/path/to/left-evidence.json /absolute/path/to/right-evidence.json
|
||||
```
|
||||
|
||||
شغّل `npx -y rea-agents --help` لمعرفة خيارات فك الترجمة المباشر والخيارات الأخرى.
|
||||
شغّل `npx -y rea-agents@latest --help` لمعرفة خيارات فك الترجمة المباشر والخيارات الأخرى.
|
||||
|
||||
يمكن لـ REA فتح مجلد `.app` على Mac مباشرة. إذا لم يعثر الوكيل على التطبيق، فأخبره بمكان تثبيته.
|
||||
|
||||
|
|
|
|||
10
README_ja.md
10
README_ja.md
|
|
@ -91,7 +91,7 @@ Ubuntu 24.04+、Fedora 41+、64 ビット Arch Linux では、REA が公式の D
|
|||
```bash
|
||||
# 1. REA をセットアップ
|
||||
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
|
||||
npx -y rea-agents setup
|
||||
npx -y rea-agents@latest setup
|
||||
```
|
||||
|
||||
macOS やインストーラーから確認を求められた場合は、その操作を完了してから同じコマンドをもう一度実行してください。
|
||||
|
|
@ -112,7 +112,7 @@ REA でメモアプリをリバースエンジニアリングしてください
|
|||
問題がある場合は次を実行します:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents doctor
|
||||
npx -y rea-agents@latest doctor
|
||||
rea uninstall
|
||||
rea uninstall --purge-data
|
||||
```
|
||||
|
|
@ -170,7 +170,7 @@ Setup は Claude Code、Claude Desktop、Codex、Cursor、Gemini CLI、Windsurf
|
|||
"mcpServers": {
|
||||
"rea": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "rea-agents", "mcp"]
|
||||
"args": ["-y", "rea-agents@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -195,10 +195,10 @@ CLI と MCP サーバーは同じ解析エンジンを使います。ターミ
|
|||
上のエージェントワークフローが、REA を使う最も簡単な方法です。ターミナルから一度だけアプリの概要を調べる場合は、次を実行します。
|
||||
|
||||
```bash
|
||||
npx -y rea-agents analyze /Applications/Notes.app
|
||||
npx -y rea-agents@latest analyze /Applications/Notes.app
|
||||
```
|
||||
|
||||
直接デコンパイルする方法やその他のオプションは、`npx -y rea-agents --help` で確認できます。
|
||||
直接デコンパイルする方法やその他のオプションは、`npx -y rea-agents@latest --help` で確認できます。
|
||||
|
||||
グローバルな `rea` コマンドとしてもインストールできます。
|
||||
|
||||
|
|
|
|||
10
README_ko.md
10
README_ko.md
|
|
@ -91,7 +91,7 @@ Ubuntu 24.04+, Fedora 41+, 64비트 Arch Linux에서 REA는 공식 DEB, RPM 또
|
|||
```bash
|
||||
# 1. REA 설정
|
||||
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
|
||||
npx -y rea-agents setup
|
||||
npx -y rea-agents@latest setup
|
||||
```
|
||||
|
||||
macOS나 설치 프로그램이 확인을 요청하면 해당 절차를 완료하고 같은 명령을 다시 실행하세요.
|
||||
|
|
@ -112,7 +112,7 @@ SQLite를 사용해 제 프로젝트에 비슷한 기능을 구현해 주세요.
|
|||
문제가 있으면 다음을 실행하세요.
|
||||
|
||||
```bash
|
||||
npx -y rea-agents doctor
|
||||
npx -y rea-agents@latest doctor
|
||||
rea uninstall
|
||||
rea uninstall --purge-data
|
||||
```
|
||||
|
|
@ -170,7 +170,7 @@ Setup은 Claude Code, Claude Desktop, Codex, Cursor, Gemini CLI, Windsurf, Devin
|
|||
"mcpServers": {
|
||||
"rea": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "rea-agents", "mcp"]
|
||||
"args": ["-y", "rea-agents@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -195,10 +195,10 @@ CLI와 MCP 서버는 같은 분석 엔진을 사용합니다. 터미널 명령
|
|||
위의 에이전트 워크플로가 REA를 사용하는 가장 쉬운 방법입니다. 터미널에서 앱을 한 번 빠르게 살펴보려면 다음을 실행하세요.
|
||||
|
||||
```bash
|
||||
npx -y rea-agents analyze /Applications/Notes.app
|
||||
npx -y rea-agents@latest analyze /Applications/Notes.app
|
||||
```
|
||||
|
||||
직접 디컴파일하는 방법과 기타 옵션은 `npx -y rea-agents --help`에서 확인할 수 있습니다.
|
||||
직접 디컴파일하는 방법과 기타 옵션은 `npx -y rea-agents@latest --help`에서 확인할 수 있습니다.
|
||||
|
||||
전역 `rea` 명령으로 설치할 수도 있습니다.
|
||||
|
||||
|
|
|
|||
10
README_zh.md
10
README_zh.md
|
|
@ -91,7 +91,7 @@ npx skills add morluto/rea
|
|||
```bash
|
||||
# 1. 安装和配置 REA
|
||||
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
|
||||
npx -y rea-agents setup
|
||||
npx -y rea-agents@latest setup
|
||||
```
|
||||
|
||||
如果 macOS 或安装程序要求确认,请完成提示,然后再次运行同一命令。
|
||||
|
|
@ -112,7 +112,7 @@ Setup 会检测 Claude Code、Claude Desktop、Codex、Cursor、Gemini CLI、Win
|
|||
如果遇到问题,请运行:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents doctor
|
||||
npx -y rea-agents@latest doctor
|
||||
rea uninstall
|
||||
rea uninstall --purge-data
|
||||
```
|
||||
|
|
@ -170,7 +170,7 @@ Setup 会检测 Claude Code、Claude Desktop、Codex、Cursor、Gemini CLI、Win
|
|||
"mcpServers": {
|
||||
"rea": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "rea-agents", "mcp"]
|
||||
"args": ["-y", "rea-agents@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -195,10 +195,10 @@ CLI 与 MCP 服务器使用相同的分析引擎。终端命令完成后会关
|
|||
上面的智能体工作流是使用 REA 最简单的方式。如果只想在终端中快速了解一个应用:
|
||||
|
||||
```bash
|
||||
npx -y rea-agents analyze /Applications/Notes.app
|
||||
npx -y rea-agents@latest analyze /Applications/Notes.app
|
||||
```
|
||||
|
||||
运行 `npx -y rea-agents --help` 查看直接反编译和其他选项。
|
||||
运行 `npx -y rea-agents@latest --help` 查看直接反编译和其他选项。
|
||||
|
||||
也可以全局安装 `rea` 命令:
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
</div>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><a href="../types/application_ProcessCaptureCapability.ProcessCaptureCapability.html" class="tsd-signature-type tsd-kind-type-alias">ProcessCaptureCapability</a><span class="tsd-signature-symbol">></span></h4><aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/application/ProcessCaptureCapability.ts#L14">src/application/ProcessCaptureCapability.ts:14</a></li></ul></aside></div></li></ul></section></div>
|
||||
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/application/ProcessCaptureCapability.ts#L13">src/application/ProcessCaptureCapability.ts:13</a></li></ul></aside></div></li></ul></section></div>
|
||||
<div class="col-sidebar">
|
||||
<div class="page-menu">
|
||||
<div class="tsd-navigation settings">
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<li><span><code class="tsd-tag">Optional</code><span class="tsd-kind-parameter">signal</span>: <span class="tsd-signature-type">AbortSignal</span></span></li></ul></div>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><a href="../types/domain_result.Result.html" class="tsd-signature-type tsd-kind-type-alias">Result</a><span class="tsd-signature-symbol"><</span><a href="../interfaces/domain_processCapture.ProcessCapture.html" class="tsd-signature-type tsd-kind-interface">ProcessCapture</a><span class="tsd-signature-symbol">,</span> <a href="../classes/application_ProcessCaptureError.ProcessCaptureError.html" class="tsd-signature-type tsd-kind-class">ProcessCaptureError</a><span class="tsd-signature-symbol">></span><span class="tsd-signature-symbol">></span></h4><aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/application/ProcessHarness.ts#L494">src/application/ProcessHarness.ts:494</a></li></ul></aside></div></li></ul></section></div>
|
||||
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/application/ProcessHarness.ts#L495">src/application/ProcessHarness.ts:495</a></li></ul></aside></div></li></ul></section></div>
|
||||
<div class="col-sidebar">
|
||||
<div class="page-menu">
|
||||
<div class="tsd-navigation settings">
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<h1>Type Alias ProcessCaptureCapability</h1></div>
|
||||
<div class="tsd-signature"><span class="tsd-kind-type-alias">ProcessCaptureCapability</span><span class="tsd-signature-symbol">:</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">available</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">true</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">backend</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"node-pty"</span> <span class="tsd-signature-symbol">}</span><br/> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-symbol">{</span> <span class="tsd-kind-property">available</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">false</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">backend</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">"node-pty"</span><span class="tsd-signature-symbol">;</span> <span class="tsd-kind-property">reason</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span> <span class="tsd-signature-symbol">}</span></div><aside class="tsd-sources">
|
||||
<ul>
|
||||
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/application/ProcessCaptureCapability.ts#L4">src/application/ProcessCaptureCapability.ts:4</a></li></ul></aside></div>
|
||||
<li>Defined in <a href="https://github.com/morluto/rea/blob/main/src/application/ProcessCaptureCapability.ts#L3">src/application/ProcessCaptureCapability.ts:3</a></li></ul></aside></div>
|
||||
<div class="col-sidebar">
|
||||
<div class="page-menu">
|
||||
<div class="tsd-navigation settings">
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ rea setup
|
|||
|
||||
REA supports Node.js 22.19+ and 24.11+ (including newer releases). It uses the npm already paired with that runtime and never upgrades Node.js, npm, or Homebrew.
|
||||
|
||||
Running `npm install rea-agents` without `--global` installs the executable only
|
||||
in the current project's `node_modules/.bin`; it does not make `rea` available
|
||||
on the shell `PATH`. Use `npx -y rea-agents@latest` for one-off commands or the
|
||||
global installation above for a shell-visible `rea` command.
|
||||
|
||||
The optional curl wrapper installs only the global npm package:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@
|
|||
"": {
|
||||
"name": "rea-agents",
|
||||
"version": "2.0.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "8.0.4",
|
||||
"@babel/types": "8.0.4",
|
||||
"@electron/asar": "4.2.0",
|
||||
"@jridgewell/trace-mapping": "0.3.31",
|
||||
"@lydell/node-pty": "1.1.0",
|
||||
"@modelcontextprotocol/server": "2.0.0-beta.4",
|
||||
"@xterm/addon-serialize": "0.14.0",
|
||||
"@xterm/headless": "6.0.0",
|
||||
|
|
@ -25,7 +25,6 @@
|
|||
"ignore": "7.0.6",
|
||||
"incur": "0.4.13",
|
||||
"isomorphic-git": "1.38.7",
|
||||
"node-pty": "1.1.0",
|
||||
"pino": "9.14.0",
|
||||
"plist": "5.0.0",
|
||||
"semver": "7.8.5",
|
||||
|
|
@ -245,6 +244,98 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@lydell/node-pty": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lydell/node-pty/-/node-pty-1.1.0.tgz",
|
||||
"integrity": "sha512-VDD8LtlMTOrPKWMXUAcB9+LTktzuunqrMwkYR1DMRBkS6LQrCt+0/Ws1o2rMml/n3guePpS7cxhHF7Nm5K4iMw==",
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"@lydell/node-pty-darwin-arm64": "1.1.0",
|
||||
"@lydell/node-pty-darwin-x64": "1.1.0",
|
||||
"@lydell/node-pty-linux-arm64": "1.1.0",
|
||||
"@lydell/node-pty-linux-x64": "1.1.0",
|
||||
"@lydell/node-pty-win32-arm64": "1.1.0",
|
||||
"@lydell/node-pty-win32-x64": "1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lydell/node-pty-darwin-arm64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lydell/node-pty-darwin-arm64/-/node-pty-darwin-arm64-1.1.0.tgz",
|
||||
"integrity": "sha512-7kFD+owAA61qmhJCtoMbqj3Uvff3YHDiU+4on5F2vQdcMI3MuwGi7dM6MkFG/yuzpw8LF2xULpL71tOPUfxs0w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@lydell/node-pty-darwin-x64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lydell/node-pty-darwin-x64/-/node-pty-darwin-x64-1.1.0.tgz",
|
||||
"integrity": "sha512-XZdvqj5FjAMjH8bdp0YfaZjur5DrCIDD1VYiE9EkkYVMDQqRUPHYV3U8BVEQVT9hYfjmpr7dNaELF2KyISWSNA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@lydell/node-pty-linux-arm64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lydell/node-pty-linux-arm64/-/node-pty-linux-arm64-1.1.0.tgz",
|
||||
"integrity": "sha512-yyDBmalCfHpLiQMT2zyLcqL2Fay4Xy7rIs8GH4dqKLnEviMvPGOK7LADVkKAsbsyXBSISL3Lt1m1MtxhPH6ckg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@lydell/node-pty-linux-x64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lydell/node-pty-linux-x64/-/node-pty-linux-x64-1.1.0.tgz",
|
||||
"integrity": "sha512-NcNqRTD14QT+vXcEuqSSvmWY+0+WUBn2uRE8EN0zKtDpIEr9d+YiFj16Uqds6QfcLCHfZmC+Ls7YzwTaqDnanA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@lydell/node-pty-win32-arm64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lydell/node-pty-win32-arm64/-/node-pty-win32-arm64-1.1.0.tgz",
|
||||
"integrity": "sha512-JOMbCou+0fA7d/m97faIIfIU0jOv8sn2OR7tI45u3AmldKoKoLP8zHY6SAvDDnI3fccO1R2HeR1doVjpS7HM0w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@lydell/node-pty-win32-x64": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lydell/node-pty-win32-x64/-/node-pty-win32-x64-1.1.0.tgz",
|
||||
"integrity": "sha512-3N56BZ+WDFnUMYRtsrr7Ky2mhWGl9xXcyqR6cexfuCqcz9RNWL+KoXRv/nZylY5dYaXkft4JaR1uVu+roiZDAw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@modelcontextprotocol/client": {
|
||||
"version": "2.0.0-beta.4",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/client/-/client-2.0.0-beta.4.tgz",
|
||||
|
|
@ -3792,22 +3883,6 @@
|
|||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-pty": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.1.0.tgz",
|
||||
"integrity": "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-addon-api": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/obliterator": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz",
|
||||
|
|
|
|||
11
package.json
11
package.json
|
|
@ -42,8 +42,6 @@
|
|||
"bridge/hopper_bridge.py",
|
||||
"bridge/ghidra/ReaGhidraBridge.java",
|
||||
"scripts/rea.mjs",
|
||||
"scripts/prepare-node-pty.mjs",
|
||||
"scripts/rebuild-native.mjs",
|
||||
"scripts/hopper-demo-x11.py",
|
||||
"skills",
|
||||
"README.md",
|
||||
|
|
@ -66,7 +64,6 @@
|
|||
"scan:todos": "node scripts/scan-todos.mjs",
|
||||
"start": "node scripts/rea.mjs mcp",
|
||||
"pretest": "npm run build",
|
||||
"postinstall": "node scripts/prepare-node-pty.mjs",
|
||||
"test": "vitest run",
|
||||
"pretest:coverage": "npm run build",
|
||||
"test:coverage": "vitest run --coverage.enabled --coverage.provider=v8",
|
||||
|
|
@ -96,8 +93,7 @@
|
|||
"docs:error-schema": "npm run build && node scripts/generate-error-schema.mjs",
|
||||
"prepack": "npm run deps:check && node scripts/generate-skill-metadata.mjs --check",
|
||||
"prepublishOnly": "npm run deps:check && node scripts/generate-skill-metadata.mjs --check",
|
||||
"prepare": "npm run build && husky",
|
||||
"rebuild:native": "node scripts/rebuild-native.mjs"
|
||||
"prepare": "npm run build && husky"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,mjs,json,md,yml,yaml}": "prettier --write",
|
||||
|
|
@ -108,6 +104,7 @@
|
|||
"@babel/types": "8.0.4",
|
||||
"@electron/asar": "4.2.0",
|
||||
"@jridgewell/trace-mapping": "0.3.31",
|
||||
"@lydell/node-pty": "1.1.0",
|
||||
"@modelcontextprotocol/server": "2.0.0-beta.4",
|
||||
"@xterm/addon-serialize": "0.14.0",
|
||||
"@xterm/headless": "6.0.0",
|
||||
|
|
@ -119,7 +116,6 @@
|
|||
"ignore": "7.0.6",
|
||||
"incur": "0.4.13",
|
||||
"isomorphic-git": "1.38.7",
|
||||
"node-pty": "1.1.0",
|
||||
"pino": "9.14.0",
|
||||
"plist": "5.0.0",
|
||||
"semver": "7.8.5",
|
||||
|
|
@ -145,8 +141,5 @@
|
|||
"typedoc": "0.28.20",
|
||||
"typescript": "5.9.3",
|
||||
"vitest": "4.1.10"
|
||||
},
|
||||
"allowScripts": {
|
||||
"node-pty@1.1.0": true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import { chmod, lstat } from "node:fs/promises";
|
||||
import { createRequire } from "node:module";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
if (process.platform !== "win32") {
|
||||
const require = createRequire(import.meta.url);
|
||||
const packageRoot = dirname(
|
||||
require.resolve("node-pty/package.json", {
|
||||
paths: [dirname(fileURLToPath(import.meta.url))],
|
||||
}),
|
||||
);
|
||||
const helperPath = join(
|
||||
packageRoot,
|
||||
"prebuilds",
|
||||
`${process.platform}-${process.arch}`,
|
||||
"spawn-helper",
|
||||
);
|
||||
|
||||
try {
|
||||
const helper = await lstat(helperPath);
|
||||
if (!helper.isFile() || helper.isSymbolicLink()) {
|
||||
throw new Error("node-pty spawn helper is not a regular file");
|
||||
}
|
||||
await chmod(helperPath, helper.mode | 0o111);
|
||||
} catch (error) {
|
||||
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
||||
// Source builds place their correctly-modeled helper under build/Release.
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -35,15 +35,17 @@ const config = {
|
|||
command: "npx",
|
||||
args: [
|
||||
"-y",
|
||||
JSON.parse(
|
||||
await readFile(
|
||||
resolve(
|
||||
fileURLToPath(new URL("..", import.meta.url)),
|
||||
"package.json",
|
||||
`${
|
||||
JSON.parse(
|
||||
await readFile(
|
||||
resolve(
|
||||
fileURLToPath(new URL("..", import.meta.url)),
|
||||
"package.json",
|
||||
),
|
||||
"utf8",
|
||||
),
|
||||
"utf8",
|
||||
),
|
||||
).name,
|
||||
).name
|
||||
}@latest`,
|
||||
"mcp",
|
||||
],
|
||||
env,
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
||||
const child = spawn(npm, ["rebuild", "node-pty"], {
|
||||
stdio: "inherit",
|
||||
env: { ...process.env, npm_config_build_from_source: "true" },
|
||||
});
|
||||
|
||||
child.once("error", (error) => {
|
||||
console.error(`Unable to rebuild node-pty: ${error.message}`);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
child.once("exit", (code, signal) => {
|
||||
if (signal !== null) {
|
||||
console.error(`node-pty rebuild terminated by ${signal}`);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
process.exitCode = code ?? 1;
|
||||
});
|
||||
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
import { Client } from "@modelcontextprotocol/client";
|
||||
|
|
@ -37,6 +38,16 @@ try {
|
|||
const packedFiles = (
|
||||
await exec("tar", ["-tf", join(root, tarball)])
|
||||
).stdout.split("\n");
|
||||
const packedManifest = JSON.parse(
|
||||
(await exec("tar", ["-xOf", join(root, tarball), "package/package.json"]))
|
||||
.stdout,
|
||||
);
|
||||
if (
|
||||
packedManifest.scripts?.postinstall !== undefined ||
|
||||
packedManifest.dependencies?.["node-pty"] !== undefined ||
|
||||
packedManifest.dependencies?.["@lydell/node-pty"] !== "1.1.0"
|
||||
)
|
||||
throw new Error("package retained a lifecycle-dependent PTY installation");
|
||||
if (
|
||||
packedFiles.some(
|
||||
(path) => path.includes("__pycache__") || path.endsWith(".pyc"),
|
||||
|
|
@ -121,10 +132,89 @@ try {
|
|||
};
|
||||
await exec(
|
||||
"npm",
|
||||
["install", "--global", "--prefix", prefix, join(root, tarball)],
|
||||
[
|
||||
"install",
|
||||
"--global",
|
||||
"--ignore-scripts",
|
||||
"--prefix",
|
||||
prefix,
|
||||
join(root, tarball),
|
||||
],
|
||||
{ env: environment },
|
||||
);
|
||||
const cli = join(prefix, "bin", "rea");
|
||||
const processCaptureCapabilityUrl = pathToFileURL(
|
||||
join(
|
||||
prefix,
|
||||
"lib/node_modules/rea-agents/dist/application/ProcessCaptureCapability.js",
|
||||
),
|
||||
).href;
|
||||
const processCaptureCapability = json(
|
||||
(
|
||||
await exec(
|
||||
process.execPath,
|
||||
[
|
||||
"--input-type=module",
|
||||
"--eval",
|
||||
`const { probeProcessCaptureCapability } = await import(${JSON.stringify(processCaptureCapabilityUrl)}); process.stdout.write(JSON.stringify(await probeProcessCaptureCapability()));`,
|
||||
],
|
||||
{ env: environment },
|
||||
)
|
||||
).stdout,
|
||||
);
|
||||
if (processCaptureCapability.available !== true)
|
||||
throw new Error(
|
||||
`packaged PTY backend failed without lifecycle scripts: ${JSON.stringify(processCaptureCapability)}`,
|
||||
);
|
||||
const noOptionalPrefix = join(workspace, "prefix-no-optional");
|
||||
await exec(
|
||||
"npm",
|
||||
[
|
||||
"install",
|
||||
"--global",
|
||||
"--ignore-scripts",
|
||||
"--omit=optional",
|
||||
"--prefix",
|
||||
noOptionalPrefix,
|
||||
join(root, tarball),
|
||||
],
|
||||
{ env: environment },
|
||||
);
|
||||
const noOptionalCli = join(noOptionalPrefix, "bin", "rea");
|
||||
await rm(
|
||||
join(
|
||||
noOptionalPrefix,
|
||||
"lib/node_modules/rea-agents/node_modules/@lydell",
|
||||
`node-pty-${process.platform}-${process.arch}`,
|
||||
),
|
||||
{ recursive: true, force: true },
|
||||
);
|
||||
const noOptionalCapabilityUrl = pathToFileURL(
|
||||
join(
|
||||
noOptionalPrefix,
|
||||
"lib/node_modules/rea-agents/dist/application/ProcessCaptureCapability.js",
|
||||
),
|
||||
).href;
|
||||
const noOptionalCapability = json(
|
||||
(
|
||||
await exec(
|
||||
process.execPath,
|
||||
[
|
||||
"--input-type=module",
|
||||
"--eval",
|
||||
`const { probeProcessCaptureCapability } = await import(${JSON.stringify(noOptionalCapabilityUrl)}); process.stdout.write(JSON.stringify(await probeProcessCaptureCapability()));`,
|
||||
],
|
||||
{ env: environment },
|
||||
)
|
||||
).stdout,
|
||||
);
|
||||
if (
|
||||
!(await run(noOptionalCli, ["--help"], environment)).includes("setup") ||
|
||||
noOptionalCapability.available !== false
|
||||
)
|
||||
throw new Error(
|
||||
`packaged CLI did not degrade without the optional PTY binary: ${JSON.stringify(noOptionalCapability)}`,
|
||||
);
|
||||
const help = await run(cli, ["--help"], environment);
|
||||
const llms = await run(cli, ["--llms"], environment);
|
||||
const doctorExecution = await runWithStatus(
|
||||
|
|
@ -662,8 +752,10 @@ try {
|
|||
);
|
||||
await run(cli, ["mcp", "add"], environment);
|
||||
const mcpRegistration = await readFile(npxLog, "utf8");
|
||||
if (!mcpRegistration.includes("add-mcp npx -y rea-agents mcp --name rea"))
|
||||
throw new Error("Incur mcp add did not register the floating npx command");
|
||||
if (
|
||||
!mcpRegistration.includes("add-mcp npx -y rea-agents@latest mcp --name rea")
|
||||
)
|
||||
throw new Error("Incur mcp add did not register the latest npx command");
|
||||
const skillPath = join(home, ".agents/skills/rea-analysis/SKILL.md");
|
||||
const siblingSkillPath = join(home, ".agents/skills/unrelated/SKILL.md");
|
||||
if (supportedSetupHost) {
|
||||
|
|
@ -1036,7 +1128,7 @@ try {
|
|||
}
|
||||
|
||||
process.stdout.write(
|
||||
`${JSON.stringify({ cli: true, analysisCli: true, artifactCli: true, managedCli: true, managedReconstructionCli: true, managedNativeVerificationCli: true, managedRuntimePlanCli: true, managedApplicationGraphCli: true, evidenceCli: true, incurMcpCommand: "npx -y rea-agents mcp", doctor: "platform-appropriate", setup: supportedSetupHost ? "planned-then-idempotent" : "unsupported-host-rejected", setupPlanReadOnly: supportedSetupHost, existingHopperPreserved: supportedSetupHost, clients: supportedSetupHost ? 3 : 0, backupReadback: supportedSetupHost, failureRecovery: supportedSetupHost, configSymlinkLifecycle: supportedSetupHost, skill: supportedSetupHost, mcpTools: TOOL_CONTRACTS.length, mcpPrompts: prompts.names.length, promptCompletion: true, promptCompletionLifecycle: true, evidenceMcp: true, targetFree: true, targetLifecycle: true, boundedRegexBridge: true })}\n`,
|
||||
`${JSON.stringify({ cli: true, analysisCli: true, artifactCli: true, managedCli: true, managedReconstructionCli: true, managedNativeVerificationCli: true, managedRuntimePlanCli: true, managedApplicationGraphCli: true, evidenceCli: true, incurMcpCommand: "npx -y rea-agents@latest mcp", lifecycleScriptsRequired: false, doctor: "platform-appropriate", setup: supportedSetupHost ? "planned-then-idempotent" : "unsupported-host-rejected", setupPlanReadOnly: supportedSetupHost, existingHopperPreserved: supportedSetupHost, clients: supportedSetupHost ? 3 : 0, backupReadback: supportedSetupHost, failureRecovery: supportedSetupHost, configSymlinkLifecycle: supportedSetupHost, skill: supportedSetupHost, mcpTools: TOOL_CONTRACTS.length, mcpPrompts: prompts.names.length, promptCompletion: true, promptCompletionLifecycle: true, evidenceMcp: true, targetFree: true, targetLifecycle: true, boundedRegexBridge: true })}\n`,
|
||||
);
|
||||
} finally {
|
||||
if (tarball) await rm(join(root, tarball), { force: true });
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ const registrationAligned = (
|
|||
command.length === 4 &&
|
||||
command[0] === "npx" &&
|
||||
command[1] === "-y" &&
|
||||
command[2] === PRODUCT_IDENTITY.packageName &&
|
||||
command[2] === PRODUCT_IDENTITY.packageSpecifier &&
|
||||
command[3] === "mcp"
|
||||
)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { tmpdir } from "node:os";
|
||||
import { spawn } from "node-pty";
|
||||
|
||||
export type ProcessCaptureCapability =
|
||||
| { readonly available: true; readonly backend: "node-pty" }
|
||||
|
|
@ -13,6 +12,7 @@ export type ProcessCaptureCapability =
|
|||
export const probeProcessCaptureCapability =
|
||||
async (): Promise<ProcessCaptureCapability> => {
|
||||
try {
|
||||
const { spawn } = await import("@lydell/node-pty");
|
||||
const terminal = spawn(
|
||||
process.platform === "win32" ? "cmd.exe" : "/bin/sh",
|
||||
process.platform === "win32" ? ["/c", "exit", "0"] : ["-c", "exit 0"],
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { createReadStream } from "node:fs";
|
|||
import { mkdir, mkdtemp, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import type { IPty } from "node-pty";
|
||||
import type { IPty } from "@lydell/node-pty";
|
||||
|
||||
import type {
|
||||
FilesystemCheckpoint,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { spawn, type IPty } from "node-pty";
|
||||
import type { IPty } from "@lydell/node-pty";
|
||||
import type {
|
||||
InteractionEvent,
|
||||
ProcessCapture,
|
||||
|
|
@ -204,6 +204,7 @@ const startCaptureRuntime = async (options: {
|
|||
let shimReplay: CommandShimReplay | undefined;
|
||||
let terminal: IPty | undefined;
|
||||
try {
|
||||
const { spawn } = await import("@lydell/node-pty");
|
||||
replay = await startLoopbackReplay(scenario);
|
||||
const startedAt = new Date();
|
||||
const started = Date.now();
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export {
|
|||
|
||||
const registrationCommand = (): readonly string[] =>
|
||||
process.env.npm_command === "exec"
|
||||
? ["npx", "-y", PRODUCT_IDENTITY.packageName, "mcp"]
|
||||
? ["npx", "-y", PRODUCT_IDENTITY.packageSpecifier, "mcp"]
|
||||
: [resolve(process.argv[1] ?? PRODUCT_IDENTITY.cliBinary), "mcp"];
|
||||
|
||||
/** Result of one backup/write/readback transaction. */
|
||||
|
|
@ -405,7 +405,7 @@ export const configureJsonClient = async (
|
|||
command: readonly string[] = [
|
||||
"npx",
|
||||
"-y",
|
||||
PRODUCT_IDENTITY.packageName,
|
||||
PRODUCT_IDENTITY.packageSpecifier,
|
||||
"mcp",
|
||||
],
|
||||
): Promise<ClientConfigurationResult> => {
|
||||
|
|
@ -483,7 +483,7 @@ export const configureTomlClient = async (
|
|||
command: readonly string[] = [
|
||||
"npx",
|
||||
"-y",
|
||||
PRODUCT_IDENTITY.packageName,
|
||||
PRODUCT_IDENTITY.packageSpecifier,
|
||||
"mcp",
|
||||
],
|
||||
): Promise<ClientConfigurationResult> => {
|
||||
|
|
|
|||
|
|
@ -229,8 +229,10 @@ const isOwnedRegistration = (value: unknown): boolean => {
|
|||
args.length === 1 &&
|
||||
args[0] === "mcp") ||
|
||||
(command === "npx" &&
|
||||
JSON.stringify(args) ===
|
||||
JSON.stringify(["-y", PRODUCT_IDENTITY.packageName, "mcp"]))
|
||||
(JSON.stringify(args) ===
|
||||
JSON.stringify(["-y", PRODUCT_IDENTITY.packageSpecifier, "mcp"]) ||
|
||||
JSON.stringify(args) ===
|
||||
JSON.stringify(["-y", PRODUCT_IDENTITY.packageName, "mcp"])))
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@
|
|||
export const PRODUCT_IDENTITY = {
|
||||
displayName: "REA",
|
||||
packageName: PACKAGE_METADATA.name,
|
||||
packageSpecifier: `${PACKAGE_METADATA.name}@latest`,
|
||||
packageVersion: PACKAGE_METADATA.version,
|
||||
cliBinary: "rea",
|
||||
mcpCommand: "npx -y rea-agents mcp",
|
||||
mcpCommand: `npx -y ${PACKAGE_METADATA.name}@latest mcp`,
|
||||
mcpServerKey: "rea",
|
||||
skillName: "rea-analysis",
|
||||
skillVersion: PACKAGE_METADATA.skillVersion,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ describe("client registration status", () => {
|
|||
]);
|
||||
await writeFile(
|
||||
join(home, ".codex/config.toml"),
|
||||
'[mcp_servers.rea]\ncommand = "npx"\nargs = ["-y", "rea-agents", "mcp"]\n',
|
||||
'[mcp_servers.rea]\ncommand = "npx"\nargs = ["-y", "rea-agents@latest", "mcp"]\n',
|
||||
);
|
||||
await writeFile(
|
||||
join(home, ".cursor/mcp.json"),
|
||||
|
|
@ -44,4 +44,23 @@ describe("client registration status", () => {
|
|||
);
|
||||
expect(JSON.stringify(statuses)).not.toContain("SECRET");
|
||||
});
|
||||
|
||||
it("reports an unversioned npx registration as stale", async () => {
|
||||
const home = await mkdtemp(join(tmpdir(), "rea-registrations-"));
|
||||
await mkdir(join(home, ".codex"));
|
||||
await writeFile(
|
||||
join(home, ".codex/config.toml"),
|
||||
'[mcp_servers.rea]\ncommand = "npx"\nargs = ["-y", "rea-agents", "mcp"]\n',
|
||||
);
|
||||
|
||||
const statuses = await readClientRegistrationStatuses(home);
|
||||
|
||||
expect(statuses).toEqual([
|
||||
expect.objectContaining({
|
||||
client: "codex",
|
||||
command: ["npx", "-y", "rea-agents", "mcp"],
|
||||
state: "stale",
|
||||
}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { z } from "zod";
|
|||
import { PRODUCT_IDENTITY } from "../src/identity.js";
|
||||
|
||||
describe("package identity", () => {
|
||||
it("keeps the manifest, executable, and floating MCP command aligned", async () => {
|
||||
it("keeps the manifest, executable, and latest MCP command aligned", async () => {
|
||||
const packageJson = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
|
|
@ -28,7 +28,12 @@ describe("package identity", () => {
|
|||
);
|
||||
expect(packageJson.name).toBe(PRODUCT_IDENTITY.packageName);
|
||||
expect(Object.keys(packageJson.bin)).toEqual([PRODUCT_IDENTITY.cliBinary]);
|
||||
expect(PRODUCT_IDENTITY.mcpCommand).toBe(`npx -y ${packageJson.name} mcp`);
|
||||
expect(PRODUCT_IDENTITY.packageSpecifier).toBe(
|
||||
`${packageJson.name}@latest`,
|
||||
);
|
||||
expect(PRODUCT_IDENTITY.mcpCommand).toBe(
|
||||
`npx -y ${packageJson.name}@latest mcp`,
|
||||
);
|
||||
expect(packageJson.scripts.start).toBe("node scripts/rea.mjs mcp");
|
||||
expect(packageJson.scripts.prepare).toBe("npm run build && husky");
|
||||
expect(packageJson.scripts.prepack).toBe(
|
||||
|
|
|
|||
|
|
@ -61,10 +61,10 @@ describe("localized README product facts", () => {
|
|||
expect(content).toContain(
|
||||
"curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash",
|
||||
);
|
||||
expect(content).toContain("npx -y rea-agents setup");
|
||||
expect(content).toContain("npx -y rea-agents doctor");
|
||||
expect(content).toContain("npx -y rea-agents@latest setup");
|
||||
expect(content).toContain("npx -y rea-agents@latest doctor");
|
||||
expect(content).toContain("rea uninstall");
|
||||
expect(content).toContain('"args": ["-y", "rea-agents", "mcp"]');
|
||||
expect(content).toContain('"args": ["-y", "rea-agents@latest", "mcp"]');
|
||||
expect(content).toContain("Node.js 22");
|
||||
expect(content).toContain("macOS 12");
|
||||
expect(content).toContain("Ubuntu 24.04");
|
||||
|
|
@ -81,7 +81,8 @@ describe("localized README product facts", () => {
|
|||
|
||||
it("keeps both English CLI onboarding paths discoverable", async () => {
|
||||
const content = await readFile(resolve("README.md"), "utf8");
|
||||
expect(content).toContain("npx -y rea-agents analyze");
|
||||
expect(content).toContain("npx -y rea-agents@latest analyze");
|
||||
expect(content).toContain("npm install rea-agents` without `--global`");
|
||||
expect(content).toContain("npm install --global rea-agents");
|
||||
expect(content).toContain("rea setup");
|
||||
expect(content).toContain("--install-hopper");
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ describe("JSON client configuration transaction", () => {
|
|||
other: { command: "other" },
|
||||
rea: {
|
||||
command: "npx",
|
||||
args: ["-y", "rea-agents", "mcp"],
|
||||
args: ["-y", "rea-agents@latest", "mcp"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -79,7 +79,7 @@ describe("JSON client configuration transaction", () => {
|
|||
mcpServers: {
|
||||
rea: {
|
||||
command: "npx",
|
||||
args: ["-y", "rea-agents", "mcp"],
|
||||
args: ["-y", "rea-agents@latest", "mcp"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
@ -108,7 +108,7 @@ describe("JSON client configuration transaction", () => {
|
|||
const configPath = join(directory, "mcp.json");
|
||||
await writeFile(
|
||||
configPath,
|
||||
'{"mcpServers":{"rea":{"command":"npx","args":["-y","rea-agents","mcp"]}}}\n',
|
||||
'{"mcpServers":{"rea":{"command":"npx","args":["-y","rea-agents@latest","mcp"]}}}\n',
|
||||
);
|
||||
expect(await configureJsonClient({ name: "cursor", configPath })).toEqual({
|
||||
status: "unchanged",
|
||||
|
|
@ -118,6 +118,30 @@ describe("JSON client configuration transaction", () => {
|
|||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("migrates an unversioned npx registration and preserves sibling configuration", async () => {
|
||||
directory = await mkdtemp(join(tmpdir(), "rea-setup-"));
|
||||
const configPath = join(directory, "mcp.json");
|
||||
const original =
|
||||
'{"theme":"dark","mcpServers":{"rea":{"command":"npx","args":["-y","rea-agents","mcp"]},"other":{"command":"other"}}}\n';
|
||||
await writeFile(configPath, original);
|
||||
|
||||
expect(await configureJsonClient({ name: "cursor", configPath })).toEqual(
|
||||
expect.objectContaining({ status: "configured" }),
|
||||
);
|
||||
|
||||
expect(JSON.parse(await readFile(configPath, "utf8"))).toEqual({
|
||||
theme: "dark",
|
||||
mcpServers: {
|
||||
rea: {
|
||||
command: "npx",
|
||||
args: ["-y", "rea-agents@latest", "mcp"],
|
||||
},
|
||||
other: { command: "other" },
|
||||
},
|
||||
});
|
||||
expect(await readFile(`${configPath}.rea.backup`, "utf8")).toBe(original);
|
||||
});
|
||||
|
||||
it("persists a custom Hopper launcher and remains idempotent", async () => {
|
||||
directory = await mkdtemp(join(tmpdir(), "rea-setup-"));
|
||||
const configPath = join(directory, "mcp.json");
|
||||
|
|
@ -132,7 +156,7 @@ describe("JSON client configuration transaction", () => {
|
|||
mcpServers: {
|
||||
rea: {
|
||||
command: "npx",
|
||||
args: ["-y", "rea-agents", "mcp"],
|
||||
args: ["-y", "rea-agents@latest", "mcp"],
|
||||
env: { HOPPER_LAUNCHER_PATH: hopperPath },
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue