@m13v/s4l 1.6.201 → 1.6.203-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 +81 -45
- package/mcp/dist/panel.html +25 -23
- package/mcp/dist/product-link.html +1 -1
- package/mcp/dist/version.json +2 -2
- package/mcp/manifest.json +1 -1
- package/mcp/menubar/dashboard_server.py +70 -0
- package/mcp/menubar/s4l_menubar.py +18 -14
- package/mcp/menubar/s4l_state.py +6 -11
- package/mcp/package.json +1 -1
- package/package.json +1 -1
- package/scripts/claude_job.py +36 -14
- package/scripts/dev_dashboard_server.py +18 -0
- package/scripts/engage_github.py +25 -0
- package/scripts/engage_reddit.py +14 -1
- package/scripts/post_github.py +9 -0
- package/scripts/post_reddit.py +11 -0
- package/skill/run-linkedin.sh +12 -0
package/mcp/dist/index.js
CHANGED
|
@@ -1794,70 +1794,52 @@ tool("project_config", {
|
|
|
1794
1794
|
}
|
|
1795
1795
|
// Status / discovery mode: no project name supplied, or explicitly asked.
|
|
1796
1796
|
if (args.status === true || !args.name) {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
//
|
|
1800
|
-
//
|
|
1801
|
-
//
|
|
1802
|
-
//
|
|
1803
|
-
const
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
const
|
|
1808
|
-
const configured = projects.some((p) => p.ready);
|
|
1809
|
-
if (rtReady)
|
|
1810
|
-
completeOnboardingMilestone("runtime_ready");
|
|
1811
|
-
if (x.connected) {
|
|
1812
|
-
completeOnboardingMilestone("x_connected", { state: x.state || "connected" });
|
|
1813
|
-
}
|
|
1814
|
-
if (configured) {
|
|
1815
|
-
completeOnboardingMilestone("project_ready", {
|
|
1816
|
-
missing_count: 0,
|
|
1817
|
-
});
|
|
1818
|
-
}
|
|
1819
|
-
// mode_chosen completes when the user explicitly picked a mode (mode.json
|
|
1820
|
-
// exists) OR this is a legacy install already past setup (a ready product),
|
|
1821
|
-
// so adding this step never regresses an already-onboarded box.
|
|
1822
|
-
if (modeChosen() || configured) {
|
|
1823
|
-
completeOnboardingMilestone("mode_chosen", {
|
|
1824
|
-
source: modeChosen() ? "chosen" : "backfilled_legacy",
|
|
1825
|
-
});
|
|
1826
|
-
}
|
|
1797
|
+
// ONE compute path: buildSnapshot -> scripts/snapshot.py, the same source
|
|
1798
|
+
// the menu bar and browser dashboard read. This branch used to recompute
|
|
1799
|
+
// projects/X/version inline (listManagedProjectStatus + xStatus), which
|
|
1800
|
+
// excluded the persona project and carried no setup_complete — so the
|
|
1801
|
+
// panel's refresh() disagreed with the dashboard tool and the menu bar on
|
|
1802
|
+
// persona-only setups. Do not reintroduce a parallel compute here.
|
|
1803
|
+
const snap = await buildSnapshot();
|
|
1804
|
+
const projects = Array.isArray(snap.projects) ? snap.projects : [];
|
|
1805
|
+
const rtReady = !!snap.runtime_ready;
|
|
1806
|
+
const xConnected = !!snap.x_connected;
|
|
1807
|
+
const configured = (snap.projects_ready || 0) > 0;
|
|
1827
1808
|
return jsonContent({
|
|
1828
1809
|
configured,
|
|
1829
1810
|
projects,
|
|
1830
1811
|
runtime_ready: rtReady,
|
|
1831
|
-
x_connected:
|
|
1832
|
-
x_state:
|
|
1833
|
-
x_handle:
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1812
|
+
x_connected: xConnected,
|
|
1813
|
+
x_state: snap.x_state,
|
|
1814
|
+
x_handle: snap.x_handle ?? null,
|
|
1815
|
+
setup_complete: !!snap.setup_complete,
|
|
1816
|
+
mcp_version: snap.version,
|
|
1817
|
+
latest_version: snap.latest_version,
|
|
1818
|
+
update_available: !!snap.update_available,
|
|
1819
|
+
mode: snap.mode,
|
|
1820
|
+
flags: snap.flags,
|
|
1821
|
+
update_hint: snap.update_available
|
|
1822
|
+
? `A newer version (${snap.latest_version}) is available — you're on ${snap.version}. ` +
|
|
1841
1823
|
`Tell the user and offer to run the \`runtime\` tool with action:'update' ` +
|
|
1842
1824
|
`(or \`npx social-autoposter@latest update\`).`
|
|
1843
1825
|
: undefined,
|
|
1844
1826
|
required_fields: REQUIRED_FIELDS,
|
|
1845
1827
|
recommended_fields: RECOMMENDED_FIELDS,
|
|
1846
1828
|
config_path: configPath(),
|
|
1847
|
-
ready_for_verification:
|
|
1848
|
-
onboarding:
|
|
1829
|
+
ready_for_verification: !!snap.setup_complete,
|
|
1830
|
+
onboarding: snap.onboarding,
|
|
1849
1831
|
next_step: !rtReady
|
|
1850
1832
|
? "Runtime is not ready yet. It provisions automatically on boot — poll runtime action:'status' until ready (only call runtime action:'install' to retry if status shows the boot provision failed or stalled), then continue setup automatically."
|
|
1851
1833
|
: projects.length === 0
|
|
1852
1834
|
? "No projects yet. Discover the product from conversation context and the connected X profile; research its website, infer a conservative complete project, and call project_config. Ask only if no product can be identified." +
|
|
1853
|
-
(
|
|
1835
|
+
(xConnected ? "" : " X is not connected yet either — detect_x_sources, warn about keychain prompts, then run connect_x with confirm:true without a separate permission turn.")
|
|
1854
1836
|
: projects.every((p) => p.ready)
|
|
1855
|
-
? (
|
|
1837
|
+
? (xConnected
|
|
1856
1838
|
? "All configured projects are ready and X is connected. SCHEDULE THE AUTOPILOT: (1) call queue_setup and create each returned task with create_scheduled_task (prompt verbatim; 'already exists' is fine); (2) the autopilot then runs on its own (launchd kicker + queue worker). Call the `dashboard` tool to confirm the schedule is firing (schedule_state 'ok') — that is the terminal step; do NOT wait for or verify a draft card. Do NOT pause to ask the user to review drafts."
|
|
1857
1839
|
: "All configured projects are ready, but X is NOT connected — posting needs a logged-in " +
|
|
1858
1840
|
"x.com session. Detect sources and run project_config action:'connect_x', confirm:true; do not ask whether to proceed.")
|
|
1859
1841
|
: "Some projects are missing required fields (see each project's missing_required). Derive them from config, context, profile_scan, and website research, then call project_config again. Ask only if a required field is genuinely unknowable." +
|
|
1860
|
-
(
|
|
1842
|
+
(xConnected ? "" : " X is also not connected yet; detect sources and run connect_x with confirm:true."),
|
|
1861
1843
|
});
|
|
1862
1844
|
}
|
|
1863
1845
|
// Apply mode (incremental): merge whatever fields were supplied onto the
|
|
@@ -3428,6 +3410,29 @@ async function buildSnapshot() {
|
|
|
3428
3410
|
completeOnboardingMilestone("project_ready", { missing_count: 0 });
|
|
3429
3411
|
if (snap.schedule_state === "ok")
|
|
3430
3412
|
completeOnboardingMilestone("tasks_scheduled");
|
|
3413
|
+
// mode_chosen completes when the user explicitly picked a mode (mode.json
|
|
3414
|
+
// exists) OR this is a legacy install already past setup (a ready project),
|
|
3415
|
+
// so adding this step never regresses an already-onboarded box. (Moved here
|
|
3416
|
+
// from project_config's status branch so ALL milestone truth lives in one
|
|
3417
|
+
// place next to the snapshot.)
|
|
3418
|
+
if (modeChosen() || (snap.projects_ready || 0) > 0) {
|
|
3419
|
+
completeOnboardingMilestone("mode_chosen", {
|
|
3420
|
+
source: modeChosen() ? "chosen" : "backfilled_legacy",
|
|
3421
|
+
});
|
|
3422
|
+
}
|
|
3423
|
+
// profile_scanned has no file signal of its own, but a provisioned persona
|
|
3424
|
+
// project can only come from the scan+dictation flow — treat its presence as
|
|
3425
|
+
// the completed scan so old installs can't stick at "profile pending".
|
|
3426
|
+
if ((Array.isArray(snap.projects) ? snap.projects : []).some((p) => p?.persona)) {
|
|
3427
|
+
completeOnboardingMilestone("profile_scanned", { backfill: true });
|
|
3428
|
+
}
|
|
3429
|
+
// topics_seeded has no cheap live signal (it's a DB fact, not a file fact), so
|
|
3430
|
+
// installs that finished setup before the persona-path completion landed stay
|
|
3431
|
+
// stuck at 7/8 forever. Heal by re-running the idempotent seed for the ready
|
|
3432
|
+
// project(s) and completing the milestone on success. Fire-and-forget: the
|
|
3433
|
+
// ledger flip shows on the next snapshot.
|
|
3434
|
+
if ((snap.projects_ready || 0) > 0)
|
|
3435
|
+
void healTopicsSeeded(snap);
|
|
3431
3436
|
// Persist this snapshot so the menu bar can answer "set up?" the SAME way when
|
|
3432
3437
|
// the loopback server is unreachable (Claude Desktop closed or mid-restart)
|
|
3433
3438
|
// instead of falling back to a divergent local rule. Refreshed on every
|
|
@@ -3436,6 +3441,37 @@ async function buildSnapshot() {
|
|
|
3436
3441
|
persistStatusSummary(snap);
|
|
3437
3442
|
return snap;
|
|
3438
3443
|
}
|
|
3444
|
+
// One attempt per process: a failed seed (offline DB) retries on the next MCP
|
|
3445
|
+
// launch, not on every dashboard poll.
|
|
3446
|
+
let topicsSeedHealAttempted = false;
|
|
3447
|
+
async function healTopicsSeeded(snap) {
|
|
3448
|
+
if (topicsSeedHealAttempted)
|
|
3449
|
+
return;
|
|
3450
|
+
topicsSeedHealAttempted = true;
|
|
3451
|
+
try {
|
|
3452
|
+
const ledger = onboardingLedger();
|
|
3453
|
+
if (ledger?.milestones?.topics_seeded?.status === "complete")
|
|
3454
|
+
return;
|
|
3455
|
+
const ready = (Array.isArray(snap.projects) ? snap.projects : []).filter((p) => p && p.ready && typeof p.name === "string");
|
|
3456
|
+
for (const p of ready) {
|
|
3457
|
+
const seed = await runPython("scripts/seed_search_topics.py", ["--project", p.name], {
|
|
3458
|
+
timeoutMs: 60_000,
|
|
3459
|
+
});
|
|
3460
|
+
if (seed.code === 0) {
|
|
3461
|
+
const m = /planned=(\d+)\s+inserted=(\d+)\s+updated=(\d+)/.exec(seed.stdout);
|
|
3462
|
+
completeOnboardingMilestone("topics_seeded", {
|
|
3463
|
+
project: p.name,
|
|
3464
|
+
topic_count: m ? Number(m[1]) : 0,
|
|
3465
|
+
backfill: true,
|
|
3466
|
+
});
|
|
3467
|
+
return;
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
catch (e) {
|
|
3472
|
+
console.error("[snapshot] topics_seeded heal failed:", e?.message || e);
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3439
3475
|
// ---- dashboard localhost fallback -----------------------------------------
|
|
3440
3476
|
// When the connected host doesn't support MCP Apps UI (Claude Code / Cowork
|
|
3441
3477
|
// today), serve the SAME dist/panel.html from a loopback HTTP server. The page
|