jefrichat-mcp 0.42.0 → 0.44.0
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/dist/index.js +111 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10677,8 +10677,11 @@ var require_extend = __commonJS({
|
|
|
10677
10677
|
// src/run.ts
|
|
10678
10678
|
var run_exports = {};
|
|
10679
10679
|
__export(run_exports, {
|
|
10680
|
+
ensureTmuxInteractive: () => ensureTmuxInteractive,
|
|
10681
|
+
hasCmd: () => hasCmd,
|
|
10680
10682
|
hasTmux: () => hasTmux,
|
|
10681
10683
|
isShellExe: () => isShellExe,
|
|
10684
|
+
resolveTmuxInstall: () => resolveTmuxInstall,
|
|
10682
10685
|
runWrapped: () => runWrapped,
|
|
10683
10686
|
sessionNameFor: () => sessionNameFor,
|
|
10684
10687
|
tmuxInstallHint: () => tmuxInstallHint,
|
|
@@ -10686,6 +10689,7 @@ __export(run_exports, {
|
|
|
10686
10689
|
});
|
|
10687
10690
|
import cp5 from "node:child_process";
|
|
10688
10691
|
import { createHash } from "node:crypto";
|
|
10692
|
+
import readline from "node:readline";
|
|
10689
10693
|
function tmuxRunArgv(agentCmd, sessionName, envPairs = []) {
|
|
10690
10694
|
const env = envPairs.flatMap((e) => ["-e", e]);
|
|
10691
10695
|
return { cmd: "tmux", args: ["new-session", "-A", "-s", sessionName, ...env, "--", ...agentCmd] };
|
|
@@ -10713,6 +10717,72 @@ function tmuxInstallHint(platform = process.platform) {
|
|
|
10713
10717
|
if (platform === "win32") return "tmux runs under WSL \u2014 or just use headless/interval mode";
|
|
10714
10718
|
return "sudo apt install tmux (or your distro's package manager)";
|
|
10715
10719
|
}
|
|
10720
|
+
function hasCmd(cmd) {
|
|
10721
|
+
try {
|
|
10722
|
+
if (process.platform === "win32") cp5.execFileSync("where", [cmd], { stdio: "ignore" });
|
|
10723
|
+
else cp5.execFileSync("sh", ["-c", `command -v "${cmd}"`], { stdio: "ignore" });
|
|
10724
|
+
return true;
|
|
10725
|
+
} catch {
|
|
10726
|
+
return false;
|
|
10727
|
+
}
|
|
10728
|
+
}
|
|
10729
|
+
function resolveTmuxInstall(platform, has = hasCmd) {
|
|
10730
|
+
if (platform === "win32") return { kind: "windows", command: "tmux has no native Windows build \u2014 run this inside WSL (sudo apt install tmux), or just use headless/interval mode (no tmux needed)" };
|
|
10731
|
+
if (platform === "darwin") return has("brew") ? { kind: "brew", command: "brew install tmux" } : { kind: "brew-missing", command: "install Homebrew first (https://brew.sh), then: brew install tmux" };
|
|
10732
|
+
const mgr = ["apt-get", "apt", "dnf", "yum", "pacman", "zypper", "apk"].find(has);
|
|
10733
|
+
const command = mgr === "pacman" ? "sudo pacman -S tmux" : mgr === "apk" ? "sudo apk add tmux" : mgr ? `sudo ${mgr} install tmux` : "install tmux with your distro's package manager";
|
|
10734
|
+
return { kind: "linux-manual", command };
|
|
10735
|
+
}
|
|
10736
|
+
async function promptYesNoDefaultYes(question) {
|
|
10737
|
+
if (!process.stdin.isTTY) return false;
|
|
10738
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
10739
|
+
try {
|
|
10740
|
+
const ans = (await new Promise((res) => rl.question(question, res))).trim().toLowerCase();
|
|
10741
|
+
return ans === "" || ans === "y" || ans === "yes";
|
|
10742
|
+
} finally {
|
|
10743
|
+
rl.close();
|
|
10744
|
+
}
|
|
10745
|
+
}
|
|
10746
|
+
async function ensureTmuxInteractive() {
|
|
10747
|
+
if (hasTmux()) return true;
|
|
10748
|
+
const plan = resolveTmuxInstall(process.platform);
|
|
10749
|
+
process.stderr.write(
|
|
10750
|
+
`
|
|
10751
|
+
\u{1F427} Autonomous "session" mode types incoming Jefri messages straight into THIS live agent
|
|
10752
|
+
window, so you can watch your agent handle them. It needs "tmux" \u2014 a small, standard
|
|
10753
|
+
tool that lets Jefri type into your terminal \u2014 and it isn't installed yet.
|
|
10754
|
+
`
|
|
10755
|
+
);
|
|
10756
|
+
if (plan.kind === "brew") {
|
|
10757
|
+
const yes = await promptYesNoDefaultYes(` Install tmux now with Homebrew? (no password / no sudo) [Y/n] `);
|
|
10758
|
+
if (!yes) {
|
|
10759
|
+
process.stderr.write(` No problem \u2014 install it any time with: ${plan.command}
|
|
10760
|
+
`);
|
|
10761
|
+
return false;
|
|
10762
|
+
}
|
|
10763
|
+
process.stderr.write(` Installing tmux via Homebrew\u2026
|
|
10764
|
+
`);
|
|
10765
|
+
try {
|
|
10766
|
+
cp5.execFileSync("brew", ["install", "tmux"], { stdio: "inherit" });
|
|
10767
|
+
} catch {
|
|
10768
|
+
process.stderr.write(` \u26A0\uFE0F 'brew install tmux' didn't finish \u2014 install it manually (${plan.command}), then re-run this command.
|
|
10769
|
+
`);
|
|
10770
|
+
return false;
|
|
10771
|
+
}
|
|
10772
|
+
if (hasTmux()) {
|
|
10773
|
+
process.stderr.write(` \u2705 tmux installed \u2014 continuing.
|
|
10774
|
+
`);
|
|
10775
|
+
return true;
|
|
10776
|
+
}
|
|
10777
|
+
process.stderr.write(` \u26A0\uFE0F tmux still isn't on PATH after install \u2014 open a new terminal and re-run.
|
|
10778
|
+
`);
|
|
10779
|
+
return false;
|
|
10780
|
+
}
|
|
10781
|
+
process.stderr.write(` To enable it: ${plan.command}
|
|
10782
|
+
Then re-run: JEFRI_EXPERIMENTAL_SESSION=1 jefrichat-mcp run <agent>
|
|
10783
|
+
`);
|
|
10784
|
+
return false;
|
|
10785
|
+
}
|
|
10716
10786
|
async function runWrapped(argv) {
|
|
10717
10787
|
const agentCmd = argv.length ? argv : ["claude"];
|
|
10718
10788
|
if (isShellExe(agentCmd[0])) {
|
|
@@ -10732,25 +10802,43 @@ async function runWrapped(argv) {
|
|
|
10732
10802
|
});
|
|
10733
10803
|
child.on("exit", (c) => res(c ?? 0));
|
|
10734
10804
|
});
|
|
10805
|
+
const cmdStr = agentCmd.join(" ");
|
|
10806
|
+
const sessionOptedIn = process.env.JEFRI_EXPERIMENTAL_SESSION === "1";
|
|
10735
10807
|
if (!hasTmux()) {
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10808
|
+
const ready = sessionOptedIn ? await ensureTmuxInteractive() : false;
|
|
10809
|
+
if (!ready) {
|
|
10810
|
+
process.stderr.write(
|
|
10811
|
+
sessionOptedIn ? `
|
|
10812
|
+
\u{1F427} Launching "${cmdStr}" normally for now.
|
|
10813
|
+
Autonomous HEADLESS and INTERVAL modes work right away \u2014 no tmux needed.
|
|
10814
|
+
Install tmux (see above) and re-run this command to enable the live "session" mode.
|
|
10815
|
+
|
|
10816
|
+
` : `
|
|
10817
|
+
\u{1F427} Launching "${cmdStr}"\u2026
|
|
10818
|
+
Autonomous HEADLESS (default) and INTERVAL modes work right away \u2014 nothing to install.
|
|
10819
|
+
The experimental "session" mode (watch messages typed into THIS window live) needs
|
|
10820
|
+
tmux + an opt-in. To try it later:
|
|
10821
|
+
JEFRI_EXPERIMENTAL_SESSION=1 jefrichat-mcp run ${cmdStr}
|
|
10740
10822
|
|
|
10741
10823
|
`
|
|
10742
|
-
|
|
10743
|
-
|
|
10824
|
+
);
|
|
10825
|
+
return spawnInherit(agentCmd[0], agentCmd.slice(1));
|
|
10826
|
+
}
|
|
10744
10827
|
}
|
|
10745
|
-
const sessionOptedIn = process.env.JEFRI_EXPERIMENTAL_SESSION === "1";
|
|
10746
10828
|
process.stderr.write(
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
(
|
|
10753
|
-
|
|
10829
|
+
sessionOptedIn ? `
|
|
10830
|
+
\u{1F427} Launching "${cmdStr}" in a Jefri-managed tmux session \u2014 SESSION mode is READY.
|
|
10831
|
+
1. Wait for your agent to start.
|
|
10832
|
+
2. Turn it on: jefri_autonomous({ enabled: true, mode: "session" })
|
|
10833
|
+
3. Message this agent from Jefri \u2014 the message gets typed in HERE and your agent answers.
|
|
10834
|
+
(leave it running in the background: Ctrl-b then d \xB7 come back: jefrichat-mcp run ${cmdStr})
|
|
10835
|
+
|
|
10836
|
+
` : `
|
|
10837
|
+
\u{1F427} Launching "${cmdStr}" in a Jefri-managed tmux session.
|
|
10838
|
+
Autonomous HEADLESS and INTERVAL modes work as usual (no extra steps).
|
|
10839
|
+
The experimental "session" mode (watch it type into THIS window) is OFF \u2014 to try it,
|
|
10840
|
+
relaunch with: JEFRI_EXPERIMENTAL_SESSION=1 jefrichat-mcp run ${cmdStr}
|
|
10841
|
+
(leave running: Ctrl-b then d \xB7 reattach: jefrichat-mcp run ${cmdStr})
|
|
10754
10842
|
|
|
10755
10843
|
`
|
|
10756
10844
|
);
|
|
@@ -40297,6 +40385,15 @@ async function main() {
|
|
|
40297
40385
|
};
|
|
40298
40386
|
await server.connect(transport);
|
|
40299
40387
|
log(`MCP server ready \u2014 identity @${USERNAME}, Jefri Chat server ${SERVER}`);
|
|
40388
|
+
let shuttingDown = false;
|
|
40389
|
+
const shutdownOnHostClose = () => {
|
|
40390
|
+
if (shuttingDown) return;
|
|
40391
|
+
shuttingDown = true;
|
|
40392
|
+
log("host closed the connection (stdin EOF) \u2014 shutting connector down");
|
|
40393
|
+
process.exit(0);
|
|
40394
|
+
};
|
|
40395
|
+
process.stdin.once("end", shutdownOnHostClose);
|
|
40396
|
+
process.stdin.once("close", shutdownOnHostClose);
|
|
40300
40397
|
void checkForUpdate().then((u) => {
|
|
40301
40398
|
if (u?.outdated)
|
|
40302
40399
|
log(
|
package/package.json
CHANGED