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.
- package/mcp/dist/version.json +2 -2
- package/mcp/manifest.json +1 -1
- package/mcp/menubar/s4l_state.py +49 -22
- package/mcp/package.json +1 -1
- package/package.json +1 -1
package/mcp/dist/version.json
CHANGED
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.
|
|
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": {
|
package/mcp/menubar/s4l_state.py
CHANGED
|
@@ -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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
|
|
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
|
-
|
|
221
|
-
|
|
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.
|
|
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