social-autoposter 1.6.44 → 1.6.46

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.
Files changed (2) hide show
  1. package/mcp/dist/index.js +57 -13
  2. package/package.json +1 -1
package/mcp/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import { z } from "zod";
16
16
  import os from "node:os";
17
17
  import path from "node:path";
18
18
  import fs from "node:fs";
19
- import { REPO_DIR, runPython, run, readPlan, writePlan, planPath, latestBatchId, } from "./repo.js";
19
+ import { REPO_DIR, runPython, run, readPlan, writePlan, planPath, } from "./repo.js";
20
20
  import { applySetup, resolveProject, hasReadyProject, listManagedProjectStatus, REQUIRED_FIELDS, RECOMMENDED_FIELDS, CONFIG_PATH, } from "./setup.js";
21
21
  import { xStatus, xConnect, summarizeXAuth } from "./twitterAuth.js";
22
22
  import { VERSION, versionStatus, latestPublishedVersion } from "./version.js";
@@ -180,7 +180,8 @@ function cycleProgressMessage(line) {
180
180
  let m;
181
181
  if (/=== Twitter Cycle \(batch=/.test(l))
182
182
  return "Starting draft cycle…";
183
- if ((m = /^Selected projects?:\s*(.+)$/.exec(l)))
183
+ // NB: lines carry a `[HH:MM:SS] ` timestamp prefix, so don't anchor on ^.
184
+ if ((m = /Selected projects?:\s*(.+)$/.exec(l)))
184
185
  return `Selected project: ${m[1]}`;
185
186
  if (/phase=phase1\b/.test(l) || /Phase 1: drafting queries/.test(l))
186
187
  return "Searching X for fresh threads…";
@@ -206,28 +207,67 @@ async function produceDrafts(project, onProgress) {
206
207
  const env = {
207
208
  DRAFT_ONLY: "1",
208
209
  TWITTER_PAGE_GEN_RATE: "0",
210
+ // Interactive draft_cycle: launch the harness Chrome ON-SCREEN so the user
211
+ // can watch the scan/scrape happen live. Cron/autopilot do NOT set these, so
212
+ // background runs keep the off-screen default in twitter-backend.sh and don't
213
+ // hijack the screen. (Only affects a fresh Chrome launch; an already-running
214
+ // harness window keeps its current position.)
215
+ BH_WINDOW_POS: "60,60",
216
+ BH_WINDOW_SIZE: "1280,900",
209
217
  };
210
218
  if (project)
211
219
  env.SAPS_FORCE_PROJECT = project;
212
220
  let step = 0;
221
+ let lastMsg = "";
222
+ // ONE predictable, host-independent place to watch a draft_cycle run, so any
223
+ // agent (or human) debugging "the cycle looks stuck" has an obvious path:
224
+ // ~/social-autoposter/skill/logs/draft_cycle-mcp.log
225
+ // It lives right next to the cycle's own twitter-cycle-*.log. We append the
226
+ // full live cycle output here (not just milestones) plus a clear run banner.
227
+ // Best-effort: a logging failure must never break the cycle.
228
+ const mcpLog = path.join(REPO_DIR, "skill", "logs", "draft_cycle-mcp.log");
229
+ const appendLog = (s) => {
230
+ try {
231
+ fs.appendFileSync(mcpLog, s);
232
+ }
233
+ catch {
234
+ /* ignore — never fail the cycle over a log write */
235
+ }
236
+ };
237
+ try {
238
+ fs.mkdirSync(path.dirname(mcpLog), { recursive: true });
239
+ }
240
+ catch {
241
+ /* ignore */
242
+ }
243
+ appendLog(`\n===== draft_cycle start ${new Date().toISOString()} ` +
244
+ `project=${project ?? "(default)"} =====\n`);
213
245
  const res = await run("bash", ["skill/run-twitter-cycle.sh"], {
214
246
  env,
215
247
  timeoutMs: 900_000, // scan+draft can take several minutes
216
- // Mirror the cycle's own log lines to THIS server's stderr (so they land
217
- // in the host's mcp-server-social-autoposter.log, which used to show only
218
- // the JSON-RPC handshake) AND forward milestone lines to the live progress
219
- // sink so the chat spinner stops looking frozen.
248
+ // Fan every cycle line out to THREE sinks so progress is never a black box:
249
+ // 1. draft_cycle-mcp.log the stable, documented, host-independent file.
250
+ // 2. this server's stderr lands in the host's MCP server log
251
+ // (mcp-server-social-autoposter.log on Desktop), which used to show
252
+ // only the JSON-RPC handshake.
253
+ // 3. the live progress sink — milestone messages under the chat spinner.
220
254
  onLine: (line) => {
221
255
  const t = line.replace(/\s+$/, "");
222
- if (t.trim())
256
+ if (t.trim()) {
257
+ appendLog(`${t}\n`);
223
258
  console.error(`[draft_cycle] ${t}`);
259
+ }
224
260
  if (!onProgress)
225
261
  return;
226
262
  const msg = cycleProgressMessage(t);
227
- if (msg)
263
+ // Skip consecutive duplicates (a phase can log a couple matching lines).
264
+ if (msg && msg !== lastMsg) {
265
+ lastMsg = msg;
228
266
  onProgress(msg, ++step);
267
+ }
229
268
  },
230
269
  });
270
+ appendLog(`===== draft_cycle end ${new Date().toISOString()} exit=${res.code} =====\n`);
231
271
  // Prefer the explicit marker; fall back to the newest plan file on disk.
232
272
  const marker = /DRAFT_ONLY_PLAN=\/tmp\/twitter_cycle_plan_(.+)\.json/.exec(res.stdout + "\n" + res.stderr);
233
273
  if (marker && marker[1])
@@ -239,13 +279,17 @@ async function produceDrafts(project, onProgress) {
239
279
  if (blockedMarker && blockedMarker[1]) {
240
280
  return { batchId: null, blocked: blockedReasonMessage(blockedMarker[1]) };
241
281
  }
242
- const existing = latestBatchId();
243
- if (existing)
244
- return { batchId: existing };
282
+ // No `DRAFT_ONLY_PLAN=` marker from THIS run => this run produced no drafts.
283
+ // We MUST NOT fall back to the newest plan file on disk (`latestBatchId()`):
284
+ // that's a *previous* run's batch, so a 5-second empty cycle would echo an old
285
+ // 7-draft batch and report phantom success. Report 0 drafts honestly, with the
286
+ // pipeline's own reason (e.g. cold-start project with no seeded queries).
245
287
  return {
246
288
  batchId: null,
247
- blocked: `Draft cycle produced no plan (exit ${res.code}). This usually means scan ` +
248
- `found no fresh candidates, or the pipeline errored. Tail:\n` +
289
+ blocked: `This run produced no drafts (exit ${res.code}). The scan found no fresh ` +
290
+ `candidates for the selected project usually a cold-start project with ` +
291
+ `no seeded search queries/topics, or a pipeline error. This is NOT a ` +
292
+ `previous batch. Tail:\n` +
249
293
  res.stderr.split("\n").slice(-12).join("\n"),
250
294
  };
251
295
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "social-autoposter",
3
- "version": "1.6.44",
3
+ "version": "1.6.46",
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"