@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.
@@ -40,7 +40,7 @@ function getMcpVersion() {
40
40
  } catch {}
41
41
  return "latest";
42
42
  }
43
- const CODEX_PLUGIN_VERSION = "0.1.27";
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. Follow that prompt exactly.
833
- 3. For message generation, load the full \`generate-messages\` prompt in the
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
- 4. Treat message quality as the gate before minting. Do not create a campaign,
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
- 5. Do not create or mutate the live campaign until the approval gate returns
849
+ 6. Do not create or mutate the live campaign until the approval gate returns
843
850
  \`approve\`.
844
- 6. Do not ask the user to run another command.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.67",
3
+ "version": "0.1.69",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code and Codex",
6
6
  "bin": {
@@ -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
- Signals / active LinkedIn posts, Sales Nav / title + company filters, and
102
- Prospeo / domains only when relevant. If the host runs them sequentially, do not
103
- claim they ran in parallel. In chat, call the downstream copy stage `message
104
- generation`; `message-validation.md` is only an internal proof artifact.
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. Follow that prompt exactly.
453
- 3. For message generation, load the full `generate-messages` prompt in the
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
- 4. Treat message quality as the gate before minting. Do not create a campaign,
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
- 5. Do not create or mutate the live campaign until the approval gate returns
473
+ 6. Do not create or mutate the live campaign until the approval gate returns
463
474
  `approve`.
464
- 6. Do not ask the user to run another command.
475
+ 7. Do not ask the user to run another command.
465
476
 
466
477
  ## Fallback
467
478