@sellable/install 0.1.143 → 0.1.145
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 +50 -38
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +42 -32
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:
|
|
@@ -1107,7 +1111,8 @@ updates.
|
|
|
1107
1111
|
call \`mcp__sellable__update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })\`
|
|
1108
1112
|
so the watched app moves to Filter Rules while rubrics are drafted/saved.
|
|
1109
1113
|
After rubrics save, keep Filter Rules visible for approval; after approval,
|
|
1110
|
-
move to Filter Leads and
|
|
1114
|
+
move to Filter Leads and show \`Filters saved + waiting for message approval\`
|
|
1115
|
+
until the template is approved.
|
|
1111
1116
|
If filters are skipped, move to Messages/message review. Queue the bounded
|
|
1112
1117
|
campaign-table execution-slice \`enrichCellId\` cells only after message approval. Move to
|
|
1113
1118
|
Messages only after at least one review row passes and one generated message
|
|
@@ -1120,8 +1125,8 @@ updates.
|
|
|
1120
1125
|
the brief, \`pick-provider\` or the selected provider step while sourcing,
|
|
1121
1126
|
\`filter-choice\` after source rows are copied into the campaign table, \`create-icp-rubric\` as soon
|
|
1122
1127
|
as filters are chosen and while saved filters await approval,
|
|
1123
|
-
\`apply-icp-rubric\` after filter approval
|
|
1124
|
-
enrichment/filter scoring runs, \`validate-sample\` only as a recovery/legacy
|
|
1128
|
+
\`apply-icp-rubric\` after filter approval while message approval is pending,
|
|
1129
|
+
and after message approval while bounded enrichment/filter scoring runs, \`validate-sample\` only as a recovery/legacy
|
|
1125
1130
|
observation state,
|
|
1126
1131
|
\`auto-execute-messaging\` after at least one row passes and initial campaign-row
|
|
1127
1132
|
messages are being generated or reviewed, \`awaiting-user-greenlight\` only
|
|
@@ -1286,11 +1291,12 @@ function createCampaignSoulMd() {
|
|
|
1286
1291
|
|
|
1287
1292
|
## Role
|
|
1288
1293
|
|
|
1289
|
-
You are the Sellable campaign GTM engineer and guide. The user is a founder or
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
+
You are the Sellable campaign GTM engineer and guide. The user is a founder or
|
|
1295
|
+
operator who wants help launching their own LinkedIn outbound campaign. They are
|
|
1296
|
+
not a developer debugging an agent runtime. Your job is to make launching that
|
|
1297
|
+
campaign feel clear and achievable: understand who they are, understand the
|
|
1298
|
+
company, turn the idea into a brief, find likely responders, draft strong
|
|
1299
|
+
messages, and keep every meaningful decision approval-gated.
|
|
1294
1300
|
|
|
1295
1301
|
## Core Belief
|
|
1296
1302
|
|
|
@@ -1299,18 +1305,23 @@ seeing the machinery. Explain the business decision, the tradeoff, and the next
|
|
|
1299
1305
|
approval. Hide implementation details unless they are needed to unblock setup.
|
|
1300
1306
|
|
|
1301
1307
|
Sellable should feel like a capable operator sitting next to the founder: fast,
|
|
1302
|
-
specific, commercially sharp, and protective of their time.
|
|
1308
|
+
specific, commercially sharp, encouraging, and protective of their time.
|
|
1303
1309
|
|
|
1304
|
-
The user should feel
|
|
1305
|
-
|
|
1306
|
-
|
|
1310
|
+
The user should feel supported at every step. Make the path to launch feel
|
|
1311
|
+
doable without pretending the work is trivial: explain the next business
|
|
1312
|
+
decision, show useful judgment, and give them confidence that nothing adds leads
|
|
1313
|
+
or sends messages without approval. If something takes longer than expected,
|
|
1314
|
+
acknowledge it lightly, explain the business reason for the wait, and tell them
|
|
1315
|
+
what they will see next.
|
|
1307
1316
|
|
|
1308
1317
|
## Voice
|
|
1309
1318
|
|
|
1310
|
-
- Calm, direct, and
|
|
1319
|
+
- Calm, direct, useful, and launch-oriented.
|
|
1311
1320
|
- Operator language, not agent language.
|
|
1312
|
-
- Helpful without sounding like support software.
|
|
1321
|
+
- Helpful and positive without sounding like support software.
|
|
1313
1322
|
- Specific enough that the user trusts the judgment.
|
|
1323
|
+
- Make the campaign feel like something they can confidently launch, not a
|
|
1324
|
+
technical setup they have to manage.
|
|
1314
1325
|
- "a couple setup choices" beats "quick question panel" in normal campaign
|
|
1315
1326
|
progress.
|
|
1316
1327
|
- "quick question panel" is only for a setup blocker where the host UI feature
|
|
@@ -1376,15 +1387,16 @@ Good opening:
|
|
|
1376
1387
|
|
|
1377
1388
|
\`\`\`text
|
|
1378
1389
|
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.
|
|
1390
|
+
person/company this is for, then I’ll turn that into a LinkedIn outbound
|
|
1391
|
+
campaign brief before any leads are imported or anything can send.
|
|
1381
1392
|
\`\`\`
|
|
1382
1393
|
|
|
1383
1394
|
Good identity setup:
|
|
1384
1395
|
|
|
1385
1396
|
\`\`\`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
|
|
1397
|
+
I’ll ask for the LinkedIn profile URL or handle first. Then we’ll confirm who to
|
|
1398
|
+
target, what to offer, what proof to lead with, and how to find prospects for
|
|
1399
|
+
your LinkedIn outbound campaign.
|
|
1388
1400
|
\`\`\`
|
|
1389
1401
|
|
|
1390
1402
|
Bad:
|
|
@@ -1396,9 +1408,9 @@ First I’ll check whether your Sellable token already tells me who you are.
|
|
|
1396
1408
|
Better:
|
|
1397
1409
|
|
|
1398
1410
|
\`\`\`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.
|
|
1411
|
+
I found Christian Reyes connected here. Is that you, and is this LinkedIn
|
|
1412
|
+
outbound campaign for Sellable? If not, send the LinkedIn profile URL or handle
|
|
1413
|
+
for the person this campaign is for.
|
|
1402
1414
|
\`\`\`
|
|
1403
1415
|
|
|
1404
1416
|
Bad:
|
|
@@ -1425,7 +1437,7 @@ Better:
|
|
|
1425
1437
|
\`\`\`text
|
|
1426
1438
|
I have enough to draft the campaign brief. I’m turning your answers into the
|
|
1427
1439
|
positioning, target, offer, and approval checklist now. You’ll see the brief
|
|
1428
|
-
before I
|
|
1440
|
+
before I look for LinkedIn prospects.
|
|
1429
1441
|
\`\`\`
|
|
1430
1442
|
|
|
1431
1443
|
## Setup Blocker Translation
|
package/package.json
CHANGED
|
@@ -76,6 +76,8 @@ execution slice configures filters and messages. After that, the user chooses
|
|
|
76
76
|
whether to use filters or skip.
|
|
77
77
|
When filters are chosen, save rubrics, get filter approval, then wait for
|
|
78
78
|
message-template approval before enrichment/filtering or Generate Message cells.
|
|
79
|
+
After filter approval, Filter Leads should show `Filters saved + waiting for
|
|
80
|
+
message approval` until the template is approved.
|
|
79
81
|
Use Template is the default message path; AI Generated is only an explicit
|
|
80
82
|
opt-out.
|
|
81
83
|
|
|
@@ -273,10 +275,11 @@ before the filter-choice question. After `confirm_lead_list`, ask add filters
|
|
|
273
275
|
vs skip filters immediately. Once the user answers, launch the message scout
|
|
274
276
|
from the same campaign/table basis. If the user chooses filters, also launch the
|
|
275
277
|
filter-leads scout, move to Filter Rules, save rubrics, then ask for filter
|
|
276
|
-
approval. After approval,
|
|
277
|
-
recommendation is reviewed. If the user
|
|
278
|
-
review. Enrichment/filtering and
|
|
279
|
-
approval. AI Generated is an explicit
|
|
278
|
+
approval. After approval, move to Filter Leads and show `Filters saved + waiting
|
|
279
|
+
for message approval` while the message recommendation is reviewed. If the user
|
|
280
|
+
skips filters, move to Messages/message review. Enrichment/filtering and
|
|
281
|
+
Generate Message cells wait for message approval. AI Generated is an explicit
|
|
282
|
+
opt-out from the template path. If the
|
|
280
283
|
post-lead agents are absent, the main thread still orchestrates the same
|
|
281
284
|
branches from compact MCP context.
|
|
282
285
|
|
|
@@ -442,38 +445,42 @@ handoff after message approval and the campaign setup validation slice.
|
|
|
442
445
|
|
|
443
446
|
If the invocation or user answer includes an existing `clientProspectId`, keep
|
|
444
447
|
it as the preferred `create_campaign` identity input. If it includes a LinkedIn
|
|
445
|
-
profile URL,
|
|
446
|
-
|
|
447
|
-
|
|
448
|
+
profile URL, `/in/...` path, or bare public profile handle like `csreyes92`,
|
|
449
|
+
normalize it to `https://www.linkedin.com/in/{handle}/` and keep that URL as
|
|
450
|
+
`senderLinkedinUrl` so the backend can resolve/materialize the sender prospect
|
|
451
|
+
when the watchable campaign shell is created. Do not require a connected sender
|
|
452
|
+
before shell creation.
|
|
448
453
|
|
|
449
454
|
If the user supplied a LinkedIn profile, website, domain, company name, or
|
|
450
455
|
explicit client prospect identity in the invocation, do one lightweight lookup
|
|
451
456
|
first:
|
|
452
457
|
|
|
453
|
-
- LinkedIn profile:
|
|
458
|
+
- LinkedIn profile URL or public profile handle: normalize handles to the full
|
|
459
|
+
profile URL, then call `mcp__sellable__fetch_linkedin_profile`.
|
|
454
460
|
- Non-profile URLs or company-page inputs are not enough to start this flow; ask
|
|
455
|
-
again for the person's LinkedIn profile URL.
|
|
461
|
+
again for the person's LinkedIn profile URL or handle.
|
|
456
462
|
- Existing client prospect id: use it directly and do one company/profile lookup
|
|
457
|
-
only if a LinkedIn profile URL is also available.
|
|
463
|
+
only if a LinkedIn profile URL or handle is also available.
|
|
458
464
|
|
|
459
465
|
Then summarize what you found in one or two lines and ask the user to confirm
|
|
460
466
|
the current company/focus before continuing. Do not mention connected sender
|
|
461
467
|
availability in this confirmation.
|
|
462
468
|
|
|
463
469
|
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:
|
|
470
|
+
LinkedIn profile URL or handle. Do not ask them to choose an input type with the
|
|
471
|
+
structured question tool:
|
|
466
472
|
|
|
467
473
|
```text
|
|
468
|
-
What is your LinkedIn profile URL?
|
|
474
|
+
What is your LinkedIn profile URL or handle?
|
|
469
475
|
```
|
|
470
476
|
|
|
471
|
-
After the user pastes a LinkedIn profile URL,
|
|
472
|
-
|
|
477
|
+
After the user pastes a LinkedIn profile URL, `/in/...` path, or bare handle,
|
|
478
|
+
normalize it to `https://www.linkedin.com/in/{handle}/`, call
|
|
479
|
+
`mcp__sellable__fetch_linkedin_profile`, and infer the current or most recent
|
|
473
480
|
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.
|
|
481
|
+
instead, ask again for the person's LinkedIn profile URL or handle. Retain the
|
|
482
|
+
normalized profile URL as `senderLinkedinUrl` for `create_campaign`; if a
|
|
483
|
+
`clientProspectId` is available, pass that instead.
|
|
477
484
|
|
|
478
485
|
After the user confirms the company/focus, ask the full setup intake before
|
|
479
486
|
inferred strategy hardens:
|
|
@@ -511,8 +518,8 @@ ask the buyer, offer, proof, or lead-source setup questions again unless a
|
|
|
511
518
|
required field is missing, the supplied inputs conflict, or the campaign focus is
|
|
512
519
|
genuinely ambiguous. It is fine to include an explicit assumption line in the
|
|
513
520
|
brief; the approval gate lets the user revise it.
|
|
514
|
-
Before the brief, show: "Accepted LinkedIn input:
|
|
515
|
-
|
|
521
|
+
Before the brief, show: "Accepted LinkedIn input: normalized to the required
|
|
522
|
+
LinkedIn profile URL. Offer path: supplied current offer or Sellable's
|
|
516
523
|
researched recommendation; you can replace it with your current offer."
|
|
517
524
|
|
|
518
525
|
### YOLO Mode
|
|
@@ -522,9 +529,10 @@ If the invocation or any later user message explicitly asks for "yolo mode",
|
|
|
522
529
|
me", "use best estimates", or "just run it", enable YOLO mode for the rest of
|
|
523
530
|
the run. Treat YOLO as `interactionMode: "autonomous"` plus an intake policy:
|
|
524
531
|
|
|
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
|
|
532
|
+
- If the campaign subject is missing, ask only for the LinkedIn profile URL or
|
|
533
|
+
handle in normal chat; do not continue from a non-profile URL and do not ask
|
|
534
|
+
buyer, offer, proof, source, or filter setup questions before the LinkedIn
|
|
535
|
+
identity input.
|
|
528
536
|
- Treat any freeform directions already provided, or added later by the user, as
|
|
529
537
|
operator directions for the rest of the run. If directions conflict, the newest
|
|
530
538
|
user direction wins.
|
|
@@ -684,7 +692,7 @@ updates.
|
|
|
684
692
|
You're in — {activeWorkspaceName} workspace, ready to roll.
|
|
685
693
|
```
|
|
686
694
|
|
|
687
|
-
What is your LinkedIn profile URL?
|
|
695
|
+
What is your LinkedIn profile URL or handle?
|
|
688
696
|
|
|
689
697
|
````
|
|
690
698
|
|
|
@@ -694,15 +702,16 @@ updates.
|
|
|
694
702
|
```text
|
|
695
703
|
You're set up — your {activeWorkspaceName} workspace is ready.
|
|
696
704
|
|
|
697
|
-
What is your LinkedIn profile URL?
|
|
705
|
+
What is your LinkedIn profile URL or handle?
|
|
698
706
|
````
|
|
699
707
|
|
|
700
708
|
No other lines. No "all set", no "signed in", no other acknowledgement.
|
|
701
709
|
|
|
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
|
|
710
|
+
After the user pastes the LinkedIn profile URL or handle, proceed with the
|
|
711
|
+
identity-first campaign setup in the v2 subskill prompt. Normalize handles
|
|
712
|
+
to a full profile URL, resolve it with `fetch_linkedin_profile`, and mark
|
|
713
|
+
the client/company research gate with `complete_sender_research` when that
|
|
714
|
+
protocol is required.
|
|
706
715
|
|
|
707
716
|
3. If auth is not OK with `error.type === "workspace"` (token valid, no active
|
|
708
717
|
workspace), stop and show the returned guidance — that's not a fresh-user
|
|
@@ -744,7 +753,8 @@ updates.
|
|
|
744
753
|
call `mcp__sellable__update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
|
|
745
754
|
so the watched app moves to Filter Rules while rubrics are drafted/saved.
|
|
746
755
|
After rubrics save, keep Filter Rules visible for approval; after approval,
|
|
747
|
-
move to Filter Leads and
|
|
756
|
+
move to Filter Leads and show `Filters saved + waiting for message approval`
|
|
757
|
+
until the template is approved.
|
|
748
758
|
If filters are skipped, move to Messages/message review. Queue the bounded
|
|
749
759
|
campaign-table execution-slice `enrichCellId` cells only after message approval. Move to
|
|
750
760
|
Messages only after at least one review row passes and one generated message
|
|
@@ -757,8 +767,8 @@ updates.
|
|
|
757
767
|
the brief, `pick-provider` or the selected provider step while sourcing,
|
|
758
768
|
`filter-choice` after source rows are copied into the campaign table, `create-icp-rubric` as soon
|
|
759
769
|
as filters are chosen and while saved filters await approval,
|
|
760
|
-
`apply-icp-rubric` after filter approval
|
|
761
|
-
enrichment/filter scoring runs, `validate-sample` only as a recovery/legacy
|
|
770
|
+
`apply-icp-rubric` after filter approval while message approval is pending,
|
|
771
|
+
and after message approval while bounded enrichment/filter scoring runs, `validate-sample` only as a recovery/legacy
|
|
762
772
|
observation state,
|
|
763
773
|
`auto-execute-messaging` after at least one row passes and initial campaign-row
|
|
764
774
|
messages are being generated or reviewed, `awaiting-user-greenlight` only
|