@sellable/install 0.1.67 → 0.1.69
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
CHANGED
|
@@ -40,7 +40,7 @@ function getMcpVersion() {
|
|
|
40
40
|
} catch {}
|
|
41
41
|
return "latest";
|
|
42
42
|
}
|
|
43
|
-
const CODEX_PLUGIN_VERSION = "0.1.
|
|
43
|
+
const CODEX_PLUGIN_VERSION = "0.1.28";
|
|
44
44
|
const CODEX_PLUGIN_COMPAT_VERSIONS = [
|
|
45
45
|
"0.1.8",
|
|
46
46
|
"0.1.9",
|
|
@@ -61,6 +61,7 @@ const CODEX_PLUGIN_COMPAT_VERSIONS = [
|
|
|
61
61
|
"0.1.24",
|
|
62
62
|
"0.1.25",
|
|
63
63
|
"0.1.26",
|
|
64
|
+
"0.1.27",
|
|
64
65
|
];
|
|
65
66
|
const INSTALL_PACKAGE_SPEC =
|
|
66
67
|
process.env.SELLABLE_INSTALL_PACKAGE_SPEC || "@sellable/install@latest";
|
|
@@ -461,6 +462,7 @@ const CREATE_CAMPAIGN_ALLOWED_TOOLS = [
|
|
|
461
462
|
"mcp__sellable__get_auth_status",
|
|
462
463
|
"mcp__sellable__bootstrap_create_campaign",
|
|
463
464
|
"mcp__sellable__get_subskill_prompt",
|
|
465
|
+
"mcp__sellable__get_subskill_asset",
|
|
464
466
|
"mcp__sellable__search_subskill_prompts",
|
|
465
467
|
"mcp__sellable__get_provider_prompt",
|
|
466
468
|
"mcp__sellable__get_message_prompt",
|
|
@@ -829,19 +831,24 @@ updates.
|
|
|
829
831
|
|
|
830
832
|
1. Load canonical prompt via
|
|
831
833
|
\`mcp__sellable__get_subskill_prompt({ subskillName: "create-campaign-v2" })\`.
|
|
832
|
-
2.
|
|
833
|
-
|
|
834
|
+
2. Load the canonical workflow config via
|
|
835
|
+
\`mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "core/flow.v2.json" })\`.
|
|
836
|
+
Treat the returned JSON as the active state machine. Do not read repo-local
|
|
837
|
+
copies of this file; packaged Claude Code and Codex runs must use the MCP
|
|
838
|
+
asset loader so they share the same config.
|
|
839
|
+
3. Follow that prompt and workflow config exactly.
|
|
840
|
+
4. For message generation, load the full \`generate-messages\` prompt in the
|
|
834
841
|
same run with chunked
|
|
835
842
|
\`mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages", offset, limit })\`
|
|
836
843
|
calls until \`hasMore\` is false. Do not synthesize
|
|
837
844
|
\`message-validation.md\` from the brief, lead review, or general knowledge.
|
|
838
|
-
|
|
845
|
+
5. Treat message quality as the gate before minting. Do not create a campaign,
|
|
839
846
|
show a commit gate, or mint anything until \`message-validation.md\` proves
|
|
840
847
|
the full generate-messages workflow ran and \`message-review.md\` recommends
|
|
841
848
|
\`approve-message\` against the gold-standard rules.
|
|
842
|
-
|
|
849
|
+
6. Do not create or mutate the live campaign until the approval gate returns
|
|
843
850
|
\`approve\`.
|
|
844
|
-
|
|
851
|
+
7. Do not ask the user to run another command.
|
|
845
852
|
|
|
846
853
|
## Fallback
|
|
847
854
|
|
|
@@ -1082,6 +1089,112 @@ function codexPluginSkills() {
|
|
|
1082
1089
|
];
|
|
1083
1090
|
}
|
|
1084
1091
|
|
|
1092
|
+
function codexCustomAgents() {
|
|
1093
|
+
const commonPrefix = `You are part of the Sellable find-leads source scout.
|
|
1094
|
+
|
|
1095
|
+
Work only on your assigned source lane. Do not import leads, create campaigns, write campaign artifacts, or draft messages. Return concise structured evidence to the parent agent so it can synthesize the lead-source decision.`;
|
|
1096
|
+
|
|
1097
|
+
return [
|
|
1098
|
+
{
|
|
1099
|
+
filename: "linkedin-engagement-scout.toml",
|
|
1100
|
+
content: `name = "linkedin_engagement_scout"
|
|
1101
|
+
description = "Sellable lead-source scout for LinkedIn post engagement and active conversation signals."
|
|
1102
|
+
model_reasoning_effort = "medium"
|
|
1103
|
+
sandbox_mode = "read-only"
|
|
1104
|
+
nickname_candidates = ["LinkedIn Engagement Scout", "Post Scout", "Engager Scout"]
|
|
1105
|
+
developer_instructions = """
|
|
1106
|
+
${commonPrefix}
|
|
1107
|
+
|
|
1108
|
+
Your lane is LinkedIn Engagement. Internally, use the signal-discovery provider prompt and the Signals tools when available.
|
|
1109
|
+
|
|
1110
|
+
Use the inherited Sellable MCP tools when available:
|
|
1111
|
+
- get_provider_prompt for signal-discovery before searching
|
|
1112
|
+
- search_signals to find recent post lanes
|
|
1113
|
+
- fetch_post_engagers to sample engagers from selected posts
|
|
1114
|
+
|
|
1115
|
+
Process:
|
|
1116
|
+
1. Search 3-5 keyword/topic lanes, favoring fresh posts from the last 7-14 days.
|
|
1117
|
+
2. Select 3-5 promising posts when available.
|
|
1118
|
+
3. Fetch or sample engagers for selected posts and score rough ICP fit from visible headline/display cues.
|
|
1119
|
+
4. Estimate usable prospects per selected post from sampled pass rate.
|
|
1120
|
+
5. If the sample is good but volume is low, say how many more similar posts should be added or scraped.
|
|
1121
|
+
|
|
1122
|
+
Return:
|
|
1123
|
+
- keyword lanes searched, timeframe, raw posts found, finalist posts reviewed
|
|
1124
|
+
- selected post URL/title, author/topic, age, engager count, sampled engagers, good fits as n/N, estimated usable prospects per post, use/discard
|
|
1125
|
+
- sample leads if any
|
|
1126
|
+
- estimated good-fit range, directional reply-rate range, false positives, recommendation, confidence
|
|
1127
|
+
"""
|
|
1128
|
+
`,
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
filename: "sales-nav-scout.toml",
|
|
1132
|
+
content: `name = "sales_nav_scout"
|
|
1133
|
+
description = "Sellable lead-source scout for Sales Navigator role, company, and activity filters."
|
|
1134
|
+
model_reasoning_effort = "medium"
|
|
1135
|
+
sandbox_mode = "read-only"
|
|
1136
|
+
nickname_candidates = ["Sales Nav Scout", "Role Filter Scout", "Activity Scout"]
|
|
1137
|
+
developer_instructions = """
|
|
1138
|
+
${commonPrefix}
|
|
1139
|
+
|
|
1140
|
+
Your lane is Sales Nav.
|
|
1141
|
+
|
|
1142
|
+
Use the inherited Sellable MCP tools when available:
|
|
1143
|
+
- get_provider_prompt for sales-nav before searching
|
|
1144
|
+
- lookup_sales_nav_filter before dynamic filters
|
|
1145
|
+
- search_sales_nav for campaignless preview searches
|
|
1146
|
+
|
|
1147
|
+
Process:
|
|
1148
|
+
1. Preserve target role names with CURRENT_TITLE lookups; do not rely on seniority alone when the brief names concrete roles.
|
|
1149
|
+
2. Build a broad-but-reasonable baseline from role/title, geography, company size, industry/account context, and recent LinkedIn activity when relevant.
|
|
1150
|
+
3. Run the baseline plus 1-2 refinements if the first pass is noisy or under-scaled.
|
|
1151
|
+
4. Verify filters actually applied: search URL contains filters, first-page rows match the intended lane, and result count does not look like an unfiltered pool.
|
|
1152
|
+
|
|
1153
|
+
Return:
|
|
1154
|
+
- exact filter recipe and lookup IDs used
|
|
1155
|
+
- raw result count, sampled people, good fits as n/N
|
|
1156
|
+
- estimated good-fit range after cleanup
|
|
1157
|
+
- directional acceptance/reply-rate ranges
|
|
1158
|
+
- sample leads, false positives, recommendation, confidence
|
|
1159
|
+
"""
|
|
1160
|
+
`,
|
|
1161
|
+
},
|
|
1162
|
+
{
|
|
1163
|
+
filename: "prospeo-contact-scout.toml",
|
|
1164
|
+
content: `name = "prospeo_contact_scout"
|
|
1165
|
+
description = "Sellable lead-source scout for Prospeo account/domain and broad contact expansion."
|
|
1166
|
+
model_reasoning_effort = "medium"
|
|
1167
|
+
sandbox_mode = "read-only"
|
|
1168
|
+
nickname_candidates = ["Prospeo Contact Scout", "Domain Scout", "Contact Scout"]
|
|
1169
|
+
developer_instructions = """
|
|
1170
|
+
${commonPrefix}
|
|
1171
|
+
|
|
1172
|
+
Your lane is Prospeo Contact.
|
|
1173
|
+
|
|
1174
|
+
Use the inherited Sellable MCP tools when available:
|
|
1175
|
+
- get_provider_prompt for prospeo before searching
|
|
1176
|
+
- load_csv_domains when the parent supplies a CSV or domain list and no domainFilterId exists
|
|
1177
|
+
- search_prospeo for campaignless people previews
|
|
1178
|
+
|
|
1179
|
+
Process:
|
|
1180
|
+
1. Identify whether this is domain/account targeting or broad persona expansion.
|
|
1181
|
+
2. For domain targeting, use or create the standalone domainFilterId before searching; never pass raw domains directly into search_prospeo.
|
|
1182
|
+
3. Run the narrowest useful Prospeo people preview and 1-2 refinements if quality or scale is unclear.
|
|
1183
|
+
4. Call out that Prospeo gives contact/account coverage but usually weaker LinkedIn intent than LinkedIn Engagement or Sales Nav activity slices.
|
|
1184
|
+
|
|
1185
|
+
Return:
|
|
1186
|
+
- mode and domain/account inputs
|
|
1187
|
+
- exact search recipe
|
|
1188
|
+
- raw result count, sampled people, good fits as n/N
|
|
1189
|
+
- estimated good-fit range after cleanup
|
|
1190
|
+
- directional reply-rate range
|
|
1191
|
+
- sample leads, false positives, recommendation, confidence
|
|
1192
|
+
"""
|
|
1193
|
+
`,
|
|
1194
|
+
},
|
|
1195
|
+
];
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1085
1198
|
function writeCodexPluginSkills(pluginRoot, opts) {
|
|
1086
1199
|
for (const skill of codexPluginSkills()) {
|
|
1087
1200
|
const skillRoot = join(pluginRoot, "skills", skill.dir);
|
|
@@ -1097,6 +1210,12 @@ function writeCodexPluginSkills(pluginRoot, opts) {
|
|
|
1097
1210
|
}
|
|
1098
1211
|
}
|
|
1099
1212
|
|
|
1213
|
+
function writeCodexCustomAgents(home, opts) {
|
|
1214
|
+
for (const agent of codexCustomAgents()) {
|
|
1215
|
+
writeFile(join(home, "agents", agent.filename), agent.content, opts);
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1100
1219
|
function installCodexDesktopPlugin(opts) {
|
|
1101
1220
|
const home = codexHome();
|
|
1102
1221
|
const configPath = join(home, "config.toml");
|
|
@@ -1147,6 +1266,7 @@ function installCodexDesktopPlugin(opts) {
|
|
|
1147
1266
|
opts
|
|
1148
1267
|
);
|
|
1149
1268
|
writeCodexPluginSkills(pluginRoot, opts);
|
|
1269
|
+
writeCodexCustomAgents(home, opts);
|
|
1150
1270
|
|
|
1151
1271
|
if (!opts.dryRun) {
|
|
1152
1272
|
rmSync(cacheRoot, { recursive: true, force: true });
|
|
@@ -1213,6 +1333,7 @@ enabled = false`
|
|
|
1213
1333
|
logVerbose(
|
|
1214
1334
|
`${C.grey}+ enable [features].default_mode_request_user_input in ${configPath}${C.reset}`
|
|
1215
1335
|
);
|
|
1336
|
+
logVerbose(`${C.grey}+ write Codex custom scout agents in ${home}/agents${C.reset}`);
|
|
1216
1337
|
}
|
|
1217
1338
|
|
|
1218
1339
|
return {
|
|
@@ -1435,6 +1556,18 @@ function verify(opts) {
|
|
|
1435
1556
|
? "Codex skill bundle present"
|
|
1436
1557
|
: "Codex skill bundle missing",
|
|
1437
1558
|
});
|
|
1559
|
+
const codexAgentPaths = codexCustomAgents().map((agent) =>
|
|
1560
|
+
join(codexHome(), "agents", agent.filename)
|
|
1561
|
+
);
|
|
1562
|
+
const hasCodexScouts = codexAgentPaths.every((agentPath) =>
|
|
1563
|
+
existsSync(agentPath)
|
|
1564
|
+
);
|
|
1565
|
+
checks.push({
|
|
1566
|
+
ok: hasCodexScouts,
|
|
1567
|
+
label: hasCodexScouts
|
|
1568
|
+
? "Codex custom scout agents present"
|
|
1569
|
+
: "Codex custom scout agents missing",
|
|
1570
|
+
});
|
|
1438
1571
|
const configPath = join(codexHome(), "config.toml");
|
|
1439
1572
|
const configContent = existsSync(configPath)
|
|
1440
1573
|
? readFileSync(configPath, "utf8")
|
|
@@ -1585,6 +1718,7 @@ function printNextSteps(installedHosts, authReused) {
|
|
|
1585
1718
|
if (hasCodex) {
|
|
1586
1719
|
console.log(` ${C.green}✓${C.reset} Codex Desktop plugin installed`);
|
|
1587
1720
|
console.log(` ${C.green}✓${C.reset} Skills installed`);
|
|
1721
|
+
console.log(` ${C.green}✓${C.reset} Codex source scout agents installed`);
|
|
1588
1722
|
}
|
|
1589
1723
|
if (authReused) {
|
|
1590
1724
|
console.log(
|
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@ allowed-tools:
|
|
|
8
8
|
- mcp__sellable__wait_for_cli_login
|
|
9
9
|
- mcp__sellable__bootstrap_create_campaign
|
|
10
10
|
- mcp__sellable__get_subskill_prompt
|
|
11
|
+
- mcp__sellable__get_subskill_asset
|
|
11
12
|
- mcp__sellable__search_subskill_prompts
|
|
12
13
|
- mcp__sellable__get_provider_prompt
|
|
13
14
|
- mcp__sellable__get_message_prompt
|
|
@@ -98,10 +99,15 @@ denominator, and sample basis.
|
|
|
98
99
|
|
|
99
100
|
When the user has not supplied a source and multiple source angles are viable,
|
|
100
101
|
scout those angles as independent branches when the host can actually do it:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
LinkedIn Engagement / active post engagers (internal `signal-discovery`
|
|
103
|
+
provider prompt), Sales Nav / title + company filters, and Prospeo Contact /
|
|
104
|
+
domains only when relevant. In Codex, explicitly spawn the named custom scouts
|
|
105
|
+
`linkedin_engagement_scout`, `sales_nav_scout`, and `prospeo_contact_scout` for
|
|
106
|
+
the credible lanes; Codex does not infer subagent fan-out from generic source
|
|
107
|
+
comparison wording. In Claude Code, keep using the existing Task agents under
|
|
108
|
+
`.claude/agents/`. If the host runs them sequentially, do not claim they ran in
|
|
109
|
+
parallel. In chat, call the downstream copy stage `message generation`;
|
|
110
|
+
`message-validation.md` is only an internal proof artifact.
|
|
105
111
|
|
|
106
112
|
Use rendered Markdown for user review surfaces, not fenced code blocks. Keep
|
|
107
113
|
lines short, use indexed section labels and bullets, and translate internal
|
|
@@ -449,19 +455,24 @@ updates.
|
|
|
449
455
|
|
|
450
456
|
1. Load canonical prompt via
|
|
451
457
|
`mcp__sellable__get_subskill_prompt({ subskillName: "create-campaign-v2" })`.
|
|
452
|
-
2.
|
|
453
|
-
|
|
458
|
+
2. Load the canonical workflow config via
|
|
459
|
+
`mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "core/flow.v2.json" })`.
|
|
460
|
+
Treat the returned JSON as the active state machine. Do not read repo-local
|
|
461
|
+
copies of this file; packaged Claude Code and Codex runs must use the MCP
|
|
462
|
+
asset loader so they share the same config.
|
|
463
|
+
3. Follow that prompt and workflow config exactly.
|
|
464
|
+
4. For message generation, load the full `generate-messages` prompt in the
|
|
454
465
|
same run with chunked
|
|
455
466
|
`mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages", offset, limit })`
|
|
456
467
|
calls until `hasMore` is false. Do not synthesize
|
|
457
468
|
`message-validation.md` from the brief, lead review, or general knowledge.
|
|
458
|
-
|
|
469
|
+
5. Treat message quality as the gate before minting. Do not create a campaign,
|
|
459
470
|
show a commit gate, or mint anything until `message-validation.md` proves
|
|
460
471
|
the full generate-messages workflow ran and `message-review.md` recommends
|
|
461
472
|
`approve-message` against the gold-standard rules.
|
|
462
|
-
|
|
473
|
+
6. Do not create or mutate the live campaign until the approval gate returns
|
|
463
474
|
`approve`.
|
|
464
|
-
|
|
475
|
+
7. Do not ask the user to run another command.
|
|
465
476
|
|
|
466
477
|
## Fallback
|
|
467
478
|
|