agent-relay-server 0.4.11 → 0.4.13
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/README.md +12 -1
- package/bin/agent-relay-codex.ts +108 -8
- package/codex/README.md +16 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -314,7 +314,18 @@ agent-relay-codex uninstall
|
|
|
314
314
|
```
|
|
315
315
|
|
|
316
316
|
This removes the Codex SessionStart hook, local plugin marketplace files, and
|
|
317
|
-
launcher shims. It leaves shell profile PATH edits
|
|
317
|
+
launcher shims. It leaves shell profile PATH edits and runtime logs in place.
|
|
318
|
+
|
|
319
|
+
Full managed cleanup:
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
agent-relay-codex uninstall --purge
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Purge also removes Agent Relay-managed shell profile PATH snippets, Codex runtime
|
|
326
|
+
logs, the launcher directory, and empty install directories. It only removes
|
|
327
|
+
profile snippets written by the installer marker; manual PATH edits are left
|
|
328
|
+
alone.
|
|
318
329
|
|
|
319
330
|
## What the Agent Sees
|
|
320
331
|
|
package/bin/agent-relay-codex.ts
CHANGED
|
@@ -55,7 +55,7 @@ function usage(exitCode = 0): never {
|
|
|
55
55
|
Usage:
|
|
56
56
|
agent-relay-codex [--relay-url URL] [--listen ws://127.0.0.1:PORT] [-- <codex args...>]
|
|
57
57
|
agent-relay-codex install [--alias|--no-alias]
|
|
58
|
-
agent-relay-codex uninstall
|
|
58
|
+
agent-relay-codex uninstall [--purge]
|
|
59
59
|
agent-relay-codex alias install
|
|
60
60
|
agent-relay-codex alias remove
|
|
61
61
|
agent-relay-codex doctor
|
|
@@ -66,6 +66,8 @@ With no subcommand, this launches Codex with live Agent Relay support.`);
|
|
|
66
66
|
process.exit(exitCode);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
const pathMarker = "# Agent Relay Codex alias";
|
|
70
|
+
|
|
69
71
|
function commandExists(command: string): boolean {
|
|
70
72
|
return findOnPath(command) !== null;
|
|
71
73
|
}
|
|
@@ -633,26 +635,110 @@ function installPathEntry(): boolean {
|
|
|
633
635
|
}
|
|
634
636
|
|
|
635
637
|
const shell = process.env.SHELL || "";
|
|
636
|
-
const marker = "# Agent Relay Codex alias";
|
|
637
638
|
const exportLine = `export PATH=${shellQuote(aliasBinDir)}:$PATH`;
|
|
638
639
|
let profilePath = join(home, ".profile");
|
|
639
|
-
let snippet = `\n${
|
|
640
|
+
let snippet = `\n${pathMarker}\n${exportLine}\n`;
|
|
640
641
|
|
|
641
642
|
if (shell.includes("zsh")) profilePath = join(home, ".zshrc");
|
|
642
643
|
if (shell.includes("bash")) profilePath = join(home, ".bashrc");
|
|
643
644
|
if (shell.includes("fish")) {
|
|
644
645
|
profilePath = join(home, ".config", "fish", "config.fish");
|
|
645
|
-
snippet = `\n${
|
|
646
|
+
snippet = `\n${pathMarker}\nfish_add_path ${shellQuote(aliasBinDir)}\n`;
|
|
646
647
|
}
|
|
647
648
|
|
|
648
649
|
mkdirSync(dirname(profilePath), { recursive: true });
|
|
649
650
|
const current = existsSync(profilePath) ? readFileSync(profilePath, "utf8") : "";
|
|
650
|
-
if (!current.includes(
|
|
651
|
+
if (!current.includes(pathMarker) && !current.includes(aliasBinDir)) {
|
|
651
652
|
writeFileSync(profilePath, `${current.replace(/\s*$/, "")}${snippet}`);
|
|
652
653
|
}
|
|
653
654
|
return true;
|
|
654
655
|
}
|
|
655
656
|
|
|
657
|
+
function managedProfilePaths(): string[] {
|
|
658
|
+
return [
|
|
659
|
+
join(home, ".profile"),
|
|
660
|
+
join(home, ".bashrc"),
|
|
661
|
+
join(home, ".zshrc"),
|
|
662
|
+
join(home, ".config", "fish", "config.fish"),
|
|
663
|
+
];
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
function removeManagedPathSnippet(input: string): string {
|
|
667
|
+
const hadTrailingNewline = /\r?\n$/.test(input);
|
|
668
|
+
const lines = input.split(/\r?\n/);
|
|
669
|
+
const output: string[] = [];
|
|
670
|
+
|
|
671
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
672
|
+
const line = lines[index]!;
|
|
673
|
+
if (line === pathMarker) {
|
|
674
|
+
const next = lines[index + 1] || "";
|
|
675
|
+
if (next.includes(aliasBinDir)) index += 1;
|
|
676
|
+
continue;
|
|
677
|
+
}
|
|
678
|
+
output.push(line);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const cleaned = output.join("\n").replace(/\n{3,}/g, "\n\n").replace(/[ \t]+\n/g, "\n");
|
|
682
|
+
return hadTrailingNewline && cleaned ? `${cleaned.replace(/\n*$/, "")}\n` : cleaned.replace(/\n*$/, "");
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function removeUnixPathEntries(): number {
|
|
686
|
+
let changed = 0;
|
|
687
|
+
for (const profilePath of managedProfilePaths()) {
|
|
688
|
+
if (!existsSync(profilePath)) continue;
|
|
689
|
+
const current = readFileSync(profilePath, "utf8");
|
|
690
|
+
if (!current.includes(pathMarker)) continue;
|
|
691
|
+
const cleaned = removeManagedPathSnippet(current);
|
|
692
|
+
if (cleaned !== current) {
|
|
693
|
+
writeFileSync(profilePath, cleaned);
|
|
694
|
+
changed += 1;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
return changed;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function removeWindowsPathEntry(): boolean {
|
|
701
|
+
const script = [
|
|
702
|
+
`$target = ${JSON.stringify(aliasBinDir)}`,
|
|
703
|
+
"$path = [Environment]::GetEnvironmentVariable('Path', 'User')",
|
|
704
|
+
"if ($path) {",
|
|
705
|
+
" $parts = $path -split ';' | Where-Object { $_ -and ($_ -ne $target) }",
|
|
706
|
+
" [Environment]::SetEnvironmentVariable('Path', ($parts -join ';'), 'User')",
|
|
707
|
+
"}",
|
|
708
|
+
"$bin = [Environment]::GetEnvironmentVariable('AGENT_RELAY_CODEX_BIN', 'User')",
|
|
709
|
+
"if ($bin -eq $target) { [Environment]::SetEnvironmentVariable('AGENT_RELAY_CODEX_BIN', $null, 'User') }",
|
|
710
|
+
].join("; ");
|
|
711
|
+
const result = Bun.spawnSync(["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", script], {
|
|
712
|
+
stdout: "pipe",
|
|
713
|
+
stderr: "pipe",
|
|
714
|
+
});
|
|
715
|
+
return result.exitCode === 0;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
function removeManagedPathEntries(): string {
|
|
719
|
+
if (process.platform === "win32") {
|
|
720
|
+
return removeWindowsPathEntry() ? "Removed managed Windows user PATH entries." : "Could not update Windows user PATH entries.";
|
|
721
|
+
}
|
|
722
|
+
const changed = removeUnixPathEntries();
|
|
723
|
+
return changed > 0 ? `Removed managed PATH snippets from ${changed} shell profile(s).` : "No managed shell profile PATH snippets found.";
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function removeEmptyDirectory(path: string): boolean {
|
|
727
|
+
if (!existsSync(path)) return false;
|
|
728
|
+
try {
|
|
729
|
+
if (readdirSync(path).length > 0) return false;
|
|
730
|
+
rmSync(path, { recursive: false, force: true });
|
|
731
|
+
return true;
|
|
732
|
+
} catch {
|
|
733
|
+
return false;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
function removeEmptyInstallParents(): void {
|
|
738
|
+
removeEmptyDirectory(installRoot);
|
|
739
|
+
removeEmptyDirectory(dirname(installRoot));
|
|
740
|
+
}
|
|
741
|
+
|
|
656
742
|
function installCodexAlias(): void {
|
|
657
743
|
installLauncherShims(true);
|
|
658
744
|
const updated = installPathEntry();
|
|
@@ -846,7 +932,11 @@ async function install(args: string[]): Promise<void> {
|
|
|
846
932
|
}
|
|
847
933
|
}
|
|
848
934
|
|
|
849
|
-
function uninstall(): void {
|
|
935
|
+
function uninstall(args: string[] = []): void {
|
|
936
|
+
const purge = args.includes("--purge");
|
|
937
|
+
const unknown = args.filter((arg) => arg !== "--purge");
|
|
938
|
+
if (unknown.length > 0) throw new Error(`Unknown uninstall option: ${unknown.join(" ")}`);
|
|
939
|
+
|
|
850
940
|
stopRuntimeSidecars();
|
|
851
941
|
removeHook();
|
|
852
942
|
removeLauncherShim("codex");
|
|
@@ -854,14 +944,24 @@ function uninstall(): void {
|
|
|
854
944
|
rmSync(marketplaceRoot, { recursive: true, force: true });
|
|
855
945
|
rmSync(installedPackageRoot, { recursive: true, force: true });
|
|
856
946
|
console.log("Uninstalled Agent Relay Codex hook, plugin marketplace files, and launcher shims.");
|
|
857
|
-
|
|
947
|
+
|
|
948
|
+
if (!purge) {
|
|
949
|
+
console.log(`PATH entries and runtime logs are left untouched. Run agent-relay-codex uninstall --purge for full managed cleanup.`);
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
rmSync(runtimeRoot, { recursive: true, force: true });
|
|
954
|
+
rmSync(aliasBinDir, { recursive: true, force: true });
|
|
955
|
+
console.log(removeManagedPathEntries());
|
|
956
|
+
removeEmptyInstallParents();
|
|
957
|
+
console.log("Purged Agent Relay Codex runtime files, launcher directory, and empty install directories.");
|
|
858
958
|
}
|
|
859
959
|
|
|
860
960
|
async function main(): Promise<void> {
|
|
861
961
|
const [command, ...args] = process.argv.slice(2);
|
|
862
962
|
if (command === "help" || command === "--help" || command === "-h") usage(0);
|
|
863
963
|
if (command === "install") return install(args);
|
|
864
|
-
if (command === "uninstall") return uninstall();
|
|
964
|
+
if (command === "uninstall") return uninstall(args);
|
|
865
965
|
if (command === "alias" && args[0] === "install") {
|
|
866
966
|
installCodexSupport(false);
|
|
867
967
|
return installCodexAlias();
|
package/codex/README.md
CHANGED
|
@@ -52,6 +52,22 @@ starts Codex with
|
|
|
52
52
|
`--remote`, lets the SessionStart hook attach a sidecar to the actual thread,
|
|
53
53
|
and kills sidecars plus the app-server when Codex exits.
|
|
54
54
|
|
|
55
|
+
Uninstall the Codex hook, local plugin marketplace files, and launcher shims:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
agent-relay-codex uninstall
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Remove all Agent Relay-managed Codex install state, including installer-written
|
|
62
|
+
PATH snippets and runtime logs:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
agent-relay-codex uninstall --purge
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Purge only removes shell profile snippets written with the Agent Relay installer
|
|
69
|
+
marker. Manual PATH edits are left alone.
|
|
70
|
+
|
|
55
71
|
## Approval mode
|
|
56
72
|
|
|
57
73
|
Relay replies are usually sent with a shell command (`curl` to
|