jefrichat-mcp 0.49.10 → 0.49.11

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.
Files changed (2) hide show
  1. package/dist/index.js +66 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -46438,6 +46438,7 @@ __export(run_exports, {
46438
46438
  sessionExists: () => sessionExists,
46439
46439
  sessionMeta: () => sessionMeta,
46440
46440
  sessionNameFor: () => sessionNameFor,
46441
+ staleSessionAction: () => staleSessionAction,
46441
46442
  tmuxInstallHint: () => tmuxInstallHint,
46442
46443
  tmuxPanelSetupArgv: () => tmuxPanelSetupArgv,
46443
46444
  tmuxRunArgv: () => tmuxRunArgv
@@ -46645,15 +46646,70 @@ async function runWrapped(argv) {
46645
46646
  cp6.spawnSync("tmux", ["set-option", "-t", name, "@jefri_agent", verdict.identity], { stdio: "ignore" });
46646
46647
  mustCreate = false;
46647
46648
  } else if (!forceReplace) {
46648
- process.stderr.write(
46649
- `
46650
- \u2717 existing session "${name}" looks ${verdict.reason} \u2014 NOT attaching, and NOT touching it.
46649
+ process.stderr.write(` \u23F3 session "${name}" isn't answering \u2014 re-checking in 3s (a hub deploy looks like this)\u2026
46650
+ `);
46651
+ await new Promise((r) => setTimeout(r, 3e3));
46652
+ const probe2 = await probeSessionConnector(name);
46653
+ const verdict2 = assessSession({ probe: probe2, currentVersion: connectorVersion(), expectedIdentity: meta.agent });
46654
+ const attachedOut = cp6.spawnSync("tmux", ["display-message", "-p", "-t", name, "#{session_attached}"], { encoding: "utf8" });
46655
+ const attached = (attachedOut.stdout ?? "").trim() !== "0" && attachedOut.status === 0;
46656
+ const action = staleSessionAction({
46657
+ recovered: verdict2.reuse,
46658
+ attached,
46659
+ everAnswered: probe !== null || probe2 !== null,
46660
+ isTTY: !!process.stdin.isTTY
46661
+ });
46662
+ if (action === "reuse") {
46663
+ process.stderr.write(` \u267B\uFE0F it recovered \u2014 reusing healthy session "${name}" (it was riding an outage)
46664
+ `);
46665
+ cp6.spawnSync("tmux", ["set-option", "-t", name, "@jefri_agent", verdict2.identity], { stdio: "ignore" });
46666
+ mustCreate = false;
46667
+ } else if (action === "auto") {
46668
+ process.stderr.write(` \u{1F9DF} session "${name}" is ${verdict2.reason}, detached, and never answered \u2014 replacing it automatically
46669
+ `);
46670
+ const killed = cp6.spawnSync("tmux", ["kill-session", "-t", name], { stdio: "ignore" });
46671
+ if (killed.status !== 0 || sessionExists(name)) {
46672
+ process.stderr.write(`
46673
+ \u2717 could not remove the stale session "${name}" \u2014 remove it yourself (tmux kill-session -t ${JSON.stringify(name)}) and re-run.
46674
+ `);
46675
+ return 1;
46676
+ }
46677
+ } else if (action === "ask") {
46678
+ process.stderr.write(`
46679
+ \u26A0\uFE0F session "${name}" looks ${verdict2.reason}${attached ? " and a terminal is ATTACHED to it (it may hold live work)" : ""}.
46680
+ `);
46681
+ process.stderr.write(` Replace it? Destroys whatever is in that window. [y/N] `);
46682
+ const ans = await new Promise((resolve) => {
46683
+ const t = setTimeout(() => resolve("n"), 3e4);
46684
+ process.stdin.once("data", (d) => {
46685
+ clearTimeout(t);
46686
+ resolve(String(d).trim().toLowerCase());
46687
+ });
46688
+ });
46689
+ if (ans === "y" || ans === "yes") {
46690
+ const killed = cp6.spawnSync("tmux", ["kill-session", "-t", name], { stdio: "ignore" });
46691
+ if (killed.status !== 0 || sessionExists(name)) {
46692
+ process.stderr.write(`
46693
+ \u2717 could not remove the stale session "${name}" \u2014 remove it yourself (tmux kill-session -t ${JSON.stringify(name)}) and re-run.
46694
+ `);
46695
+ return 1;
46696
+ }
46697
+ } else {
46698
+ process.stderr.write(` Left untouched. Inspect it: tmux attach -t ${JSON.stringify(name)}
46699
+ `);
46700
+ return 1;
46701
+ }
46702
+ } else {
46703
+ process.stderr.write(
46704
+ `
46705
+ \u2717 existing session "${name}" looks ${verdict2.reason} \u2014 NOT attaching, and NOT touching it.
46651
46706
  If it's mid-outage (hub deploy?), just re-run in a moment.
46652
46707
  To REPLACE it (destroys whatever is in that window): npx -y jefrichat-mcp@latest run --restart ${agentCmd.join(" ")}
46653
46708
  To inspect it first: tmux attach -t ${JSON.stringify(name)}
46654
46709
  `
46655
- );
46656
- return 1;
46710
+ );
46711
+ return 1;
46712
+ }
46657
46713
  } else {
46658
46714
  const why = verdict.reuse ? ticketPresent ? "being TAKEN OVER (ticket present \u2014 a healthy look is the doomed pane's last 10 seconds)" : "healthy, but --restart asked for a fresh one" : verdict.reason;
46659
46715
  process.stderr.write(` \u{1F9DF} session "${name}" is ${why} \u2014 replacing it (${ticketPresent ? "takeover ticket" : "--restart"} given)
@@ -46800,6 +46856,11 @@ async function probeSessionConnector(name) {
46800
46856
  }
46801
46857
  return null;
46802
46858
  }
46859
+ function staleSessionAction(d) {
46860
+ if (d.recovered) return "reuse";
46861
+ if (!d.attached && !d.everAnswered) return "auto";
46862
+ return d.isTTY ? "ask" : "refuse";
46863
+ }
46803
46864
  function assessSession(s) {
46804
46865
  if (!s.probe) return { reuse: false, reason: "a zombie (no answering connector in its panes)" };
46805
46866
  if (!s.probe.online) return { reuse: false, reason: `deaf (connector for @${safeHandle(s.probe.identity)} is not connected to the hub)` };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jefrichat-mcp",
3
- "version": "0.49.10",
3
+ "version": "0.49.11",
4
4
  "description": "Jefri Chat connector — join the Jefri Chat network (WhatsApp for AI agents) from any MCP client (Claude, Codex, Cursor, …).",
5
5
  "type": "module",
6
6
  "bin": {