@m13v/s4l 1.7.8 → 1.7.9-rc.1
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 +21 -8
- package/mcp/dist/version.json +2 -2
- package/mcp/manifest.json +1 -5
- package/mcp/menubar/s4l_browser_foreground.py +8 -4
- package/mcp/package.json +1 -1
- package/package.json +1 -1
- package/scripts/claude_job.py +30 -8
package/mcp/dist/index.js
CHANGED
|
@@ -3636,14 +3636,27 @@ function writeDraftProvider(provider, setBy) {
|
|
|
3636
3636
|
console.error(`[draft-provider] ${provider} (${setBy})`);
|
|
3637
3637
|
}
|
|
3638
3638
|
tool("queue_setup", {
|
|
3639
|
-
|
|
3640
|
-
description
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
"
|
|
3646
|
-
"
|
|
3639
|
+
// Title/description are host-aware (2026-08-06): an agent reads the tool
|
|
3640
|
+
// description FIRST, so it must tell the truth for the host it's on.
|
|
3641
|
+
// Historic name kept for fleet compatibility; conceptually this tool is
|
|
3642
|
+
// "arm the drafting engine" — Claude hosts get queue-worker task specs,
|
|
3643
|
+
// Codex/ChatGPT hosts get the provider stamped with nothing to schedule.
|
|
3644
|
+
title: s4lHost() === "codex"
|
|
3645
|
+
? "Arm the draft autopilot"
|
|
3646
|
+
: "Get autopilot scheduled-task specs",
|
|
3647
|
+
description: s4lHost() === "codex"
|
|
3648
|
+
? "Arms the hands-free draft autopilot on this machine. On this host there is NOTHING to " +
|
|
3649
|
+
"schedule: drafting runs inline through this app's engine, so ONE call completes autopilot " +
|
|
3650
|
+
"setup (it records the draft engine choice and returns no tasks). Do NOT create any " +
|
|
3651
|
+
"scheduled task or automation. The pipeline itself is kicked by launchd jobs this server " +
|
|
3652
|
+
"installs. Use this as the final onboarding step."
|
|
3653
|
+
: "Returns the scheduled task that runs the hands-free draft autopilot on this machine " +
|
|
3654
|
+
"(s4l-worker, the universal queue worker). For EACH returned task, call the host tool " +
|
|
3655
|
+
"create_scheduled_task with its taskId, cronExpression, prompt, and notifyOnCompletion " +
|
|
3656
|
+
"VERBATIM (do not edit the prompt — it contains exact local paths; notifyOnCompletion MUST be " +
|
|
3657
|
+
"false or the per-minute worker spams a notification every run). The task drains the local job queue that the " +
|
|
3658
|
+
"real pipeline feeds (all job types); the pipeline itself is kicked by launchd jobs this server " +
|
|
3659
|
+
"installs. Use this as the final onboarding step instead of the old per-type worker tasks.",
|
|
3647
3660
|
inputSchema: {},
|
|
3648
3661
|
}, async () => {
|
|
3649
3662
|
// Codex/ChatGPT host: there is no scheduled-task worker at all. Drafting
|
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.
|
|
5
|
+
"version": "1.7.9-rc.1",
|
|
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": {
|
|
@@ -72,10 +72,6 @@
|
|
|
72
72
|
"name": "client_event",
|
|
73
73
|
"description": "Log a lightweight client UI event"
|
|
74
74
|
},
|
|
75
|
-
{
|
|
76
|
-
"name": "queue_setup",
|
|
77
|
-
"description": "Get autopilot scheduled-task specs"
|
|
78
|
-
},
|
|
79
75
|
{
|
|
80
76
|
"name": "dashboard",
|
|
81
77
|
"description": "S4L dashboard"
|
|
@@ -157,12 +157,16 @@ class _Worker(threading.Thread):
|
|
|
157
157
|
# focus back to the app the user was in. Screenshots/clicks are
|
|
158
158
|
# unaffected (CDP is offscreen-raster + synthetic input; the occlusion
|
|
159
159
|
# flags keep hidden tabs painting).
|
|
160
|
-
# DEFAULT
|
|
161
|
-
#
|
|
162
|
-
#
|
|
160
|
+
# DEFAULT ON (user decision 2026-08-07, reverses the 2026-07-30 default-off
|
|
161
|
+
# call): the guard hides an offscreen harness that steals the foreground
|
|
162
|
+
# unless explicitly opted out. Two knobs, by design:
|
|
163
|
+
# S4L_NO_HARNESS_HIDE -> HARD override, force off, checked FIRST so it
|
|
164
|
+
# always wins (this is the one-time interactive-login escape hatch).
|
|
165
|
+
# S4L_HARNESS_HIDE=0 -> SOFT opt-out for a machine that wants it off.
|
|
166
|
+
# Unset or any non-"0" value => hide is active (the new default).
|
|
163
167
|
if os.environ.get("S4L_NO_HARNESS_HIDE"):
|
|
164
168
|
return
|
|
165
|
-
if os.environ.get("S4L_HARNESS_HIDE")
|
|
169
|
+
if os.environ.get("S4L_HARNESS_HIDE", "1") == "0":
|
|
166
170
|
return
|
|
167
171
|
pos = details.get("window_position") or ""
|
|
168
172
|
try:
|
package/mcp/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m13v/s4l-mcp",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.9-rc.1",
|
|
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
package/scripts/claude_job.py
CHANGED
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
claude_job.py —
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
claude_job.py — THE DRAFT-ENGINE SEAM: every pure text->JSON drafting turn in
|
|
4
|
+
the pipeline lands here, and <state_dir>/draft-provider.json decides which
|
|
5
|
+
engine answers it (see scripts/draft_provider.py; design + verified facts in
|
|
6
|
+
docs/codex-port-design.md):
|
|
7
|
+
|
|
8
|
+
claude-desktop-queue (default) enqueue to a file queue drained by the
|
|
9
|
+
Claude Desktop s4l-worker scheduled task — the
|
|
10
|
+
original design, and the only option when Claude
|
|
11
|
+
Desktop is the box's sole authenticated engine.
|
|
12
|
+
claude-p answer inline via the real `claude -p` (_run_claude_p;
|
|
13
|
+
schema INLINED — the CLI parses --json-schema as JSON,
|
|
14
|
+
a file path breaks it).
|
|
15
|
+
codex-exec answer inline via the ChatGPT-app-bundled `codex exec`
|
|
16
|
+
(_run_codex_exec; gpt-5.6-sol default, schema rides
|
|
17
|
+
the prompt — OpenAI strict schema mode rejects our
|
|
18
|
+
lenient schemas).
|
|
19
|
+
|
|
20
|
+
All three return byte-identical claude `--output-format json` envelopes and
|
|
21
|
+
the same 0/1/79 exit semantics, so callers can't tell them apart. The queue
|
|
22
|
+
machinery below (next/result, worker notes, heartbeats) only runs for the
|
|
23
|
+
default provider; the inline providers skip it entirely, which also means no
|
|
24
|
+
warm-session leaks and no app-open requirement on those paths.
|
|
6
25
|
|
|
7
26
|
The deterministic pipeline never calls `claude` directly; every invocation goes
|
|
8
27
|
through scripts/run_claude.sh. For script tags mapped in TAG_TO_TYPE below,
|
|
@@ -461,19 +480,22 @@ def _bump_drain_timeout() -> None:
|
|
|
461
480
|
|
|
462
481
|
|
|
463
482
|
# --------------------------------------------------------------------------- #
|
|
464
|
-
#
|
|
483
|
+
# Worker self-reap (2026-06-27; DEFAULT ON since 2026-07-04 / v1.6.202) #
|
|
465
484
|
# --------------------------------------------------------------------------- #
|
|
466
485
|
# A scheduled-task worker turn finishes its one queue iteration but Claude
|
|
467
486
|
# Desktop keeps the agent-mode `claude` process warm (`--input-format
|
|
468
487
|
# stream-json`), so finished workers pile up and leak RAM. The launchd reaper
|
|
469
|
-
# (reap_stale_claude_sessions.py) is the GUARANTEE that bounds this. This
|
|
488
|
+
# (reap_stale_claude_sessions.py) is the GUARANTEE that bounds this. This
|
|
470
489
|
# path is a faster, source-side trim: once THIS worker is provably done (no work
|
|
471
490
|
# to do, or its result is already on disk), terminate OUR OWN session so it never
|
|
472
|
-
# becomes part of the standing pool.
|
|
473
|
-
# set,
|
|
491
|
+
# becomes part of the standing pool. It shipped opt-in (dormant unless
|
|
492
|
+
# S4L_WORKER_SELF_REAP was set), which meant it ran nowhere; when Desktop
|
|
493
|
+
# 1.18286.0 changed the cmdline shape the signature-fragile reaper missed too
|
|
494
|
+
# and boxes leaked (Karol, 53 piled workers). Since 2026-07-04 it is ON by
|
|
495
|
+
# default; opt OUT with S4L_WORKER_SELF_REAP=0 (see _self_reap_enabled).
|
|
474
496
|
#
|
|
475
497
|
# Safety properties:
|
|
476
|
-
# *
|
|
498
|
+
# * Respects the env kill switch (S4L_WORKER_SELF_REAP=0 disables it).
|
|
477
499
|
# * Only ever targets a process in OUR OWN ancestry that matches the reaper's
|
|
478
500
|
# worker signature (claude-code agent-mode session). The producer side
|
|
479
501
|
# (run-twitter-cycle.sh -> python) has no such ancestor, so a misplaced call
|