agentic-relay 3.8.3 → 3.8.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.
- package/bin/install.mjs +113 -12
- package/package.json +1 -1
package/bin/install.mjs
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* deeplink Print URL the agent registers (tome://, raycast://) — user clicks Install
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
32
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, realpathSync } from "fs";
|
|
33
33
|
import { homedir } from "os";
|
|
34
34
|
import { join, dirname } from "path";
|
|
35
35
|
import { fileURLToPath } from "url";
|
|
@@ -610,24 +610,125 @@ function getExistingKey() {
|
|
|
610
610
|
|
|
611
611
|
/**
|
|
612
612
|
* Link a bare global `agentrelay` command so users skip `npx` after install.
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
*
|
|
613
|
+
* No-ops only when a GENUINE install of `agentrelay` already matches this
|
|
614
|
+
* package's version — a stale global install gets upgraded, not skipped.
|
|
615
|
+
*
|
|
616
|
+
* npx trap: `npx agentic-relay` prepends its ephemeral cache's .bin to this
|
|
617
|
+
* process's PATH, so `agentrelay` ALWAYS resolves here (to the very copy being
|
|
618
|
+
* run) and disappears when npx exits. A naive "already on your PATH" check
|
|
619
|
+
* therefore never links anything and the user gets `command not found` in
|
|
620
|
+
* their next shell. We resolve the command's real location and ignore it when
|
|
621
|
+
* it lives in an npx/npm-exec cache or inside this package itself.
|
|
622
|
+
*
|
|
623
|
+
* Prefers a registry install (`agentic-relay@<version>`) over the local path
|
|
624
|
+
* (the npx cache dir is ephemeral; npm would link/copy from it). Falls back to
|
|
625
|
+
* the path for unpublished checkouts. Surfaces npm's actual error (EACCES
|
|
626
|
+
* etc.) instead of swallowing it, and verifies the command resolves afterwards
|
|
627
|
+
* so a PATH mismatch is reported, not discovered later as `command not found`.
|
|
616
628
|
*/
|
|
617
|
-
function
|
|
629
|
+
function resolveCommandPath(cmd) {
|
|
618
630
|
try {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
return;
|
|
631
|
+
const probe = process.platform === "win32" ? `where ${cmd}` : `command -v ${cmd}`;
|
|
632
|
+
const out = execSync(probe, { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
|
|
633
|
+
return out.split("\n")[0].trim() || null;
|
|
634
|
+
} catch {
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/** True when a resolved bin path is an ephemeral npx/npm-exec shim (or this package's own copy), not a real install. */
|
|
640
|
+
function isEphemeralBin(binPath, pkgRoot) {
|
|
641
|
+
if (!binPath) return false;
|
|
642
|
+
let real = binPath;
|
|
643
|
+
try {
|
|
644
|
+
real = realpathSync(binPath);
|
|
645
|
+
} catch {
|
|
646
|
+
// dangling symlink — definitely not a usable install
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
649
|
+
const sep = process.platform === "win32" ? "\\" : "/";
|
|
650
|
+
return (
|
|
651
|
+
real.includes(`${sep}_npx${sep}`) ||
|
|
652
|
+
binPath.includes(`${sep}_npx${sep}`) ||
|
|
653
|
+
real.startsWith(realpathSafe(pkgRoot))
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function realpathSafe(p) {
|
|
658
|
+
try {
|
|
659
|
+
return realpathSync(p);
|
|
622
660
|
} catch {
|
|
623
|
-
|
|
661
|
+
return p;
|
|
624
662
|
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function linkGlobalCli() {
|
|
625
666
|
const pkgRoot = join(__dirname, "..");
|
|
667
|
+
let version = null;
|
|
626
668
|
try {
|
|
627
|
-
|
|
628
|
-
success("linked global `agentrelay` CLI");
|
|
669
|
+
version = JSON.parse(readFileSync(join(pkgRoot, "package.json"), "utf-8")).version;
|
|
629
670
|
} catch {
|
|
630
|
-
|
|
671
|
+
// unknown version — fall through to the path install
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
const binPath = resolveCommandPath("agentrelay");
|
|
675
|
+
if (binPath && !isEphemeralBin(binPath, pkgRoot)) {
|
|
676
|
+
try {
|
|
677
|
+
const out = execSync("agentrelay version", { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] });
|
|
678
|
+
const installed = (out.trim().split(/\s+/).pop() || "").trim();
|
|
679
|
+
if (version && installed === version) {
|
|
680
|
+
success(`\`agentrelay\` ${version} already on your PATH`);
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
log(`global \`agentrelay\` is ${installed || "an unknown version"} — updating to ${version}…`);
|
|
684
|
+
} catch {
|
|
685
|
+
// resolves but doesn't run — reinstall it
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
const attempts = version ? [`agentic-relay@${version}`, `"${pkgRoot}"`] : [`"${pkgRoot}"`];
|
|
690
|
+
let lastErr = null;
|
|
691
|
+
let installedFrom = null;
|
|
692
|
+
for (const spec of attempts) {
|
|
693
|
+
try {
|
|
694
|
+
execSync(`npm install -g ${spec}`, { stdio: ["ignore", "ignore", "pipe"], encoding: "utf-8" });
|
|
695
|
+
installedFrom = spec;
|
|
696
|
+
break;
|
|
697
|
+
} catch (err) {
|
|
698
|
+
lastErr = err;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
if (!installedFrom) {
|
|
702
|
+
const stderr = String((lastErr && lastErr.stderr) || "");
|
|
703
|
+
const detail =
|
|
704
|
+
stderr.split("\n").find((l) => /EACCES|EEXIST|E404|ERR!|error/i.test(l)) || "";
|
|
705
|
+
warn(
|
|
706
|
+
`could not auto-link the global CLI${detail ? ` — ${detail.trim()}` : ""}.` +
|
|
707
|
+
` Run once: npm i -g agentic-relay` +
|
|
708
|
+
(/EACCES/.test(stderr) ? " (npm's global prefix isn't writable — fix permissions or use a user-level prefix)" : ""),
|
|
709
|
+
);
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Verify the global bin actually landed. Don't probe the bare command here:
|
|
714
|
+
// in this process it resolves to the ephemeral npx shim (which shadows the
|
|
715
|
+
// global install), so check the file in npm's global prefix directly.
|
|
716
|
+
let binDir = null;
|
|
717
|
+
let globalBin = null;
|
|
718
|
+
try {
|
|
719
|
+
const prefix = execSync("npm prefix -g", { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
720
|
+
binDir = process.platform === "win32" ? prefix : join(prefix, "bin");
|
|
721
|
+
const cand = join(binDir, process.platform === "win32" ? "agentrelay.cmd" : "agentrelay");
|
|
722
|
+
if (existsSync(cand)) globalBin = cand;
|
|
723
|
+
} catch {
|
|
724
|
+
// can't resolve the prefix — fall through to the warn
|
|
725
|
+
}
|
|
726
|
+
if (globalBin) {
|
|
727
|
+
success(`linked global \`agentrelay\` CLI (${installedFrom})`);
|
|
728
|
+
const onPath = (process.env.PATH || "").split(process.platform === "win32" ? ";" : ":").includes(binDir);
|
|
729
|
+
if (!onPath) warn(`note: ${binDir} doesn't appear to be on your PATH — add it to use \`agentrelay\` directly`);
|
|
730
|
+
} else {
|
|
731
|
+
warn(`installed, but no global \`agentrelay\` found in ${binDir || "npm's global bin directory"} — run once: npm i -g agentic-relay`);
|
|
631
732
|
}
|
|
632
733
|
}
|
|
633
734
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-relay",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.5",
|
|
4
4
|
"description": "Install Agent Relay AI search across 17+ agents — Claude Code, Codex, Cursor, Gemini CLI, Goose, Windsurf, Cline, BoltAI, Claude Desktop, VS Code, Amazon Q, Roo Code, Witsy, LibreChat, OpenClaw, Tome, Raycast — plus the `agentrelay` CLI for token-cheap parallel agent consulting",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agentrelay": "bin/cli.mjs"
|