@m13v/s4l 1.7.2-rc.3 → 1.7.2-rc.4
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
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.7.2-rc.
|
|
5
|
+
"version": "1.7.2-rc.4",
|
|
6
6
|
"description": "Draft, review, approve, and autopilot X/Twitter posts.",
|
|
7
7
|
"long_description": "## **⚠️ The disclaimer above is generic Claude boilerplate.** Anthropic shows the same warning on every plugin regardless of what it does; any plugin has the same level of access as any app you download from the internet.\n\nS4L 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 plugin end to end**\n\n2\\. Quit with CMD+Q, reopen Claude, paste into a new chat.\n\nWhat happens next:\n\n* About every 5 minutes S4L scans X for posts that match your topics and drafts replies in your voice.\n* Drafts show up as review cards, usually the first within a few minutes. Nothing is posted automatically; you approve each one.\n* Posting autopilot stays off until you explicitly turn it on.",
|
|
8
8
|
"author": {
|
|
@@ -1140,7 +1140,7 @@ class S4LMenuBar(rumps.App):
|
|
|
1140
1140
|
"Uninstall: keep your X login + browser layer (quick uninstall).\n"
|
|
1141
1141
|
"Deep wipe: also remove the shared browser profiles + toolchain."
|
|
1142
1142
|
),
|
|
1143
|
-
ok="Uninstall & Restart Claude", cancel="Cancel", other="Deep wipe",
|
|
1143
|
+
ok="Uninstall & Restart Claude", cancel="Cancel", other="Deep wipe & Restart Claude",
|
|
1144
1144
|
)
|
|
1145
1145
|
if choice == 0: # cancel
|
|
1146
1146
|
return
|
|
@@ -3001,7 +3001,6 @@ class S4LMenuBar(rumps.App):
|
|
|
3001
3001
|
items.append(rumps.MenuItem("Resume S4L", callback=self._pause_toggle))
|
|
3002
3002
|
else:
|
|
3003
3003
|
items.append(rumps.MenuItem("Pause S4L", callback=self._pause_toggle))
|
|
3004
|
-
items.append(self._label(" stop drafting/posting, keep Claude + tray running"))
|
|
3005
3004
|
items.append(rumps.separator)
|
|
3006
3005
|
|
|
3007
3006
|
# Attention = the draft schedule isn't running for THIS account (missing or
|
|
@@ -3105,19 +3104,15 @@ class S4LMenuBar(rumps.App):
|
|
|
3105
3104
|
personal_on = bool(flags.get("personal_brand"))
|
|
3106
3105
|
promo_on = bool(flags.get("promotion"))
|
|
3107
3106
|
items.append(rumps.separator)
|
|
3108
|
-
items.append(self._label("Engagement lanes"))
|
|
3109
3107
|
pb_item = rumps.MenuItem("Personal brand", callback=self._toggle_personal)
|
|
3110
3108
|
pb_item.state = 1 if personal_on else 0
|
|
3111
3109
|
items.append(pb_item)
|
|
3112
|
-
items.append(self._label(" organic, link-free engagement"))
|
|
3113
3110
|
pr_item = rumps.MenuItem("Product promotion", callback=self._toggle_promotion)
|
|
3114
3111
|
pr_item.state = 1 if promo_on else 0
|
|
3115
3112
|
items.append(pr_item)
|
|
3116
|
-
items.append(self._label(" promoting your products (link replies)"))
|
|
3117
3113
|
if personal_on and promo_on:
|
|
3118
3114
|
# Both lanes on: the split becomes meaningful, so offer the presets.
|
|
3119
3115
|
share = st.read_split()
|
|
3120
|
-
items.append(self._label(f" both on · cycles split {self._split_pct(share)}"))
|
|
3121
3116
|
split_menu = rumps.MenuItem(f"Lane split: {self._split_pct(share)}")
|
|
3122
3117
|
for preset in self.SPLIT_PRESETS:
|
|
3123
3118
|
it = rumps.MenuItem(
|
|
@@ -3134,7 +3129,6 @@ class S4LMenuBar(rumps.App):
|
|
|
3134
3129
|
# carries a Feedback button); named for what it does to the pipeline,
|
|
3135
3130
|
# not the mechanism.
|
|
3136
3131
|
items.append(rumps.MenuItem("Give overall feedback to AI…", callback=self._menu_feedback))
|
|
3137
|
-
items.append(self._label(" overall guidance, steers future drafts"))
|
|
3138
3132
|
# While the update-verify marker is pending, the pipeline copy still
|
|
3139
3133
|
# resolves the OLD version (it only advances once the restarted server
|
|
3140
3134
|
# re-provisions repo/package, ~2 min), so the snapshot honestly reports
|
|
@@ -3161,8 +3155,10 @@ class S4LMenuBar(rumps.App):
|
|
|
3161
3155
|
items.append(rumps.separator)
|
|
3162
3156
|
items.append(rumps.MenuItem("Tidy autopilot history…", callback=self._prompt_relocate_tasks))
|
|
3163
3157
|
items.append(rumps.separator)
|
|
3164
|
-
|
|
3165
|
-
|
|
3158
|
+
quit_menu = rumps.MenuItem("Quit or Uninstall")
|
|
3159
|
+
quit_menu.add(rumps.MenuItem("Uninstall S4L…", callback=self._reset_machine))
|
|
3160
|
+
quit_menu.add(rumps.MenuItem("Quit", callback=self._quit_app))
|
|
3161
|
+
items.append(quit_menu)
|
|
3166
3162
|
|
|
3167
3163
|
# Collapse consecutive/edge separators so an empty section (e.g. State C
|
|
3168
3164
|
# now renders no status labels) can't leave a doubled or dangling divider.
|
package/mcp/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m13v/s4l-mcp",
|
|
3
|
-
"version": "1.7.2-rc.
|
|
3
|
+
"version": "1.7.2-rc.4",
|
|
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
|
@@ -60,14 +60,26 @@ except Exception: # standalone fallbacks
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
def _is_prep_result(obj):
|
|
63
|
-
"""True iff obj looks like a twitter-prep result (candidates
|
|
63
|
+
"""True iff obj looks like a twitter-prep result (drafted candidates).
|
|
64
|
+
|
|
65
|
+
"reply_text" was the single-draft field before the 2026-07-07/08 two-draft
|
|
66
|
+
redesign (draft_a_text/draft_b_text per candidate, no single recommended
|
|
67
|
+
reply). Checking only "reply_text" made every post-redesign orphaned
|
|
68
|
+
result silently misclassified as non-prep and marked .skipped instead of
|
|
69
|
+
recovered — the exact "worker drafted but no card" bug this script exists
|
|
70
|
+
to prevent. Accept either field so both old and current schema results
|
|
71
|
+
are recognized.
|
|
72
|
+
"""
|
|
64
73
|
if not isinstance(obj, dict):
|
|
65
74
|
return False
|
|
66
75
|
cands = obj.get("candidates")
|
|
67
76
|
if not isinstance(cands, list) or not cands:
|
|
68
77
|
return False
|
|
69
78
|
c0 = cands[0]
|
|
70
|
-
|
|
79
|
+
if not isinstance(c0, dict):
|
|
80
|
+
return False
|
|
81
|
+
has_text = "reply_text" in c0 or "draft_a_text" in c0
|
|
82
|
+
return has_text and ("candidate_url" in c0 or "candidate_id" in c0)
|
|
71
83
|
|
|
72
84
|
|
|
73
85
|
def main():
|