@m13v/s4l 1.6.197-rc.9 → 1.6.198
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 +50 -19
- package/mcp/dist/panel.html +46 -25
- package/mcp/dist/product-link.html +1 -1
- package/mcp/dist/runtime.js +38 -8
- package/mcp/dist/screencast.js +15 -1
- package/mcp/dist/setup.js +59 -2
- package/mcp/dist/version.json +2 -2
- package/mcp/manifest.json +1 -1
- package/mcp/menubar/s4l_card.py +146 -47
- package/mcp/menubar/s4l_menubar.py +93 -33
- package/mcp/menubar/s4l_state.py +299 -17
- package/mcp/package.json +2 -1
- package/package.json +1 -1
- package/scripts/identity.py +72 -19
- package/scripts/learned_preferences.py +16 -8
- package/scripts/linkedin_presence.py +384 -0
- package/scripts/merge_review_queue.py +77 -3
- package/scripts/reap_stale_claude_sessions.py +10 -7
- package/scripts/s4l_box_update.sh +88 -44
- package/skill/lib/linkedin-backend.sh +8 -1
- package/skill/linkedin-presence.sh +77 -86
- package/skill/run-twitter-cycle.sh +8 -3
package/mcp/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import os from "node:os";
|
|
|
20
20
|
import path from "node:path";
|
|
21
21
|
import fs from "node:fs";
|
|
22
22
|
import { repoDir, runPython, run, readPlan, writePlan, planPath, } from "./repo.js";
|
|
23
|
-
import { applySetup, resolveProject, personaReady, listManagedProjectStatus, ensureShortLinksDefault, ensurePersonaProject, findPersonaProject, REQUIRED_FIELDS, RECOMMENDED_FIELDS, configPath, normalizeStringList, } from "./setup.js";
|
|
23
|
+
import { applySetup, resolveProject, personaReady, listManagedProjectStatus, listProjectSettings, ensureShortLinksDefault, ensurePersonaProject, findPersonaProject, REQUIRED_FIELDS, RECOMMENDED_FIELDS, configPath, normalizeStringList, } from "./setup.js";
|
|
24
24
|
import { xStatus, xConnect, xDetectSources, xScanProfile, summarizeXAuth } from "./twitterAuth.js";
|
|
25
25
|
import { startProvisioning, isProvisioning, readProgress, runtimeReady, readRuntime, resolvePython, resolveChrome, ensureMenubar, menubarRunning, clearMenubarStop, ensurePipelineCurrent, ensureRuntimeProvisioned, } from "./runtime.js";
|
|
26
26
|
import { blockOnboardingMilestone, completeOnboardingMilestone, ensureDoctorPhase, onboardingLedger, onboardingSnapshot, recordOnboardingAttempt, runDoctorPhase, } from "./onboarding.js";
|
|
@@ -1397,9 +1397,14 @@ tool("project_config", {
|
|
|
1397
1397
|
inputSchema: {
|
|
1398
1398
|
status: z.boolean().optional(),
|
|
1399
1399
|
action: z
|
|
1400
|
-
.enum(["connect_x", "detect_x_sources", "profile_scan"])
|
|
1400
|
+
.enum(["get", "connect_x", "detect_x_sources", "profile_scan"])
|
|
1401
1401
|
.optional()
|
|
1402
|
-
.describe("
|
|
1402
|
+
.describe("get = read the CURRENT SAVED VALUES of every project's editable fields (website, " +
|
|
1403
|
+
"description, icp, voice, differentiator, search_topics, get_started_link, " +
|
|
1404
|
+
"content_guardrails, content_angle) plus readiness — the read companion to editing. " +
|
|
1405
|
+
"Use it before tweaking part of a nested value; the panel's Project settings section " +
|
|
1406
|
+
"is built on it. " +
|
|
1407
|
+
"connect_x = import/validate your X session in the autoposter's managed browser. " +
|
|
1403
1408
|
"With an explicit setup/connect request, warn about possible keychain prompts and call " +
|
|
1404
1409
|
"with confirm:true without waiting for another yes/no reply. Without confirm:true it " +
|
|
1405
1410
|
"only previews the operation for users who asked to inspect it rather than run it. " +
|
|
@@ -1469,12 +1474,25 @@ tool("project_config", {
|
|
|
1469
1474
|
"weight, platform, voice_relationship, booking_link, qualification, subreddit_bans, " +
|
|
1470
1475
|
"short_links_host, short_links_live, content_angle, messaging, landing_pages, posthog. " +
|
|
1471
1476
|
"Pass {name:'<project>', fields:{<key>:<value>, ...}}; each key SHALLOW-merges onto the " +
|
|
1472
|
-
"project, REPLACING that key's whole value (read the current value via
|
|
1477
|
+
"project, REPLACING that key's whole value (read the current value via action:'get' first if " +
|
|
1473
1478
|
"you only want to tweak part of a nested object, then pass the full new value). A value of " +
|
|
1474
1479
|
"null DELETES the key. 'name' is ignored here (can't rename through this path). This is how " +
|
|
1475
1480
|
"you edit advanced config without any raw whole-file overwrite."),
|
|
1476
1481
|
},
|
|
1477
1482
|
}, async (args) => {
|
|
1483
|
+
// ---- Read current saved values (the panel's Project settings source) ---
|
|
1484
|
+
// Whitelisted field values + readiness for every managed project and the
|
|
1485
|
+
// persona. Read-only; the write path stays the validated merge below.
|
|
1486
|
+
if (args.action === "get") {
|
|
1487
|
+
return jsonContent({
|
|
1488
|
+
action: "get",
|
|
1489
|
+
projects: listProjectSettings(),
|
|
1490
|
+
config_path: configPath(),
|
|
1491
|
+
note: "Current saved values of each project's editable fields. To change one, call project_config " +
|
|
1492
|
+
"with {name, <field>: <new value>} — it merges onto what's saved and re-seeds topics. " +
|
|
1493
|
+
"extra_keys lists advanced keys editable only via the `fields` escape hatch.",
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1478
1496
|
// ---- List import sources (for the panel dropdown) ---------------------
|
|
1479
1497
|
// Read-only browser/profile detection. Never reads the keychain or decrypts
|
|
1480
1498
|
// a cookie, so it shows no macOS Safe Storage prompt. Lets the user pick the
|
|
@@ -1724,11 +1742,20 @@ tool("project_config", {
|
|
|
1724
1742
|
// Apply mode (incremental): merge whatever fields were supplied onto the
|
|
1725
1743
|
// named project, then report whether it's now ready or still missing fields.
|
|
1726
1744
|
try {
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1745
|
+
// Editing the persona project must not touch the PRODUCT onboarding
|
|
1746
|
+
// milestone (a persona is never "project_ready" in the product sense; it
|
|
1747
|
+
// validates against PERSONA_REQUIRED_FIELDS inside applySetup).
|
|
1748
|
+
const editingPersona = findPersonaProject()?.name === args.name;
|
|
1749
|
+
if (!editingPersona) {
|
|
1750
|
+
recordOnboardingAttempt("project_ready", {
|
|
1751
|
+
missing_count: 0,
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1730
1754
|
const result = applySetup(args);
|
|
1731
|
-
if (result.
|
|
1755
|
+
if (result.persona) {
|
|
1756
|
+
// no-op on the onboarding ledger; readiness is reported below as usual.
|
|
1757
|
+
}
|
|
1758
|
+
else if (result.ready) {
|
|
1732
1759
|
completeOnboardingMilestone("project_ready", { missing_count: 0 });
|
|
1733
1760
|
}
|
|
1734
1761
|
else {
|
|
@@ -1809,6 +1836,7 @@ tool("project_config", {
|
|
|
1809
1836
|
ok: true,
|
|
1810
1837
|
project: result.project,
|
|
1811
1838
|
action: result.created ? "created" : "updated",
|
|
1839
|
+
persona: result.persona,
|
|
1812
1840
|
ready: result.ready,
|
|
1813
1841
|
missing_required: result.missing_required,
|
|
1814
1842
|
topics_seeded: topicsSeeded,
|
|
@@ -1820,16 +1848,19 @@ tool("project_config", {
|
|
|
1820
1848
|
fields_removed: result.fields_removed,
|
|
1821
1849
|
config_path: configPath(),
|
|
1822
1850
|
onboarding: onboardingSnapshot(),
|
|
1823
|
-
note: (result.
|
|
1824
|
-
? `
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
`
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1851
|
+
note: (result.persona
|
|
1852
|
+
? `Persona '${result.project}' updated.${seedNote}` +
|
|
1853
|
+
(result.ready ? "" : ` Still needs: ${result.missing_required.join(", ")}.`)
|
|
1854
|
+
: result.ready
|
|
1855
|
+
? `Project '${result.project}' is fully configured.${seedNote} Next: if X is not connected, ` +
|
|
1856
|
+
`detect sources, warn about keychain prompts, and call project_config with ` +
|
|
1857
|
+
`action:'connect_x', confirm:true immediately. Once X is connected, schedule the autopilot ` +
|
|
1858
|
+
`(queue_setup + create_scheduled_task per task); the autopilot then drafts on its own. Call the ` +
|
|
1859
|
+
`dashboard to confirm the schedule is firing (schedule_state 'ok') — that is the final step, ` +
|
|
1860
|
+
`no need to wait for or verify a draft card.`
|
|
1861
|
+
: `Saved what you provided for '${result.project}'. Still need: ${result.missing_required.join(", ")}. ` +
|
|
1862
|
+
`First derive those fields from existing context, profile_scan, and website research, then ` +
|
|
1863
|
+
`call project_config again with name='${result.project}'. Ask only if a required field is genuinely unknowable.`) +
|
|
1833
1864
|
advancedNote,
|
|
1834
1865
|
});
|
|
1835
1866
|
}
|
|
@@ -4004,7 +4035,7 @@ tool("show_browser_to_user", {
|
|
|
4004
4035
|
const message = ensured.error === "no_browser"
|
|
4005
4036
|
? "No managed Chrome is running right now. Start a draft cycle or autopilot so there's a live browser session to show."
|
|
4006
4037
|
: ensured.error === "no_websocket"
|
|
4007
|
-
? "This
|
|
4038
|
+
? "This runtime has no WebSocket support, so a live screencast can't be opened. Use 'Bring to front' to see the browser window instead."
|
|
4008
4039
|
: "Couldn't attach to the browser: " + String(ensured.error);
|
|
4009
4040
|
return jsonContent({ ok: false, running: false, frame: null, message });
|
|
4010
4041
|
}
|