social-autoposter 1.6.149 → 1.6.150

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/mcp/dist/index.js CHANGED
@@ -1037,9 +1037,9 @@ tool("engagement_mode", {
1037
1037
  "toggle.",
1038
1038
  inputSchema: {
1039
1039
  action: z
1040
- .enum(["get", "set"])
1040
+ .enum(["get", "set", "toggle"])
1041
1041
  .optional()
1042
- .describe("get = read current mode + persona status. set = record the user's chosen mode."),
1042
+ .describe("get = read current mode + persona status. set = record the user's chosen mode (provisions the persona). toggle = lightweight flip promotion<->personal_brand (mode.json only, no persona work) — the dashboard/menu-bar quick toggle."),
1043
1043
  mode: z
1044
1044
  .enum(["personal_brand", "promotion"])
1045
1045
  .optional()
@@ -1070,6 +1070,20 @@ tool("engagement_mode", {
1070
1070
  const persona = findPersonaProject();
1071
1071
  return jsonContent({ mode, persona: persona ? persona.name : null });
1072
1072
  }
1073
+ // Lightweight flip (the dashboard/menu-bar quick toggle): just rewrite
1074
+ // mode.json via saps_mode.py — NO persona provisioning. Mirrors the menu
1075
+ // bar's pure-local _toggle_mode so flipping from either surface is cheap.
1076
+ if (action === "toggle") {
1077
+ const cur = await runPython("scripts/saps_mode.py", ["get"], { timeoutMs: 15_000 });
1078
+ const now = (cur.stdout || "").trim() || "promotion";
1079
+ const next = now === "personal_brand" ? "promotion" : "personal_brand";
1080
+ const res = await runPython("scripts/saps_mode.py", ["set", next], { timeoutMs: 15_000 });
1081
+ if (res.code !== 0) {
1082
+ const tail = (res.stderr || res.stdout).trim().split("\n").slice(-1)[0] || "unknown error";
1083
+ return textContent(`Could not switch mode: ${tail}`);
1084
+ }
1085
+ return jsonContent({ mode: next });
1086
+ }
1073
1087
  const mode = args.mode;
1074
1088
  if (mode !== "personal_brand" && mode !== "promotion") {
1075
1089
  return textContent("Ask the user which they want, then call again with mode:'personal_brand' (organic brand " +
@@ -1435,6 +1449,7 @@ tool("project_config", {
1435
1449
  mcp_version: ver.installed,
1436
1450
  latest_version: ver.latest,
1437
1451
  update_available: ver.update_available,
1452
+ mode: currentMode(),
1438
1453
  update_hint: ver.update_available
1439
1454
  ? `A newer version (${ver.latest}) is available — you're on ${ver.installed}. ` +
1440
1455
  `Tell the user and offer to run the \`runtime\` tool with action:'update' ` +
@@ -2753,6 +2768,8 @@ async function buildSnapshot() {
2753
2768
  runtime_ready: rtReady,
2754
2769
  runtime_provisioning: isProvisioning(),
2755
2770
  setup_complete: setupComplete,
2771
+ // Engagement mode for display in BOTH surfaces (single source: mode.json).
2772
+ mode: currentMode(),
2756
2773
  onboarding: onboardingLive,
2757
2774
  };
2758
2775
  // Persist this snapshot so the menu bar can answer "set up?" the SAME way when
@@ -2915,6 +2932,18 @@ function modeChosen() {
2915
2932
  return false;
2916
2933
  }
2917
2934
  }
2935
+ // The current engagement mode ('promotion' | 'personal_brand'), surfaced in the
2936
+ // snapshot so the dashboard AND menu bar read it from ONE place (mode.json, the
2937
+ // same file saps_mode.py writes). Defaults to promotion when unset.
2938
+ function currentMode() {
2939
+ try {
2940
+ const m = (JSON.parse(fs.readFileSync(path.join(sapsStateDir(), "mode.json"), "utf-8")).mode || "").trim();
2941
+ return m === "personal_brand" ? "personal_brand" : "promotion";
2942
+ }
2943
+ catch {
2944
+ return "promotion";
2945
+ }
2946
+ }
2918
2947
  // ---- Cross-instance "posting active" flag ----------------------------------
2919
2948
  // posting-active.json in the shared state dir is the CROSS-MCP-INSTANCE version
2920
2949
  // of the in-process `postingActive` flag. The autopilot scan and the post