social-autoposter 1.6.1 → 1.6.2

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/bin/server.js CHANGED
@@ -49,6 +49,13 @@ const JOBS = [
49
49
  // Post Threads row (original threads/posts)
50
50
  { label: 'com.m13v.social-reddit-threads', name: 'Reddit Threads', type: 'Post Threads', platform: 'Reddit', script: 'run-reddit-threads.sh', logPrefix: 'run-reddit-threads-', plist: 'com.m13v.social-reddit-threads.plist' },
51
51
  { label: 'com.m13v.social-twitter-threads', name: 'Twitter Threads', type: 'Post Threads', platform: 'Twitter', script: 'run-twitter-threads.sh', logPrefix: 'run-twitter-threads-', plist: 'com.m13v.social-twitter-threads.plist' },
52
+ // Instagram per-account daily posters (5×/day each, FORCE_ACCOUNT pinned).
53
+ { label: 'com.m13v.social-instagram-daily-matt_diak', name: 'IG Daily (matt_diak)', type: 'Post Threads', platform: 'Instagram', script: 'run-instagram-daily.sh', logPrefix: 'instagram-daily-', plist: 'com.m13v.social-instagram-daily-matt_diak.plist' },
54
+ { label: 'com.m13v.social-instagram-daily-matthewheartful', name: 'IG Daily (matthewheartful)', type: 'Post Threads', platform: 'Instagram', script: 'run-instagram-daily.sh', logPrefix: 'instagram-daily-', plist: 'com.m13v.social-instagram-daily-matthewheartful.plist' },
55
+ // Instagram per-account render (upstream of daily-posters; produces the
56
+ // mp4 + caption draft that the daily-poster then uploads).
57
+ { label: 'com.m13v.social-instagram-render-matt_diak', name: 'IG Render (matt_diak)', type: 'Other', platform: 'Instagram', script: 'run-instagram-render.sh', logPrefix: 'instagram-render-', plist: 'com.m13v.social-instagram-render-matt_diak.plist' },
58
+ { label: 'com.m13v.social-instagram-render-matthewheartful', name: 'IG Render (matthewheartful)', type: 'Other', platform: 'Instagram', script: 'run-instagram-render.sh', logPrefix: 'instagram-render-', plist: 'com.m13v.social-instagram-render-matthewheartful.plist' },
52
59
  // Post Comments row (replies/comments on others' content)
53
60
  { label: 'com.m13v.social-reddit-search', name: 'Reddit', type: 'Post Comments', platform: 'Reddit', script: 'run-reddit-search.sh', logPrefix: 'run-reddit-search-', plist: 'com.m13v.social-reddit-search.plist' },
54
61
  { label: 'com.m13v.social-twitter-cycle', name: 'Twitter', type: 'Post Comments', platform: 'Twitter', script: 'run-twitter-cycle.sh', logPrefix: 'twitter-cycle-', plist: 'com.m13v.social-twitter-cycle.plist' },
@@ -130,6 +137,8 @@ const REQUIRED_LOCKS = {
130
137
  'link-edit-github.sh': ['link-edit-github'],
131
138
  'stats-reddit.sh': ['reddit-browser'],
132
139
  'stats-instagram.sh': ['instagram-poster'],
140
+ 'run-instagram-daily.sh': ['instagram-poster'],
141
+ 'run-instagram-render.sh': ['instagram-render'],
133
142
  'audit-reddit.sh': ['reddit-browser', 'audit-reddit'],
134
143
  'audit-twitter.sh': ['twitter-browser', 'audit-twitter'],
135
144
  'audit-linkedin.sh': ['linkedin-browser', 'audit-linkedin'],
@@ -5234,7 +5243,7 @@ async function handleApi(req, res) {
5234
5243
  const url = new URL(req.url, 'http://localhost');
5235
5244
  const windowHours = Math.max(1, Math.min(720, parseInt(url.searchParams.get('hours') || '24', 10) || 24));
5236
5245
  const rawProject = (url.searchParams.get('project') || '').trim();
5237
- const ALLOWED_COST_PLATFORMS = new Set(['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'seo', 'email']);
5246
+ const ALLOWED_COST_PLATFORMS = new Set(['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'seo', 'email', 'instagram']);
5238
5247
  let rawPlat = String(url.searchParams.get('platform') || '').toLowerCase().trim();
5239
5248
  if (rawPlat === 'x') rawPlat = 'twitter';
5240
5249
  const plat = ALLOWED_COST_PLATFORMS.has(rawPlat) ? rawPlat : '';
@@ -5376,7 +5385,7 @@ async function handleApi(req, res) {
5376
5385
  const project = (rawProject === '' || rawProject.toLowerCase() === 'all') ? '' : rawProject;
5377
5386
  const projectOk = project === '' || /^[A-Za-z0-9_\- ]{1,64}$/.test(project);
5378
5387
  if (!projectOk) return json(res, { error: 'invalid project' }, 400);
5379
- const ALLOWED_COST_PLATFORMS = new Set(['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'seo', 'email']);
5388
+ const ALLOWED_COST_PLATFORMS = new Set(['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'seo', 'email', 'instagram']);
5380
5389
  let rawPlat = String(url.searchParams.get('platform') || '').toLowerCase().trim();
5381
5390
  if (rawPlat === 'x') rawPlat = 'twitter';
5382
5391
  const plat = ALLOWED_COST_PLATFORMS.has(rawPlat) ? rawPlat : '';
@@ -6751,7 +6760,7 @@ async function handleApi(req, res) {
6751
6760
  const configuredProjects = Array.isArray(config.projects) ? config.projects : [];
6752
6761
  const weighted = configuredProjects.filter(p => (p.weight || 0) > 0);
6753
6762
  const totalWeight = weighted.reduce((a, p) => a + (p.weight || 0), 0) || 1;
6754
- const platforms = ['reddit', 'twitter', 'linkedin', 'moltbook', 'github'];
6763
+ const platforms = ['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'instagram'];
6755
6764
  // Per-platform eligibility: a project is eligible to be picked for a
6756
6765
  // platform only if it has the data that platform's picker needs. Mirrors
6757
6766
  // scripts/pick_project.py and scripts/pick_thread_target.py. Projects
@@ -8093,6 +8102,7 @@ const HTML = `<!DOCTYPE html>
8093
8102
  <th>LinkedIn</th>
8094
8103
  <th>MoltBook</th>
8095
8104
  <th>GitHub</th>
8105
+ <th>Instagram</th>
8096
8106
  </tr>
8097
8107
  </thead>
8098
8108
  <tbody id="matrix-body"></tbody>
@@ -10574,8 +10584,8 @@ const EVENT_DESCRIPTIONS = {
10574
10584
  page_expired: 'SEO page deleted by the daily expire pipeline because it had zero clicks in the last 30 days. The on-disk source file was removed; Next.js now returns 404 for the URL. Logged for audit/revert in seo_expired_pages.',
10575
10585
  resurrected: 'Previously archived or unavailable item brought back into rotation (e.g., a removed post restored after reappearing).',
10576
10586
  };
10577
- const ACTIVITY_PLATFORMS = ['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'seo'];
10578
- const ACTIVITY_PLATFORM_LABELS = { reddit: 'Reddit', twitter: 'Twitter / X', linkedin: 'LinkedIn', moltbook: 'Moltbook', github: 'GitHub', seo: 'SEO' };
10587
+ const ACTIVITY_PLATFORMS = ['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'seo', 'instagram'];
10588
+ const ACTIVITY_PLATFORM_LABELS = { reddit: 'Reddit', twitter: 'Twitter / X', linkedin: 'LinkedIn', moltbook: 'Moltbook', github: 'GitHub', seo: 'SEO', instagram: 'Instagram' };
10579
10589
  const PROJECT_LABELS = { tenxats: '10xats' };
10580
10590
  const ACTIVITY_PROJECT_NONE = '(none)';
10581
10591
  const ACTIVITY_CAMPAIGN_ORGANIC = '(organic)';
@@ -16515,10 +16525,10 @@ async function loadDeployHealth() {
16515
16525
  // hours by platform against config.json weight targets. Each platform cell
16516
16526
  // shows the count plus that project's share of the platform's posts in
16517
16527
  // brackets, so operators can spot imbalance without a separate deficit field.
16518
- const PROJECT_STATUS_PLATFORMS = ['reddit', 'twitter', 'linkedin', 'moltbook', 'github'];
16528
+ const PROJECT_STATUS_PLATFORMS = ['reddit', 'twitter', 'linkedin', 'moltbook', 'github', 'instagram'];
16519
16529
  const PROJECT_STATUS_PLATFORM_LABELS = {
16520
16530
  reddit: 'Reddit', twitter: 'Twitter', linkedin: 'LinkedIn',
16521
- moltbook: 'MoltBook', github: 'GitHub',
16531
+ moltbook: 'MoltBook', github: 'GitHub', instagram: 'Instagram',
16522
16532
  };
16523
16533
  let _projectStatusLoading = false;
16524
16534
  let _projectStatusData = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "social-autoposter",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
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"
@@ -1047,7 +1047,7 @@ export CLAUDE_SESSION_ID
1047
1047
 
1048
1048
  PREP_SCHEMA='{"type":"object","properties":{"candidates":{"type":"array","items":{"type":"object","properties":{"candidate_id":{"type":"integer"},"candidate_url":{"type":"string"},"thread_author":{"type":"string"},"thread_text":{"type":"string"},"matched_project":{"type":"string"},"reply_text":{"type":"string"},"engagement_style":{"type":"string"},"language":{"type":"string"},"has_landing_pages":{"type":"boolean"},"link_keyword":{"type":"string"},"link_slug":{"type":"string"}},"required":["candidate_id","candidate_url","matched_project","reply_text","engagement_style","language","has_landing_pages"]}},"rejected":{"type":"array","items":{"type":"object","properties":{"candidate_id":{"type":"integer"},"reason":{"type":"string"},"proposed_excludes":{"type":"array","items":{"type":"string"}}},"required":["candidate_id","reason"]}}},"required":["candidates","rejected"]}'
1049
1049
 
1050
- PREP_OUTPUT=$("$REPO_DIR/scripts/run_claude.sh" "run-twitter-cycle-prep" --strict-mcp-config --mcp-config "$TW_MCP_CONFIG" -p --output-format json --json-schema "$PREP_SCHEMA" "${TW_ENGINE_PREFIX}You are the Social Autoposter prep step.
1050
+ PREP_PROMPT="${TW_ENGINE_PREFIX}You are the Social Autoposter prep step.
1051
1051
 
1052
1052
  Your ONLY job in THIS session:
1053
1053
  1. Read each thread you decide to reply to (browser tools from the BROWSER BACKEND block above, READ-ONLY).
@@ -1130,7 +1130,13 @@ CRITICAL:
1130
1130
  - DO NOT call log_post.py or campaign_bump.py.
1131
1131
  - Browser tools (from the BROWSER BACKEND block) are READ-ONLY in this step.
1132
1132
  - NEVER use em dashes. Use commas, periods, or regular dashes (-).
1133
- - Reply in the SAME LANGUAGE as the parent tweet." 2>&1)
1133
+ - Reply in the SAME LANGUAGE as the parent tweet."
1134
+
1135
+ # Pipe the prep prompt via stdin instead of passing as a shell argument.
1136
+ # On Linux ARG_MAX is 2MB; the assembled prompt (config.json + top_report +
1137
+ # styles + schema + candidates) busts that on the VM, dying with E2BIG
1138
+ # "Argument list too long". stdin has no such cap.
1139
+ PREP_OUTPUT=$(printf '%s' "$PREP_PROMPT" | "$REPO_DIR/scripts/run_claude.sh" "run-twitter-cycle-prep" --strict-mcp-config --mcp-config "$TW_MCP_CONFIG" -p --output-format json --json-schema "$PREP_SCHEMA" 2>&1)
1134
1140
 
1135
1141
  echo "$PREP_OUTPUT" >> "$LOG_FILE"
1136
1142