mirror of
https://github.com/morluto/rea.git
synced 2026-10-12 02:19:24 +00:00
* feat: add Hermes as a supported MCP client Hermes Agent reads stdio MCP servers from `mcp_servers.<name>` in `config.yaml`. REA had no Hermes client, so setup could not register it and Hermes users had to wire the server up by hand. - SupportedClients: add the `hermes` format and client definition, resolving the config path from HERMES_HOME, else the platform default that Hermes's own resolver uses (LOCALAPPDATA/hermes on Windows, ~/.hermes elsewhere), including HERMES_DATA_DIR_SUFFIX. - ClientConfigurationDocument: parse and serialize Hermes YAML, upserting the rea entry into the parsed document so user comments and unrelated settings are preserved; emit `enabled: true` since Hermes connects entries unless disabled. - ClientRegistrationStatus: forward the Hermes location variables so status checks resolve the same path as setup. - Tests: cover path resolution on both platforms and the register/read/uninstall round trip, and clear the Hermes location variables between tests. - delilah 🌸 * docs: document the Hermes client and its config path - delilah 🌸 * refactor(setup): resolve skill destinations per client * fix(setup): install Hermes skills in the active profile * fix(setup): identify each client skill action uniquely --------- Co-authored-by: morluto <[email protected]>
118 lines
3.5 KiB
JavaScript
118 lines
3.5 KiB
JavaScript
import { rm } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
import { exec, json, run } from "./lib/verify-package-core.mjs";
|
|
|
|
/** Install the packed CLI globally with and without optional dependencies and verify PTY degradation. */
|
|
export async function verifyPackageInstall({
|
|
tarball,
|
|
prefix,
|
|
workspace,
|
|
environment,
|
|
}) {
|
|
await exec(
|
|
"npm",
|
|
[
|
|
"install",
|
|
"--global",
|
|
"--ignore-scripts",
|
|
"--omit=dev",
|
|
"--install-strategy=nested",
|
|
"--prefix",
|
|
prefix,
|
|
tarball,
|
|
],
|
|
{ env: environment },
|
|
);
|
|
const cli = join(prefix, "bin", "rea");
|
|
const packageRunnerCli = join(prefix, "bin", "rea-agents");
|
|
if (!(await run(packageRunnerCli, ["--help"], environment)).includes("setup"))
|
|
throw new Error("packaged rea-agents alias did not expose setup");
|
|
const processCaptureCapabilityUrl = pathToFileURL(
|
|
join(
|
|
prefix,
|
|
"lib/node_modules/rea-agents/dist/process/capture/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,
|
|
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/process/capture/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)}`,
|
|
);
|
|
await verifyInstalledPackageCanRepack(prefix, environment);
|
|
return { cli, packageRunnerCli };
|
|
}
|
|
|
|
const verifyInstalledPackageCanRepack = async (prefix, environment) => {
|
|
const installedPackageRoot = join(prefix, "lib/node_modules/rea-agents");
|
|
const repackedTarball = (
|
|
await exec("npm", ["pack", "--silent"], {
|
|
cwd: installedPackageRoot,
|
|
env: environment,
|
|
})
|
|
).stdout.trim();
|
|
await rm(join(installedPackageRoot, repackedTarball), { force: true });
|
|
};
|