@sellable/install 0.1.70 → 0.1.71
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/README.md +5 -3
- package/agents/registry.json +57 -18
- package/bin/sellable-install.mjs +48 -14
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +6 -3
- /package/agents/{linkedin-engagement-scout.md → source-scout-linkedin-engagement.md} +0 -0
- /package/agents/{prospeo-contact-scout.md → source-scout-prospeo-contact.md} +0 -0
- /package/agents/{sales-nav-scout.md → source-scout-sales-nav.md} +0 -0
package/README.md
CHANGED
|
@@ -35,9 +35,11 @@ Auth is stored once at:
|
|
|
35
35
|
|
|
36
36
|
Claude Code and Codex are configured to launch the same packaged MCP server. The
|
|
37
37
|
installer also writes Sellable source-scout agents for both hosts from the
|
|
38
|
-
packaged `agents/` registry: Claude Code gets `
|
|
39
|
-
Codex gets `
|
|
40
|
-
`
|
|
38
|
+
packaged `agents/` registry: Claude Code gets `source-scout-*` subagents, and
|
|
39
|
+
Codex gets `source-scout-linkedin-engagement`, `source-scout-sales-nav`, and
|
|
40
|
+
`source-scout-prospeo-contact`. The MCP exposes the same list through
|
|
41
|
+
`get_source_scout_registry`, so adding a future scout starts in one registry
|
|
42
|
+
entry instead of scattered prompt edits.
|
|
41
43
|
|
|
42
44
|
## Names
|
|
43
45
|
|
package/agents/registry.json
CHANGED
|
@@ -2,12 +2,27 @@
|
|
|
2
2
|
"version": 1,
|
|
3
3
|
"agents": [
|
|
4
4
|
{
|
|
5
|
-
"id": "linkedin-engagement
|
|
6
|
-
"
|
|
5
|
+
"id": "linkedin-engagement",
|
|
6
|
+
"name": "source-scout-linkedin-engagement",
|
|
7
|
+
"promptFile": "source-scout-linkedin-engagement.md",
|
|
7
8
|
"displayName": "LinkedIn Engagement Scout",
|
|
9
|
+
"provider": "signal-discovery",
|
|
10
|
+
"lane": "linkedin-engagement",
|
|
11
|
+
"legacy": {
|
|
12
|
+
"codex": [
|
|
13
|
+
{
|
|
14
|
+
"name": "linkedin_engagement_scout",
|
|
15
|
+
"filename": "linkedin-engagement-scout.toml"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"claude": [
|
|
19
|
+
{
|
|
20
|
+
"name": "lead-explorer-signals",
|
|
21
|
+
"filename": "lead-explorer-signals.md"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
8
25
|
"codex": {
|
|
9
|
-
"name": "linkedin_engagement_scout",
|
|
10
|
-
"filename": "linkedin-engagement-scout.toml",
|
|
11
26
|
"description": "Sellable lead-source scout for LinkedIn post engagement and active conversation signals.",
|
|
12
27
|
"modelReasoningEffort": "medium",
|
|
13
28
|
"sandboxMode": "read-only",
|
|
@@ -18,8 +33,6 @@
|
|
|
18
33
|
]
|
|
19
34
|
},
|
|
20
35
|
"claude": {
|
|
21
|
-
"name": "lead-explorer-signals",
|
|
22
|
-
"filename": "lead-explorer-signals.md",
|
|
23
36
|
"description": "Use proactively as a background Sellable source scout when find-leads or create-campaign needs LinkedIn post engagement, Signals, or active conversation evidence.",
|
|
24
37
|
"model": "inherit",
|
|
25
38
|
"background": true,
|
|
@@ -36,12 +49,27 @@
|
|
|
36
49
|
}
|
|
37
50
|
},
|
|
38
51
|
{
|
|
39
|
-
"id": "sales-nav
|
|
40
|
-
"
|
|
52
|
+
"id": "sales-nav",
|
|
53
|
+
"name": "source-scout-sales-nav",
|
|
54
|
+
"promptFile": "source-scout-sales-nav.md",
|
|
41
55
|
"displayName": "Sales Nav Scout",
|
|
56
|
+
"provider": "sales-nav",
|
|
57
|
+
"lane": "sales-nav",
|
|
58
|
+
"legacy": {
|
|
59
|
+
"codex": [
|
|
60
|
+
{
|
|
61
|
+
"name": "sales_nav_scout",
|
|
62
|
+
"filename": "sales-nav-scout.toml"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"claude": [
|
|
66
|
+
{
|
|
67
|
+
"name": "lead-explorer-sales-nav",
|
|
68
|
+
"filename": "lead-explorer-sales-nav.md"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
},
|
|
42
72
|
"codex": {
|
|
43
|
-
"name": "sales_nav_scout",
|
|
44
|
-
"filename": "sales-nav-scout.toml",
|
|
45
73
|
"description": "Sellable lead-source scout for Sales Navigator role, company, and activity filters.",
|
|
46
74
|
"modelReasoningEffort": "medium",
|
|
47
75
|
"sandboxMode": "read-only",
|
|
@@ -52,8 +80,6 @@
|
|
|
52
80
|
]
|
|
53
81
|
},
|
|
54
82
|
"claude": {
|
|
55
|
-
"name": "lead-explorer-sales-nav",
|
|
56
|
-
"filename": "lead-explorer-sales-nav.md",
|
|
57
83
|
"description": "Use proactively as a background Sellable source scout when find-leads or create-campaign needs Sales Navigator title, company, geography, or activity-filter evidence.",
|
|
58
84
|
"model": "inherit",
|
|
59
85
|
"background": true,
|
|
@@ -70,12 +96,27 @@
|
|
|
70
96
|
}
|
|
71
97
|
},
|
|
72
98
|
{
|
|
73
|
-
"id": "prospeo-contact
|
|
74
|
-
"
|
|
99
|
+
"id": "prospeo-contact",
|
|
100
|
+
"name": "source-scout-prospeo-contact",
|
|
101
|
+
"promptFile": "source-scout-prospeo-contact.md",
|
|
75
102
|
"displayName": "Prospeo Contact Scout",
|
|
103
|
+
"provider": "prospeo",
|
|
104
|
+
"lane": "prospeo-contact",
|
|
105
|
+
"legacy": {
|
|
106
|
+
"codex": [
|
|
107
|
+
{
|
|
108
|
+
"name": "prospeo_contact_scout",
|
|
109
|
+
"filename": "prospeo-contact-scout.toml"
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"claude": [
|
|
113
|
+
{
|
|
114
|
+
"name": "lead-explorer-prospeo",
|
|
115
|
+
"filename": "lead-explorer-prospeo.md"
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
},
|
|
76
119
|
"codex": {
|
|
77
|
-
"name": "prospeo_contact_scout",
|
|
78
|
-
"filename": "prospeo-contact-scout.toml",
|
|
79
120
|
"description": "Sellable lead-source scout for Prospeo account/domain and broad contact expansion.",
|
|
80
121
|
"modelReasoningEffort": "medium",
|
|
81
122
|
"sandboxMode": "read-only",
|
|
@@ -86,8 +127,6 @@
|
|
|
86
127
|
]
|
|
87
128
|
},
|
|
88
129
|
"claude": {
|
|
89
|
-
"name": "lead-explorer-prospeo",
|
|
90
|
-
"filename": "lead-explorer-prospeo.md",
|
|
91
130
|
"description": "Use proactively as a background Sellable source scout when find-leads or create-campaign needs Prospeo account, domain-list, CSV-domain, or verified-contact evidence.",
|
|
92
131
|
"model": "inherit",
|
|
93
132
|
"background": true,
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -465,6 +465,7 @@ const CREATE_CAMPAIGN_ALLOWED_TOOLS = [
|
|
|
465
465
|
"mcp__sellable__get_subskill_asset",
|
|
466
466
|
"mcp__sellable__search_subskill_prompts",
|
|
467
467
|
"mcp__sellable__get_provider_prompt",
|
|
468
|
+
"mcp__sellable__get_source_scout_registry",
|
|
468
469
|
"mcp__sellable__get_message_prompt",
|
|
469
470
|
"mcp__sellable__get_active_workspace",
|
|
470
471
|
"mcp__sellable__list_senders",
|
|
@@ -1124,14 +1125,18 @@ function loadCanonicalAgents() {
|
|
|
1124
1125
|
|
|
1125
1126
|
return registry.agents.map((agent) => {
|
|
1126
1127
|
const promptPath = join(root, agent.promptFile || "");
|
|
1127
|
-
if (!agent.id || !agent.promptFile || !existsSync(promptPath)) {
|
|
1128
|
+
if (!agent.id || !agent.name || !agent.promptFile || !existsSync(promptPath)) {
|
|
1128
1129
|
throw new Error(`Invalid Sellable agent registry entry: ${agent.id || "unknown"}`);
|
|
1129
1130
|
}
|
|
1130
|
-
if (
|
|
1131
|
-
throw new Error(
|
|
1131
|
+
if (agent.codex?.name && agent.codex.name !== agent.name) {
|
|
1132
|
+
throw new Error(
|
|
1133
|
+
`Sellable agent ${agent.id} has divergent Codex name ${agent.codex.name}; use canonical name ${agent.name}.`
|
|
1134
|
+
);
|
|
1132
1135
|
}
|
|
1133
|
-
if (
|
|
1134
|
-
throw new Error(
|
|
1136
|
+
if (agent.claude?.name && agent.claude.name !== agent.name) {
|
|
1137
|
+
throw new Error(
|
|
1138
|
+
`Sellable agent ${agent.id} has divergent Claude name ${agent.claude.name}; use canonical name ${agent.name}.`
|
|
1139
|
+
);
|
|
1135
1140
|
}
|
|
1136
1141
|
|
|
1137
1142
|
return {
|
|
@@ -1141,6 +1146,22 @@ function loadCanonicalAgents() {
|
|
|
1141
1146
|
});
|
|
1142
1147
|
}
|
|
1143
1148
|
|
|
1149
|
+
function codexAgentFilename(agent) {
|
|
1150
|
+
return agent.codex?.filename || `${agent.name}.toml`;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
function claudeAgentFilename(agent) {
|
|
1154
|
+
return agent.claude?.filename || `${agent.name}.md`;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
function legacyCodexCustomAgents() {
|
|
1158
|
+
return loadCanonicalAgents().flatMap((agent) => agent.legacy?.codex || []);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function legacyClaudeCustomAgents() {
|
|
1162
|
+
return loadCanonicalAgents().flatMap((agent) => agent.legacy?.claude || []);
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1144
1165
|
function tomlArray(values) {
|
|
1145
1166
|
return `[${values.map((value) => quoteToml(value)).join(", ")}]`;
|
|
1146
1167
|
}
|
|
@@ -1152,7 +1173,7 @@ function tomlMultilineString(value) {
|
|
|
1152
1173
|
|
|
1153
1174
|
function generateCodexAgentToml(agent) {
|
|
1154
1175
|
const codex = agent.codex;
|
|
1155
|
-
return `name = ${quoteToml(
|
|
1176
|
+
return `name = ${quoteToml(agent.name)}
|
|
1156
1177
|
description = ${quoteToml(codex.description)}
|
|
1157
1178
|
model_reasoning_effort = ${quoteToml(codex.modelReasoningEffort || "medium")}
|
|
1158
1179
|
sandbox_mode = ${quoteToml(codex.sandboxMode || "read-only")}
|
|
@@ -1163,8 +1184,8 @@ developer_instructions = ${tomlMultilineString(agent.prompt)}
|
|
|
1163
1184
|
|
|
1164
1185
|
function codexCustomAgents() {
|
|
1165
1186
|
return loadCanonicalAgents().map((agent) => ({
|
|
1166
|
-
name: agent.
|
|
1167
|
-
filename: agent
|
|
1187
|
+
name: agent.name,
|
|
1188
|
+
filename: codexAgentFilename(agent),
|
|
1168
1189
|
content: generateCodexAgentToml(agent),
|
|
1169
1190
|
}));
|
|
1170
1191
|
}
|
|
@@ -1172,7 +1193,7 @@ function codexCustomAgents() {
|
|
|
1172
1193
|
function generateClaudeAgentMd(agent) {
|
|
1173
1194
|
const claude = agent.claude;
|
|
1174
1195
|
return `---
|
|
1175
|
-
name: ${
|
|
1196
|
+
name: ${agent.name}
|
|
1176
1197
|
description: ${JSON.stringify(claude.description)}
|
|
1177
1198
|
tools: ${(claude.tools || []).join(", ")}
|
|
1178
1199
|
model: ${claude.model || "inherit"}
|
|
@@ -1187,8 +1208,8 @@ ${agent.prompt}
|
|
|
1187
1208
|
|
|
1188
1209
|
function claudeCustomAgents() {
|
|
1189
1210
|
return loadCanonicalAgents().map((agent) => ({
|
|
1190
|
-
name: agent.
|
|
1191
|
-
filename: agent
|
|
1211
|
+
name: agent.name,
|
|
1212
|
+
filename: claudeAgentFilename(agent),
|
|
1192
1213
|
tools: agent.claude.tools || [],
|
|
1193
1214
|
content: generateClaudeAgentMd(agent),
|
|
1194
1215
|
}));
|
|
@@ -1213,6 +1234,11 @@ function writeCodexCustomAgents(home, opts) {
|
|
|
1213
1234
|
for (const agent of codexCustomAgents()) {
|
|
1214
1235
|
writeFile(join(home, "agents", agent.filename), agent.content, opts);
|
|
1215
1236
|
}
|
|
1237
|
+
for (const agent of legacyCodexCustomAgents()) {
|
|
1238
|
+
const legacyPath = join(home, "agents", agent.filename);
|
|
1239
|
+
logVerbose(`${C.grey}Removing legacy Codex scout agent ${legacyPath}${C.reset}`);
|
|
1240
|
+
if (!opts.dryRun) rmSync(legacyPath, { force: true });
|
|
1241
|
+
}
|
|
1216
1242
|
}
|
|
1217
1243
|
|
|
1218
1244
|
function claudeHome() {
|
|
@@ -1224,6 +1250,11 @@ function writeClaudeCustomAgents(opts) {
|
|
|
1224
1250
|
for (const agent of claudeCustomAgents()) {
|
|
1225
1251
|
writeFile(join(home, "agents", agent.filename), agent.content, opts);
|
|
1226
1252
|
}
|
|
1253
|
+
for (const agent of legacyClaudeCustomAgents()) {
|
|
1254
|
+
const legacyPath = join(home, "agents", agent.filename);
|
|
1255
|
+
logVerbose(`${C.grey}Removing legacy Claude scout agent ${legacyPath}${C.reset}`);
|
|
1256
|
+
if (!opts.dryRun) rmSync(legacyPath, { force: true });
|
|
1257
|
+
}
|
|
1227
1258
|
}
|
|
1228
1259
|
|
|
1229
1260
|
function installCodexDesktopPlugin(opts) {
|
|
@@ -1339,6 +1370,9 @@ enabled = false`
|
|
|
1339
1370
|
max_threads = 6
|
|
1340
1371
|
max_depth = 1`
|
|
1341
1372
|
);
|
|
1373
|
+
for (const agent of legacyCodexCustomAgents()) {
|
|
1374
|
+
content = removeTomlSection(content, `agents.${agent.name}`);
|
|
1375
|
+
}
|
|
1342
1376
|
for (const agent of codexCustomAgents()) {
|
|
1343
1377
|
content = upsertTomlTable(
|
|
1344
1378
|
content,
|
|
@@ -1861,7 +1895,7 @@ function runUninstall() {
|
|
|
1861
1895
|
after = removeTomlSection(after, "marketplaces.sellable");
|
|
1862
1896
|
after = removeTomlSection(after, 'plugins."sellable@sellable"');
|
|
1863
1897
|
after = removeTomlSection(after, 'plugins."sellable@sellable-local"');
|
|
1864
|
-
for (const agent of codexCustomAgents()) {
|
|
1898
|
+
for (const agent of [...codexCustomAgents(), ...legacyCodexCustomAgents()]) {
|
|
1865
1899
|
after = removeTomlSection(after, `agents.${agent.name}`);
|
|
1866
1900
|
}
|
|
1867
1901
|
// Collapse 3+ blank lines that the removals may leave behind.
|
|
@@ -1884,7 +1918,7 @@ function runUninstall() {
|
|
|
1884
1918
|
skipped.push(`Codex config not found at ${codexConfigPath}`);
|
|
1885
1919
|
}
|
|
1886
1920
|
|
|
1887
|
-
for (const agent of codexCustomAgents()) {
|
|
1921
|
+
for (const agent of [...codexCustomAgents(), ...legacyCodexCustomAgents()]) {
|
|
1888
1922
|
const agentPath = join(codexHome(), "agents", agent.filename);
|
|
1889
1923
|
if (!existsSync(agentPath)) continue;
|
|
1890
1924
|
try {
|
|
@@ -1911,7 +1945,7 @@ function runUninstall() {
|
|
|
1911
1945
|
skipped.push(`Claude Code CLI not found`);
|
|
1912
1946
|
}
|
|
1913
1947
|
|
|
1914
|
-
for (const agent of claudeCustomAgents()) {
|
|
1948
|
+
for (const agent of [...claudeCustomAgents(), ...legacyClaudeCustomAgents()]) {
|
|
1915
1949
|
const agentPath = join(claudeHome(), "agents", agent.filename);
|
|
1916
1950
|
if (!existsSync(agentPath)) continue;
|
|
1917
1951
|
try {
|
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ allowed-tools:
|
|
|
11
11
|
- mcp__sellable__get_subskill_asset
|
|
12
12
|
- mcp__sellable__search_subskill_prompts
|
|
13
13
|
- mcp__sellable__get_provider_prompt
|
|
14
|
+
- mcp__sellable__get_source_scout_registry
|
|
14
15
|
- mcp__sellable__get_message_prompt
|
|
15
16
|
- mcp__sellable__get_active_workspace
|
|
16
17
|
- mcp__sellable__list_senders
|
|
@@ -102,12 +103,14 @@ scout those angles as independent branches when the host can actually do it:
|
|
|
102
103
|
LinkedIn Engagement / active post engagers (internal `signal-discovery`
|
|
103
104
|
provider prompt), Sales Nav / title + company filters, and Prospeo Contact /
|
|
104
105
|
domains only when relevant. In Codex, explicitly spawn the named custom scouts
|
|
105
|
-
`
|
|
106
|
+
`source-scout-linkedin-engagement`, `source-scout-sales-nav`, and `source-scout-prospeo-contact` for
|
|
106
107
|
the credible lanes; Codex does not infer subagent fan-out from generic source
|
|
107
|
-
comparison wording. In Claude Code, invoke the generated `
|
|
108
|
+
comparison wording. In Claude Code, invoke the generated `source-scout-*`
|
|
108
109
|
Task/Agent subagents for all credible lanes in one assistant message; the
|
|
109
110
|
installer writes them from the same canonical Sellable agent registry with
|
|
110
|
-
explicit Sellable MCP tool allowlists.
|
|
111
|
+
explicit Sellable MCP tool allowlists. The create-campaign-v2 subskill calls
|
|
112
|
+
`get_source_scout_registry` before dispatch so the current registry, not this
|
|
113
|
+
copy, is the runtime source of truth. If the host runs them sequentially, do not
|
|
111
114
|
claim they ran in parallel. In chat, call the downstream copy stage `message generation`;
|
|
112
115
|
`message-validation.md` is only an internal proof artifact.
|
|
113
116
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|