social-autoposter 1.6.154 → 1.6.155

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.
@@ -1,4 +1,4 @@
1
1
  {
2
- "version": "1.6.154",
3
- "installedAt": "2026-06-29T23:14:44.360Z"
2
+ "version": "1.6.155",
3
+ "installedAt": "2026-06-29T23:16:11.195Z"
4
4
  }
package/mcp/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "dxt_version": "0.1",
3
3
  "name": "social-autoposter",
4
4
  "display_name": "S4L",
5
- "version": "1.6.154",
5
+ "version": "1.6.155",
6
6
  "description": "Draft, review, approve, and autopilot X/Twitter posts.",
7
7
  "long_description": "The disclaimer above is generic Claude boilerplate. S4L is an open source product developed by Mediar.ai Incorporated, a VC-backed San Francisco-based startup.\n\nTo get started:\n\n1\\. Copy this prompt: **Set me up on S4L end to end**\n\n2\\. Quit fully with CMD+Q, restart Claude, and paste the prompt into a new chat.",
8
8
  "author": {
@@ -22,6 +22,7 @@ import os
22
22
  import subprocess
23
23
  import sys
24
24
  import threading
25
+ import time
25
26
  import urllib.request
26
27
  from pathlib import Path
27
28
 
@@ -195,32 +196,58 @@ def loopback_tool(name: str, args=None, timeout: float = 20.0):
195
196
 
196
197
 
197
198
  # ---- the snapshot the menu bar renders ------------------------------------
198
- def snapshot():
199
- """Full snapshot computed DIRECTLY from the stateful files via
200
- scripts/snapshot.py the SAME single-source module the MCP shells out to, so
201
- the two surfaces can't diverge. The menu bar no longer depends on the MCP /
202
- Claude being up: there is NO loopback call here, so a restarting or closed
203
- Claude can't freeze or stale the menu (the old tier-1 `loopback_tool` blocked
204
- the UI thread up to 20s and was the freeze).
205
-
206
- Three tiers, in order:
207
- 1. LIVE — compute locally from the files (zero MCP dependency).
208
- 2. SUMMARY the server's last persisted `status-summary.json`, if the local
209
- compute somehow failed.
210
- 3. LEDGER nothing else available: derive the essentials from the onboarding
211
- ledger so progress still shows."""
199
+ # Background snapshot cache. scripts/snapshot.py reads files but may spawn the
200
+ # X-status subprocess (setup_twitter_auth.py -> CDP to Chrome), which must NEVER
201
+ # run on the menu bar's UI thread a hung Chrome would freeze the menu. So a
202
+ # daemon thread recomputes and snapshot() returns the last cached value INSTANTLY.
203
+ _snap_cache = {"val": None, "at": 0.0}
204
+ _snap_lock = threading.Lock()
205
+ _snap_refreshing = [False]
206
+
207
+
208
+ def _compute_snapshot_full():
209
+ repo = os.environ.get("SAPS_REPO_DIR") or str(Path.home() / "social-autoposter")
210
+ scripts = os.path.join(repo, "scripts")
211
+ if scripts not in sys.path:
212
+ sys.path.insert(0, scripts)
213
+ import snapshot as _snapshot_mod # scripts/snapshot.py
214
+ return _snapshot_mod.compute()
215
+
216
+
217
+ def _refresh_snapshot_bg():
212
218
  try:
213
- repo = os.environ.get("SAPS_REPO_DIR") or str(Path.home() / "social-autoposter")
214
- scripts = os.path.join(repo, "scripts")
215
- if scripts not in sys.path:
216
- sys.path.insert(0, scripts)
217
- import snapshot as _snapshot_mod # scripts/snapshot.py
218
- snap = _snapshot_mod.compute()
219
+ snap = _compute_snapshot_full()
219
220
  if isinstance(snap, dict) and "projects_total" in snap:
220
- snap["_live"] = True
221
- return snap
221
+ with _snap_lock:
222
+ _snap_cache["val"] = snap
223
+ _snap_cache["at"] = time.time()
222
224
  except Exception:
223
225
  pass
226
+ finally:
227
+ _snap_refreshing[0] = False
228
+
229
+
230
+ def snapshot():
231
+ """Full snapshot computed DIRECTLY from the stateful files via
232
+ scripts/snapshot.py — the SAME single-source module the MCP shells out to, so
233
+ the two surfaces can't diverge. NO loopback / MCP dependency, so a restarting
234
+ or closed Claude can't freeze or stale the menu (the old tier-1 `loopback_tool`
235
+ blocked the UI thread up to 20s and was the freeze). The heavy compute runs on
236
+ a BACKGROUND thread; this returns the last cached result instantly.
237
+
238
+ Tiers: (1) the background-computed local snapshot; (2) the server's last
239
+ persisted `status-summary.json`; (3) the onboarding ledger."""
240
+ now = time.time()
241
+ with _snap_lock:
242
+ cached = _snap_cache["val"]
243
+ age = now - _snap_cache["at"]
244
+ if (cached is None or age > 4.0) and not _snap_refreshing[0]:
245
+ _snap_refreshing[0] = True
246
+ threading.Thread(target=_refresh_snapshot_bg, daemon=True).start()
247
+ if cached is not None:
248
+ out = dict(cached)
249
+ out["_live"] = True
250
+ return out
224
251
  summ = read_json("status-summary.json")
225
252
  if isinstance(summ, dict) and "projects_total" in summ:
226
253
  summ["_live"] = False
package/mcp/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m13v/social-autoposter-mcp",
3
- "version": "1.6.154",
3
+ "version": "1.6.155",
4
4
  "private": true,
5
5
  "description": "Desktop MCP client for social-autoposter (X/Twitter rail): manual draft/review/approve loop, autopilot control, and stats. Thin wrapper over the existing pipeline scripts.",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "social-autoposter",
3
- "version": "1.6.154",
3
+ "version": "1.6.155",
4
4
  "description": "Automated social posting pipeline for Reddit, X/Twitter, LinkedIn, and Moltbook. Install as a Claude Code agent skill.",
5
5
  "bin": {
6
6
  "social-autoposter": "bin/cli.js"