@m13v/s4l 1.7.1-rc.7 → 1.7.1-rc.8

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.7.1-rc.7",
3
- "installedAt": "2026-07-07T23:08:38.967Z"
2
+ "version": "1.7.1-rc.8",
3
+ "installedAt": "2026-07-07T23:28:11.193Z"
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.7.1-rc.7",
5
+ "version": "1.7.1-rc.8",
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": {
@@ -132,20 +132,24 @@ except Exception as _import_err:
132
132
  import s4l_state as st # noqa: E402
133
133
 
134
134
  # AppKit is available in the owned venv (PyObjC is a rumps dependency). We use it
135
- # only to pull the accessory (LSUIElement) app to the front before showing an
136
- # NSAlert: an agent app that isn't the active app has its rumps.alert appear
137
- # BEHIND the frontmost window ("modal doesn't show on top"), because runModal
138
- # doesn't activate the app for us. Guarded so a missing AppKit never breaks the
139
- # menu bar — the alert still shows, just possibly not front-most.
135
+ # to pull the accessory (LSUIElement) app to the front AND to force the alert
136
+ # window itself above whatever else is on screen. Guarded so a missing AppKit
137
+ # never breaks the menu bar — the alert still shows, just possibly not
138
+ # front-most.
140
139
  try:
141
- from AppKit import NSApplication # noqa: E402
140
+ from AppKit import NSApplication, NSAlert, NSFloatingWindowLevel # noqa: E402
142
141
  except Exception:
143
142
  NSApplication = None
143
+ NSAlert = None
144
+ NSFloatingWindowLevel = None
144
145
 
145
146
 
146
147
  def _activate_front():
147
- """Bring this accessory app to the front so the next NSAlert (rumps.alert)
148
- opens on top of whatever was frontmost, instead of behind it. Best-effort."""
148
+ """Bring this accessory app to the front so the next alert opens on top of
149
+ whatever was frontmost, instead of behind it. Best-effort; kept as a
150
+ belt-and-suspenders call alongside _show_alert's own window-level fix
151
+ below, since activation also affects which app is "key" for keyboard
152
+ input on the alert's buttons."""
149
153
  try:
150
154
  if NSApplication is not None:
151
155
  NSApplication.sharedApplication().activateIgnoringOtherApps_(True)
@@ -153,6 +157,44 @@ def _activate_front():
153
157
  pass
154
158
 
155
159
 
160
+ def _show_alert(title=None, message='', ok=None, cancel=None, other=None):
161
+ """Like rumps.alert(), but actually shows up on top.
162
+
163
+ rumps.alert() builds an NSAlert and immediately calls runModal() with no
164
+ window-level or ordering call at all — it just assumes the app is already
165
+ active. activateIgnoringOtherApps_ (_activate_front, above) is async, so
166
+ it can lose the race against runModal()'s own (assumed-active) window
167
+ presentation: the alert window is created at the default level and never
168
+ explicitly raised, so when this accessory app ISN'T active (e.g. Claude
169
+ Desktop is frontmost), it renders BEHIND Claude's window instead of on
170
+ top of it. Confirmed recurring 2026-07-07 (uninstall modal hidden behind
171
+ Claude Desktop) despite the activation call landing 2026-06-30.
172
+
173
+ Fix: build the NSAlert ourselves (same call rumps.alert uses) and force
174
+ its window to NSFloatingWindowLevel + orderFrontRegardless() BEFORE
175
+ runModal(), mirroring the pattern s4l_card.py's review panel already uses
176
+ successfully (see _ReviewPanel._build: setLevel_(NSFloatingWindowLevel) +
177
+ orderFrontRegardless()). Floating level sits above normal app windows in
178
+ the window server's global z-order regardless of app-activation state,
179
+ so it doesn't depend on the activation race resolving in time."""
180
+ _activate_front()
181
+ if NSAlert is None:
182
+ # AppKit unavailable in this venv: fall back to rumps' plain alert.
183
+ return rumps.alert(title=title, message=message, ok=ok, cancel=cancel, other=other)
184
+ msg = str(message).replace('%', '%%')
185
+ if not isinstance(cancel, str):
186
+ cancel = 'Cancel' if cancel else None
187
+ alert = NSAlert.alertWithMessageText_defaultButton_alternateButton_otherButton_informativeTextWithFormat_(
188
+ title, ok, cancel, other, msg)
189
+ alert.setAlertStyle_(0) # same style rumps.alert() uses
190
+ try:
191
+ alert.window().setLevel_(NSFloatingWindowLevel)
192
+ alert.window().orderFrontRegardless()
193
+ except Exception:
194
+ pass
195
+ return alert.runModal()
196
+
197
+
156
198
  CLAUDE_APP = "Claude"
157
199
 
158
200
 
@@ -595,7 +637,7 @@ class S4LMenuBar(rumps.App):
595
637
  msg = "Click OK, then open Claude and ask it to " + action_desc + "."
596
638
  try:
597
639
  _activate_front()
598
- rumps.alert(title=title, message=msg, ok="OK")
640
+ _show_alert(title=title, message=msg, ok="OK")
599
641
  except Exception:
600
642
  self._notify("S4L · prompt copied" if copied else "S4L",
601
643
  "Paste the prompt into Claude (Cmd+V) and press Enter.")
@@ -666,7 +708,7 @@ class S4LMenuBar(rumps.App):
666
708
  also run the registry self-heal, which additionally repairs the
667
709
  account-switch orphan case, so this one click covers both known causes."""
668
710
  _activate_front()
669
- choice = rumps.alert(
711
+ choice = _show_alert(
670
712
  title="Restart Claude Desktop?",
671
713
  message=(
672
714
  "Claude’s scheduler stopped running the draft tasks (a known "
@@ -994,7 +1036,7 @@ class S4LMenuBar(rumps.App):
994
1036
  # ok=1 (plugin reset, keeps X login + browser layer), other=-1 (deep wipe),
995
1037
  # cancel=0. See rumps.alert: default=1, alternate=0, other=-1.
996
1038
  _activate_front()
997
- choice = rumps.alert(
1039
+ choice = _show_alert(
998
1040
  title="Uninstall S4L?",
999
1041
  message=(
1000
1042
  "This quits Claude Desktop, removes the S4L extension + its "
@@ -1037,7 +1079,7 @@ class S4LMenuBar(rumps.App):
1037
1079
  def _alert(self, title, message):
1038
1080
  try:
1039
1081
  _activate_front()
1040
- rumps.alert(title=title, message=message, ok="OK")
1082
+ _show_alert(title=title, message=message, ok="OK")
1041
1083
  except Exception:
1042
1084
  pass
1043
1085
 
@@ -1072,7 +1114,7 @@ class S4LMenuBar(rumps.App):
1072
1114
  modal FIRST that Claude Desktop will restart, since the app window will
1073
1115
  close and reopen under them."""
1074
1116
  _activate_front()
1075
- choice = rumps.alert(
1117
+ choice = _show_alert(
1076
1118
  title="Quit the S4L autoposter?",
1077
1119
  message=(
1078
1120
  "Quitting stops the autoposter completely: the draft + query "
@@ -1758,7 +1800,7 @@ class S4LMenuBar(rumps.App):
1758
1800
  self._cwd_healed = True
1759
1801
  return
1760
1802
  _activate_front()
1761
- choice = rumps.alert(
1803
+ choice = _show_alert(
1762
1804
  title="Tidy the S4L background tasks?",
1763
1805
  message=(
1764
1806
  "S4L can tidy its background tasks: merge the old draft + query "
package/mcp/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m13v/s4l-mcp",
3
- "version": "1.7.1-rc.7",
3
+ "version": "1.7.1-rc.8",
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": "@m13v/s4l",
3
- "version": "1.7.1-rc.7",
3
+ "version": "1.7.1-rc.8",
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",