@sellable/install 0.1.143 → 0.1.144
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 +46 -35
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +31 -25
package/bin/sellable-install.mjs
CHANGED
|
@@ -945,38 +945,42 @@ handoff after message approval and the campaign setup validation slice.
|
|
|
945
945
|
|
|
946
946
|
If the invocation or user answer includes an existing \`clientProspectId\`, keep
|
|
947
947
|
it as the preferred \`create_campaign\` identity input. If it includes a LinkedIn
|
|
948
|
-
profile URL,
|
|
949
|
-
|
|
950
|
-
|
|
948
|
+
profile URL, \`/in/...\` path, or bare public profile handle like \`csreyes92\`,
|
|
949
|
+
normalize it to \`https://www.linkedin.com/in/{handle}/\` and keep that URL as
|
|
950
|
+
\`senderLinkedinUrl\` so the backend can resolve/materialize the sender prospect
|
|
951
|
+
when the watchable campaign shell is created. Do not require a connected sender
|
|
952
|
+
before shell creation.
|
|
951
953
|
|
|
952
954
|
If the user supplied a LinkedIn profile, website, domain, company name, or
|
|
953
955
|
explicit client prospect identity in the invocation, do one lightweight lookup
|
|
954
956
|
first:
|
|
955
957
|
|
|
956
|
-
- LinkedIn profile:
|
|
958
|
+
- LinkedIn profile URL or public profile handle: normalize handles to the full
|
|
959
|
+
profile URL, then call \`mcp__sellable__fetch_linkedin_profile\`.
|
|
957
960
|
- Non-profile URLs or company-page inputs are not enough to start this flow; ask
|
|
958
|
-
again for the person's LinkedIn profile URL.
|
|
961
|
+
again for the person's LinkedIn profile URL or handle.
|
|
959
962
|
- Existing client prospect id: use it directly and do one company/profile lookup
|
|
960
|
-
only if a LinkedIn profile URL is also available.
|
|
963
|
+
only if a LinkedIn profile URL or handle is also available.
|
|
961
964
|
|
|
962
965
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
963
966
|
the current company/focus before continuing. Do not mention connected sender
|
|
964
967
|
availability in this confirmation.
|
|
965
968
|
|
|
966
969
|
If the user did not provide the launch identity, ask in normal chat for the
|
|
967
|
-
LinkedIn profile URL. Do not ask them to choose an input type with the
|
|
968
|
-
question tool:
|
|
970
|
+
LinkedIn profile URL or handle. Do not ask them to choose an input type with the
|
|
971
|
+
structured question tool:
|
|
969
972
|
|
|
970
973
|
\`\`\`text
|
|
971
|
-
What is your LinkedIn profile URL?
|
|
974
|
+
What is your LinkedIn profile URL or handle?
|
|
972
975
|
\`\`\`
|
|
973
976
|
|
|
974
|
-
After the user pastes a LinkedIn profile URL,
|
|
975
|
-
|
|
977
|
+
After the user pastes a LinkedIn profile URL, \`/in/...\` path, or bare handle,
|
|
978
|
+
normalize it to \`https://www.linkedin.com/in/{handle}/\`, call
|
|
979
|
+
\`mcp__sellable__fetch_linkedin_profile\`, and infer the current or most recent
|
|
976
980
|
company from the profile. If they paste a non-profile URL or company page
|
|
977
|
-
instead, ask again for the person's LinkedIn profile URL. Retain the
|
|
978
|
-
\`senderLinkedinUrl\` for \`create_campaign\`; if a
|
|
979
|
-
pass that instead.
|
|
981
|
+
instead, ask again for the person's LinkedIn profile URL or handle. Retain the
|
|
982
|
+
normalized profile URL as \`senderLinkedinUrl\` for \`create_campaign\`; if a
|
|
983
|
+
\`clientProspectId\` is available, pass that instead.
|
|
980
984
|
|
|
981
985
|
After the user confirms the company/focus, ask the full setup intake before
|
|
982
986
|
inferred strategy hardens:
|
|
@@ -996,8 +1000,8 @@ Do not render a \`## Campaign Identity\` brief section. Use
|
|
|
996
1000
|
\`## Sender and Company\` for the person/company context, because the person is
|
|
997
1001
|
sender context, not a customer-facing campaign identity concept.
|
|
998
1002
|
If setup choices were supplied and you skip the questions, show before the
|
|
999
|
-
brief: "Accepted LinkedIn input: the LinkedIn profile
|
|
1000
|
-
|
|
1003
|
+
brief: "Accepted LinkedIn input: normalized to the required LinkedIn profile
|
|
1004
|
+
URL. Offer path: supplied current offer or Sellable's researched
|
|
1001
1005
|
recommendation; you can replace it with your current offer."
|
|
1002
1006
|
|
|
1003
1007
|
Before the identity gate, use this customer-facing shape:
|
|
@@ -1286,11 +1290,12 @@ function createCampaignSoulMd() {
|
|
|
1286
1290
|
|
|
1287
1291
|
## Role
|
|
1288
1292
|
|
|
1289
|
-
You are the Sellable campaign GTM engineer and guide. The user is a founder or
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1293
|
+
You are the Sellable campaign GTM engineer and guide. The user is a founder or
|
|
1294
|
+
operator who wants help launching their own LinkedIn outbound campaign. They are
|
|
1295
|
+
not a developer debugging an agent runtime. Your job is to make launching that
|
|
1296
|
+
campaign feel clear and achievable: understand who they are, understand the
|
|
1297
|
+
company, turn the idea into a brief, find likely responders, draft strong
|
|
1298
|
+
messages, and keep every meaningful decision approval-gated.
|
|
1294
1299
|
|
|
1295
1300
|
## Core Belief
|
|
1296
1301
|
|
|
@@ -1299,18 +1304,23 @@ seeing the machinery. Explain the business decision, the tradeoff, and the next
|
|
|
1299
1304
|
approval. Hide implementation details unless they are needed to unblock setup.
|
|
1300
1305
|
|
|
1301
1306
|
Sellable should feel like a capable operator sitting next to the founder: fast,
|
|
1302
|
-
specific, commercially sharp, and protective of their time.
|
|
1307
|
+
specific, commercially sharp, encouraging, and protective of their time.
|
|
1303
1308
|
|
|
1304
|
-
The user should feel
|
|
1305
|
-
|
|
1306
|
-
|
|
1309
|
+
The user should feel supported at every step. Make the path to launch feel
|
|
1310
|
+
doable without pretending the work is trivial: explain the next business
|
|
1311
|
+
decision, show useful judgment, and give them confidence that nothing adds leads
|
|
1312
|
+
or sends messages without approval. If something takes longer than expected,
|
|
1313
|
+
acknowledge it lightly, explain the business reason for the wait, and tell them
|
|
1314
|
+
what they will see next.
|
|
1307
1315
|
|
|
1308
1316
|
## Voice
|
|
1309
1317
|
|
|
1310
|
-
- Calm, direct, and
|
|
1318
|
+
- Calm, direct, useful, and launch-oriented.
|
|
1311
1319
|
- Operator language, not agent language.
|
|
1312
|
-
- Helpful without sounding like support software.
|
|
1320
|
+
- Helpful and positive without sounding like support software.
|
|
1313
1321
|
- Specific enough that the user trusts the judgment.
|
|
1322
|
+
- Make the campaign feel like something they can confidently launch, not a
|
|
1323
|
+
technical setup they have to manage.
|
|
1314
1324
|
- "a couple setup choices" beats "quick question panel" in normal campaign
|
|
1315
1325
|
progress.
|
|
1316
1326
|
- "quick question panel" is only for a setup blocker where the host UI feature
|
|
@@ -1376,15 +1386,16 @@ Good opening:
|
|
|
1376
1386
|
|
|
1377
1387
|
\`\`\`text
|
|
1378
1388
|
I’ll help you launch this as a Sellable campaign. First I’ll research the
|
|
1379
|
-
person/company this is for, then I’ll turn that into a
|
|
1380
|
-
any leads are imported or anything can send.
|
|
1389
|
+
person/company this is for, then I’ll turn that into a LinkedIn outbound
|
|
1390
|
+
campaign brief before any leads are imported or anything can send.
|
|
1381
1391
|
\`\`\`
|
|
1382
1392
|
|
|
1383
1393
|
Good identity setup:
|
|
1384
1394
|
|
|
1385
1395
|
\`\`\`text
|
|
1386
|
-
I’ll ask for the LinkedIn profile URL first. Then we’ll confirm who to
|
|
1387
|
-
what to offer, what proof to lead with, and how to find prospects
|
|
1396
|
+
I’ll ask for the LinkedIn profile URL or handle first. Then we’ll confirm who to
|
|
1397
|
+
target, what to offer, what proof to lead with, and how to find prospects for
|
|
1398
|
+
your LinkedIn outbound campaign.
|
|
1388
1399
|
\`\`\`
|
|
1389
1400
|
|
|
1390
1401
|
Bad:
|
|
@@ -1396,9 +1407,9 @@ First I’ll check whether your Sellable token already tells me who you are.
|
|
|
1396
1407
|
Better:
|
|
1397
1408
|
|
|
1398
1409
|
\`\`\`text
|
|
1399
|
-
I found Christian Reyes connected here. Is that you, and is this
|
|
1400
|
-
Sellable? If not, send the LinkedIn profile URL
|
|
1401
|
-
for.
|
|
1410
|
+
I found Christian Reyes connected here. Is that you, and is this LinkedIn
|
|
1411
|
+
outbound campaign for Sellable? If not, send the LinkedIn profile URL or handle
|
|
1412
|
+
for the person this campaign is for.
|
|
1402
1413
|
\`\`\`
|
|
1403
1414
|
|
|
1404
1415
|
Bad:
|
|
@@ -1425,7 +1436,7 @@ Better:
|
|
|
1425
1436
|
\`\`\`text
|
|
1426
1437
|
I have enough to draft the campaign brief. I’m turning your answers into the
|
|
1427
1438
|
positioning, target, offer, and approval checklist now. You’ll see the brief
|
|
1428
|
-
before I
|
|
1439
|
+
before I look for LinkedIn prospects.
|
|
1429
1440
|
\`\`\`
|
|
1430
1441
|
|
|
1431
1442
|
## Setup Blocker Translation
|
package/package.json
CHANGED
|
@@ -442,38 +442,42 @@ handoff after message approval and the campaign setup validation slice.
|
|
|
442
442
|
|
|
443
443
|
If the invocation or user answer includes an existing `clientProspectId`, keep
|
|
444
444
|
it as the preferred `create_campaign` identity input. If it includes a LinkedIn
|
|
445
|
-
profile URL,
|
|
446
|
-
|
|
447
|
-
|
|
445
|
+
profile URL, `/in/...` path, or bare public profile handle like `csreyes92`,
|
|
446
|
+
normalize it to `https://www.linkedin.com/in/{handle}/` and keep that URL as
|
|
447
|
+
`senderLinkedinUrl` so the backend can resolve/materialize the sender prospect
|
|
448
|
+
when the watchable campaign shell is created. Do not require a connected sender
|
|
449
|
+
before shell creation.
|
|
448
450
|
|
|
449
451
|
If the user supplied a LinkedIn profile, website, domain, company name, or
|
|
450
452
|
explicit client prospect identity in the invocation, do one lightweight lookup
|
|
451
453
|
first:
|
|
452
454
|
|
|
453
|
-
- LinkedIn profile:
|
|
455
|
+
- LinkedIn profile URL or public profile handle: normalize handles to the full
|
|
456
|
+
profile URL, then call `mcp__sellable__fetch_linkedin_profile`.
|
|
454
457
|
- Non-profile URLs or company-page inputs are not enough to start this flow; ask
|
|
455
|
-
again for the person's LinkedIn profile URL.
|
|
458
|
+
again for the person's LinkedIn profile URL or handle.
|
|
456
459
|
- Existing client prospect id: use it directly and do one company/profile lookup
|
|
457
|
-
only if a LinkedIn profile URL is also available.
|
|
460
|
+
only if a LinkedIn profile URL or handle is also available.
|
|
458
461
|
|
|
459
462
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
460
463
|
the current company/focus before continuing. Do not mention connected sender
|
|
461
464
|
availability in this confirmation.
|
|
462
465
|
|
|
463
466
|
If the user did not provide the launch identity, ask in normal chat for the
|
|
464
|
-
LinkedIn profile URL. Do not ask them to choose an input type with the
|
|
465
|
-
question tool:
|
|
467
|
+
LinkedIn profile URL or handle. Do not ask them to choose an input type with the
|
|
468
|
+
structured question tool:
|
|
466
469
|
|
|
467
470
|
```text
|
|
468
|
-
What is your LinkedIn profile URL?
|
|
471
|
+
What is your LinkedIn profile URL or handle?
|
|
469
472
|
```
|
|
470
473
|
|
|
471
|
-
After the user pastes a LinkedIn profile URL,
|
|
472
|
-
|
|
474
|
+
After the user pastes a LinkedIn profile URL, `/in/...` path, or bare handle,
|
|
475
|
+
normalize it to `https://www.linkedin.com/in/{handle}/`, call
|
|
476
|
+
`mcp__sellable__fetch_linkedin_profile`, and infer the current or most recent
|
|
473
477
|
company from the profile. If they paste a non-profile URL or company page
|
|
474
|
-
instead, ask again for the person's LinkedIn profile URL. Retain the
|
|
475
|
-
`senderLinkedinUrl` for `create_campaign`; if a
|
|
476
|
-
pass that instead.
|
|
478
|
+
instead, ask again for the person's LinkedIn profile URL or handle. Retain the
|
|
479
|
+
normalized profile URL as `senderLinkedinUrl` for `create_campaign`; if a
|
|
480
|
+
`clientProspectId` is available, pass that instead.
|
|
477
481
|
|
|
478
482
|
After the user confirms the company/focus, ask the full setup intake before
|
|
479
483
|
inferred strategy hardens:
|
|
@@ -511,8 +515,8 @@ ask the buyer, offer, proof, or lead-source setup questions again unless a
|
|
|
511
515
|
required field is missing, the supplied inputs conflict, or the campaign focus is
|
|
512
516
|
genuinely ambiguous. It is fine to include an explicit assumption line in the
|
|
513
517
|
brief; the approval gate lets the user revise it.
|
|
514
|
-
Before the brief, show: "Accepted LinkedIn input:
|
|
515
|
-
|
|
518
|
+
Before the brief, show: "Accepted LinkedIn input: normalized to the required
|
|
519
|
+
LinkedIn profile URL. Offer path: supplied current offer or Sellable's
|
|
516
520
|
researched recommendation; you can replace it with your current offer."
|
|
517
521
|
|
|
518
522
|
### YOLO Mode
|
|
@@ -522,9 +526,10 @@ If the invocation or any later user message explicitly asks for "yolo mode",
|
|
|
522
526
|
me", "use best estimates", or "just run it", enable YOLO mode for the rest of
|
|
523
527
|
the run. Treat YOLO as `interactionMode: "autonomous"` plus an intake policy:
|
|
524
528
|
|
|
525
|
-
- If the campaign subject is missing, ask only for the LinkedIn profile URL
|
|
526
|
-
normal chat; do not continue from a non-profile URL and do not ask
|
|
527
|
-
proof, source, or filter setup questions before the LinkedIn
|
|
529
|
+
- If the campaign subject is missing, ask only for the LinkedIn profile URL or
|
|
530
|
+
handle in normal chat; do not continue from a non-profile URL and do not ask
|
|
531
|
+
buyer, offer, proof, source, or filter setup questions before the LinkedIn
|
|
532
|
+
identity input.
|
|
528
533
|
- Treat any freeform directions already provided, or added later by the user, as
|
|
529
534
|
operator directions for the rest of the run. If directions conflict, the newest
|
|
530
535
|
user direction wins.
|
|
@@ -684,7 +689,7 @@ updates.
|
|
|
684
689
|
You're in — {activeWorkspaceName} workspace, ready to roll.
|
|
685
690
|
```
|
|
686
691
|
|
|
687
|
-
What is your LinkedIn profile URL?
|
|
692
|
+
What is your LinkedIn profile URL or handle?
|
|
688
693
|
|
|
689
694
|
````
|
|
690
695
|
|
|
@@ -694,15 +699,16 @@ updates.
|
|
|
694
699
|
```text
|
|
695
700
|
You're set up — your {activeWorkspaceName} workspace is ready.
|
|
696
701
|
|
|
697
|
-
What is your LinkedIn profile URL?
|
|
702
|
+
What is your LinkedIn profile URL or handle?
|
|
698
703
|
````
|
|
699
704
|
|
|
700
705
|
No other lines. No "all set", no "signed in", no other acknowledgement.
|
|
701
706
|
|
|
702
|
-
After the user pastes the LinkedIn profile URL, proceed with the
|
|
703
|
-
identity-first campaign setup in the v2 subskill prompt.
|
|
704
|
-
|
|
705
|
-
`complete_sender_research` when that
|
|
707
|
+
After the user pastes the LinkedIn profile URL or handle, proceed with the
|
|
708
|
+
identity-first campaign setup in the v2 subskill prompt. Normalize handles
|
|
709
|
+
to a full profile URL, resolve it with `fetch_linkedin_profile`, and mark
|
|
710
|
+
the client/company research gate with `complete_sender_research` when that
|
|
711
|
+
protocol is required.
|
|
706
712
|
|
|
707
713
|
3. If auth is not OK with `error.type === "workspace"` (token valid, no active
|
|
708
714
|
workspace), stop and show the returned guidance — that's not a fresh-user
|