social-autoposter 1.6.150 → 1.6.151
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 +37 -6
- package/mcp/dist/version.json +2 -2
- package/mcp/manifest.json +1 -1
- package/mcp/package.json +1 -1
- package/package.json +1 -1
- package/scripts/_scan_pending_detail.py +0 -33
package/mcp/dist/index.js
CHANGED
|
@@ -2077,7 +2077,7 @@ async function autopilotLoaded() {
|
|
|
2077
2077
|
// fires every minute, claims ONE job, runs the pipeline's own prompt as its
|
|
2078
2078
|
// Claude turn, writes the result back, and stops.
|
|
2079
2079
|
// ===========================================================================
|
|
2080
|
-
const QUEUE_WORKER_PROMPT_VERSION =
|
|
2080
|
+
const QUEUE_WORKER_PROMPT_VERSION = 6; // v6: the ~90s kill is a host INACTIVITY watchdog (resets on each tool call), not a fixed cap. The worker was drafting all candidates in ONE silent turn (its HARD RULES even forbade log_draft.py), starving the clock -> killed mid-draft. v6 requires incremental draft-then-log per candidate and allows the log_draft.py persist commands, so per-candidate tool calls keep the session alive and the full set drains.
|
|
2081
2081
|
const QUEUE_WORKER_PROMPT_MARKER = "saps_queue_worker_prompt_version";
|
|
2082
2082
|
// One spec per worker task. queueType MUST match scripts/claude_job.py TAG_TO_TYPE.
|
|
2083
2083
|
const QUEUE_WORKERS = [
|
|
@@ -2180,6 +2180,13 @@ function queueWorkerBody(spec) {
|
|
|
2180
2180
|
const job = path.join(repoDir(), "scripts", "claude_job.py");
|
|
2181
2181
|
const sd = sapsStateDir();
|
|
2182
2182
|
const outDir = queueDir();
|
|
2183
|
+
// The Phase-2b "twitter-prep" worker drafts replies for several candidates. The
|
|
2184
|
+
// host kills an unattended scheduled session ~90s after its LAST tool call (an
|
|
2185
|
+
// inactivity watchdog). Drafting everything in one silent turn starves that clock
|
|
2186
|
+
// and the session is killed mid-draft having submitted nothing. So it MUST work
|
|
2187
|
+
// incrementally — draft + run log_draft.py per candidate — which persists drafts
|
|
2188
|
+
// (the pipeline already wants this) AND keeps the activity clock alive.
|
|
2189
|
+
const isDraft = spec.queueType === "twitter-prep";
|
|
2183
2190
|
return [
|
|
2184
2191
|
`You are the S4L "${spec.human}" queue worker. Run ONE iteration, then STOP.`,
|
|
2185
2192
|
``,
|
|
@@ -2189,6 +2196,23 @@ function queueWorkerBody(spec) {
|
|
|
2189
2196
|
`You do this with Bash and Write, and NOTHING else. This run is unattended — ` +
|
|
2190
2197
|
`reaching for any other tool, or trying to "investigate", STALLS it forever.`,
|
|
2191
2198
|
``,
|
|
2199
|
+
...(isDraft
|
|
2200
|
+
? [
|
|
2201
|
+
`PACING — CRITICAL: this unattended session is terminated ~90 seconds after ` +
|
|
2202
|
+
`your LAST tool call (a host inactivity timeout). The prompt below asks ` +
|
|
2203
|
+
`you to draft replies for SEVERAL candidates. Do NOT draft them all ` +
|
|
2204
|
+
`silently in one turn — that emits no tool calls, the clock expires, and ` +
|
|
2205
|
+
`you are KILLED mid-draft having submitted NOTHING. Work ONE candidate at ` +
|
|
2206
|
+
`a time: draft its reply, then IMMEDIATELY run that candidate's ` +
|
|
2207
|
+
`log_draft.py command exactly as the prompt's persist step (3a) specifies ` +
|
|
2208
|
+
`(a quick Bash call), THEN move to the next. Those per-candidate Bash ` +
|
|
2209
|
+
`calls are what keep the session alive. Begin the first candidate ` +
|
|
2210
|
+
`promptly — do NOT spend a long silent stretch analysing before your ` +
|
|
2211
|
+
`first tool call. Only after EVERY candidate is drafted and logged do you ` +
|
|
2212
|
+
`do step 3.`,
|
|
2213
|
+
``,
|
|
2214
|
+
]
|
|
2215
|
+
: []),
|
|
2192
2216
|
`Steps:`,
|
|
2193
2217
|
`1. Claim the next job. Run this EXACT Bash command:`,
|
|
2194
2218
|
` ${py} ${job} next --type ${spec.queueType} --prompt-file --state-dir ${sd}`,
|
|
@@ -2211,11 +2235,18 @@ function queueWorkerBody(spec) {
|
|
|
2211
2235
|
`4. Report in ONE short line what you did, then STOP. Do NOT claim another job, ` +
|
|
2212
2236
|
`do NOT loop, do NOT read other files, do NOT call any other tool.`,
|
|
2213
2237
|
``,
|
|
2214
|
-
|
|
2215
|
-
`
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2238
|
+
isDraft
|
|
2239
|
+
? `HARD RULES: use ONLY the Bash tool (to run claude_job.py AND the per-candidate ` +
|
|
2240
|
+
`log_draft.py persist commands the prompt tells you to run), the Read tool (the ` +
|
|
2241
|
+
`prompt/schema sidecar + the SKILL/config files the prompt names), and the Write ` +
|
|
2242
|
+
`tool (the result file). NEVER post, reply, edit a draft, open a browser, or run ` +
|
|
2243
|
+
`any command the prompt does not explicitly give you. An empty queue is the ` +
|
|
2244
|
+
`NORMAL, expected case most minutes — it is success, not a problem to debug.`
|
|
2245
|
+
: `HARD RULES: ONLY the Bash tool (to run claude_job.py), the Read tool (to read ` +
|
|
2246
|
+
`the prompt/schema sidecar files), and the Write tool (to write the result ` +
|
|
2247
|
+
`file). NEVER run any other shell command. NEVER edit, post, or touch anything ` +
|
|
2248
|
+
`else. An empty queue is the NORMAL, expected case most minutes — it is success, ` +
|
|
2249
|
+
`not a problem to debug.`,
|
|
2219
2250
|
].join("\n");
|
|
2220
2251
|
}
|
|
2221
2252
|
// Full canonical SKILL.md (frontmatter + body + version marker) the MCP writes
|
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.151",
|
|
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m13v/social-autoposter-mcp",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.151",
|
|
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,33 +0,0 @@
|
|
|
1
|
-
import json, sys
|
|
2
|
-
sys.path.insert(0, "scripts")
|
|
3
|
-
import http_api
|
|
4
|
-
|
|
5
|
-
resp = http_api.api_get("/api/v1/dms/pending")
|
|
6
|
-
rows = (resp.get("data") or {}).get("pending") or []
|
|
7
|
-
ids = [r["id"] for r in rows]
|
|
8
|
-
out = []
|
|
9
|
-
for dm_id in ids:
|
|
10
|
-
r = http_api.api_get(f"/api/v1/dms/{dm_id}", ok_on_404=True)
|
|
11
|
-
dm = (r.get("data") or {}).get("dm") or {}
|
|
12
|
-
mr = http_api.api_get(f"/api/v1/dms/{dm_id}/messages")
|
|
13
|
-
msgs = (mr.get("data") or {}).get("messages") or []
|
|
14
|
-
hist = [{"d": m.get("direction"), "a": m.get("author"), "c": (m.get("content") or "")} for m in msgs]
|
|
15
|
-
out.append({
|
|
16
|
-
"id": dm_id,
|
|
17
|
-
"platform": dm.get("platform"),
|
|
18
|
-
"author": dm.get("their_author"),
|
|
19
|
-
"surface": dm.get("surface"),
|
|
20
|
-
"chat_url": dm.get("chat_url"),
|
|
21
|
-
"tier": dm.get("tier"),
|
|
22
|
-
"qual": dm.get("qualification_status"),
|
|
23
|
-
"mode": dm.get("mode"),
|
|
24
|
-
"target_project": dm.get("target_project"),
|
|
25
|
-
"project_name": dm.get("project_name"),
|
|
26
|
-
"interest": dm.get("interest_level"),
|
|
27
|
-
"origin_public_comment_url": dm.get("origin_public_comment_url"),
|
|
28
|
-
"our_prior_public_reply_url": dm.get("our_prior_public_reply_url"),
|
|
29
|
-
"booking_sent": dm.get("booking_link_sent_at"),
|
|
30
|
-
"msgcount": dm.get("message_count"),
|
|
31
|
-
"hist": hist,
|
|
32
|
-
})
|
|
33
|
-
print(json.dumps(out, indent=1, ensure_ascii=False))
|