@sellable/install 0.1.121 → 0.1.123
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
|
|
|
@@ -679,10 +735,12 @@ precision, and referral paths, but it does not provide hiring-by-role filters;
|
|
|
679
735
|
say that distinction plainly in the source-plan gate.
|
|
680
736
|
|
|
681
737
|
After scouting, ask for a second approval on the concrete source action. For
|
|
682
|
-
LinkedIn engagement (\`signal-discovery\` internally), name how many
|
|
738
|
+
LinkedIn engagement (\`signal-discovery\` internally), name how many recommended
|
|
683
739
|
posts will be scraped, the target engager/source-candidate volume, and the
|
|
684
|
-
internal campaign-table execution-slice size.
|
|
685
|
-
|
|
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.
|
|
686
744
|
Do not call \`import_leads\` or \`confirm_lead_list\` until this second approval is
|
|
687
745
|
granted.
|
|
688
746
|
|
|
@@ -841,10 +899,10 @@ customer-facing progress copy.
|
|
|
841
899
|
|
|
842
900
|
Do not treat the active Sellable workspace as the campaign subject. The
|
|
843
901
|
workspace only tells you where the campaign will be saved. Before buyer, CTA,
|
|
844
|
-
proof, or source questions, identify the
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
\`
|
|
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.
|
|
848
906
|
|
|
849
907
|
Do not call \`mcp__sellable__list_senders\`, \`mcp__sellable__get_sender\`, or
|
|
850
908
|
surface connected/missing sender state during setup, brief, source, filter, or
|
|
@@ -868,19 +926,20 @@ first:
|
|
|
868
926
|
only if a URL/domain is also available.
|
|
869
927
|
|
|
870
928
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
871
|
-
the
|
|
872
|
-
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.
|
|
873
931
|
|
|
874
932
|
If the user did not provide the launch identity, ask in normal chat for the
|
|
875
|
-
LinkedIn profile
|
|
933
|
+
LinkedIn profile URL first, with the company website as the fallback. Do not ask
|
|
876
934
|
them to choose an input type with the structured question tool:
|
|
877
935
|
|
|
878
936
|
\`\`\`text
|
|
879
937
|
I’m ready to build this in {workspace}.
|
|
880
938
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
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.
|
|
884
943
|
\`\`\`
|
|
885
944
|
|
|
886
945
|
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
|
|
@@ -890,18 +949,28 @@ most recent company from the profile. For a company website, call
|
|
|
890
949
|
LinkedIn profile URL is available, retain it as \`senderLinkedinUrl\` for
|
|
891
950
|
\`create_campaign\`; if a \`clientProspectId\` is available, pass that instead.
|
|
892
951
|
|
|
893
|
-
After the user confirms the
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
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.
|
|
897
965
|
|
|
898
966
|
Before the identity gate, use this customer-facing shape:
|
|
899
967
|
|
|
900
968
|
\`\`\`text
|
|
901
969
|
I’m ready to build the campaign in {workspace}.
|
|
902
970
|
|
|
903
|
-
First I’ll
|
|
904
|
-
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.
|
|
905
974
|
|
|
906
975
|
Then I’ll turn that into a campaign brief for you to approve before anything is created.
|
|
907
976
|
\`\`\`
|
|
@@ -1269,17 +1338,17 @@ show you the draft next so you can approve it or change it.
|
|
|
1269
1338
|
Good opening:
|
|
1270
1339
|
|
|
1271
1340
|
\`\`\`text
|
|
1272
|
-
I’ll help you launch this as a Sellable campaign. First I’ll
|
|
1273
|
-
|
|
1274
|
-
|
|
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.
|
|
1275
1344
|
\`\`\`
|
|
1276
1345
|
|
|
1277
1346
|
Good identity setup:
|
|
1278
1347
|
|
|
1279
1348
|
\`\`\`text
|
|
1280
|
-
I’ll
|
|
1281
|
-
|
|
1282
|
-
|
|
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.
|
|
1283
1352
|
\`\`\`
|
|
1284
1353
|
|
|
1285
1354
|
Bad:
|
|
@@ -1770,7 +1839,7 @@ function withWatchModeDriver(command, args, driver) {
|
|
|
1770
1839
|
|
|
1771
1840
|
function mcpCommand(opts) {
|
|
1772
1841
|
if (opts.server === "package") {
|
|
1773
|
-
return [
|
|
1842
|
+
return [packageRunnerCommand(), ["-y", opts.mcpPackage]];
|
|
1774
1843
|
}
|
|
1775
1844
|
if (opts.server === "local") {
|
|
1776
1845
|
if (!opts.localCommand) {
|
|
@@ -1792,6 +1861,33 @@ function mcpCommandForHost(opts, driver) {
|
|
|
1792
1861
|
return withWatchModeDriver(command, args, driver);
|
|
1793
1862
|
}
|
|
1794
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
|
+
|
|
1795
1891
|
function installClaude(opts) {
|
|
1796
1892
|
if (!commandExists("claude")) {
|
|
1797
1893
|
const message =
|
|
@@ -1890,17 +1986,16 @@ function installCodex(opts) {
|
|
|
1890
1986
|
throw new Error(message);
|
|
1891
1987
|
}
|
|
1892
1988
|
if (opts.server === "hosted") {
|
|
1893
|
-
run("codex",
|
|
1989
|
+
run("codex", codexMcpAddArgs(opts), opts);
|
|
1894
1990
|
const info = installCodexDesktopPlugin(opts);
|
|
1895
1991
|
return { installed: true, ...info };
|
|
1896
1992
|
}
|
|
1897
|
-
const [command, args] = mcpCommandForHost(opts, "codex");
|
|
1898
1993
|
run("codex", ["mcp", "remove", "sellable"], {
|
|
1899
1994
|
...opts,
|
|
1900
1995
|
dryRun: opts.dryRun,
|
|
1901
1996
|
allowFail: true,
|
|
1902
1997
|
});
|
|
1903
|
-
run("codex",
|
|
1998
|
+
run("codex", codexMcpAddArgs(opts), opts);
|
|
1904
1999
|
const info = installCodexDesktopPlugin(opts);
|
|
1905
2000
|
return { installed: true, ...info };
|
|
1906
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
|
|
|
@@ -163,11 +163,13 @@ precision, and referral paths, but it does not provide hiring-by-role filters;
|
|
|
163
163
|
say that distinction plainly in the source-plan gate.
|
|
164
164
|
|
|
165
165
|
After scouting, ask for a second approval on the concrete source action. For
|
|
166
|
-
LinkedIn engagement (`signal-discovery` internally), name how many
|
|
167
|
-
posts will be scraped and the target engager/source-candidate
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
source
|
|
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.
|
|
171
173
|
|
|
172
174
|
Do not call `import_leads` or `confirm_lead_list` until this second approval is
|
|
173
175
|
granted.
|
|
@@ -185,8 +187,8 @@ granted.
|
|
|
185
187
|
the campaign table and return the initial campaign-table execution slice rows.
|
|
186
188
|
|
|
187
189
|
For LinkedIn engagement, the customer-facing approval card must use the exact
|
|
188
|
-
action shape "Approve scraping N
|
|
189
|
-
should be a compact `## Source Recommendation` block with:
|
|
190
|
+
action shape "Approve scraping N recommended LinkedIn posts?" and the chat
|
|
191
|
+
summary should be a compact `## Source Recommendation` block with:
|
|
190
192
|
|
|
191
193
|
- goal: about 300 headline-fit prospects from relevant LinkedIn engagement
|
|
192
194
|
- source-candidate plan: use sample math first: target headline-fit prospects
|
|
@@ -396,10 +398,10 @@ customer-facing progress copy.
|
|
|
396
398
|
|
|
397
399
|
Do not treat the active Sellable workspace as the campaign subject. The
|
|
398
400
|
workspace only tells you where the campaign will be saved. Before buyer, CTA,
|
|
399
|
-
proof, or source questions, identify the
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
`
|
|
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.
|
|
403
405
|
|
|
404
406
|
Do not call `mcp__sellable__list_senders`, `mcp__sellable__get_sender`, or
|
|
405
407
|
surface connected/missing sender state during setup, brief, source, filter, or
|
|
@@ -423,19 +425,20 @@ first:
|
|
|
423
425
|
only if a URL/domain is also available.
|
|
424
426
|
|
|
425
427
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
426
|
-
the
|
|
427
|
-
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.
|
|
428
430
|
|
|
429
431
|
If the user did not provide the launch identity, ask in normal chat for the
|
|
430
|
-
LinkedIn profile
|
|
432
|
+
LinkedIn profile URL first, with the company website as the fallback. Do not ask
|
|
431
433
|
them to choose an input type with the structured question tool:
|
|
432
434
|
|
|
433
435
|
```text
|
|
434
436
|
I’m ready to build this in {workspace}.
|
|
435
437
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
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.
|
|
439
442
|
```
|
|
440
443
|
|
|
441
444
|
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
|
|
@@ -445,10 +448,19 @@ most recent company from the profile. For a company website, call
|
|
|
445
448
|
LinkedIn profile URL is available, retain it as `senderLinkedinUrl` for
|
|
446
449
|
`create_campaign`; if a `clientProspectId` is available, pass that instead.
|
|
447
450
|
|
|
448
|
-
After the user confirms the
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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.
|
|
452
464
|
|
|
453
465
|
### Sufficient Intake Bypass
|
|
454
466
|
|
|
@@ -476,9 +488,9 @@ If the invocation or any later user message explicitly asks for "yolo mode",
|
|
|
476
488
|
me", "use best estimates", or "just run it", enable YOLO mode for the rest of
|
|
477
489
|
the run. Treat YOLO as `interactionMode: "autonomous"` plus an intake policy:
|
|
478
490
|
|
|
479
|
-
- If campaign
|
|
480
|
-
website in normal chat; do not ask buyer,
|
|
481
|
-
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.
|
|
482
494
|
- Treat any freeform directions already provided, or added later by the user, as
|
|
483
495
|
operator directions for the rest of the run. If directions conflict, the newest
|
|
484
496
|
user direction wins.
|
|
@@ -500,8 +512,9 @@ Before the identity gate, use this customer-facing shape:
|
|
|
500
512
|
```text
|
|
501
513
|
I’m ready to build the campaign in {workspace}.
|
|
502
514
|
|
|
503
|
-
First I’ll
|
|
504
|
-
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.
|
|
505
518
|
|
|
506
519
|
Then I’ll turn that into a campaign brief for you to approve before any leads
|
|
507
520
|
are sourced.
|
|
@@ -636,9 +649,9 @@ updates.
|
|
|
636
649
|
```text
|
|
637
650
|
You're in — {activeWorkspaceName} workspace, ready to roll.
|
|
638
651
|
|
|
639
|
-
|
|
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.
|
|
640
653
|
|
|
641
|
-
|
|
654
|
+
e.g. https://www.linkedin.com/in/client-handle or https://example.com
|
|
642
655
|
```
|
|
643
656
|
|
|
644
657
|
- If `isReturningUser === false`, prepend ONE line confirming the new
|
|
@@ -647,9 +660,9 @@ updates.
|
|
|
647
660
|
```text
|
|
648
661
|
You're set up — your {activeWorkspaceName} workspace is ready.
|
|
649
662
|
|
|
650
|
-
|
|
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.
|
|
651
664
|
|
|
652
|
-
|
|
665
|
+
e.g. https://www.linkedin.com/in/client-handle or https://example.com
|
|
653
666
|
```
|
|
654
667
|
|
|
655
668
|
No other lines. No "all set", no "signed in", no other acknowledgement.
|