@sellable/install 0.1.77 → 0.1.79
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/sellable-install.mjs +103 -19
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +19 -13
package/bin/sellable-install.mjs
CHANGED
|
@@ -601,12 +601,11 @@ data, compare sources by source volume, sampled ICP fit, activity/warmth
|
|
|
601
601
|
signals, cleanup risk, and confidence basis. If a user asks for a forecast,
|
|
602
602
|
label it explicitly as not estimated from this run.
|
|
603
603
|
|
|
604
|
-
Every approval gate must include
|
|
605
|
-
content. Show
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
substitute for showing the content in chat.
|
|
604
|
+
Every approval gate must include live campaign access after the readable inline
|
|
605
|
+
content. Show a \`Watch link:\` line once the campaign shell exists. In normal
|
|
606
|
+
customer runs, do not show local draft filenames or filesystem paths unless the
|
|
607
|
+
user asks for debug artifacts. The link is for deeper inspection; never use it
|
|
608
|
+
as a substitute for showing the content in chat.
|
|
610
609
|
|
|
611
610
|
Never mention MCP namespaces, prompt chunking, plugin cache paths, missing
|
|
612
611
|
linked skill versions, runbooks, or local skill files in normal customer-facing
|
|
@@ -960,10 +959,10 @@ approval should show who we are targeting, why they should care, the offer/CTA,
|
|
|
960
959
|
proof, lead source hypothesis, message angle, risks/assumptions, and what
|
|
961
960
|
happens after approval.
|
|
962
961
|
|
|
963
|
-
Every approval should also give the user a way to inspect the
|
|
964
|
-
After the readable inline content, include
|
|
965
|
-
|
|
966
|
-
|
|
962
|
+
Every approval should also give the user a way to inspect the live campaign.
|
|
963
|
+
After the readable inline content, include a \`Watch link:\` line when a
|
|
964
|
+
campaign shell exists. Local artifacts are optional debug/UAT diagnostics only;
|
|
965
|
+
do not surface file paths or local draft filenames in normal customer runs.
|
|
967
966
|
|
|
968
967
|
This applies especially to message approvals. Never ask someone to approve a
|
|
969
968
|
message they cannot see. Show the subject, tokenized template, a filled sample
|
|
@@ -1127,15 +1126,24 @@ function agentTemplateRoot() {
|
|
|
1127
1126
|
|
|
1128
1127
|
function loadCanonicalAgents() {
|
|
1129
1128
|
const root = agentTemplateRoot();
|
|
1130
|
-
const registry = JSON.parse(
|
|
1129
|
+
const registry = JSON.parse(
|
|
1130
|
+
readFileSync(join(root, "registry.json"), "utf8")
|
|
1131
|
+
);
|
|
1131
1132
|
if (!Array.isArray(registry.agents)) {
|
|
1132
1133
|
throw new Error("Sellable agent registry is missing agents array.");
|
|
1133
1134
|
}
|
|
1134
1135
|
|
|
1135
1136
|
return registry.agents.map((agent) => {
|
|
1136
1137
|
const promptPath = join(root, agent.promptFile || "");
|
|
1137
|
-
if (
|
|
1138
|
-
|
|
1138
|
+
if (
|
|
1139
|
+
!agent.id ||
|
|
1140
|
+
!agent.name ||
|
|
1141
|
+
!agent.promptFile ||
|
|
1142
|
+
!existsSync(promptPath)
|
|
1143
|
+
) {
|
|
1144
|
+
throw new Error(
|
|
1145
|
+
`Invalid Sellable agent registry entry: ${agent.id || "unknown"}`
|
|
1146
|
+
);
|
|
1139
1147
|
}
|
|
1140
1148
|
if (agent.codex?.name && agent.codex.name !== agent.name) {
|
|
1141
1149
|
throw new Error(
|
|
@@ -1171,6 +1179,15 @@ function legacyClaudeCustomAgents() {
|
|
|
1171
1179
|
return loadCanonicalAgents().flatMap((agent) => agent.legacy?.claude || []);
|
|
1172
1180
|
}
|
|
1173
1181
|
|
|
1182
|
+
function legacyClaudeCommands() {
|
|
1183
|
+
return [
|
|
1184
|
+
{
|
|
1185
|
+
name: "sellable-create-campaign",
|
|
1186
|
+
filename: join("sellable", "create-campaign.md"),
|
|
1187
|
+
},
|
|
1188
|
+
];
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1174
1191
|
function tomlArray(values) {
|
|
1175
1192
|
return `[${values.map((value) => quoteToml(value)).join(", ")}]`;
|
|
1176
1193
|
}
|
|
@@ -1246,7 +1263,9 @@ function writeCodexCustomAgents(home, opts) {
|
|
|
1246
1263
|
}
|
|
1247
1264
|
for (const agent of legacyCodexCustomAgents()) {
|
|
1248
1265
|
const legacyPath = join(home, "agents", agent.filename);
|
|
1249
|
-
logVerbose(
|
|
1266
|
+
logVerbose(
|
|
1267
|
+
`${C.grey}Removing legacy Codex scout agent ${legacyPath}${C.reset}`
|
|
1268
|
+
);
|
|
1250
1269
|
if (!opts.dryRun) rmSync(legacyPath, { force: true });
|
|
1251
1270
|
}
|
|
1252
1271
|
}
|
|
@@ -1262,9 +1281,22 @@ function writeClaudeCustomAgents(opts) {
|
|
|
1262
1281
|
}
|
|
1263
1282
|
for (const agent of legacyClaudeCustomAgents()) {
|
|
1264
1283
|
const legacyPath = join(home, "agents", agent.filename);
|
|
1265
|
-
logVerbose(
|
|
1284
|
+
logVerbose(
|
|
1285
|
+
`${C.grey}Removing legacy Claude scout agent ${legacyPath}${C.reset}`
|
|
1286
|
+
);
|
|
1266
1287
|
if (!opts.dryRun) rmSync(legacyPath, { force: true });
|
|
1267
1288
|
}
|
|
1289
|
+
removeLegacyClaudeCommands(home, opts);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
function removeLegacyClaudeCommands(home, opts) {
|
|
1293
|
+
for (const command of legacyClaudeCommands()) {
|
|
1294
|
+
const commandPath = join(home, "commands", command.filename);
|
|
1295
|
+
logVerbose(
|
|
1296
|
+
`${C.grey}Removing legacy Claude command ${commandPath}${C.reset}`
|
|
1297
|
+
);
|
|
1298
|
+
if (!opts.dryRun) rmSync(commandPath, { force: true });
|
|
1299
|
+
}
|
|
1268
1300
|
}
|
|
1269
1301
|
|
|
1270
1302
|
function installCodexDesktopPlugin(opts) {
|
|
@@ -1402,8 +1434,12 @@ config_file = ${quoteToml(join(home, "agents", agent.filename))}`
|
|
|
1402
1434
|
logVerbose(
|
|
1403
1435
|
`${C.grey}+ enable [features].default_mode_request_user_input in ${configPath}${C.reset}`
|
|
1404
1436
|
);
|
|
1405
|
-
logVerbose(
|
|
1406
|
-
|
|
1437
|
+
logVerbose(
|
|
1438
|
+
`${C.grey}+ write Codex custom agents in ${home}/agents${C.reset}`
|
|
1439
|
+
);
|
|
1440
|
+
logVerbose(
|
|
1441
|
+
`${C.grey}+ register Codex custom agents in ${configPath}${C.reset}`
|
|
1442
|
+
);
|
|
1407
1443
|
}
|
|
1408
1444
|
|
|
1409
1445
|
return {
|
|
@@ -1613,6 +1649,23 @@ function verify(opts) {
|
|
|
1613
1649
|
? "Claude scout MCP tool allowlists present"
|
|
1614
1650
|
: "Claude scout MCP tool allowlists missing",
|
|
1615
1651
|
});
|
|
1652
|
+
const legacyClaudePaths = [
|
|
1653
|
+
...legacyClaudeCustomAgents().map((agent) =>
|
|
1654
|
+
join(claudeHome(), "agents", agent.filename)
|
|
1655
|
+
),
|
|
1656
|
+
...legacyClaudeCommands().map((command) =>
|
|
1657
|
+
join(claudeHome(), "commands", command.filename)
|
|
1658
|
+
),
|
|
1659
|
+
];
|
|
1660
|
+
const hasNoLegacyClaudeArtifacts = legacyClaudePaths.every(
|
|
1661
|
+
(artifactPath) => !existsSync(artifactPath)
|
|
1662
|
+
);
|
|
1663
|
+
checks.push({
|
|
1664
|
+
ok: hasNoLegacyClaudeArtifacts,
|
|
1665
|
+
label: hasNoLegacyClaudeArtifacts
|
|
1666
|
+
? "Legacy Claude Sellable host artifacts cleaned"
|
|
1667
|
+
: "Legacy Claude Sellable host artifacts still present",
|
|
1668
|
+
});
|
|
1616
1669
|
}
|
|
1617
1670
|
if (opts.host === "codex" || opts.host === "all") {
|
|
1618
1671
|
checks.push({
|
|
@@ -1677,6 +1730,19 @@ function verify(opts) {
|
|
|
1677
1730
|
? "Codex custom scout agents registered"
|
|
1678
1731
|
: "Codex custom scout agents unregistered",
|
|
1679
1732
|
});
|
|
1733
|
+
const hasNoLegacyCodexAgents = legacyCodexCustomAgents().every((agent) => {
|
|
1734
|
+
const agentPath = join(codexHome(), "agents", agent.filename);
|
|
1735
|
+
return (
|
|
1736
|
+
!existsSync(agentPath) &&
|
|
1737
|
+
!configContent.includes(`[agents.${agent.name}]`)
|
|
1738
|
+
);
|
|
1739
|
+
});
|
|
1740
|
+
checks.push({
|
|
1741
|
+
ok: hasNoLegacyCodexAgents,
|
|
1742
|
+
label: hasNoLegacyCodexAgents
|
|
1743
|
+
? "Legacy Codex custom scout agents cleaned"
|
|
1744
|
+
: "Legacy Codex custom scout agents still present",
|
|
1745
|
+
});
|
|
1680
1746
|
const hasFlag = configContent.includes(
|
|
1681
1747
|
"default_mode_request_user_input = true"
|
|
1682
1748
|
);
|
|
@@ -1905,7 +1971,10 @@ function runUninstall() {
|
|
|
1905
1971
|
after = removeTomlSection(after, "marketplaces.sellable");
|
|
1906
1972
|
after = removeTomlSection(after, 'plugins."sellable@sellable"');
|
|
1907
1973
|
after = removeTomlSection(after, 'plugins."sellable@sellable-local"');
|
|
1908
|
-
for (const agent of [
|
|
1974
|
+
for (const agent of [
|
|
1975
|
+
...codexCustomAgents(),
|
|
1976
|
+
...legacyCodexCustomAgents(),
|
|
1977
|
+
]) {
|
|
1909
1978
|
after = removeTomlSection(after, `agents.${agent.name}`);
|
|
1910
1979
|
}
|
|
1911
1980
|
// Collapse 3+ blank lines that the removals may leave behind.
|
|
@@ -1955,7 +2024,10 @@ function runUninstall() {
|
|
|
1955
2024
|
skipped.push(`Claude Code CLI not found`);
|
|
1956
2025
|
}
|
|
1957
2026
|
|
|
1958
|
-
for (const agent of [
|
|
2027
|
+
for (const agent of [
|
|
2028
|
+
...claudeCustomAgents(),
|
|
2029
|
+
...legacyClaudeCustomAgents(),
|
|
2030
|
+
]) {
|
|
1959
2031
|
const agentPath = join(claudeHome(), "agents", agent.filename);
|
|
1960
2032
|
if (!existsSync(agentPath)) continue;
|
|
1961
2033
|
try {
|
|
@@ -1967,6 +2039,18 @@ function runUninstall() {
|
|
|
1967
2039
|
);
|
|
1968
2040
|
}
|
|
1969
2041
|
}
|
|
2042
|
+
for (const command of legacyClaudeCommands()) {
|
|
2043
|
+
const commandPath = join(claudeHome(), "commands", command.filename);
|
|
2044
|
+
if (!existsSync(commandPath)) continue;
|
|
2045
|
+
try {
|
|
2046
|
+
rmSync(commandPath, { force: true });
|
|
2047
|
+
removed.push(`${commandPath}`);
|
|
2048
|
+
} catch (err) {
|
|
2049
|
+
console.log(
|
|
2050
|
+
` ${C.yellow}!${C.reset} Could not remove ${commandPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
2051
|
+
);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
1970
2054
|
|
|
1971
2055
|
// 3) Surgical removal of Sellable-installed artifacts inside ~/.sellable/
|
|
1972
2056
|
const sellableDir = join(homedir(), ".sellable");
|
package/package.json
CHANGED
|
@@ -66,10 +66,10 @@ allowed-tools:
|
|
|
66
66
|
|
|
67
67
|
Use this as the customer-facing entrypoint for Sellable campaign creation.
|
|
68
68
|
|
|
69
|
-
CampaignOffer state
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
state first. The
|
|
69
|
+
CampaignOffer state and the watch link are the customer-facing source of truth.
|
|
70
|
+
Disk artifacts are optional debug/UAT diagnostics; normal customer runs should
|
|
71
|
+
not create, link, or surface local draft files unless the user explicitly asks
|
|
72
|
+
for them. Resume, gating, and handoff read campaign state first. The
|
|
73
73
|
watchable campaign exists after the short brief; lead import is bounded to the
|
|
74
74
|
first review batch, and enrichment/message generation waits until rubrics and
|
|
75
75
|
the approved message template are saved on the campaign.
|
|
@@ -147,13 +147,12 @@ Use rendered Markdown for user review surfaces, not fenced code blocks. Keep
|
|
|
147
147
|
lines short, use indexed section labels and bullets, and translate internal
|
|
148
148
|
sourcing terms into plain language.
|
|
149
149
|
|
|
150
|
-
Every approval gate must include
|
|
151
|
-
content. Show a short `
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
content in chat.
|
|
150
|
+
Every approval gate must include live campaign access after the readable inline
|
|
151
|
+
content. Show a short `Watch link:` line once the campaign shell exists. In
|
|
152
|
+
normal customer runs, do not show `Open artifact:` lines, raw filesystem paths,
|
|
153
|
+
or local draft filenames. Local artifacts are debug/UAT-only unless the user asks
|
|
154
|
+
for them. The link is for deeper inspection; never use it as a substitute for
|
|
155
|
+
showing the content in chat.
|
|
157
156
|
|
|
158
157
|
Never mention MCP namespaces, prompt chunking, plugin cache paths, missing
|
|
159
158
|
linked skill versions, runbooks, or local skill files in normal customer-facing
|
|
@@ -503,9 +502,16 @@ updates.
|
|
|
503
502
|
`message-validation.md` proves the message-review safety-gate workflow ran,
|
|
504
503
|
`message-review.md` approves the template, rubrics are saved, and the
|
|
505
504
|
approved message set is synced into the campaign brief.
|
|
506
|
-
6.
|
|
505
|
+
6. The main thread owns watch navigation. Call
|
|
506
|
+
`mcp__sellable__update_campaign({ campaignId, currentStep })` before major
|
|
507
|
+
visible work so the user can watch progress in the app: `create-offer` for
|
|
508
|
+
the brief, `pick-provider` or the selected provider step while sourcing,
|
|
509
|
+
`filter-choice` after the 10-row review batch, `messages` or
|
|
510
|
+
`auto-execute-messaging` for message work, `validate-sample` for validation,
|
|
511
|
+
and `awaiting-user-greenlight` for Settings. Do not advance the step backward.
|
|
512
|
+
7. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
|
|
507
513
|
campaign table. Do not use disk files as the post-mint source of truth.
|
|
508
|
-
|
|
514
|
+
8. Do not ask the user to run another command.
|
|
509
515
|
|
|
510
516
|
## Fallback
|
|
511
517
|
|