fix(npm): preserve explicit setup versions (#465)
* fix(npm): refresh stale setup bootstraps * fix(npm): preserve explicit setup versions * docs: distinguish first-run and refresh setup
This commit is contained in:
1 parent
ed4a62871f
commit
1783bf6dfd
13 files changed
+34
-296
No files matched your search
@@ -89,13 +89,13 @@ REA shows how it reached its conclusions. It does not claim to recover original
|
||||
### Run setup — recommended
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
The npm package-runner prompt, when shown, approves downloading REA for this
|
||||
invocation; it does not approve any setup changes. The REA wizard separately
|
||||
shows its complete plan and asks before applying it. Setup does not update
|
||||
Homebrew, Node.js, or npm. `npx rea-agents setup` opens with the work it
|
||||
Homebrew, Node.js, or npm. The setup command opens with the work it
|
||||
enables: investigate local apps from an agent, recover evidence through a
|
||||
deep-analysis provider, and reuse REA's guided workflow. It summarizes the
|
||||
detected agents, then asks which capabilities to set up: agent integration
|
||||
@@ -103,12 +103,10 @@ detected agents, then asks which capabilities to set up: agent integration
|
||||
Nothing is preselected. Choosing agent integration opens a second empty
|
||||
checklist for the specific detected agents that should receive a registration.
|
||||
|
||||
If bare `npx` finds a project-local REA package, its dispatcher restarts setup
|
||||
through `rea-agents@latest` before planning any changes. This prevents an older
|
||||
local dependency from silently writing stale integration state. An already
|
||||
published older release cannot contain that dispatcher protection; run
|
||||
`npx -y rea-agents@latest setup` once to repair registrations created by one.
|
||||
Intentional rollbacks remain available through an exact package request.
|
||||
`@latest` makes the requested release explicit, and `--prefer-online` asks npm
|
||||
to refresh package metadata instead of relying on a cached resolution. REA does
|
||||
not silently replace the package version npm selected. Intentional rollbacks
|
||||
therefore remain available through an exact package request.
|
||||
|
||||
REA keeps the journey inline so its history remains in the terminal. Selecting
|
||||
a capability does not select every detected target or authorize a change.
|
||||
@@ -139,7 +137,7 @@ Pass installer options after `bash -s --`, for example `--dry-run`, `--no-setup`
|
||||
### With an agent — recommended
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
Choose Agent Integration in the reviewed setup plan. REA installs the pinned MCP
|
||||
@@ -151,7 +149,7 @@ Review the setup plan, approve it if appropriate, then describe the app or featu
|
||||
### From Terminal — no installation
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
npx -y rea-agents@latest doctor
|
||||
npx -y rea-agents@latest analyze /Applications/Notes.app
|
||||
```
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ npx rea-agents setup
|
||||
### باستخدام وكيل برمجة — موصى به
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
اطلب من الوكيل إعداد REA. سيفحص جهاز Mac ويشرح ما يحتاج إلى تثبيته ويطلب الموافقة ويرشدك خلال رسائل النظام. أعد تشغيل الوكيل بعد الإعداد إذا طلب ذلك لتحميل مجموعة الأدوات الكاملة.
|
||||
@@ -90,7 +90,7 @@ npx rea-agents setup
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
إذا طلب macOS أو برنامج التثبيت تأكيدًا، فأكمل الخطوة ثم شغّل الأمر نفسه مرة أخرى.
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ REA は調査をバイナリ上の根拠に結び付けます。元のソース
|
||||
### コーディングエージェントから(推奨)
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
エージェントに REA のセットアップを依頼してください。Mac を確認し、必要なインストールを説明して承認を求め、システムプロンプトを案内します。完全なツールを読み込むため再起動を求められた場合は、セットアップ後に再起動してください。
|
||||
@@ -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 rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
macOS やインストーラーから確認を求められた場合は、その操作を完了してから同じコマンドをもう一度実行してください。
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ REA는 분석을 바이너리 증거에 근거하게 합니다. 원본 소스
|
||||
### 코딩 에이전트에서 시작하기(권장)
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
에이전트에게 REA 설정을 요청하세요. Mac을 확인하고 필요한 설치 내용을 설명한 뒤 승인을 요청하며 시스템 프롬프트를 안내합니다. 전체 도구를 불러오기 위해 재시작하라고 하면 설정 후 에이전트를 재시작하세요.
|
||||
@@ -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 rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
macOS나 설치 프로그램이 확인을 요청하면 해당 절차를 완료하고 같은 명령을 다시 실행하세요.
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ REA 让调查始终以二进制证据为依据。它不会声称能恢复原始
|
||||
### 使用编程智能体(推荐)
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
让智能体设置 REA。它会检查你的 Mac,说明需要安装的内容,先征得同意,并引导你处理系统提示。如果智能体要求重启以加载完整工具,请在设置后重启。
|
||||
@@ -91,7 +91,7 @@ npx rea-agents setup
|
||||
```bash
|
||||
# 1. 安装和配置 REA
|
||||
curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
如果 macOS 或安装程序要求确认,请完成提示,然后再次运行同一命令。
|
||||
|
||||
+8
-10
@@ -7,7 +7,7 @@ REA separates installing its CLI from configuring external software and agents.
|
||||
The recommended setup entrypoint is:
|
||||
|
||||
```bash
|
||||
npx rea-agents setup
|
||||
npx --yes --prefer-online rea-agents@latest setup
|
||||
```
|
||||
|
||||
If npm asks to download and run the package, that approval applies only to the
|
||||
@@ -15,13 +15,11 @@ current package-runner invocation. REA still prints its own setup plan and asks
|
||||
for separate approval before changing agent configuration or installing a
|
||||
product-owned component.
|
||||
|
||||
When bare `npx` resolves `rea-agents` from the current project's
|
||||
`node_modules`, the selected dispatcher restarts setup through
|
||||
`rea-agents@latest` before REA plans or writes configuration. This protects
|
||||
current and future releases from silently persisting stale integration state.
|
||||
Code in an already-published older release cannot acquire that check
|
||||
retroactively; invoke `npx -y rea-agents@latest setup` once to repair any
|
||||
registration it created.
|
||||
The explicit `@latest` request and `--prefer-online` metadata policy prevent a
|
||||
project dependency or stale npx cache entry from choosing the setup version.
|
||||
REA runs the version npm selected and never silently replaces an intentional
|
||||
version request after launch. To repair registrations written by an older
|
||||
release, rerun the command above and review the resulting setup plan.
|
||||
|
||||
For an intentional rollback, make the package request explicit:
|
||||
|
||||
@@ -37,8 +35,8 @@ REA supports Node.js 22.19+ and 24.11+ (including newer releases). It uses the n
|
||||
|
||||
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 rea-agents setup` for the guided setup journey,
|
||||
`npx -y rea-agents@latest` for unattended one-off commands, or install globally
|
||||
on the shell `PATH`. Use the explicit setup command above for the guided setup
|
||||
journey, `npx -y rea-agents@latest` for unattended one-off commands, or install globally
|
||||
with `npm install --global rea-agents` for a shell-visible `rea` command.
|
||||
|
||||
The optional curl wrapper installs only the global npm package:
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
"bridge/hopper_bridge.py",
|
||||
"bridge/ghidra/ReaGhidraBridge.java",
|
||||
"scripts/rea.mjs",
|
||||
"scripts/package-runner-bootstrap.mjs",
|
||||
"scripts/electron-active-hook.cjs",
|
||||
"scripts/electron-active-hook-boundaries.cjs",
|
||||
"scripts/hopper-demo-x11.py",
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
export interface PackageRunnerSetupInput {
|
||||
readonly args: readonly string[];
|
||||
readonly environment: Readonly<Record<string, string | undefined>>;
|
||||
readonly packageRoot: string;
|
||||
readonly packageName: string;
|
||||
}
|
||||
|
||||
export interface PackageRunnerSetupPlan {
|
||||
readonly command: "npm";
|
||||
readonly args: readonly string[];
|
||||
}
|
||||
|
||||
export function packageRunnerSetupPlan(
|
||||
input: PackageRunnerSetupInput,
|
||||
): PackageRunnerSetupPlan | undefined;
|
||||
|
||||
export function runPackageRunnerSetupBootstrap(
|
||||
input: PackageRunnerSetupInput,
|
||||
): Promise<number | undefined>;
|
||||
@@ -1,72 +0,0 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
const BOOTSTRAP_MARKER = "REA_PACKAGE_RUNNER_BOOTSTRAPPED";
|
||||
|
||||
/**
|
||||
* Plan a current-release setup bootstrap when bare npx selected a project-local
|
||||
* package. Explicit `npm exec --package=<name>@<version>` rollbacks bypass it.
|
||||
*/
|
||||
export function packageRunnerSetupPlan(input) {
|
||||
if (input.args[0] !== "setup") return undefined;
|
||||
if (input.environment[BOOTSTRAP_MARKER] === "1") return undefined;
|
||||
if (input.environment.npm_lifecycle_event !== "npx") return undefined;
|
||||
|
||||
const localPrefix = input.environment.npm_config_local_prefix;
|
||||
if (localPrefix === undefined || localPrefix.length === 0) return undefined;
|
||||
if (
|
||||
!isPackageBelowLocalPrefix(
|
||||
input.packageRoot,
|
||||
localPrefix,
|
||||
input.packageName,
|
||||
)
|
||||
)
|
||||
return undefined;
|
||||
|
||||
const requestedPackage = input.environment.npm_config_package;
|
||||
if (
|
||||
requestedPackage !== undefined &&
|
||||
isExactPackageVersion(requestedPackage, input.packageName)
|
||||
)
|
||||
return undefined;
|
||||
|
||||
return {
|
||||
command: "npm",
|
||||
args: [
|
||||
"exec",
|
||||
"--yes",
|
||||
`--package=${input.packageName}@latest`,
|
||||
"--",
|
||||
"rea",
|
||||
...input.args,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/** Execute a planned package-runner bootstrap and return its exit status. */
|
||||
export async function runPackageRunnerSetupBootstrap(input) {
|
||||
const plan = packageRunnerSetupPlan(input);
|
||||
if (plan === undefined) return undefined;
|
||||
|
||||
return await new Promise((resolveExitCode) => {
|
||||
const child = spawn(plan.command, plan.args, {
|
||||
stdio: "inherit",
|
||||
env: { ...input.environment, [BOOTSTRAP_MARKER]: "1" },
|
||||
});
|
||||
child.once("error", () => resolveExitCode(1));
|
||||
child.once("exit", (code) => resolveExitCode(code ?? 1));
|
||||
});
|
||||
}
|
||||
|
||||
function isPackageBelowLocalPrefix(packageRoot, localPrefix, packageName) {
|
||||
const expectedRoot = resolve(localPrefix, "node_modules", packageName);
|
||||
return resolve(packageRoot) === expectedRoot;
|
||||
}
|
||||
|
||||
function isExactPackageVersion(packageSpecifier, packageName) {
|
||||
const version = packageSpecifier.slice(`${packageName}@`.length);
|
||||
return (
|
||||
packageSpecifier.startsWith(`${packageName}@`) &&
|
||||
/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u.test(version)
|
||||
);
|
||||
}
|
||||
+1
-11
@@ -4,8 +4,6 @@ import { access } from "node:fs/promises";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import { runPackageRunnerSetupBootstrap } from "./package-runner-bootstrap.mjs";
|
||||
|
||||
// Route production MCP before importing Incur. Incur owns registration helpers
|
||||
// such as `mcp add`, while only dist/main.js may serve the stdio tool catalog.
|
||||
const args = process.argv.slice(2);
|
||||
@@ -17,21 +15,13 @@ const isMcpMode =
|
||||
args.length === 1 && (args[0] === "--mcp" || args[0] === "mcp");
|
||||
const isMcpDoctorMode = args[0] === "mcp" && args[1] === "doctor";
|
||||
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const bootstrapExitCode = await runPackageRunnerSetupBootstrap({
|
||||
args,
|
||||
environment: process.env,
|
||||
packageRoot,
|
||||
packageName: packageJson.name,
|
||||
});
|
||||
const runtimeFiles = isMcpMode
|
||||
? ["dist/main.js"]
|
||||
: isMcpDoctorMode
|
||||
? ["dist/main.js", "dist/mcpDoctor.js"]
|
||||
: ["dist/cli.js", "dist/cliOutput.js"];
|
||||
|
||||
if (bootstrapExitCode !== undefined) {
|
||||
process.exitCode = bootstrapExitCode;
|
||||
} else if (!(await compiledRuntimeExists(runtimeFiles))) {
|
||||
if (!(await compiledRuntimeExists(runtimeFiles))) {
|
||||
process.stderr.write(
|
||||
`REA's compiled runtime is missing. Run \`npm ci\` in ${packageRoot} to install dependencies and build REA, then restart it. If this is an installed package, reinstall rea-agents.\n`,
|
||||
);
|
||||
|
||||
@@ -13,10 +13,6 @@ describe("executable dispatcher", () => {
|
||||
await workspace.mkdir("dist");
|
||||
await Promise.all([
|
||||
copyFile("scripts/rea.mjs", join(scripts, "rea.mjs")),
|
||||
copyFile(
|
||||
"scripts/package-runner-bootstrap.mjs",
|
||||
join(scripts, "package-runner-bootstrap.mjs"),
|
||||
),
|
||||
workspace.write(
|
||||
"package.json",
|
||||
JSON.stringify({ type: "module", version: "1.0.0" }),
|
||||
@@ -72,10 +68,6 @@ describe("executable dispatcher", () => {
|
||||
const scripts = await workspace.mkdir("scripts");
|
||||
await Promise.all([
|
||||
copyFile("scripts/rea.mjs", join(scripts, "rea.mjs")),
|
||||
copyFile(
|
||||
"scripts/package-runner-bootstrap.mjs",
|
||||
join(scripts, "package-runner-bootstrap.mjs"),
|
||||
),
|
||||
workspace.write(
|
||||
"package.json",
|
||||
JSON.stringify({ type: "module", version: "1.0.0" }),
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import { chmod, readFile, writeFile } from "node:fs/promises";
|
||||
import { delimiter, join } from "node:path";
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
packageRunnerSetupPlan,
|
||||
runPackageRunnerSetupBootstrap,
|
||||
} from "../../../scripts/package-runner-bootstrap.mjs";
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
|
||||
describe("package-runner setup bootstrap", () => {
|
||||
it("reruns bare setup through the current release when npm selected a local package", () => {
|
||||
expect(
|
||||
packageRunnerSetupPlan({
|
||||
args: ["setup", "--client", "codex"],
|
||||
environment: {
|
||||
npm_lifecycle_event: "npx",
|
||||
npm_config_local_prefix: "/work/project",
|
||||
},
|
||||
packageRoot: "/work/project/node_modules/rea-agents",
|
||||
packageName: "rea-agents",
|
||||
}),
|
||||
).toEqual({
|
||||
command: "npm",
|
||||
args: [
|
||||
"exec",
|
||||
"--yes",
|
||||
"--package=rea-agents@latest",
|
||||
"--",
|
||||
"rea",
|
||||
"setup",
|
||||
"--client",
|
||||
"codex",
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("leaves explicit rollback and non-local invocations untouched", () => {
|
||||
const base = {
|
||||
args: ["setup"],
|
||||
packageRoot: "/work/project/node_modules/rea-agents",
|
||||
packageName: "rea-agents",
|
||||
} as const;
|
||||
|
||||
expect(
|
||||
packageRunnerSetupPlan({
|
||||
...base,
|
||||
environment: {
|
||||
npm_lifecycle_event: "npx",
|
||||
npm_config_local_prefix: "/work/project",
|
||||
npm_config_package: "rea-agents@2.4.0",
|
||||
},
|
||||
}),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
packageRunnerSetupPlan({
|
||||
...base,
|
||||
environment: {
|
||||
npm_lifecycle_event: "npx",
|
||||
npm_config_local_prefix: "/work/project",
|
||||
npm_config_package: "rea-agents@^2.4.0",
|
||||
},
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
args: expect.arrayContaining(["--package=rea-agents@latest"]),
|
||||
}),
|
||||
);
|
||||
expect(
|
||||
packageRunnerSetupPlan({
|
||||
...base,
|
||||
packageRoot: "/root/.npm/_npx/cache/node_modules/rea-agents",
|
||||
environment: {
|
||||
npm_lifecycle_event: "npx",
|
||||
npm_config_local_prefix: "/work/project",
|
||||
},
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not redirect recursively or affect commands other than setup", () => {
|
||||
const environment = {
|
||||
npm_lifecycle_event: "npx",
|
||||
npm_config_local_prefix: "/work/project",
|
||||
REA_PACKAGE_RUNNER_BOOTSTRAPPED: "1",
|
||||
};
|
||||
|
||||
expect(
|
||||
packageRunnerSetupPlan({
|
||||
args: ["setup"],
|
||||
environment,
|
||||
packageRoot: "/work/project/node_modules/rea-agents",
|
||||
packageName: "rea-agents",
|
||||
}),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
packageRunnerSetupPlan({
|
||||
args: ["doctor"],
|
||||
environment: {
|
||||
npm_lifecycle_event: "npx",
|
||||
npm_config_local_prefix: "/work/project",
|
||||
},
|
||||
packageRoot: "/work/project/node_modules/rea-agents",
|
||||
packageName: "rea-agents",
|
||||
}),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("forwards setup arguments to npm with a recursion marker", async () => {
|
||||
const directory = await createTestTempDirectory("rea-bootstrap-");
|
||||
const npm = join(directory, "npm");
|
||||
const log = join(directory, "invocation.json");
|
||||
await writeFile(
|
||||
npm,
|
||||
`#!/usr/bin/env node
|
||||
import { writeFileSync } from "node:fs";
|
||||
writeFileSync(process.env.REA_BOOTSTRAP_TEST_LOG, JSON.stringify({
|
||||
args: process.argv.slice(2),
|
||||
marker: process.env.REA_PACKAGE_RUNNER_BOOTSTRAPPED,
|
||||
}));
|
||||
`,
|
||||
);
|
||||
await chmod(npm, 0o755);
|
||||
|
||||
await expect(
|
||||
runPackageRunnerSetupBootstrap({
|
||||
args: ["setup", "--dry-run"],
|
||||
environment: {
|
||||
...process.env,
|
||||
PATH: `${directory}${delimiter}${process.env.PATH ?? ""}`,
|
||||
REA_BOOTSTRAP_TEST_LOG: log,
|
||||
npm_lifecycle_event: "npx",
|
||||
npm_config_local_prefix: "/work/project",
|
||||
},
|
||||
packageRoot: "/work/project/node_modules/rea-agents",
|
||||
packageName: "rea-agents",
|
||||
}),
|
||||
).resolves.toBe(0);
|
||||
await expect(readFile(log, "utf8").then(JSON.parse)).resolves.toEqual({
|
||||
args: [
|
||||
"exec",
|
||||
"--yes",
|
||||
"--package=rea-agents@latest",
|
||||
"--",
|
||||
"rea",
|
||||
"setup",
|
||||
"--dry-run",
|
||||
],
|
||||
marker: "1",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -67,6 +67,9 @@ describe("localized README product facts", () => {
|
||||
"curl -fsSL https://raw.githubusercontent.com/morluto/rea/main/install.sh | bash",
|
||||
);
|
||||
expect(content).toContain("npx rea-agents setup");
|
||||
expect(content).toContain(
|
||||
"npx --yes --prefer-online rea-agents@latest setup",
|
||||
);
|
||||
expect(content).toContain("npx -y rea-agents@latest doctor");
|
||||
expect(content).toContain("rea uninstall");
|
||||
expect(content).toContain(
|
||||
@@ -95,15 +98,17 @@ describe("localized README product facts", () => {
|
||||
expect(content).toContain("--install-hopper");
|
||||
expect(content).toContain("docs/installation.md");
|
||||
expect(content).toContain("You do not need both");
|
||||
expect(normalizedProse(content)).toContain(
|
||||
"npx -y rea-agents@latest setup` once to repair registrations",
|
||||
expect(content).toContain(
|
||||
"npx --yes --prefer-online rea-agents@latest setup",
|
||||
);
|
||||
});
|
||||
|
||||
it("documents stale bootstrap recovery and explicit rollback", async () => {
|
||||
it("documents explicit setup freshness and rollback", async () => {
|
||||
const content = await readFile(resolve("docs/installation.md"), "utf8");
|
||||
const prose = normalizedProse(content);
|
||||
expect(prose).toContain("before REA plans or writes configuration");
|
||||
expect(prose).toContain(
|
||||
"explicit `@latest` request and `--prefer-online` metadata policy",
|
||||
);
|
||||
expect(prose).toContain(
|
||||
"npm exec --yes --package=rea-agents@2.4.0 -- rea setup",
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user