@sellable/install 0.1.120 → 0.1.122
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
CHANGED
|
@@ -6,6 +6,16 @@ Installs Sellable MCP for Claude Code and Codex.
|
|
|
6
6
|
npx -y @sellable/install@latest --host all
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+
Paste that command in your terminal, not inside the Codex chat. Mac/Linux
|
|
10
|
+
users can use Terminal. Windows users can use PowerShell or Windows Terminal;
|
|
11
|
+
if PowerShell blocks `npx`, run:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
npx.cmd -y @sellable/install@latest --host all
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
After install, restart Codex Desktop so the Sellable skill appears.
|
|
18
|
+
|
|
9
19
|
After install, `sellable create` is a terminal helper that prints the correct
|
|
10
20
|
agent command for launching a campaign:
|
|
11
21
|
|
|
@@ -60,9 +60,14 @@ currentStep: "signal-discovery" })` before sampling so the watched Signal
|
|
|
60
60
|
sampled/projected headline-fit rate clears the 10% planning floor. Treat the
|
|
61
61
|
10% floor as a reject threshold, not as the scrape-count denominator when the
|
|
62
62
|
actual sample rate is higher.
|
|
63
|
-
8. Select/promote enough right-content posts to plausibly hit the target.
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
8. Select/promote enough right-content posts to plausibly hit the target. After
|
|
64
|
+
the sample math is known, treat the promoted sample set and final scrape set
|
|
65
|
+
as separate: recommend the smallest right-content post subset whose
|
|
66
|
+
scrapable/reachable engagers clears the required engager count, with a modest
|
|
67
|
+
buffer when needed. If one 1,200+ engager post clears a ~1,000-engager target,
|
|
68
|
+
recommend scraping that one post, not all 3 sample posts. If the warm Signals
|
|
69
|
+
pool is useful but too small, return the expected warm range and recommend
|
|
70
|
+
Sales Nav/Prospeo for scale instead of padding with noisy posts.
|
|
66
71
|
9. Return false positives and dead ends explicitly.
|
|
67
72
|
|
|
68
73
|
Return a concise structured result with:
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawnSync } from "node:child_process";
|
|
3
3
|
import {
|
|
4
|
+
cpSync,
|
|
4
5
|
existsSync,
|
|
5
6
|
mkdirSync,
|
|
6
7
|
readdirSync,
|
|
@@ -30,16 +31,6 @@ function getInstallVersion() {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
function getMcpVersion() {
|
|
34
|
-
try {
|
|
35
|
-
const r = spawnSync("npm", ["view", "@sellable/mcp", "version"], {
|
|
36
|
-
encoding: "utf8",
|
|
37
|
-
timeout: 5000,
|
|
38
|
-
});
|
|
39
|
-
if (r.status === 0 && r.stdout) return r.stdout.trim();
|
|
40
|
-
} catch {}
|
|
41
|
-
return "latest";
|
|
42
|
-
}
|
|
43
34
|
const CODEX_PLUGIN_VERSION = "0.1.33";
|
|
44
35
|
const CODEX_PLUGIN_COMPAT_VERSIONS = [
|
|
45
36
|
"0.1.8",
|
|
@@ -282,13 +273,59 @@ function run(command, args, opts = {}) {
|
|
|
282
273
|
return result;
|
|
283
274
|
}
|
|
284
275
|
|
|
285
|
-
function
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
276
|
+
function isWindowsPlatform(platform = process.platform) {
|
|
277
|
+
return platform === "win32";
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function packageRunnerCommand(platform = process.platform) {
|
|
281
|
+
return isWindowsPlatform(platform) ? "npx.cmd" : "npx";
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function packageManagerCommand(platform = process.platform) {
|
|
285
|
+
return isWindowsPlatform(platform) ? "npm.cmd" : "npm";
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function commandExists(command, platform = process.platform) {
|
|
289
|
+
const result = isWindowsPlatform(platform)
|
|
290
|
+
? spawnSync("where.exe", [command], {
|
|
291
|
+
encoding: "utf8",
|
|
292
|
+
})
|
|
293
|
+
: spawnSync("sh", ["-lc", `command -v ${command}`], {
|
|
294
|
+
encoding: "utf8",
|
|
295
|
+
});
|
|
289
296
|
return result.status === 0;
|
|
290
297
|
}
|
|
291
298
|
|
|
299
|
+
function commandExistsDetails(command, platform = process.platform) {
|
|
300
|
+
const result = isWindowsPlatform(platform)
|
|
301
|
+
? spawnSync("where.exe", [command], {
|
|
302
|
+
encoding: "utf8",
|
|
303
|
+
})
|
|
304
|
+
: spawnSync("sh", ["-lc", `command -v ${command}`], {
|
|
305
|
+
encoding: "utf8",
|
|
306
|
+
});
|
|
307
|
+
return {
|
|
308
|
+
exists: result.status === 0,
|
|
309
|
+
stdout: (result.stdout || "").trim(),
|
|
310
|
+
platform,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function getMcpVersion() {
|
|
315
|
+
try {
|
|
316
|
+
const r = spawnSync(
|
|
317
|
+
packageManagerCommand(),
|
|
318
|
+
["view", "@sellable/mcp", "version"],
|
|
319
|
+
{
|
|
320
|
+
encoding: "utf8",
|
|
321
|
+
timeout: 5000,
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
if (r.status === 0 && r.stdout) return r.stdout.trim();
|
|
325
|
+
} catch {}
|
|
326
|
+
return "latest";
|
|
327
|
+
}
|
|
328
|
+
|
|
292
329
|
function authPath() {
|
|
293
330
|
return join(homedir(), ".sellable", "config.json");
|
|
294
331
|
}
|
|
@@ -420,7 +457,26 @@ function ensureSymlink(target, linkPath, opts) {
|
|
|
420
457
|
// ignore
|
|
421
458
|
}
|
|
422
459
|
const rel = relative(dirname(linkPath), target);
|
|
423
|
-
|
|
460
|
+
try {
|
|
461
|
+
symlinkSync(rel, linkPath, "dir");
|
|
462
|
+
} catch (err) {
|
|
463
|
+
const code = err && typeof err === "object" ? err.code : "";
|
|
464
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
465
|
+
const isDenied =
|
|
466
|
+
code === "EPERM" ||
|
|
467
|
+
code === "EACCES" ||
|
|
468
|
+
/privilege|permission|operation not permitted/i.test(message);
|
|
469
|
+
|
|
470
|
+
if (!isWindowsPlatform() || !isDenied) {
|
|
471
|
+
throw err;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
logVerbose(
|
|
475
|
+
`${C.grey}+ symlink denied on Windows; copying compatibility cache ${linkPath}${C.reset}`
|
|
476
|
+
);
|
|
477
|
+
rmSync(linkPath, { recursive: true, force: true });
|
|
478
|
+
cpSync(target, linkPath, { recursive: true, force: true });
|
|
479
|
+
}
|
|
424
480
|
}
|
|
425
481
|
|
|
426
482
|
function codexPluginManifest(opts) {
|
|
@@ -492,7 +548,7 @@ function codexPluginMcp(opts) {
|
|
|
492
548
|
mcpServers: {
|
|
493
549
|
sellable: {
|
|
494
550
|
type: "stdio",
|
|
495
|
-
command:
|
|
551
|
+
command: packageRunnerCommand(),
|
|
496
552
|
args: ["-y", opts.mcpPackage],
|
|
497
553
|
env: {
|
|
498
554
|
SELLABLE_WATCH_MODE_DRIVER: "codex",
|
|
@@ -608,8 +664,8 @@ instruction loading, file lookup, plugin cache versions, missing linked files,
|
|
|
608
664
|
or tool discovery. Start in product language:
|
|
609
665
|
|
|
610
666
|
\`\`\`text
|
|
611
|
-
I’ll help you launch this as a Sellable campaign. First I’ll
|
|
612
|
-
|
|
667
|
+
I’ll help you launch this as a Sellable campaign. First I’ll research the
|
|
668
|
+
person/company this campaign is for, then I’ll turn that into a campaign brief
|
|
613
669
|
before anything is created.
|
|
614
670
|
\`\`\`
|
|
615
671
|
|
|
@@ -655,10 +711,12 @@ should say:
|
|
|
655
711
|
- that approval authorizes scouting/search only, not lead import or sending
|
|
656
712
|
|
|
657
713
|
Do not surface blanket source heuristics as product copy. Make the
|
|
658
|
-
recommendation specific to the campaign. If
|
|
659
|
-
name the exact post themes you will search
|
|
660
|
-
|
|
661
|
-
|
|
714
|
+
recommendation specific to the campaign. If LinkedIn engagement is recommended,
|
|
715
|
+
name the exact post themes you will search and avoid using "Signal Discovery" in
|
|
716
|
+
customer-facing chat; that is the internal provider/app label. If relevant
|
|
717
|
+
public conversations look unlikely, recommend the specific Sales Nav or Prospeo
|
|
718
|
+
lane instead and say why. Do not call \`search_signals\`, \`search_sales_nav\`,
|
|
719
|
+
\`search_prospeo\`,
|
|
662
720
|
\`fetch_post_engagers\`, or provider-scoped subagents until the user approves this
|
|
663
721
|
source plan or explicitly chooses a different source.
|
|
664
722
|
|
|
@@ -677,9 +735,12 @@ precision, and referral paths, but it does not provide hiring-by-role filters;
|
|
|
677
735
|
say that distinction plainly in the source-plan gate.
|
|
678
736
|
|
|
679
737
|
After scouting, ask for a second approval on the concrete source action. For
|
|
680
|
-
|
|
681
|
-
engager/source-candidate volume, and the
|
|
682
|
-
|
|
738
|
+
LinkedIn engagement (\`signal-discovery\` internally), name how many recommended
|
|
739
|
+
posts will be scraped, the target engager/source-candidate volume, and the
|
|
740
|
+
internal campaign-table execution-slice size. N must be the smallest
|
|
741
|
+
right-content post set that clears the source target, not the default 3
|
|
742
|
+
promoted sample posts. For Sales Nav or Prospeo, name the specific approved
|
|
743
|
+
import lane and source lead count.
|
|
683
744
|
Do not call \`import_leads\` or \`confirm_lead_list\` until this second approval is
|
|
684
745
|
granted.
|
|
685
746
|
|
|
@@ -838,10 +899,10 @@ customer-facing progress copy.
|
|
|
838
899
|
|
|
839
900
|
Do not treat the active Sellable workspace as the campaign subject. The
|
|
840
901
|
workspace only tells you where the campaign will be saved. Before buyer, CTA,
|
|
841
|
-
proof, or source questions, identify the
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
\`
|
|
902
|
+
proof, or source questions, identify the person/profile or company this
|
|
903
|
+
campaign is for, plus enough current company/product context to build the
|
|
904
|
+
brief. This client/company lookup feeds \`clientProspectId\` or
|
|
905
|
+
\`senderLinkedinUrl\`; it is not a connected-sender check.
|
|
845
906
|
|
|
846
907
|
Do not call \`mcp__sellable__list_senders\`, \`mcp__sellable__get_sender\`, or
|
|
847
908
|
surface connected/missing sender state during setup, brief, source, filter, or
|
|
@@ -865,19 +926,20 @@ first:
|
|
|
865
926
|
only if a URL/domain is also available.
|
|
866
927
|
|
|
867
928
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
868
|
-
the
|
|
869
|
-
availability in this confirmation.
|
|
929
|
+
the current company/focus before continuing, especially if public website data
|
|
930
|
+
may be stale. Do not mention connected sender availability in this confirmation.
|
|
870
931
|
|
|
871
932
|
If the user did not provide the launch identity, ask in normal chat for the
|
|
872
|
-
LinkedIn profile
|
|
933
|
+
LinkedIn profile URL first, with the company website as the fallback. Do not ask
|
|
873
934
|
them to choose an input type with the structured question tool:
|
|
874
935
|
|
|
875
936
|
\`\`\`text
|
|
876
937
|
I’m ready to build this in {workspace}.
|
|
877
938
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
the target, offer, proof, and
|
|
939
|
+
What is your LinkedIn profile URL? If you do not have it handy, send your
|
|
940
|
+
company website instead. I’ll research the person and company from that, then
|
|
941
|
+
ask you to correct anything stale before we pick the target, offer, proof, and
|
|
942
|
+
lead source.
|
|
881
943
|
\`\`\`
|
|
882
944
|
|
|
883
945
|
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
|
|
@@ -887,18 +949,28 @@ most recent company from the profile. For a company website, call
|
|
|
887
949
|
LinkedIn profile URL is available, retain it as \`senderLinkedinUrl\` for
|
|
888
950
|
\`create_campaign\`; if a \`clientProspectId\` is available, pass that instead.
|
|
889
951
|
|
|
890
|
-
After the user confirms the
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
952
|
+
After the user confirms the company/focus, run one lightweight company lookup
|
|
953
|
+
if it has not already run, then ask an offer-readiness question before inferred
|
|
954
|
+
strategy hardens:
|
|
955
|
+
|
|
956
|
+
\`\`\`text
|
|
957
|
+
Do you already know the offer for this campaign, should I use the researched
|
|
958
|
+
recommendation, or should we shape the offer together? If the website is stale,
|
|
959
|
+
tell me what is current before I build the brief.
|
|
960
|
+
\`\`\`
|
|
961
|
+
|
|
962
|
+
The setup questions should use the confirmed company context so they do not feel
|
|
963
|
+
generic. When you present a recommendation, introduce it as based on the
|
|
964
|
+
research you just did and keep it editable.
|
|
894
965
|
|
|
895
966
|
Before the identity gate, use this customer-facing shape:
|
|
896
967
|
|
|
897
968
|
\`\`\`text
|
|
898
969
|
I’m ready to build the campaign in {workspace}.
|
|
899
970
|
|
|
900
|
-
First I’ll
|
|
901
|
-
context to
|
|
971
|
+
First I’ll research the person/company this campaign is for. I’ll use that
|
|
972
|
+
context to recommend a target, offer, proof, and lead source, then you can
|
|
973
|
+
correct anything stale before I build from it.
|
|
902
974
|
|
|
903
975
|
Then I’ll turn that into a campaign brief for you to approve before anything is created.
|
|
904
976
|
\`\`\`
|
|
@@ -1266,17 +1338,17 @@ show you the draft next so you can approve it or change it.
|
|
|
1266
1338
|
Good opening:
|
|
1267
1339
|
|
|
1268
1340
|
\`\`\`text
|
|
1269
|
-
I’ll help you launch this as a Sellable campaign. First I’ll
|
|
1270
|
-
|
|
1271
|
-
|
|
1341
|
+
I’ll help you launch this as a Sellable campaign. First I’ll research the
|
|
1342
|
+
person/company this is for, then I’ll turn that into a campaign brief before
|
|
1343
|
+
any leads are imported or anything can send.
|
|
1272
1344
|
\`\`\`
|
|
1273
1345
|
|
|
1274
1346
|
Good identity setup:
|
|
1275
1347
|
|
|
1276
1348
|
\`\`\`text
|
|
1277
|
-
I’ll
|
|
1278
|
-
|
|
1279
|
-
|
|
1349
|
+
I’ll ask for the LinkedIn profile URL first, with the company website as a
|
|
1350
|
+
fallback. Then I’ll show the researched recommendation and you can correct
|
|
1351
|
+
anything stale before we pick the target, offer, proof, and lead source.
|
|
1280
1352
|
\`\`\`
|
|
1281
1353
|
|
|
1282
1354
|
Bad:
|
|
@@ -1767,7 +1839,7 @@ function withWatchModeDriver(command, args, driver) {
|
|
|
1767
1839
|
|
|
1768
1840
|
function mcpCommand(opts) {
|
|
1769
1841
|
if (opts.server === "package") {
|
|
1770
|
-
return [
|
|
1842
|
+
return [packageRunnerCommand(), ["-y", opts.mcpPackage]];
|
|
1771
1843
|
}
|
|
1772
1844
|
if (opts.server === "local") {
|
|
1773
1845
|
if (!opts.localCommand) {
|
|
@@ -1789,6 +1861,33 @@ function mcpCommandForHost(opts, driver) {
|
|
|
1789
1861
|
return withWatchModeDriver(command, args, driver);
|
|
1790
1862
|
}
|
|
1791
1863
|
|
|
1864
|
+
function codexMcpAddArgs(opts) {
|
|
1865
|
+
const [command, args] = mcpCommand(opts);
|
|
1866
|
+
if (command === "hosted") {
|
|
1867
|
+
return ["mcp", "add", "sellable", "--url", args[0]];
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
if (isWindowsPlatform()) {
|
|
1871
|
+
return [
|
|
1872
|
+
"mcp",
|
|
1873
|
+
"add",
|
|
1874
|
+
"sellable",
|
|
1875
|
+
"--env",
|
|
1876
|
+
WATCH_MODE_DRIVER_ENV.codex,
|
|
1877
|
+
"--",
|
|
1878
|
+
command,
|
|
1879
|
+
...args,
|
|
1880
|
+
];
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
const [wrappedCommand, wrappedArgs] = withWatchModeDriver(
|
|
1884
|
+
command,
|
|
1885
|
+
args,
|
|
1886
|
+
"codex"
|
|
1887
|
+
);
|
|
1888
|
+
return ["mcp", "add", "sellable", "--", wrappedCommand, ...wrappedArgs];
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1792
1891
|
function installClaude(opts) {
|
|
1793
1892
|
if (!commandExists("claude")) {
|
|
1794
1893
|
const message =
|
|
@@ -1887,17 +1986,16 @@ function installCodex(opts) {
|
|
|
1887
1986
|
throw new Error(message);
|
|
1888
1987
|
}
|
|
1889
1988
|
if (opts.server === "hosted") {
|
|
1890
|
-
run("codex",
|
|
1989
|
+
run("codex", codexMcpAddArgs(opts), opts);
|
|
1891
1990
|
const info = installCodexDesktopPlugin(opts);
|
|
1892
1991
|
return { installed: true, ...info };
|
|
1893
1992
|
}
|
|
1894
|
-
const [command, args] = mcpCommandForHost(opts, "codex");
|
|
1895
1993
|
run("codex", ["mcp", "remove", "sellable"], {
|
|
1896
1994
|
...opts,
|
|
1897
1995
|
dryRun: opts.dryRun,
|
|
1898
1996
|
allowFail: true,
|
|
1899
1997
|
});
|
|
1900
|
-
run("codex",
|
|
1998
|
+
run("codex", codexMcpAddArgs(opts), opts);
|
|
1901
1999
|
const info = installCodexDesktopPlugin(opts);
|
|
1902
2000
|
return { installed: true, ...info };
|
|
1903
2001
|
}
|
package/package.json
CHANGED
|
@@ -86,8 +86,8 @@ instruction loading, file lookup, plugin cache versions, missing linked files,
|
|
|
86
86
|
or tool discovery. Start in product language:
|
|
87
87
|
|
|
88
88
|
```text
|
|
89
|
-
I’ll help you launch this as a Sellable campaign. First I’ll
|
|
90
|
-
|
|
89
|
+
I’ll help you launch this as a Sellable campaign. First I’ll research the
|
|
90
|
+
person/company this campaign is for, then I’ll turn that into a campaign brief
|
|
91
91
|
before we move into lead sourcing.
|
|
92
92
|
```
|
|
93
93
|
|
|
@@ -139,10 +139,12 @@ should say:
|
|
|
139
139
|
- what approval covers in one concise line
|
|
140
140
|
|
|
141
141
|
Do not surface blanket source heuristics as product copy. Make the
|
|
142
|
-
recommendation specific to the campaign. If
|
|
143
|
-
name the exact post themes you will search
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
recommendation specific to the campaign. If LinkedIn engagement is recommended,
|
|
143
|
+
name the exact post themes you will search and avoid using "Signal Discovery" in
|
|
144
|
+
customer-facing chat; that is the internal provider/app label. If relevant
|
|
145
|
+
public conversations look unlikely, recommend the specific Sales Nav or Prospeo
|
|
146
|
+
lane instead and say why. Do not call `search_signals`, `search_sales_nav`,
|
|
147
|
+
`search_prospeo`,
|
|
146
148
|
`fetch_post_engagers`, or provider-scoped subagents until the user approves this
|
|
147
149
|
source plan or explicitly chooses a different source.
|
|
148
150
|
|
|
@@ -161,10 +163,13 @@ precision, and referral paths, but it does not provide hiring-by-role filters;
|
|
|
161
163
|
say that distinction plainly in the source-plan gate.
|
|
162
164
|
|
|
163
165
|
After scouting, ask for a second approval on the concrete source action. For
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
LinkedIn engagement (`signal-discovery` internally), name how many
|
|
167
|
+
recommended posts will be scraped and the target engager/source-candidate
|
|
168
|
+
volume. N must be the smallest right-content post set that clears the source
|
|
169
|
+
target, not the default 3 promoted sample posts. For Sales Nav or Prospeo,
|
|
170
|
+
name the specific approved import lane and source lead count. Keep the
|
|
171
|
+
internal 15-row campaign-table execution slice separate from source
|
|
172
|
+
sampling.
|
|
168
173
|
|
|
169
174
|
Do not call `import_leads` or `confirm_lead_list` until this second approval is
|
|
170
175
|
granted.
|
|
@@ -181,16 +186,15 @@ granted.
|
|
|
181
186
|
should `confirm_lead_list({ reviewBatchLimit: 15 })` copy confirmed rows into
|
|
182
187
|
the campaign table and return the initial campaign-table execution slice rows.
|
|
183
188
|
|
|
184
|
-
For
|
|
185
|
-
action shape "Approve scraping N
|
|
186
|
-
should be a compact `## Source Recommendation` block with:
|
|
189
|
+
For LinkedIn engagement, the customer-facing approval card must use the exact
|
|
190
|
+
action shape "Approve scraping N recommended LinkedIn posts?" and the chat
|
|
191
|
+
summary should be a compact `## Source Recommendation` block with:
|
|
187
192
|
|
|
188
|
-
- goal: about 300 headline-fit prospects
|
|
189
|
-
headline criteria for now
|
|
193
|
+
- goal: about 300 headline-fit prospects from relevant LinkedIn engagement
|
|
190
194
|
- source-candidate plan: use sample math first: target headline-fit prospects
|
|
191
195
|
divided by sampled headline-pass rate. If there is no stronger sample, use
|
|
192
196
|
about 1,500 raw engagers from the 20% working headline-pass assumption.
|
|
193
|
-
- planning floor: continue with
|
|
197
|
+
- planning floor: continue with LinkedIn engagement only when sampled/projected
|
|
194
198
|
headline-fit rate is at least 10%; below that, move to Sales Nav recent
|
|
195
199
|
activity instead of scraping noisy engagers. Do not use the 10% floor as the
|
|
196
200
|
scrape-count denominator when the actual sample rate is higher.
|
|
@@ -394,10 +398,10 @@ customer-facing progress copy.
|
|
|
394
398
|
|
|
395
399
|
Do not treat the active Sellable workspace as the campaign subject. The
|
|
396
400
|
workspace only tells you where the campaign will be saved. Before buyer, CTA,
|
|
397
|
-
proof, or source questions, identify the
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
`
|
|
401
|
+
proof, or source questions, identify the person/profile or company this
|
|
402
|
+
campaign is for, plus enough current company/product context to build the
|
|
403
|
+
brief. This client/company lookup feeds `clientProspectId` or
|
|
404
|
+
`senderLinkedinUrl`; it is not a connected-sender check.
|
|
401
405
|
|
|
402
406
|
Do not call `mcp__sellable__list_senders`, `mcp__sellable__get_sender`, or
|
|
403
407
|
surface connected/missing sender state during setup, brief, source, filter, or
|
|
@@ -421,19 +425,20 @@ first:
|
|
|
421
425
|
only if a URL/domain is also available.
|
|
422
426
|
|
|
423
427
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
424
|
-
the
|
|
425
|
-
availability in this confirmation.
|
|
428
|
+
the current company/focus before continuing, especially if public website data
|
|
429
|
+
may be stale. Do not mention connected sender availability in this confirmation.
|
|
426
430
|
|
|
427
431
|
If the user did not provide the launch identity, ask in normal chat for the
|
|
428
|
-
LinkedIn profile
|
|
432
|
+
LinkedIn profile URL first, with the company website as the fallback. Do not ask
|
|
429
433
|
them to choose an input type with the structured question tool:
|
|
430
434
|
|
|
431
435
|
```text
|
|
432
436
|
I’m ready to build this in {workspace}.
|
|
433
437
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
the target, offer, proof, and
|
|
438
|
+
What is your LinkedIn profile URL? If you do not have it handy, send your
|
|
439
|
+
company website instead. I’ll research the person and company from that, then
|
|
440
|
+
ask you to correct anything stale before we pick the target, offer, proof, and
|
|
441
|
+
lead source.
|
|
437
442
|
```
|
|
438
443
|
|
|
439
444
|
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
|
|
@@ -443,10 +448,19 @@ most recent company from the profile. For a company website, call
|
|
|
443
448
|
LinkedIn profile URL is available, retain it as `senderLinkedinUrl` for
|
|
444
449
|
`create_campaign`; if a `clientProspectId` is available, pass that instead.
|
|
445
450
|
|
|
446
|
-
After the user confirms the
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
451
|
+
After the user confirms the company/focus, run one lightweight company lookup
|
|
452
|
+
if it has not already run, then ask an offer-readiness question before inferred
|
|
453
|
+
strategy hardens:
|
|
454
|
+
|
|
455
|
+
```text
|
|
456
|
+
Do you already know the offer for this campaign, should I use the researched
|
|
457
|
+
recommendation, or should we shape the offer together? If the website is stale,
|
|
458
|
+
tell me what is current before I build the brief.
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
The setup questions should use the confirmed company context so they do not feel
|
|
462
|
+
generic. When you present a recommendation, introduce it as based on the
|
|
463
|
+
research you just did and keep it editable.
|
|
450
464
|
|
|
451
465
|
### Sufficient Intake Bypass
|
|
452
466
|
|
|
@@ -474,9 +488,9 @@ If the invocation or any later user message explicitly asks for "yolo mode",
|
|
|
474
488
|
me", "use best estimates", or "just run it", enable YOLO mode for the rest of
|
|
475
489
|
the run. Treat YOLO as `interactionMode: "autonomous"` plus an intake policy:
|
|
476
490
|
|
|
477
|
-
- If campaign
|
|
478
|
-
website in normal chat; do not ask buyer,
|
|
479
|
-
questions before that.
|
|
491
|
+
- If the campaign subject is missing, ask only for the LinkedIn profile URL
|
|
492
|
+
first, with company website as the fallback, in normal chat; do not ask buyer,
|
|
493
|
+
offer, proof, source, or filter setup questions before that.
|
|
480
494
|
- Treat any freeform directions already provided, or added later by the user, as
|
|
481
495
|
operator directions for the rest of the run. If directions conflict, the newest
|
|
482
496
|
user direction wins.
|
|
@@ -498,8 +512,9 @@ Before the identity gate, use this customer-facing shape:
|
|
|
498
512
|
```text
|
|
499
513
|
I’m ready to build the campaign in {workspace}.
|
|
500
514
|
|
|
501
|
-
First I’ll
|
|
502
|
-
context to
|
|
515
|
+
First I’ll research the person/company this campaign is for. I’ll use that
|
|
516
|
+
context to recommend a target, offer, proof, and lead source, then you can
|
|
517
|
+
correct anything stale before I build from it.
|
|
503
518
|
|
|
504
519
|
Then I’ll turn that into a campaign brief for you to approve before any leads
|
|
505
520
|
are sourced.
|
|
@@ -634,9 +649,9 @@ updates.
|
|
|
634
649
|
```text
|
|
635
650
|
You're in — {activeWorkspaceName} workspace, ready to roll.
|
|
636
651
|
|
|
637
|
-
|
|
652
|
+
Now — what is your LinkedIn profile URL? If you do not have it handy, send your company website instead. I’ll research the person and company from that, then ask you to correct anything stale before we pick the target, offer, proof, and lead source.
|
|
638
653
|
|
|
639
|
-
|
|
654
|
+
e.g. https://www.linkedin.com/in/client-handle or https://example.com
|
|
640
655
|
```
|
|
641
656
|
|
|
642
657
|
- If `isReturningUser === false`, prepend ONE line confirming the new
|
|
@@ -645,9 +660,9 @@ updates.
|
|
|
645
660
|
```text
|
|
646
661
|
You're set up — your {activeWorkspaceName} workspace is ready.
|
|
647
662
|
|
|
648
|
-
|
|
663
|
+
Now — what is your LinkedIn profile URL? If you do not have it handy, send your company website instead. I’ll research the person and company from that, then ask you to correct anything stale before we pick the target, offer, proof, and lead source.
|
|
649
664
|
|
|
650
|
-
|
|
665
|
+
e.g. https://www.linkedin.com/in/client-handle or https://example.com
|
|
651
666
|
```
|
|
652
667
|
|
|
653
668
|
No other lines. No "all set", no "signed in", no other acknowledgement.
|