@signaliz/sdk 1.0.6 → 1.0.8
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 +100 -8
- package/dist/{chunk-GRVV37LD.mjs → chunk-KL6KNOP6.mjs} +1432 -55
- package/dist/cli.js +2390 -62
- package/dist/cli.mjs +963 -9
- package/dist/index.d.mts +245 -10
- package/dist/index.d.ts +245 -10
- package/dist/index.js +1442 -55
- package/dist/index.mjs +21 -1
- package/dist/mcp-config.js +1320 -55
- package/dist/mcp-config.mjs +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -21,17 +21,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
Ai: () => Ai,
|
|
24
|
+
CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS: () => CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS,
|
|
25
|
+
CAMPAIGN_BUILDER_STRATEGY_TEMPLATES: () => CAMPAIGN_BUILDER_STRATEGY_TEMPLATES,
|
|
24
26
|
CampaignBuilderAgent: () => CampaignBuilderAgent,
|
|
25
27
|
Campaigns: () => Campaigns,
|
|
28
|
+
DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES: () => DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES,
|
|
29
|
+
DEFAULT_CAMPAIGN_BUILDER_BUILT_INS: () => DEFAULT_CAMPAIGN_BUILDER_BUILT_INS,
|
|
26
30
|
DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS: () => DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS,
|
|
27
31
|
GtmKernel: () => GtmKernel,
|
|
28
32
|
Icps: () => Icps,
|
|
29
33
|
Ops: () => Ops,
|
|
30
34
|
Signaliz: () => Signaliz,
|
|
31
35
|
SignalizError: () => SignalizError,
|
|
36
|
+
applyCampaignBuilderStrategyTemplate: () => applyCampaignBuilderStrategyTemplate,
|
|
32
37
|
collectExecutionReferences: () => collectExecutionReferences,
|
|
33
38
|
createCampaignBuilderAgentPlan: () => createCampaignBuilderAgentPlan,
|
|
39
|
+
createCampaignBuilderAgentRequestTemplate: () => createCampaignBuilderAgentRequestTemplate,
|
|
34
40
|
createCampaignBuilderApproval: () => createCampaignBuilderApproval,
|
|
41
|
+
createCampaignBuilderToolRoute: () => createCampaignBuilderToolRoute,
|
|
42
|
+
getCampaignBuilderOperatingPlaybook: () => getCampaignBuilderOperatingPlaybook,
|
|
43
|
+
getCampaignBuilderOperatingPlaybooksForRequest: () => getCampaignBuilderOperatingPlaybooksForRequest,
|
|
44
|
+
getCampaignBuilderStrategyTemplate: () => getCampaignBuilderStrategyTemplate,
|
|
35
45
|
getMissingCampaignBuilderApprovals: () => getMissingCampaignBuilderApprovals,
|
|
36
46
|
normalizeExecutionReference: () => normalizeExecutionReference
|
|
37
47
|
});
|
|
@@ -790,7 +800,7 @@ var Campaigns = class {
|
|
|
790
800
|
async build(request, options) {
|
|
791
801
|
return this.buildCampaign(request, options);
|
|
792
802
|
}
|
|
793
|
-
/** Scope an agency/
|
|
803
|
+
/** Scope an agency/customer campaign into a markdown brief plus build_campaign dry-run args. */
|
|
794
804
|
async scope(request) {
|
|
795
805
|
return this.scopeCampaign(request);
|
|
796
806
|
}
|
|
@@ -972,6 +982,10 @@ function mapStatus(data) {
|
|
|
972
982
|
errors: diagnosticMessages(data.errors),
|
|
973
983
|
artifactCount: data.artifact_count ?? 0,
|
|
974
984
|
providerRoute: mapProviderRoute(data),
|
|
985
|
+
triggerRunId: typeof data.trigger_run_id === "string" ? data.trigger_run_id : null,
|
|
986
|
+
staleRunningPhase: data.stale_running_phase === true,
|
|
987
|
+
phaseAgeSeconds: numberOrNull(data.phase_age_seconds),
|
|
988
|
+
diagnostics: recordOrNull(data.diagnostics) ?? {},
|
|
975
989
|
nextAction: formatNextAction(data.next_action),
|
|
976
990
|
createdAt: data.created_at,
|
|
977
991
|
updatedAt: data.updated_at,
|
|
@@ -1065,7 +1079,7 @@ function mapArtifact(a) {
|
|
|
1065
1079
|
function mapScope(data) {
|
|
1066
1080
|
return {
|
|
1067
1081
|
campaignScopeId: data.campaign_scope_id,
|
|
1068
|
-
|
|
1082
|
+
accountLabel: data.account_label,
|
|
1069
1083
|
campaignName: data.campaign_name,
|
|
1070
1084
|
approach: data.approach,
|
|
1071
1085
|
approachLabel: data.approach_label,
|
|
@@ -1091,8 +1105,8 @@ function scopeArgs(request) {
|
|
|
1091
1105
|
const args = {
|
|
1092
1106
|
prompt: request.prompt
|
|
1093
1107
|
};
|
|
1094
|
-
if (request.
|
|
1095
|
-
if (request.
|
|
1108
|
+
if (request.accountLabel) args.account_label = request.accountLabel;
|
|
1109
|
+
if (request.accountContext) args.account_context = request.accountContext;
|
|
1096
1110
|
if (request.campaignGoal) args.campaign_goal = request.campaignGoal;
|
|
1097
1111
|
if (request.targetCount) args.target_count = request.targetCount;
|
|
1098
1112
|
if (request.destinations) args.destinations = request.destinations;
|
|
@@ -1220,22 +1234,565 @@ var DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS = {
|
|
|
1220
1234
|
approvalRequired: true
|
|
1221
1235
|
}
|
|
1222
1236
|
};
|
|
1237
|
+
var DEFAULT_CAMPAIGN_BUILDER_BUILT_INS = [
|
|
1238
|
+
"lead_generation",
|
|
1239
|
+
"email_finding",
|
|
1240
|
+
"email_verification",
|
|
1241
|
+
"signals"
|
|
1242
|
+
];
|
|
1243
|
+
var DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES = [
|
|
1244
|
+
"memory_retrieval",
|
|
1245
|
+
"spend",
|
|
1246
|
+
"customer_tool",
|
|
1247
|
+
"external_write",
|
|
1248
|
+
"delivery",
|
|
1249
|
+
"launch"
|
|
1250
|
+
];
|
|
1251
|
+
var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
1252
|
+
{
|
|
1253
|
+
slug: "cache-first-large-list",
|
|
1254
|
+
label: "Cache-First Large List",
|
|
1255
|
+
whenToUse: [
|
|
1256
|
+
"The target count is high and reusable workspace lead or cache coverage may exist.",
|
|
1257
|
+
"The deliverable is a verified list or top-up rather than a deeply custom one-off workflow."
|
|
1258
|
+
],
|
|
1259
|
+
sequence: [
|
|
1260
|
+
"Inventory reusable cache before paid sourcing.",
|
|
1261
|
+
"Report unique emails, role buckets, exclusions, and missing-field counts.",
|
|
1262
|
+
"Use fresh sourcing only for the approved gap.",
|
|
1263
|
+
"Write newly approved source metadata back to memory or cache after review."
|
|
1264
|
+
],
|
|
1265
|
+
requiredFields: {
|
|
1266
|
+
inventory: ["matching_cached_rows", "unique_cached_emails", "persona_bucket_counts", "exclusions_applied", "missing_field_counts"],
|
|
1267
|
+
finalRows: ["first_name", "last_name", "company_name", "company_domain", "work_email", "email_status", "source_type"]
|
|
1268
|
+
},
|
|
1269
|
+
qualityGates: [
|
|
1270
|
+
"Deduplicate by normalized email before counting final rows.",
|
|
1271
|
+
"Separate cache reuse from fresh sourcing in the build receipt.",
|
|
1272
|
+
"Block export when required identity, company, or email fields are missing."
|
|
1273
|
+
],
|
|
1274
|
+
activationBoundary: "Cache inventory is read-only. Fresh sourcing, cache writes, export, and sender loading require explicit approval.",
|
|
1275
|
+
memoryKeywords: ["cache inventory", "large list", "unique emails", "top-up sourcing", "source metadata"]
|
|
1276
|
+
},
|
|
1277
|
+
{
|
|
1278
|
+
slug: "net-new-suppressed-list",
|
|
1279
|
+
label: "Net-New Suppressed List",
|
|
1280
|
+
whenToUse: [
|
|
1281
|
+
"A prior campaign, seed list, or exclusion list must be suppressed.",
|
|
1282
|
+
"The operator needs both outreach-facing rows and provenance-rich QA evidence."
|
|
1283
|
+
],
|
|
1284
|
+
sequence: [
|
|
1285
|
+
"Load suppression baselines before source selection.",
|
|
1286
|
+
"Apply email suppression as a hard gate and domain suppression as required by the brief.",
|
|
1287
|
+
"Keep provenance, source, and validation fields outside the outreach-facing export when needed.",
|
|
1288
|
+
"Run final overlap checks before any delivery action."
|
|
1289
|
+
],
|
|
1290
|
+
requiredFields: {
|
|
1291
|
+
suppression: ["suppression_source", "prior_email_overlap", "prior_domain_match", "suppression_decision"],
|
|
1292
|
+
finalRows: ["first_name", "last_name", "company_name", "company_domain", "work_email", "email_status", "provenance_id"]
|
|
1293
|
+
},
|
|
1294
|
+
qualityGates: [
|
|
1295
|
+
"Prior email overlap must be zero for rows marked export ready.",
|
|
1296
|
+
"Prior-domain matches must be flagged or blocked according to the approved campaign promise.",
|
|
1297
|
+
"Do not describe rows as fully qualified when the approved path only proves net-new email status."
|
|
1298
|
+
],
|
|
1299
|
+
activationBoundary: "Suppression review must pass before export, upload, CRM sync, sender load, or sequence launch.",
|
|
1300
|
+
memoryKeywords: ["suppression", "net-new", "prior email overlap", "domain review", "provenance-rich QA"]
|
|
1301
|
+
},
|
|
1302
|
+
{
|
|
1303
|
+
slug: "proof-first-vertical-gate",
|
|
1304
|
+
label: "Proof-First Vertical Gate",
|
|
1305
|
+
whenToUse: [
|
|
1306
|
+
"Wrong-account risk is high or the target category has close lookalike exclusions.",
|
|
1307
|
+
"Account proof is more important than raw lead volume."
|
|
1308
|
+
],
|
|
1309
|
+
sequence: [
|
|
1310
|
+
"Define positive and negative proof fields before sourcing at scale.",
|
|
1311
|
+
"Qualify companies before contact discovery.",
|
|
1312
|
+
"Qualify contacts before email finding.",
|
|
1313
|
+
"Keep pass, review, and fail rows distinct through delivery review."
|
|
1314
|
+
],
|
|
1315
|
+
requiredFields: {
|
|
1316
|
+
account: ["company_name", "company_domain", "source_url", "positive_proof", "negative_proof", "fit_score", "account_qualified"],
|
|
1317
|
+
contact: ["person_name", "person_title", "persona_match", "contact_fit_score", "contact_qualified"]
|
|
1318
|
+
},
|
|
1319
|
+
qualityGates: [
|
|
1320
|
+
"Do not spend on contact or email enrichment until the account passes the proof gate.",
|
|
1321
|
+
"Adjacent excluded categories must stay exclusions, not synonyms.",
|
|
1322
|
+
"Contact fit should meet the configured threshold before email finding or copy generation."
|
|
1323
|
+
],
|
|
1324
|
+
activationBoundary: "Proof gates are required before contact spend, copy, export, or external writes.",
|
|
1325
|
+
memoryKeywords: ["proof gate", "vertical exclusion", "company before contact", "pass review fail", "fit threshold"]
|
|
1326
|
+
},
|
|
1327
|
+
{
|
|
1328
|
+
slug: "signal-led-copy-approval",
|
|
1329
|
+
label: "Signal-Led Copy With Approval",
|
|
1330
|
+
whenToUse: [
|
|
1331
|
+
"Outbound copy should be grounded in company signals, proof fields, or row context.",
|
|
1332
|
+
"Delivery destinations must remain locked after copy generation until review."
|
|
1333
|
+
],
|
|
1334
|
+
sequence: [
|
|
1335
|
+
"Validate list quality before copy.",
|
|
1336
|
+
"Attach the strongest supported signal and source evidence.",
|
|
1337
|
+
"Generate copy only for fit-qualified and contactable rows.",
|
|
1338
|
+
"Hold every destination behind explicit approval."
|
|
1339
|
+
],
|
|
1340
|
+
requiredFields: {
|
|
1341
|
+
evidence: ["strongest_signal", "signal_source_url", "why_now", "personalization_basis"],
|
|
1342
|
+
copy: ["subject_line", "opening_line", "email_copy", "copy_ready", "copy_blocker"]
|
|
1343
|
+
},
|
|
1344
|
+
qualityGates: [
|
|
1345
|
+
"Copy cannot invent unsupported pain, claims, numbers, or recent events.",
|
|
1346
|
+
"Weak evidence should route the row to review instead of send-ready copy.",
|
|
1347
|
+
"Destination fields must remain blocked until approval metadata is present."
|
|
1348
|
+
],
|
|
1349
|
+
activationBoundary: "Copy readiness is not delivery approval. Export, sync, sender load, and launch require a separate human-approved gate.",
|
|
1350
|
+
memoryKeywords: ["company signals", "evidence-fed copy", "why now", "copy blocker", "approval gate"]
|
|
1351
|
+
},
|
|
1352
|
+
{
|
|
1353
|
+
slug: "domain-first-recovery",
|
|
1354
|
+
label: "Domain-First Recovery",
|
|
1355
|
+
whenToUse: [
|
|
1356
|
+
"Strict yield is low and broad people sourcing creates noisy, duplicated, or off-fit rows.",
|
|
1357
|
+
"The account universe should be recovered or expanded before more contact spend."
|
|
1358
|
+
],
|
|
1359
|
+
sequence: [
|
|
1360
|
+
"Model attrition after an initial sample.",
|
|
1361
|
+
"Source or recover account domains in tight slices.",
|
|
1362
|
+
"Filter domains locally before contact discovery.",
|
|
1363
|
+
"Use accepted domains as the seed for person and email work."
|
|
1364
|
+
],
|
|
1365
|
+
requiredFields: {
|
|
1366
|
+
domainReview: ["company_domain", "source_slice", "domain_fit_score", "domain_rejection_reason", "accepted_domain"],
|
|
1367
|
+
recovery: ["target_gap", "expected_yield", "accepted_domain_count", "contact_pull_limit"]
|
|
1368
|
+
},
|
|
1369
|
+
qualityGates: [
|
|
1370
|
+
"Do not repeat broad people-with-email sourcing after strict yield proves low.",
|
|
1371
|
+
"Rejected domains should stay suppressed unless the operator changes the ICP.",
|
|
1372
|
+
"Target count means final held rows, not raw sourced rows."
|
|
1373
|
+
],
|
|
1374
|
+
activationBoundary: "Domain recovery informs sourcing. Contact enrichment, paid qualification, and export still require approved gates.",
|
|
1375
|
+
memoryKeywords: ["domain-first", "yield modeling", "attrition", "accepted domains", "gap fill"]
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
slug: "table-workflow-handoff",
|
|
1379
|
+
label: "Table Workflow Handoff",
|
|
1380
|
+
whenToUse: [
|
|
1381
|
+
"The campaign needs connected source, account, people, enrichment, copy, and destination tables.",
|
|
1382
|
+
"A workspace or partner tool owns part of the workflow through MCP, webhook, API, or managed integration."
|
|
1383
|
+
],
|
|
1384
|
+
sequence: [
|
|
1385
|
+
"Create source/account context before child people rows.",
|
|
1386
|
+
"Carry source context into enrichment, copy, and destination mapping.",
|
|
1387
|
+
"Expose request-ready, result, error, blocker, and export-ready fields for every action.",
|
|
1388
|
+
"Dry-run provider routes and destination writes before activation."
|
|
1389
|
+
],
|
|
1390
|
+
requiredFields: {
|
|
1391
|
+
workflow: ["source_record_id", "company_context", "request_ready", "provider_status", "error", "export_ready", "export_blocker"],
|
|
1392
|
+
destination: ["destination_type", "destination_status", "approval_status", "approved_by", "approved_at"]
|
|
1393
|
+
},
|
|
1394
|
+
qualityGates: [
|
|
1395
|
+
"Every paid/API action needs visible request readiness and parsed output fields.",
|
|
1396
|
+
"Child people rows must preserve the account context that justified the search.",
|
|
1397
|
+
"Provider route activation must dry-run before any external write."
|
|
1398
|
+
],
|
|
1399
|
+
activationBoundary: "MCP, webhook, managed integration, and destination routes remain dry-run until the reviewed route and campaign are approved.",
|
|
1400
|
+
memoryKeywords: ["table workflow", "request ready", "provider status", "export blocker", "BYO integration"]
|
|
1401
|
+
}
|
|
1402
|
+
];
|
|
1403
|
+
var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
1404
|
+
{
|
|
1405
|
+
slug: "industrial-ot-resilience",
|
|
1406
|
+
label: "Industrial OT Resilience",
|
|
1407
|
+
aliases: ["industrial ot", "ot resilience", "industrial continuity", "industrial-ot-resilience"],
|
|
1408
|
+
defaultTargetCount: 3e3,
|
|
1409
|
+
campaignName: "Industrial OT Resilience Net-New",
|
|
1410
|
+
accountContext: [
|
|
1411
|
+
"Strategy template: Signaliz-only OT, industrial, manufacturing, embedded systems, field service, cyber resilience, and business continuity sourcing.",
|
|
1412
|
+
"Use prior approved campaign output as the email suppression baseline; final files must have zero prior-used email overlap.",
|
|
1413
|
+
"Keep external qualification providers disabled unless the operator explicitly changes the requirement."
|
|
1414
|
+
].join(" "),
|
|
1415
|
+
icp: {
|
|
1416
|
+
personas: [
|
|
1417
|
+
"OT leader",
|
|
1418
|
+
"Industrial automation leader",
|
|
1419
|
+
"Engineering leader",
|
|
1420
|
+
"IT infrastructure leader",
|
|
1421
|
+
"Reliability or maintenance leader",
|
|
1422
|
+
"Operations leader"
|
|
1423
|
+
],
|
|
1424
|
+
industries: [
|
|
1425
|
+
"Machinery",
|
|
1426
|
+
"Electrical and electronic manufacturing",
|
|
1427
|
+
"Mechanical or industrial engineering",
|
|
1428
|
+
"Industrial automation",
|
|
1429
|
+
"Semiconductors",
|
|
1430
|
+
"Medical devices",
|
|
1431
|
+
"Oil and energy",
|
|
1432
|
+
"Automotive"
|
|
1433
|
+
],
|
|
1434
|
+
geographies: ["United States", "United Kingdom", "Canada", "Nordics", "Netherlands"],
|
|
1435
|
+
keywords: [
|
|
1436
|
+
"OT",
|
|
1437
|
+
"ICS",
|
|
1438
|
+
"SCADA",
|
|
1439
|
+
"control systems",
|
|
1440
|
+
"industrial automation",
|
|
1441
|
+
"manufacturing",
|
|
1442
|
+
"plant operations",
|
|
1443
|
+
"reliability",
|
|
1444
|
+
"maintenance",
|
|
1445
|
+
"PLC",
|
|
1446
|
+
"business continuity"
|
|
1447
|
+
],
|
|
1448
|
+
exclusions: [
|
|
1449
|
+
"sales",
|
|
1450
|
+
"marketing",
|
|
1451
|
+
"recruiting",
|
|
1452
|
+
"HR",
|
|
1453
|
+
"finance",
|
|
1454
|
+
"legal",
|
|
1455
|
+
"customer success",
|
|
1456
|
+
"retail",
|
|
1457
|
+
"restaurants",
|
|
1458
|
+
"staffing",
|
|
1459
|
+
"real estate"
|
|
1460
|
+
],
|
|
1461
|
+
requireVerifiedEmail: true
|
|
1462
|
+
},
|
|
1463
|
+
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1464
|
+
preferredProviders: ["signaliz_native"],
|
|
1465
|
+
memoryQueries: [{
|
|
1466
|
+
query: "industrial OT net-new prior email suppression verified manufacturing embedded systems field service cyber resilience business continuity",
|
|
1467
|
+
scopes: ["workspace", "operator_notes"],
|
|
1468
|
+
topK: 10,
|
|
1469
|
+
required: true,
|
|
1470
|
+
rationale: "Load OT sourcing, dedupe, cache metadata, and approval gates before planning net-new work."
|
|
1471
|
+
}],
|
|
1472
|
+
constraints: {
|
|
1473
|
+
deliverabilityNotes: [
|
|
1474
|
+
"Require verified email, valid syntax, first name, last name, company name, and normalized company domain.",
|
|
1475
|
+
"Keep export, upload, sync, send, and replacement actions blocked until explicit approval.",
|
|
1476
|
+
"Treat prior-domain matches as flagged review evidence unless strict domain suppression is explicitly requested."
|
|
1477
|
+
]
|
|
1478
|
+
},
|
|
1479
|
+
signalizDefaults: {
|
|
1480
|
+
copy: {
|
|
1481
|
+
offerContext: "Do not invent product claims. Anchor messaging only in row-supported OT, industrial, cyber resilience, backup/recovery, or business-continuity context."
|
|
1482
|
+
}
|
|
1483
|
+
},
|
|
1484
|
+
agencyContext: {
|
|
1485
|
+
partnerEcosystem: ["signaliz", "instantly", "nango"]
|
|
1486
|
+
},
|
|
1487
|
+
operatingPlaybookSlugs: ["net-new-suppressed-list", "proof-first-vertical-gate", "signal-led-copy-approval"]
|
|
1488
|
+
},
|
|
1489
|
+
{
|
|
1490
|
+
slug: "non-medical-home-care",
|
|
1491
|
+
label: "Non-Medical Home Care Operations",
|
|
1492
|
+
aliases: ["home care", "non-medical home care", "home-care-operations", "non-medical-home-care"],
|
|
1493
|
+
defaultTargetCount: 3e3,
|
|
1494
|
+
campaignName: "Mature Home Care Agency Operators",
|
|
1495
|
+
accountContext: [
|
|
1496
|
+
"Strategy template: mature US non-medical home care agencies with scale signals, proof fields, strict home-care vs home-health separation, and approval-gated export.",
|
|
1497
|
+
"Use proof before paid enrichment or copy. Preserve pass vs review ICP status because healthcare language often blurs home care and home health."
|
|
1498
|
+
].join(" "),
|
|
1499
|
+
icp: {
|
|
1500
|
+
personas: [
|
|
1501
|
+
"Owner",
|
|
1502
|
+
"CEO",
|
|
1503
|
+
"COO",
|
|
1504
|
+
"Administrator",
|
|
1505
|
+
"Operations Director",
|
|
1506
|
+
"Scheduler",
|
|
1507
|
+
"Care coordinator leader"
|
|
1508
|
+
],
|
|
1509
|
+
industries: ["Non-medical home care", "Senior care", "Private duty care", "Home services"],
|
|
1510
|
+
companySizes: ["20+ employees", "600+ billable care hours/week", "1000+ billable care hours/week ideal"],
|
|
1511
|
+
geographies: ["United States"],
|
|
1512
|
+
keywords: [
|
|
1513
|
+
"non-medical home care",
|
|
1514
|
+
"private duty",
|
|
1515
|
+
"caregiver recruiting",
|
|
1516
|
+
"multi-location",
|
|
1517
|
+
"franchise",
|
|
1518
|
+
"scheduler",
|
|
1519
|
+
"billing",
|
|
1520
|
+
"payroll",
|
|
1521
|
+
"EVV",
|
|
1522
|
+
"WellSky",
|
|
1523
|
+
"AxisCare",
|
|
1524
|
+
"CareSmartz360"
|
|
1525
|
+
],
|
|
1526
|
+
exclusions: [
|
|
1527
|
+
"home health",
|
|
1528
|
+
"skilled nursing",
|
|
1529
|
+
"hospice",
|
|
1530
|
+
"hospital",
|
|
1531
|
+
"clinic",
|
|
1532
|
+
"therapy practice",
|
|
1533
|
+
"very small owner-only shop"
|
|
1534
|
+
],
|
|
1535
|
+
requireVerifiedEmail: true
|
|
1536
|
+
},
|
|
1537
|
+
builtIns: ["lead_generation", "local_leads", "email_finding", "email_verification", "signals"],
|
|
1538
|
+
preferredProviders: ["signaliz_native", "octave", "clay_webhook", "apify"],
|
|
1539
|
+
memoryQueries: [{
|
|
1540
|
+
query: "mature non-medical home care agencies billable hours franchise caregiver recruiting proof gate qualification export approval",
|
|
1541
|
+
scopes: ["workspace", "operator_notes"],
|
|
1542
|
+
topK: 10,
|
|
1543
|
+
required: true,
|
|
1544
|
+
rationale: "Load home-care ICP gates, source lanes, qualification thresholds, and home-care exclusion logic."
|
|
1545
|
+
}],
|
|
1546
|
+
constraints: {
|
|
1547
|
+
deliverabilityNotes: [
|
|
1548
|
+
"Company proof and strict ICP gate must pass before contact search, email finding, Signaliz signals, or export.",
|
|
1549
|
+
"Home health is an exclusion signal, not a synonym for home care."
|
|
1550
|
+
]
|
|
1551
|
+
},
|
|
1552
|
+
signalizDefaults: {
|
|
1553
|
+
copy: {
|
|
1554
|
+
offerContext: "Use angles around after-hours shift recovery, billing/payroll exceptions, multi-location consistency, and caregiver retention only when supported by evidence."
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
agencyContext: {
|
|
1558
|
+
partnerEcosystem: ["clay", "octave", "signaliz", "instantly", "nango"]
|
|
1559
|
+
},
|
|
1560
|
+
operatingPlaybookSlugs: ["proof-first-vertical-gate", "domain-first-recovery", "table-workflow-handoff"]
|
|
1561
|
+
},
|
|
1562
|
+
{
|
|
1563
|
+
slug: "agency-founder-led",
|
|
1564
|
+
label: "Founder-Led Agency Services",
|
|
1565
|
+
aliases: ["agency founder", "founder-led agency", "agency-founder-led"],
|
|
1566
|
+
defaultTargetCount: 3e3,
|
|
1567
|
+
campaignName: "Founder-Led Agency Executive Campaign",
|
|
1568
|
+
accountContext: [
|
|
1569
|
+
"Strategy template: agency founder, owner, CEO, and executive sourcing across marketing services, creative, web, PR, ecommerce, paid media, SEO, content, and specialist digital agencies.",
|
|
1570
|
+
"Use suppression files, company-domain pool review, people/email verification queues, and final approval gates before any delivery action."
|
|
1571
|
+
].join(" "),
|
|
1572
|
+
icp: {
|
|
1573
|
+
personas: ["Founder", "Owner", "CEO", "Managing Partner", "President", "Agency Executive"],
|
|
1574
|
+
industries: [
|
|
1575
|
+
"Marketing services",
|
|
1576
|
+
"Advertising services",
|
|
1577
|
+
"Digital marketing agency",
|
|
1578
|
+
"Creative agency",
|
|
1579
|
+
"PR and communications",
|
|
1580
|
+
"Ecommerce agency",
|
|
1581
|
+
"Paid media agency",
|
|
1582
|
+
"SEO agency",
|
|
1583
|
+
"Content agency"
|
|
1584
|
+
],
|
|
1585
|
+
companySizes: ["11-50", "25-150", "51-200"],
|
|
1586
|
+
geographies: ["United States"],
|
|
1587
|
+
keywords: [
|
|
1588
|
+
"agency founder",
|
|
1589
|
+
"performance marketing",
|
|
1590
|
+
"paid media",
|
|
1591
|
+
"SEO",
|
|
1592
|
+
"content",
|
|
1593
|
+
"creative",
|
|
1594
|
+
"web design",
|
|
1595
|
+
"brand agency",
|
|
1596
|
+
"PR communications",
|
|
1597
|
+
"Shopify",
|
|
1598
|
+
"Klaviyo"
|
|
1599
|
+
],
|
|
1600
|
+
exclusions: ["enterprise holding company", "staffing", "recruiting", "software-only vendor", "freelancer-only profile"],
|
|
1601
|
+
requireVerifiedEmail: true
|
|
1602
|
+
},
|
|
1603
|
+
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1604
|
+
preferredProviders: ["signaliz_native", "octave"],
|
|
1605
|
+
memoryQueries: [{
|
|
1606
|
+
query: "agency founder owner CEO marketing services suppression domain pool email verification final approval gate",
|
|
1607
|
+
scopes: ["workspace", "operator_notes"],
|
|
1608
|
+
topK: 10,
|
|
1609
|
+
required: true,
|
|
1610
|
+
rationale: "Load agency-segment sourcing lanes, suppression rules, and verification workflow lessons."
|
|
1611
|
+
}],
|
|
1612
|
+
constraints: {
|
|
1613
|
+
deliverabilityNotes: [
|
|
1614
|
+
"Keep email and domain suppression visible in the plan.",
|
|
1615
|
+
"Do not export or send until the final verified file and suppression checks are approved."
|
|
1616
|
+
]
|
|
1617
|
+
},
|
|
1618
|
+
agencyContext: {
|
|
1619
|
+
partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
|
|
1620
|
+
},
|
|
1621
|
+
operatingPlaybookSlugs: ["net-new-suppressed-list", "signal-led-copy-approval", "table-workflow-handoff"]
|
|
1622
|
+
},
|
|
1623
|
+
{
|
|
1624
|
+
slug: "cloud-infrastructure-displacement",
|
|
1625
|
+
label: "Cloud Infrastructure Displacement",
|
|
1626
|
+
aliases: ["cloud displacement", "private cloud displacement", "cloud infrastructure", "cloud-infrastructure-displacement"],
|
|
1627
|
+
defaultTargetCount: 3e3,
|
|
1628
|
+
campaignName: "Cloud Infrastructure Displacement Campaign",
|
|
1629
|
+
accountContext: [
|
|
1630
|
+
"Strategy template: managed infrastructure, private cloud, disaster recovery, colocation, and VMware/Broadcom displacement motions.",
|
|
1631
|
+
"The spend-efficient ladder is Signaliz company search, Octave company qualification, Signaliz people search, Octave person qualification, then Signaliz email finding and verification."
|
|
1632
|
+
].join(" "),
|
|
1633
|
+
icp: {
|
|
1634
|
+
personas: [
|
|
1635
|
+
"CTO",
|
|
1636
|
+
"CIO",
|
|
1637
|
+
"CISO",
|
|
1638
|
+
"CFO tied to cloud spend",
|
|
1639
|
+
"VP Engineering",
|
|
1640
|
+
"VP Infrastructure",
|
|
1641
|
+
"VP Cloud",
|
|
1642
|
+
"Head of Platform",
|
|
1643
|
+
"Director IT",
|
|
1644
|
+
"Cloud Architect",
|
|
1645
|
+
"Infrastructure Architect"
|
|
1646
|
+
],
|
|
1647
|
+
industries: [
|
|
1648
|
+
"SaaS",
|
|
1649
|
+
"Software",
|
|
1650
|
+
"Cybersecurity",
|
|
1651
|
+
"Fintech",
|
|
1652
|
+
"Healthcare technology",
|
|
1653
|
+
"Compliance and GRC",
|
|
1654
|
+
"DevOps",
|
|
1655
|
+
"Infrastructure",
|
|
1656
|
+
"Observability"
|
|
1657
|
+
],
|
|
1658
|
+
companySizes: ["$10M-$500M revenue", "50-1500 employees"],
|
|
1659
|
+
geographies: ["United States"],
|
|
1660
|
+
keywords: [
|
|
1661
|
+
"VMware Broadcom",
|
|
1662
|
+
"VxRail",
|
|
1663
|
+
"cloud cost pressure",
|
|
1664
|
+
"private cloud",
|
|
1665
|
+
"Proxmox",
|
|
1666
|
+
"Hyper-V",
|
|
1667
|
+
"managed infrastructure",
|
|
1668
|
+
"DRaaS",
|
|
1669
|
+
"colocation",
|
|
1670
|
+
"uptime",
|
|
1671
|
+
"reliability"
|
|
1672
|
+
],
|
|
1673
|
+
exclusions: [
|
|
1674
|
+
"MSP competitor",
|
|
1675
|
+
"hosting provider",
|
|
1676
|
+
"data center competitor",
|
|
1677
|
+
"staffing",
|
|
1678
|
+
"recruiting",
|
|
1679
|
+
"international-only",
|
|
1680
|
+
"procurement-only",
|
|
1681
|
+
"AI GPU-heavy infrastructure"
|
|
1682
|
+
],
|
|
1683
|
+
requireVerifiedEmail: true
|
|
1684
|
+
},
|
|
1685
|
+
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1686
|
+
preferredProviders: ["signaliz_native", "octave"],
|
|
1687
|
+
memoryQueries: [{
|
|
1688
|
+
query: "cloud hosting infrastructure VMware Broadcom qualification verified email persona trigger SKU mapping",
|
|
1689
|
+
scopes: ["workspace", "operator_notes"],
|
|
1690
|
+
topK: 10,
|
|
1691
|
+
required: true,
|
|
1692
|
+
rationale: "Load cloud-infrastructure qualification order, persona clusters, trigger/SKU mapping, and verified-list QA rules."
|
|
1693
|
+
}],
|
|
1694
|
+
constraints: {
|
|
1695
|
+
deliverabilityNotes: [
|
|
1696
|
+
"Qualify accounts and people before email verification.",
|
|
1697
|
+
"If signal enrichment is deferred or unavailable, state it plainly instead of inventing evidence."
|
|
1698
|
+
]
|
|
1699
|
+
},
|
|
1700
|
+
signalizDefaults: {
|
|
1701
|
+
copy: {
|
|
1702
|
+
offerContext: "Map pain to routes such as VMware/Broadcom exit, cloud cost reduction, infrastructure modernization, compliance gap, managed infrastructure, private cloud, Proxmox/Hyper-V, colocation, or DRaaS."
|
|
1703
|
+
}
|
|
1704
|
+
},
|
|
1705
|
+
agencyContext: {
|
|
1706
|
+
partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
|
|
1707
|
+
},
|
|
1708
|
+
operatingPlaybookSlugs: ["proof-first-vertical-gate", "domain-first-recovery", "signal-led-copy-approval"]
|
|
1709
|
+
}
|
|
1710
|
+
];
|
|
1223
1711
|
var CampaignBuilderAgent = class {
|
|
1224
1712
|
constructor(client) {
|
|
1225
1713
|
this.client = client;
|
|
1226
1714
|
}
|
|
1227
1715
|
async createPlan(request, options = {}) {
|
|
1716
|
+
const resolvedRequest = applyCampaignBuilderStrategyTemplate(request);
|
|
1228
1717
|
const warnings = [];
|
|
1229
|
-
const workspaceContext =
|
|
1230
|
-
const scopeResult = options.scopeCampaign === false ? void 0 : await this.scopeCampaign(
|
|
1718
|
+
const workspaceContext = resolvedRequest.workspaceContext ?? await this.getWorkspaceContext(warnings);
|
|
1719
|
+
const scopeResult = options.scopeCampaign === false ? void 0 : await this.scopeCampaign(resolvedRequest, warnings);
|
|
1231
1720
|
if (options.discoverCapabilities !== false) {
|
|
1232
|
-
await this.discoverPlannedRoutes(
|
|
1721
|
+
await this.discoverPlannedRoutes(resolvedRequest, warnings);
|
|
1233
1722
|
}
|
|
1234
|
-
|
|
1723
|
+
const plan = createCampaignBuilderAgentPlan(resolvedRequest, {
|
|
1235
1724
|
workspaceContext,
|
|
1236
1725
|
scopeBuildArgs: asRecord(scopeResult?.build_campaign_args ?? scopeResult?.buildCampaignArgs),
|
|
1237
1726
|
warnings
|
|
1238
1727
|
});
|
|
1728
|
+
if (options.includeStrategyMemoryStatus !== false) {
|
|
1729
|
+
await this.attachStrategyMemoryStatus(plan, warnings);
|
|
1730
|
+
}
|
|
1731
|
+
if (options.includeKernelPlan !== false) {
|
|
1732
|
+
await this.attachKernelCampaignBuildPlan(plan, warnings);
|
|
1733
|
+
}
|
|
1734
|
+
if (options.includeDeliveryRisk !== false) {
|
|
1735
|
+
await this.attachDeliveryRiskPreflight(plan, warnings);
|
|
1736
|
+
}
|
|
1737
|
+
return plan;
|
|
1738
|
+
}
|
|
1739
|
+
async commitPlan(plan, options = {}) {
|
|
1740
|
+
const writeMode = options.confirm === true && options.dryRun === false;
|
|
1741
|
+
if (writeMode && !options.approvedBy) {
|
|
1742
|
+
throw new Error("Campaign builder plan commit requires approvedBy before writing state");
|
|
1743
|
+
}
|
|
1744
|
+
const plannerStep = plan.mcpFlow.find((step) => step.id === "agency-campaign-build-plan");
|
|
1745
|
+
const plannerArgs = asRecord(plannerStep?.arguments);
|
|
1746
|
+
const commitArgs = compact({
|
|
1747
|
+
campaign_id: plan.buildRequest.gtmCampaignId,
|
|
1748
|
+
name: plan.campaignName,
|
|
1749
|
+
campaign_brief: plan.buildRequest.prompt || plan.goal,
|
|
1750
|
+
target_icp: plan.buildRequest.icp ? buildGtmTargetIcpContext(plan.buildRequest.icp) : void 0,
|
|
1751
|
+
lead_count: plan.targetCount,
|
|
1752
|
+
layers: plannerArgs.layers,
|
|
1753
|
+
preferred_providers: plannerArgs.preferred_providers,
|
|
1754
|
+
plan_snapshot: Object.keys(asRecord(plan.kernelPlan)).length > 0 ? plan.kernelPlan : buildFallbackPlanSnapshot(plan),
|
|
1755
|
+
send_config: plan.buildRequest.delivery ? {
|
|
1756
|
+
delivery: plan.buildRequest.delivery,
|
|
1757
|
+
approval_required: true
|
|
1758
|
+
} : void 0,
|
|
1759
|
+
brain_config: compact({
|
|
1760
|
+
campaign_builder_agent_v1: {
|
|
1761
|
+
plan_id: plan.planId,
|
|
1762
|
+
kernel_plan_attached: Object.keys(asRecord(plan.kernelPlan)).length > 0,
|
|
1763
|
+
approval_ids: plan.approvals.map((approval) => approval.id)
|
|
1764
|
+
},
|
|
1765
|
+
brain_defaults: plan.buildRequest.brainDefaults,
|
|
1766
|
+
brain_preflight: plan.buildRequest.brainPreflight,
|
|
1767
|
+
delivery_risk_preflight: plan.buildRequest.deliveryRisk,
|
|
1768
|
+
delivery_risk: plan.buildRequest.deliveryRisk
|
|
1769
|
+
}),
|
|
1770
|
+
metadata: {
|
|
1771
|
+
campaign_builder_agent_v1: {
|
|
1772
|
+
plan_id: plan.planId,
|
|
1773
|
+
source: "campaign-builder-agent",
|
|
1774
|
+
approval_required: plan.approvals.some((approval) => approval.blocking),
|
|
1775
|
+
approval_ids: plan.approvals.map((approval) => approval.id),
|
|
1776
|
+
estimated_credits: plan.estimatedCredits
|
|
1777
|
+
},
|
|
1778
|
+
brain_delivery_risk_preflight: plan.buildRequest.deliveryRisk,
|
|
1779
|
+
delivery_risk: plan.buildRequest.deliveryRisk
|
|
1780
|
+
},
|
|
1781
|
+
approval_required: plan.approvals.some((approval) => approval.blocking),
|
|
1782
|
+
actor_type: "agent",
|
|
1783
|
+
actor_id: options.approvedBy,
|
|
1784
|
+
rationale: options.rationale || "Committed a reviewed strategy-template campaign-builder plan before execution.",
|
|
1785
|
+
idempotency_key: options.idempotencyKey,
|
|
1786
|
+
dry_run: !writeMode,
|
|
1787
|
+
confirm: writeMode
|
|
1788
|
+
});
|
|
1789
|
+
const data = asRecord(await this.callMcp("gtm_campaign_build_plan_commit", commitArgs));
|
|
1790
|
+
const result = mapPlanCommitResult(data);
|
|
1791
|
+
if (result.wroteState && result.campaignId) {
|
|
1792
|
+
plan.buildRequest.gtmCampaignId = result.campaignId;
|
|
1793
|
+
refreshBuildStepArguments(plan);
|
|
1794
|
+
}
|
|
1795
|
+
return result;
|
|
1239
1796
|
}
|
|
1240
1797
|
async dryRunPlan(plan, options) {
|
|
1241
1798
|
let args = buildCampaignArgs({
|
|
@@ -1270,6 +1827,15 @@ var CampaignBuilderAgent = class {
|
|
|
1270
1827
|
if (missing.length > 0) {
|
|
1271
1828
|
throw new Error(`Campaign builder approval is incomplete: ${missing.map((a) => a.label).join(", ")}`);
|
|
1272
1829
|
}
|
|
1830
|
+
if (options?.commitBeforeLaunch && !plan.buildRequest.gtmCampaignId) {
|
|
1831
|
+
await this.commitPlan(plan, {
|
|
1832
|
+
confirm: true,
|
|
1833
|
+
dryRun: false,
|
|
1834
|
+
approvedBy: approval.approvedBy,
|
|
1835
|
+
idempotencyKey: options.idempotencyKey ? `${options.idempotencyKey}:plan-commit` : void 0,
|
|
1836
|
+
rationale: "Committed reviewed campaign-builder plan immediately before approved launch."
|
|
1837
|
+
});
|
|
1838
|
+
}
|
|
1273
1839
|
let args = buildCampaignArgs({
|
|
1274
1840
|
...plan.buildRequest,
|
|
1275
1841
|
dryRun: false,
|
|
@@ -1316,8 +1882,8 @@ var CampaignBuilderAgent = class {
|
|
|
1316
1882
|
try {
|
|
1317
1883
|
return await this.callMcp("scope_campaign", {
|
|
1318
1884
|
prompt: request.goal,
|
|
1319
|
-
|
|
1320
|
-
|
|
1885
|
+
account_label: campaignBuilderAccountLabel(request),
|
|
1886
|
+
account_context: campaignBuilderAccountContext(request),
|
|
1321
1887
|
campaign_goal: request.goal,
|
|
1322
1888
|
target_count: request.targetCount,
|
|
1323
1889
|
approval_policy: request.approvalPolicy?.requireHumanApproval ? "human_required" : "standard"
|
|
@@ -1342,25 +1908,70 @@ var CampaignBuilderAgent = class {
|
|
|
1342
1908
|
}
|
|
1343
1909
|
}
|
|
1344
1910
|
}
|
|
1911
|
+
async attachStrategyMemoryStatus(plan, warnings) {
|
|
1912
|
+
const statusStep = plan.mcpFlow.find((step) => step.id === "strategy-memory-status");
|
|
1913
|
+
if (!statusStep) return;
|
|
1914
|
+
try {
|
|
1915
|
+
const status = asRecord(await this.callMcp("gtm_campaign_strategy_memory_status", asRecord(statusStep.arguments)));
|
|
1916
|
+
plan.strategyMemoryStatus = status;
|
|
1917
|
+
const blockers = arrayOfStrings(status.blockers) ?? [];
|
|
1918
|
+
if (status.ready === false || blockers.length > 0) {
|
|
1919
|
+
warnings.push(`Strategy memory readiness is incomplete: ${blockers.join("; ") || "missing required strategy or workflow memory"}`);
|
|
1920
|
+
}
|
|
1921
|
+
} catch (error) {
|
|
1922
|
+
warnings.push(`Strategy memory readiness check failed: ${errorMessage(error)}`);
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
async attachKernelCampaignBuildPlan(plan, warnings) {
|
|
1926
|
+
const plannerStep = plan.mcpFlow.find((step) => step.id === "agency-campaign-build-plan");
|
|
1927
|
+
if (!plannerStep) return;
|
|
1928
|
+
try {
|
|
1929
|
+
const kernelPlan = await this.callMcp("gtm_campaign_build_plan", asRecord(plannerStep.arguments));
|
|
1930
|
+
plan.kernelPlan = asRecord(kernelPlan);
|
|
1931
|
+
const brainDefaults = asRecord(plan.kernelPlan.brain_defaults ?? plan.kernelPlan.brainDefaults);
|
|
1932
|
+
if (Object.keys(brainDefaults).length > 0 && Object.keys(asRecord(plan.buildRequest.brainDefaults)).length === 0) {
|
|
1933
|
+
plan.buildRequest.brainDefaults = brainDefaults;
|
|
1934
|
+
refreshBuildStepArguments(plan);
|
|
1935
|
+
}
|
|
1936
|
+
} catch (error) {
|
|
1937
|
+
warnings.push(`GTM Kernel campaign build plan failed: ${errorMessage(error)}`);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
async attachDeliveryRiskPreflight(plan, warnings) {
|
|
1941
|
+
if (Object.keys(asRecord(plan.buildRequest.deliveryRisk)).length > 0) return;
|
|
1942
|
+
const riskStep = plan.mcpFlow.find((step) => step.tool === "gtm_brain_delivery_risk");
|
|
1943
|
+
if (!riskStep) return;
|
|
1944
|
+
try {
|
|
1945
|
+
const deliveryRisk = asRecord(await this.callMcp("gtm_brain_delivery_risk", asRecord(riskStep.arguments)));
|
|
1946
|
+
if (Object.keys(deliveryRisk).length > 0) {
|
|
1947
|
+
plan.buildRequest.deliveryRisk = deliveryRisk;
|
|
1948
|
+
refreshBuildStepArguments(plan);
|
|
1949
|
+
}
|
|
1950
|
+
} catch (error) {
|
|
1951
|
+
warnings.push(`GTM Brain delivery risk preflight failed: ${errorMessage(error)}`);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1345
1954
|
async callMcp(tool, args) {
|
|
1346
1955
|
return this.client.mcp("tools/call", { name: tool, arguments: compact(args) });
|
|
1347
1956
|
}
|
|
1348
1957
|
};
|
|
1349
1958
|
function createCampaignBuilderAgentPlan(request, context = {}) {
|
|
1350
|
-
const
|
|
1351
|
-
const
|
|
1352
|
-
const
|
|
1353
|
-
const
|
|
1354
|
-
const
|
|
1355
|
-
const
|
|
1356
|
-
const
|
|
1357
|
-
const
|
|
1959
|
+
const resolvedRequest = applyCampaignBuilderStrategyTemplate(request);
|
|
1960
|
+
const defaults = mergeDefaults(resolvedRequest.signalizDefaults);
|
|
1961
|
+
const targetCount = resolvedRequest.targetCount ?? numberOrUndefined2(context.scopeBuildArgs?.target_count) ?? 100;
|
|
1962
|
+
const campaignName = resolvedRequest.campaignName ?? stringValue(context.scopeBuildArgs?.name) ?? titleFromGoal(resolvedRequest.goal);
|
|
1963
|
+
const workspaceContext = context.workspaceContext ?? resolvedRequest.workspaceContext ?? {};
|
|
1964
|
+
const memory = normalizeMemory(resolvedRequest);
|
|
1965
|
+
const routes = normalizeRoutes(resolvedRequest);
|
|
1966
|
+
const operatingPlaybooks = getCampaignBuilderOperatingPlaybooksForRequest(resolvedRequest);
|
|
1967
|
+
const estimatedCredits = estimateCredits(resolvedRequest, defaults, targetCount);
|
|
1968
|
+
const buildRequest = createBuildRequest(resolvedRequest, defaults, targetCount, campaignName, context.scopeBuildArgs, routes, memory, context.scopeBrainPreflight);
|
|
1358
1969
|
const brainPreflight = asRecord(buildRequest.brainPreflight);
|
|
1359
|
-
const approvals = deriveApprovals(
|
|
1970
|
+
const approvals = deriveApprovals(resolvedRequest, routes, memory, estimatedCredits, defaults.delivery?.approvalRequired !== false);
|
|
1360
1971
|
return {
|
|
1361
|
-
planId: `cbp_${hashString(JSON.stringify({ goal:
|
|
1972
|
+
planId: `cbp_${hashString(JSON.stringify({ goal: resolvedRequest.goal, campaignName, targetCount, routes }))}`,
|
|
1362
1973
|
campaignName,
|
|
1363
|
-
goal:
|
|
1974
|
+
goal: resolvedRequest.goal,
|
|
1364
1975
|
targetCount,
|
|
1365
1976
|
workspaceContext,
|
|
1366
1977
|
memory,
|
|
@@ -1373,7 +1984,8 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
|
|
|
1373
1984
|
approvals,
|
|
1374
1985
|
buildRequest,
|
|
1375
1986
|
brainPreflight,
|
|
1376
|
-
|
|
1987
|
+
operatingPlaybooks,
|
|
1988
|
+
mcpFlow: createMcpFlow(resolvedRequest, buildRequest, routes, memory, approvals),
|
|
1377
1989
|
estimatedCredits,
|
|
1378
1990
|
warnings: context.warnings ?? []
|
|
1379
1991
|
};
|
|
@@ -1401,6 +2013,249 @@ function createCampaignBuilderApproval(plan, input) {
|
|
|
1401
2013
|
approvedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1402
2014
|
};
|
|
1403
2015
|
}
|
|
2016
|
+
function getCampaignBuilderStrategyTemplate(value) {
|
|
2017
|
+
const normalized = normalizeTemplateKey(value);
|
|
2018
|
+
if (!normalized) return void 0;
|
|
2019
|
+
return CAMPAIGN_BUILDER_STRATEGY_TEMPLATES.find(
|
|
2020
|
+
(template) => template.slug === normalized || template.aliases.some((alias) => normalizeTemplateKey(alias) === normalized)
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
function getCampaignBuilderOperatingPlaybook(value) {
|
|
2024
|
+
const normalized = normalizeTemplateKey(value);
|
|
2025
|
+
if (!normalized) return void 0;
|
|
2026
|
+
return CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS.find((playbook) => playbook.slug === normalized);
|
|
2027
|
+
}
|
|
2028
|
+
function getCampaignBuilderOperatingPlaybooksForRequest(request) {
|
|
2029
|
+
const template = getCampaignBuilderStrategyTemplate(request.strategyTemplate);
|
|
2030
|
+
const slugs = uniqueStrings([
|
|
2031
|
+
...template?.operatingPlaybookSlugs ?? [],
|
|
2032
|
+
...request.operatingPlaybooks ?? []
|
|
2033
|
+
]);
|
|
2034
|
+
return slugs.map(getCampaignBuilderOperatingPlaybook).filter((playbook) => Boolean(playbook));
|
|
2035
|
+
}
|
|
2036
|
+
function applyCampaignBuilderStrategyTemplate(request) {
|
|
2037
|
+
const template = getCampaignBuilderStrategyTemplate(request.strategyTemplate);
|
|
2038
|
+
if (!template) return request;
|
|
2039
|
+
return {
|
|
2040
|
+
...request,
|
|
2041
|
+
strategyTemplate: template.slug,
|
|
2042
|
+
campaignName: request.campaignName ?? template.campaignName,
|
|
2043
|
+
accountContext: mergeText(template.accountContext, campaignBuilderAccountContext(request)),
|
|
2044
|
+
targetCount: request.targetCount ?? template.defaultTargetCount,
|
|
2045
|
+
icp: mergeIcp(template.icp, request.icp),
|
|
2046
|
+
builtIns: request.builtIns ?? template.builtIns,
|
|
2047
|
+
operatingPlaybooks: uniqueStrings([
|
|
2048
|
+
...template.operatingPlaybookSlugs,
|
|
2049
|
+
...request.operatingPlaybooks ?? []
|
|
2050
|
+
]),
|
|
2051
|
+
preferredProviders: uniqueStrings([
|
|
2052
|
+
...template.preferredProviders,
|
|
2053
|
+
...request.preferredProviders ?? []
|
|
2054
|
+
]),
|
|
2055
|
+
memory: mergeMemoryPlan({
|
|
2056
|
+
enabled: true,
|
|
2057
|
+
useWorkspaceHistory: true,
|
|
2058
|
+
useNetworkPatterns: request.memory?.useNetworkPatterns,
|
|
2059
|
+
privacyMode: request.memory?.privacyMode,
|
|
2060
|
+
queries: template.memoryQueries
|
|
2061
|
+
}, request.memory),
|
|
2062
|
+
constraints: mergeConstraints(template.constraints, request.constraints),
|
|
2063
|
+
signalizDefaults: mergeSignalizDefaultOverrides(template.signalizDefaults, request.signalizDefaults),
|
|
2064
|
+
agencyContext: mergeAgencyContext(template.agencyContext, request.agencyContext)
|
|
2065
|
+
};
|
|
2066
|
+
}
|
|
2067
|
+
function createCampaignBuilderAgentRequestTemplate(input = {}) {
|
|
2068
|
+
const builtIns = new Set(input.builtIns ?? DEFAULT_CAMPAIGN_BUILDER_BUILT_INS);
|
|
2069
|
+
if (input.includeLocalLeads) builtIns.add("local_leads");
|
|
2070
|
+
const integrations = input.integrations ?? (input.includeCustomToolPlaceholder ? [createCampaignBuilderToolRoute({
|
|
2071
|
+
provider: "custom_mcp",
|
|
2072
|
+
layer: "enrichment",
|
|
2073
|
+
gtmLayers: ["company_enrichment"],
|
|
2074
|
+
toolName: "workspace_enrich",
|
|
2075
|
+
mcpServerName: "workspace-mcp",
|
|
2076
|
+
label: "Workspace enrichment MCP",
|
|
2077
|
+
mode: "if_available",
|
|
2078
|
+
approvalRequired: true
|
|
2079
|
+
})] : void 0);
|
|
2080
|
+
const preferredProviders = uniqueStrings([
|
|
2081
|
+
...input.preferredProviders ?? [],
|
|
2082
|
+
...input.includeNango === false ? [] : ["nango"]
|
|
2083
|
+
]);
|
|
2084
|
+
const templated = applyCampaignBuilderStrategyTemplate({
|
|
2085
|
+
goal: input.goal || "Build a strategy-template campaign for mature operators in the target ICP.",
|
|
2086
|
+
strategyTemplate: input.strategyTemplate || "non-medical-home-care",
|
|
2087
|
+
campaignName: input.campaignName,
|
|
2088
|
+
accountLabel: input.accountLabel || "Workspace Campaign",
|
|
2089
|
+
accountContext: input.accountContext || "Use private workspace memory, current suppression rules, verified-email quality gates, and approval-gated provider routes.",
|
|
2090
|
+
targetCount: input.targetCount,
|
|
2091
|
+
icp: input.icp ?? {
|
|
2092
|
+
personas: ["Operations leader", "Founder", "Revenue leader"],
|
|
2093
|
+
industries: ["B2B services", "Vertical software", "Local operators"],
|
|
2094
|
+
geographies: ["United States"],
|
|
2095
|
+
keywords: ["growth", "operations", "customer acquisition"],
|
|
2096
|
+
requireVerifiedEmail: true
|
|
2097
|
+
},
|
|
2098
|
+
builtIns: [...builtIns],
|
|
2099
|
+
integrations,
|
|
2100
|
+
customerTools: input.customerTools,
|
|
2101
|
+
preferredProviders,
|
|
2102
|
+
constraints: input.constraints,
|
|
2103
|
+
workspaceContext: input.workspaceContext,
|
|
2104
|
+
brainDefaults: input.brainDefaults,
|
|
2105
|
+
deliveryRisk: input.deliveryRisk,
|
|
2106
|
+
gtmCampaignId: input.gtmCampaignId
|
|
2107
|
+
});
|
|
2108
|
+
return compact({
|
|
2109
|
+
...templated,
|
|
2110
|
+
memory: mergeMemoryPlan({
|
|
2111
|
+
enabled: true,
|
|
2112
|
+
useWorkspaceHistory: true,
|
|
2113
|
+
useNetworkPatterns: false,
|
|
2114
|
+
privacyMode: "anonymized_patterns",
|
|
2115
|
+
queries: [{
|
|
2116
|
+
query: `${templated.strategyTemplate || "strategy-template"} campaign reply patterns, objections, qualification gates, and verified-email QA`,
|
|
2117
|
+
scopes: ["workspace", "operator_notes"],
|
|
2118
|
+
topK: 10,
|
|
2119
|
+
required: true,
|
|
2120
|
+
rationale: "Load approved private strategy and workflow patterns before campaign planning."
|
|
2121
|
+
}]
|
|
2122
|
+
}, input.memory),
|
|
2123
|
+
agencyContext: mergeAgencyContext({
|
|
2124
|
+
strategyModel: "strategy_template",
|
|
2125
|
+
includeStrategyPatterns: true,
|
|
2126
|
+
includeWorkflowPatterns: true,
|
|
2127
|
+
includeNangoCatalog: true,
|
|
2128
|
+
partnerEcosystem: input.includeNango === false ? ["signaliz"] : ["signaliz", "nango"]
|
|
2129
|
+
}, input.agencyContext),
|
|
2130
|
+
signalizDefaults: mergeSignalizDefaultOverrides({
|
|
2131
|
+
maxCredits: input.signalizDefaults?.maxCredits,
|
|
2132
|
+
delivery: {
|
|
2133
|
+
enabled: true,
|
|
2134
|
+
destinationType: input.signalizDefaults?.delivery?.destinationType ?? "json",
|
|
2135
|
+
approvalRequired: true
|
|
2136
|
+
}
|
|
2137
|
+
}, input.signalizDefaults),
|
|
2138
|
+
approvalPolicy: {
|
|
2139
|
+
requireHumanApproval: true,
|
|
2140
|
+
maxCreditsWithoutApproval: 0,
|
|
2141
|
+
requireApprovalFor: DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES,
|
|
2142
|
+
...input.approvalPolicy
|
|
2143
|
+
}
|
|
2144
|
+
});
|
|
2145
|
+
}
|
|
2146
|
+
function createCampaignBuilderToolRoute(input) {
|
|
2147
|
+
return {
|
|
2148
|
+
provider: input.provider ?? "custom_mcp",
|
|
2149
|
+
layer: input.layer,
|
|
2150
|
+
toolName: input.toolName,
|
|
2151
|
+
mcpServerName: input.mcpServerName,
|
|
2152
|
+
label: input.label,
|
|
2153
|
+
mode: input.mode ?? "if_available",
|
|
2154
|
+
gtmLayer: input.gtmLayer,
|
|
2155
|
+
gtmLayers: input.gtmLayers,
|
|
2156
|
+
approvalRequired: input.approvalRequired ?? input.mode === "required",
|
|
2157
|
+
config: input.config,
|
|
2158
|
+
rationale: `${input.label ?? input.provider ?? "Custom tool"} is a user-provided campaign-builder route for ${input.layer}.`
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
function normalizeTemplateKey(value) {
|
|
2162
|
+
return String(value || "").trim().toLowerCase().replace(/[_\s]+/g, "-");
|
|
2163
|
+
}
|
|
2164
|
+
function mergeText(base, override) {
|
|
2165
|
+
if (base && override && !base.includes(override)) return `${base}
|
|
2166
|
+
${override}`;
|
|
2167
|
+
return override ?? base;
|
|
2168
|
+
}
|
|
2169
|
+
function mergeIcp(base, override) {
|
|
2170
|
+
if (!base) return override;
|
|
2171
|
+
if (!override) return base;
|
|
2172
|
+
return {
|
|
2173
|
+
...base,
|
|
2174
|
+
...override,
|
|
2175
|
+
personas: uniqueStrings([...base.personas ?? [], ...override.personas ?? []]),
|
|
2176
|
+
industries: uniqueStrings([...base.industries ?? [], ...override.industries ?? []]),
|
|
2177
|
+
companySizes: uniqueStrings([...base.companySizes ?? [], ...override.companySizes ?? []]),
|
|
2178
|
+
geographies: uniqueStrings([...base.geographies ?? [], ...override.geographies ?? []]),
|
|
2179
|
+
keywords: uniqueStrings([...base.keywords ?? [], ...override.keywords ?? []]),
|
|
2180
|
+
exclusions: uniqueStrings([...base.exclusions ?? [], ...override.exclusions ?? []]),
|
|
2181
|
+
requireVerifiedEmail: override.requireVerifiedEmail ?? base.requireVerifiedEmail
|
|
2182
|
+
};
|
|
2183
|
+
}
|
|
2184
|
+
function mergeMemoryPlan(base, override) {
|
|
2185
|
+
const queries = dedupeMemoryQueries([...base.queries ?? [], ...override?.queries ?? []]);
|
|
2186
|
+
return {
|
|
2187
|
+
...base,
|
|
2188
|
+
...override,
|
|
2189
|
+
queries: queries.length > 0 ? queries : void 0,
|
|
2190
|
+
enabled: override?.enabled ?? base.enabled,
|
|
2191
|
+
useWorkspaceHistory: override?.useWorkspaceHistory ?? base.useWorkspaceHistory,
|
|
2192
|
+
useNetworkPatterns: override?.useNetworkPatterns ?? base.useNetworkPatterns,
|
|
2193
|
+
privacyMode: override?.privacyMode ?? base.privacyMode
|
|
2194
|
+
};
|
|
2195
|
+
}
|
|
2196
|
+
function dedupeMemoryQueries(queries) {
|
|
2197
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2198
|
+
return queries.filter((query) => {
|
|
2199
|
+
const key = query.query.trim().toLowerCase();
|
|
2200
|
+
if (!key || seen.has(key)) return false;
|
|
2201
|
+
seen.add(key);
|
|
2202
|
+
return true;
|
|
2203
|
+
});
|
|
2204
|
+
}
|
|
2205
|
+
function mergeConstraints(base, override) {
|
|
2206
|
+
if (!base) return override;
|
|
2207
|
+
if (!override) return base;
|
|
2208
|
+
return {
|
|
2209
|
+
...base,
|
|
2210
|
+
...override,
|
|
2211
|
+
geographies: uniqueStrings([...base.geographies ?? [], ...override.geographies ?? []]),
|
|
2212
|
+
exclusions: uniqueStrings([...base.exclusions ?? [], ...override.exclusions ?? []]),
|
|
2213
|
+
deliverabilityNotes: uniqueStrings([...base.deliverabilityNotes ?? [], ...override.deliverabilityNotes ?? []]),
|
|
2214
|
+
maxDailySends: override.maxDailySends ?? base.maxDailySends
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2217
|
+
function mergeSignalizDefaultOverrides(base, override) {
|
|
2218
|
+
if (!base) return override;
|
|
2219
|
+
if (!override) return base;
|
|
2220
|
+
return {
|
|
2221
|
+
...base,
|
|
2222
|
+
...override,
|
|
2223
|
+
signals: { ...base.signals, ...override.signals },
|
|
2224
|
+
qualification: { ...base.qualification, ...override.qualification },
|
|
2225
|
+
copy: { ...base.copy, ...override.copy },
|
|
2226
|
+
delivery: { ...base.delivery, ...override.delivery }
|
|
2227
|
+
};
|
|
2228
|
+
}
|
|
2229
|
+
function mergeAgencyContext(base, override) {
|
|
2230
|
+
if (!base) return override;
|
|
2231
|
+
if (!override) return base;
|
|
2232
|
+
return {
|
|
2233
|
+
...base,
|
|
2234
|
+
...override,
|
|
2235
|
+
partnerEcosystem: uniqueStrings([...base.partnerEcosystem ?? [], ...override.partnerEcosystem ?? []]),
|
|
2236
|
+
strategyModel: override.strategyModel ?? base.strategyModel,
|
|
2237
|
+
includeStrategyPatterns: override.includeStrategyPatterns ?? base.includeStrategyPatterns,
|
|
2238
|
+
includeWorkflowPatterns: override.includeWorkflowPatterns ?? base.includeWorkflowPatterns,
|
|
2239
|
+
includeClayPatterns: override.includeClayPatterns ?? base.includeClayPatterns,
|
|
2240
|
+
includeNangoCatalog: override.includeNangoCatalog ?? base.includeNangoCatalog,
|
|
2241
|
+
revenueMotion: override.revenueMotion ?? base.revenueMotion
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
function campaignBuilderStrategyModel(agencyContext) {
|
|
2245
|
+
return agencyContext?.strategyModel ?? "strategy_template";
|
|
2246
|
+
}
|
|
2247
|
+
function campaignBuilderStrategyPatternsEnabled(agencyContext) {
|
|
2248
|
+
return agencyContext?.includeStrategyPatterns ?? true;
|
|
2249
|
+
}
|
|
2250
|
+
function campaignBuilderWorkflowPatternsEnabled(agencyContext) {
|
|
2251
|
+
return agencyContext?.includeWorkflowPatterns ?? agencyContext?.includeClayPatterns ?? true;
|
|
2252
|
+
}
|
|
2253
|
+
function campaignBuilderAccountLabel(request) {
|
|
2254
|
+
return request.accountLabel;
|
|
2255
|
+
}
|
|
2256
|
+
function campaignBuilderAccountContext(request) {
|
|
2257
|
+
return request.accountContext;
|
|
2258
|
+
}
|
|
1404
2259
|
function mergeDefaults(overrides) {
|
|
1405
2260
|
return {
|
|
1406
2261
|
...DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS,
|
|
@@ -1413,12 +2268,9 @@ function mergeDefaults(overrides) {
|
|
|
1413
2268
|
}
|
|
1414
2269
|
function normalizeMemory(request) {
|
|
1415
2270
|
const configured = request.memory ?? {};
|
|
1416
|
-
const
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
topK: 8,
|
|
1420
|
-
rationale: "Seed the campaign plan with prior ICP, angle, source, and reply-performance patterns."
|
|
1421
|
-
}];
|
|
2271
|
+
const defaultQueries = defaultAgencyMemoryQueries(request, configured);
|
|
2272
|
+
const configuredQueries = configured.queries ?? [];
|
|
2273
|
+
const queries = configuredQueries.length > 0 ? request.strategyTemplate ? dedupeMemoryQueries([...configuredQueries, ...defaultQueries]) : configuredQueries : defaultQueries;
|
|
1422
2274
|
return {
|
|
1423
2275
|
enabled: configured.enabled !== false,
|
|
1424
2276
|
queries,
|
|
@@ -1427,40 +2279,130 @@ function normalizeMemory(request) {
|
|
|
1427
2279
|
privacyMode: configured.privacyMode ?? (configured.useNetworkPatterns ? "anonymized_patterns" : "workspace_only")
|
|
1428
2280
|
};
|
|
1429
2281
|
}
|
|
2282
|
+
function defaultAgencyMemoryQueries(request, configured) {
|
|
2283
|
+
const operatingPlaybookTerms = getCampaignBuilderOperatingPlaybooksForRequest(request).flatMap((playbook) => [playbook.label, ...playbook.memoryKeywords]).join(" ");
|
|
2284
|
+
const queries = [{
|
|
2285
|
+
query: request.goal,
|
|
2286
|
+
scopes: ["workspace", configured.useNetworkPatterns ? "network_patterns" : "operator_notes"],
|
|
2287
|
+
topK: 8,
|
|
2288
|
+
rationale: "Seed the campaign plan with prior ICP, angle, source, and reply-performance patterns."
|
|
2289
|
+
}];
|
|
2290
|
+
if (campaignBuilderStrategyModel(request.agencyContext) !== "custom" && campaignBuilderStrategyPatternsEnabled(request.agencyContext)) {
|
|
2291
|
+
queries.push({
|
|
2292
|
+
query: [
|
|
2293
|
+
"Private campaign strategy pattern library prior campaign casebook",
|
|
2294
|
+
campaignBuilderAccountLabel(request),
|
|
2295
|
+
operatingPlaybookTerms,
|
|
2296
|
+
request.goal
|
|
2297
|
+
].filter(Boolean).join(" "),
|
|
2298
|
+
scopes: ["workspace", "operator_notes"],
|
|
2299
|
+
topK: 8,
|
|
2300
|
+
required: true,
|
|
2301
|
+
rationale: "Anchor the plan in private strategy learnings from prior industrial, healthcare, agency-services, infrastructure, recruiting, media, and integration builds."
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
if (campaignBuilderWorkflowPatternsEnabled(request.agencyContext)) {
|
|
2305
|
+
queries.push({
|
|
2306
|
+
query: [
|
|
2307
|
+
"Workflow table architecture enrichment qualification copy export gates",
|
|
2308
|
+
request.goal
|
|
2309
|
+
].filter(Boolean).join(" "),
|
|
2310
|
+
scopes: ["workspace", "operator_notes"],
|
|
2311
|
+
topK: 6,
|
|
2312
|
+
rationale: "Pull workflow patterns for source tables, enrichment order, qualification gates, and handoff controls."
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
return queries;
|
|
2316
|
+
}
|
|
1430
2317
|
function normalizeRoutes(request) {
|
|
1431
|
-
const routes =
|
|
1432
|
-
|
|
1433
|
-
|
|
2318
|
+
const routes = builtInRoutesFor(request);
|
|
2319
|
+
routes.push(...routesFromCustomerTools(request.customerTools ?? []));
|
|
2320
|
+
routes.push(...request.integrations ?? []);
|
|
2321
|
+
return routes.map((route, index) => ({
|
|
2322
|
+
...route,
|
|
2323
|
+
id: route.id ?? `${route.provider}-${route.layer}-${index + 1}`,
|
|
2324
|
+
mode: route.mode ?? "if_available"
|
|
2325
|
+
}));
|
|
2326
|
+
}
|
|
2327
|
+
function builtInRoutesFor(request) {
|
|
2328
|
+
const builtIns = new Set(normalizeBuiltIns(request));
|
|
2329
|
+
const routes = [];
|
|
2330
|
+
if (builtIns.has("lead_generation")) {
|
|
2331
|
+
routes.push({
|
|
2332
|
+
id: "signaliz-lead-generation",
|
|
1434
2333
|
layer: "source",
|
|
2334
|
+
gtmLayers: ["find_company", "find_people", "lead_generation"],
|
|
1435
2335
|
provider: "signaliz",
|
|
1436
2336
|
mode: "required",
|
|
1437
2337
|
toolName: "generate_leads",
|
|
1438
2338
|
rationale: "Use Signaliz fresh workspace acquisition as the default source of truth."
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
if (builtIns.has("local_leads")) {
|
|
2342
|
+
routes.push({
|
|
2343
|
+
id: "signaliz-local-leads",
|
|
2344
|
+
layer: "source",
|
|
2345
|
+
gtmLayer: "local_leads",
|
|
2346
|
+
provider: "signaliz",
|
|
2347
|
+
mode: "if_available",
|
|
2348
|
+
toolName: "generate_local_leads",
|
|
2349
|
+
rationale: "Use Signaliz local-leads sourcing for geography-bound local business campaigns."
|
|
2350
|
+
});
|
|
2351
|
+
}
|
|
2352
|
+
if (builtIns.has("email_finding")) {
|
|
2353
|
+
routes.push({
|
|
2354
|
+
id: "signaliz-email-finding",
|
|
2355
|
+
layer: "enrichment",
|
|
2356
|
+
gtmLayer: "email_finding",
|
|
1443
2357
|
provider: "signaliz",
|
|
1444
2358
|
mode: "required",
|
|
1445
2359
|
toolName: "find_and_verify_emails",
|
|
2360
|
+
rationale: "Find contact emails before verification and campaign handoff."
|
|
2361
|
+
});
|
|
2362
|
+
}
|
|
2363
|
+
if (builtIns.has("email_verification")) {
|
|
2364
|
+
routes.push({
|
|
2365
|
+
id: "signaliz-email-verification",
|
|
2366
|
+
layer: "qualification",
|
|
2367
|
+
gtmLayer: "email_verification",
|
|
2368
|
+
provider: "signaliz",
|
|
2369
|
+
mode: "required",
|
|
2370
|
+
toolName: "verify_emails",
|
|
1446
2371
|
rationale: "Require verified contactability before sequence delivery."
|
|
1447
|
-
}
|
|
1448
|
-
|
|
2372
|
+
});
|
|
2373
|
+
}
|
|
2374
|
+
if (builtIns.has("signals")) {
|
|
2375
|
+
routes.push({
|
|
1449
2376
|
id: "signaliz-signals",
|
|
1450
2377
|
layer: "enrichment",
|
|
2378
|
+
gtmLayer: "company_enrichment",
|
|
1451
2379
|
provider: "signaliz",
|
|
1452
2380
|
mode: "if_available",
|
|
1453
2381
|
toolName: "enrich_company_signals",
|
|
1454
2382
|
rationale: "Attach current buying signals and evidence for qualification and copy."
|
|
1455
|
-
}
|
|
1456
|
-
|
|
1457
|
-
routes
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
2383
|
+
});
|
|
2384
|
+
}
|
|
2385
|
+
return routes;
|
|
2386
|
+
}
|
|
2387
|
+
function normalizeBuiltIns(request) {
|
|
2388
|
+
const configured = request.builtIns !== void 0 ? request.builtIns : DEFAULT_CAMPAIGN_BUILDER_BUILT_INS;
|
|
2389
|
+
const builtIns = new Set(configured);
|
|
2390
|
+
if (request.builtIns === void 0 && looksLikeLocalLeadCampaign(request)) {
|
|
2391
|
+
builtIns.add("local_leads");
|
|
2392
|
+
}
|
|
2393
|
+
return [...builtIns].filter(isCampaignBuilderBuiltInTool);
|
|
2394
|
+
}
|
|
2395
|
+
function isCampaignBuilderBuiltInTool(value) {
|
|
2396
|
+
return ["lead_generation", "local_leads", "email_finding", "email_verification", "signals"].includes(String(value));
|
|
2397
|
+
}
|
|
2398
|
+
function looksLikeLocalLeadCampaign(request) {
|
|
2399
|
+
const text = [
|
|
2400
|
+
request.goal,
|
|
2401
|
+
campaignBuilderAccountContext(request),
|
|
2402
|
+
...request.icp?.industries ?? [],
|
|
2403
|
+
...request.icp?.keywords ?? []
|
|
2404
|
+
].filter(Boolean).join(" ").toLowerCase();
|
|
2405
|
+
return /\b(local|google maps|near me|nearby|city|cities|location|locations|home services?|clinics?|restaurants?|contractors?)\b/.test(text);
|
|
1464
2406
|
}
|
|
1465
2407
|
function routesFromCustomerTools(tools) {
|
|
1466
2408
|
return tools.flatMap(
|
|
@@ -1478,7 +2420,7 @@ function routesFromCustomerTools(tools) {
|
|
|
1478
2420
|
...tool.config,
|
|
1479
2421
|
available_tools: tool.availableTools
|
|
1480
2422
|
},
|
|
1481
|
-
rationale: `${tool.label ?? tool.provider} is
|
|
2423
|
+
rationale: `${tool.label ?? tool.provider} is operator-provided for ${layer}.`
|
|
1482
2424
|
}))
|
|
1483
2425
|
);
|
|
1484
2426
|
}
|
|
@@ -1523,6 +2465,7 @@ function createBuildRequest(request, defaults, targetCount, campaignName, scopeB
|
|
|
1523
2465
|
return buildRequest;
|
|
1524
2466
|
}
|
|
1525
2467
|
function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
2468
|
+
const operatingPlaybooks = getCampaignBuilderOperatingPlaybooksForRequest(request);
|
|
1526
2469
|
const layers = uniqueStrings([
|
|
1527
2470
|
"icp",
|
|
1528
2471
|
"email_finding",
|
|
@@ -1532,7 +2475,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
1532
2475
|
["instantly", "smartlead", "heyreach"].some((provider) => routes.some((route) => route.provider === provider)) ? "sender" : void 0,
|
|
1533
2476
|
memory.enabled ? "feedback" : void 0
|
|
1534
2477
|
]);
|
|
1535
|
-
const providerChain = uniqueStrings(["signaliz", ...routes.map((route) => route.provider)]);
|
|
2478
|
+
const providerChain = uniqueStrings(["signaliz", ...request.preferredProviders ?? [], ...routes.map((route) => route.provider)]);
|
|
1536
2479
|
const targetIcp = compact({
|
|
1537
2480
|
personas: buildRequest.icp?.personas,
|
|
1538
2481
|
industries: buildRequest.icp?.industries,
|
|
@@ -1573,6 +2516,13 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
1573
2516
|
required: true,
|
|
1574
2517
|
policy: "Run read-only GTM Brain preflight before build_campaign so learned defaults, memory, and deliverability risk stay attached to the build.",
|
|
1575
2518
|
layers,
|
|
2519
|
+
operating_playbooks: operatingPlaybooks.map((playbook) => ({
|
|
2520
|
+
slug: playbook.slug,
|
|
2521
|
+
label: playbook.label,
|
|
2522
|
+
quality_gates: playbook.qualityGates,
|
|
2523
|
+
required_fields: playbook.requiredFields,
|
|
2524
|
+
activation_boundary: playbook.activationBoundary
|
|
2525
|
+
})),
|
|
1576
2526
|
target_icp: targetIcp,
|
|
1577
2527
|
provider_chain: providerChain,
|
|
1578
2528
|
lead_source: providerChain[0] ?? "signaliz",
|
|
@@ -1705,6 +2655,47 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
|
|
|
1705
2655
|
approvalRequired: false
|
|
1706
2656
|
}
|
|
1707
2657
|
];
|
|
2658
|
+
steps.push({
|
|
2659
|
+
id: "gtm-provider-catalog",
|
|
2660
|
+
phase: "plan",
|
|
2661
|
+
tool: "gtm_provider_catalog",
|
|
2662
|
+
arguments: {
|
|
2663
|
+
include_layer_catalog: true,
|
|
2664
|
+
include_planned: true
|
|
2665
|
+
},
|
|
2666
|
+
readOnly: true,
|
|
2667
|
+
approvalRequired: false
|
|
2668
|
+
});
|
|
2669
|
+
if (request.agencyContext?.includeNangoCatalog !== false) {
|
|
2670
|
+
steps.push({
|
|
2671
|
+
id: "nango-tool-catalog",
|
|
2672
|
+
phase: "plan",
|
|
2673
|
+
tool: "nango_mcp_tools_list",
|
|
2674
|
+
arguments: {
|
|
2675
|
+
format: "mcp"
|
|
2676
|
+
},
|
|
2677
|
+
readOnly: true,
|
|
2678
|
+
approvalRequired: false
|
|
2679
|
+
});
|
|
2680
|
+
}
|
|
2681
|
+
if (memory.enabled) {
|
|
2682
|
+
steps.push({
|
|
2683
|
+
id: "strategy-memory-status",
|
|
2684
|
+
phase: "memory",
|
|
2685
|
+
tool: "gtm_campaign_strategy_memory_status",
|
|
2686
|
+
arguments: buildGtmCampaignStrategyMemoryStatusArgs(request, buildRequest),
|
|
2687
|
+
readOnly: true,
|
|
2688
|
+
approvalRequired: false
|
|
2689
|
+
});
|
|
2690
|
+
}
|
|
2691
|
+
steps.push({
|
|
2692
|
+
id: "agency-campaign-build-plan",
|
|
2693
|
+
phase: "plan",
|
|
2694
|
+
tool: "gtm_campaign_build_plan",
|
|
2695
|
+
arguments: buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory),
|
|
2696
|
+
readOnly: true,
|
|
2697
|
+
approvalRequired: memory.useNetworkPatterns === true
|
|
2698
|
+
});
|
|
1708
2699
|
if (memory.enabled) {
|
|
1709
2700
|
for (const [index, query] of memory.queries.entries()) {
|
|
1710
2701
|
steps.push({
|
|
@@ -1718,6 +2709,25 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
|
|
|
1718
2709
|
}
|
|
1719
2710
|
}
|
|
1720
2711
|
for (const route of routes) {
|
|
2712
|
+
if (shouldPrepareProviderRoute(route)) {
|
|
2713
|
+
steps.push({
|
|
2714
|
+
id: `prepare-${route.id}`,
|
|
2715
|
+
phase: "plan",
|
|
2716
|
+
tool: "gtm_provider_recipe_prepare",
|
|
2717
|
+
arguments: buildProviderRecipePrepareArgs(route, buildRequest),
|
|
2718
|
+
readOnly: true,
|
|
2719
|
+
approvalRequired: false
|
|
2720
|
+
});
|
|
2721
|
+
steps.push({
|
|
2722
|
+
id: `activate-${route.id}-dry-run`,
|
|
2723
|
+
phase: "plan",
|
|
2724
|
+
tool: "gtm_provider_route_activate",
|
|
2725
|
+
arguments: buildProviderRouteActivateArgs(route, buildRequest),
|
|
2726
|
+
readOnly: true,
|
|
2727
|
+
approvalRequired: false
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2730
|
+
const routeApprovalRequired = route.approvalRequired === true || route.provider !== "signaliz" && route.approvalRequired !== false && route.mode === "required" || route.layer === "delivery" || route.layer === "feedback";
|
|
1721
2731
|
steps.push({
|
|
1722
2732
|
id: `route-${route.id}`,
|
|
1723
2733
|
phase: route.layer,
|
|
@@ -1729,7 +2739,7 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
|
|
|
1729
2739
|
config: route.config
|
|
1730
2740
|
},
|
|
1731
2741
|
readOnly: !["delivery", "feedback"].includes(route.layer),
|
|
1732
|
-
approvalRequired:
|
|
2742
|
+
approvalRequired: routeApprovalRequired
|
|
1733
2743
|
});
|
|
1734
2744
|
}
|
|
1735
2745
|
steps.push({
|
|
@@ -1738,8 +2748,8 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
|
|
|
1738
2748
|
tool: "scope_campaign",
|
|
1739
2749
|
arguments: {
|
|
1740
2750
|
prompt: request.goal,
|
|
1741
|
-
|
|
1742
|
-
|
|
2751
|
+
account_label: campaignBuilderAccountLabel(request),
|
|
2752
|
+
account_context: campaignBuilderAccountContext(request),
|
|
1743
2753
|
target_count: request.targetCount
|
|
1744
2754
|
},
|
|
1745
2755
|
readOnly: true,
|
|
@@ -1799,11 +2809,212 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
|
|
|
1799
2809
|
readOnly: false,
|
|
1800
2810
|
approvalRequired: approvals.some((approval) => approval.blocking)
|
|
1801
2811
|
});
|
|
2812
|
+
const deliveryApprovalArgs = buildDeliveryApprovalArgs(buildRequest);
|
|
2813
|
+
if (deliveryApprovalArgs) {
|
|
2814
|
+
steps.push({
|
|
2815
|
+
id: "delivery-approval",
|
|
2816
|
+
phase: "delivery",
|
|
2817
|
+
tool: "approve_campaign_delivery",
|
|
2818
|
+
arguments: deliveryApprovalArgs,
|
|
2819
|
+
readOnly: false,
|
|
2820
|
+
approvalRequired: true
|
|
2821
|
+
});
|
|
2822
|
+
}
|
|
1802
2823
|
return steps.map((step) => ({ ...step, arguments: compact(step.arguments) }));
|
|
1803
2824
|
}
|
|
2825
|
+
function shouldPrepareProviderRoute(route) {
|
|
2826
|
+
return !["signaliz", "csv"].includes(route.provider);
|
|
2827
|
+
}
|
|
2828
|
+
function buildProviderRecipePrepareArgs(route, buildRequest) {
|
|
2829
|
+
const layerCapabilities = uniqueStrings(gtmLayersForRoute(route));
|
|
2830
|
+
const layer = layerCapabilities[0] ?? mapCampaignBuilderLayerToGtmLayer(route.layer) ?? "custom";
|
|
2831
|
+
const config = asRecord(route.config);
|
|
2832
|
+
return compact({
|
|
2833
|
+
provider_id: route.provider,
|
|
2834
|
+
provider_name: route.label,
|
|
2835
|
+
layer,
|
|
2836
|
+
layer_capabilities: layerCapabilities.length > 0 ? layerCapabilities : void 0,
|
|
2837
|
+
invocation_type: route.providerCapability?.invocationType ?? inferProviderInvocationType(route),
|
|
2838
|
+
auth_strategy: inferProviderAuthStrategy(route),
|
|
2839
|
+
workspace_mcp_server_id: stringValue(config.workspace_mcp_server_id ?? config.workspaceMcpServerId ?? route.mcpServerName),
|
|
2840
|
+
workspace_integration_id: stringValue(config.workspace_integration_id ?? config.workspaceIntegrationId),
|
|
2841
|
+
workspace_connection_id: stringValue(config.workspace_connection_id ?? config.workspaceConnectionId),
|
|
2842
|
+
endpoint_url: stringValue(config.endpoint_url ?? config.endpointUrl ?? config.webhook_url ?? config.webhookUrl),
|
|
2843
|
+
request_template: asOptionalRecord(config.request_template ?? config.requestTemplate),
|
|
2844
|
+
response_mapping: asOptionalRecord(config.response_mapping ?? config.responseMapping),
|
|
2845
|
+
input_schema: asOptionalRecord(config.input_schema ?? config.inputSchema ?? route.providerCapability?.exampleInputSchema),
|
|
2846
|
+
output_schema: asOptionalRecord(config.output_schema ?? config.outputSchema ?? route.providerCapability?.exampleOutputSchema),
|
|
2847
|
+
readiness: asOptionalRecord(config.readiness),
|
|
2848
|
+
metadata: compact({
|
|
2849
|
+
source: "campaign-builder-agent",
|
|
2850
|
+
route_id: route.id,
|
|
2851
|
+
campaign_name: buildRequest.name,
|
|
2852
|
+
tool_name: route.toolName,
|
|
2853
|
+
mcp_server_name: route.mcpServerName,
|
|
2854
|
+
dry_run_only: true
|
|
2855
|
+
}),
|
|
2856
|
+
context: compact({
|
|
2857
|
+
source: "campaign-builder-agent",
|
|
2858
|
+
route_id: route.id,
|
|
2859
|
+
gtm_campaign_id: buildRequest.gtmCampaignId
|
|
2860
|
+
}),
|
|
2861
|
+
use_signaliz_fallback: route.routingPolicy?.useSignalizFallback ?? true,
|
|
2862
|
+
priority: numberOrUndefined2(config.priority),
|
|
2863
|
+
status: stringValue(config.status) ?? "needs_setup"
|
|
2864
|
+
});
|
|
2865
|
+
}
|
|
2866
|
+
function buildProviderRouteActivateArgs(route, buildRequest) {
|
|
2867
|
+
const layerCapabilities = uniqueStrings(gtmLayersForRoute(route));
|
|
2868
|
+
const config = asRecord(route.config);
|
|
2869
|
+
return compact({
|
|
2870
|
+
provider_id: route.provider,
|
|
2871
|
+
provider_name: route.label,
|
|
2872
|
+
campaign_id: buildRequest.gtmCampaignId,
|
|
2873
|
+
layer: layerCapabilities[0] ?? mapCampaignBuilderLayerToGtmLayer(route.layer) ?? "custom",
|
|
2874
|
+
layers: layerCapabilities.length > 0 ? layerCapabilities : void 0,
|
|
2875
|
+
invocation_type: route.providerCapability?.invocationType ?? inferProviderInvocationType(route),
|
|
2876
|
+
auth_strategy: inferProviderAuthStrategy(route),
|
|
2877
|
+
workspace_mcp_server_id: stringValue(config.workspace_mcp_server_id ?? config.workspaceMcpServerId ?? route.mcpServerName),
|
|
2878
|
+
workspace_integration_id: stringValue(config.workspace_integration_id ?? config.workspaceIntegrationId),
|
|
2879
|
+
workspace_connection_id: stringValue(config.workspace_connection_id ?? config.workspaceConnectionId),
|
|
2880
|
+
endpoint_url: stringValue(config.endpoint_url ?? config.endpointUrl ?? config.webhook_url ?? config.webhookUrl),
|
|
2881
|
+
route_config: compact({
|
|
2882
|
+
...asRecord(config.route_config ?? config.routeConfig),
|
|
2883
|
+
source: "campaign-builder-agent",
|
|
2884
|
+
route_id: route.id,
|
|
2885
|
+
tool_name: route.toolName,
|
|
2886
|
+
mcp_server_name: route.mcpServerName
|
|
2887
|
+
}),
|
|
2888
|
+
use_signaliz_fallback: route.routingPolicy?.useSignalizFallback ?? true,
|
|
2889
|
+
priority: numberOrUndefined2(config.priority),
|
|
2890
|
+
dry_run: true,
|
|
2891
|
+
confirm: false
|
|
2892
|
+
});
|
|
2893
|
+
}
|
|
2894
|
+
function inferProviderInvocationType(route) {
|
|
2895
|
+
if (route.provider === "airbyte") return "airbyte";
|
|
2896
|
+
if (route.provider === "nango") return "managed_integration";
|
|
2897
|
+
if (["custom_webhook", "webhook", "clay_webhook"].includes(route.provider)) return "webhook";
|
|
2898
|
+
if (["custom_api", "apollo", "ai_ark", "apify"].includes(route.provider)) return "api";
|
|
2899
|
+
if (route.mcpServerName || route.toolName || ["custom_mcp", "octave"].includes(route.provider)) return "mcp_tool";
|
|
2900
|
+
return "manual";
|
|
2901
|
+
}
|
|
2902
|
+
function inferProviderAuthStrategy(route) {
|
|
2903
|
+
const config = asRecord(route.config);
|
|
2904
|
+
const configured = stringValue(config.auth_strategy ?? config.authStrategy);
|
|
2905
|
+
if (configured) return configured;
|
|
2906
|
+
const invocationType = route.providerCapability?.invocationType ?? inferProviderInvocationType(route);
|
|
2907
|
+
if (invocationType === "webhook") return "webhook_secret";
|
|
2908
|
+
if (invocationType === "mcp_tool") return "mcp_auth";
|
|
2909
|
+
if (invocationType === "managed_integration") return "byo_runtime";
|
|
2910
|
+
if (invocationType === "api" || invocationType === "airbyte") return "integration_key";
|
|
2911
|
+
return void 0;
|
|
2912
|
+
}
|
|
2913
|
+
function refreshBuildStepArguments(plan) {
|
|
2914
|
+
for (const step of plan.mcpFlow) {
|
|
2915
|
+
if (step.id === "dry-run-build") {
|
|
2916
|
+
step.arguments = compact({
|
|
2917
|
+
...buildCampaignArgs({ ...plan.buildRequest, dryRun: true, confirmSpend: false }),
|
|
2918
|
+
dry_run: true
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2921
|
+
if (step.id === "approved-build") {
|
|
2922
|
+
step.arguments = compact({
|
|
2923
|
+
...buildCampaignArgs({ ...plan.buildRequest, dryRun: false, confirmSpend: true }),
|
|
2924
|
+
required_approvals: plan.approvals.map((approval) => approval.id)
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
function buildFallbackPlanSnapshot(plan) {
|
|
2930
|
+
const plannerStep = plan.mcpFlow.find((step) => step.id === "agency-campaign-build-plan");
|
|
2931
|
+
return compact({
|
|
2932
|
+
source_tool: "campaign-builder-agent",
|
|
2933
|
+
plan_id: plan.planId,
|
|
2934
|
+
query: asRecord(plannerStep?.arguments),
|
|
2935
|
+
campaign_name: plan.campaignName,
|
|
2936
|
+
goal: plan.goal,
|
|
2937
|
+
target_count: plan.targetCount,
|
|
2938
|
+
approvals: plan.approvals,
|
|
2939
|
+
brain_preflight: plan.brainPreflight,
|
|
2940
|
+
operating_playbooks: plan.operatingPlaybooks
|
|
2941
|
+
});
|
|
2942
|
+
}
|
|
2943
|
+
function mapPlanCommitResult(data) {
|
|
2944
|
+
const campaign = asRecord(data.campaign);
|
|
2945
|
+
const campaignBuild = asRecord(data.campaign_build ?? data.campaignBuild);
|
|
2946
|
+
const committedPlan = asRecord(data.committed_plan ?? data.committedPlan);
|
|
2947
|
+
const commitPlan = asRecord(data.commit_plan ?? data.commitPlan);
|
|
2948
|
+
const campaignArgs = asRecord(commitPlan.campaign_arguments ?? commitPlan.campaignArguments);
|
|
2949
|
+
return {
|
|
2950
|
+
dryRun: data.dry_run === true || data.dryRun === true,
|
|
2951
|
+
wroteState: data.wrote_state === true || data.wroteState === true,
|
|
2952
|
+
campaignId: stringValue(campaign.id ?? committedPlan.campaign_id ?? committedPlan.campaignId ?? commitPlan.campaign_id ?? commitPlan.campaignId ?? campaignArgs.id),
|
|
2953
|
+
campaignBuildId: stringValue(campaignBuild.id ?? committedPlan.campaign_build_id ?? committedPlan.campaignBuildId ?? campaignArgs.campaign_build_id ?? campaignArgs.campaignBuildId),
|
|
2954
|
+
raw: data
|
|
2955
|
+
};
|
|
2956
|
+
}
|
|
2957
|
+
function buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory) {
|
|
2958
|
+
const agencyContext = request.agencyContext ?? {};
|
|
2959
|
+
const strategyModel = campaignBuilderStrategyModel(agencyContext);
|
|
2960
|
+
const partnerEcosystem = agencyContext.partnerEcosystem ?? (strategyModel === "custom" ? void 0 : ["clay", "instantly", "nango"]);
|
|
2961
|
+
const layers = uniqueStrings([
|
|
2962
|
+
"icp",
|
|
2963
|
+
buildRequest.icp?.requireVerifiedEmail !== false ? "email_finding" : void 0,
|
|
2964
|
+
buildRequest.icp?.requireVerifiedEmail !== false ? "email_verification" : void 0,
|
|
2965
|
+
...routes.flatMap(gtmLayersForRoute),
|
|
2966
|
+
buildRequest.delivery?.destinationType === "webhook" ? "destination_export" : void 0,
|
|
2967
|
+
memory.enabled ? "feedback" : void 0
|
|
2968
|
+
]);
|
|
2969
|
+
const preferredProviders = uniqueStrings([
|
|
2970
|
+
...request.preferredProviders ?? [],
|
|
2971
|
+
...routes.map((route) => route.provider).filter((provider) => provider !== "signaliz")
|
|
2972
|
+
]);
|
|
2973
|
+
const operatingPlaybooks = getCampaignBuilderOperatingPlaybooksForRequest(request);
|
|
2974
|
+
return compact({
|
|
2975
|
+
campaign_id: buildRequest.gtmCampaignId,
|
|
2976
|
+
campaign_brief: buildRequest.prompt || request.goal,
|
|
2977
|
+
strategy_template: request.strategyTemplate,
|
|
2978
|
+
target_icp: buildRequest.icp ? buildGtmTargetIcpContext(buildRequest.icp) : void 0,
|
|
2979
|
+
lead_count: buildRequest.targetCount,
|
|
2980
|
+
layers: layers.length > 0 ? layers : void 0,
|
|
2981
|
+
preferred_providers: preferredProviders.length > 0 ? preferredProviders : void 0,
|
|
2982
|
+
strategy_model: strategyModel,
|
|
2983
|
+
include_strategy_patterns: campaignBuilderStrategyPatternsEnabled(agencyContext),
|
|
2984
|
+
include_workflow_patterns: campaignBuilderWorkflowPatternsEnabled(agencyContext),
|
|
2985
|
+
include_nango_catalog: agencyContext.includeNangoCatalog !== false,
|
|
2986
|
+
partner_ecosystem: partnerEcosystem,
|
|
2987
|
+
operating_playbooks: operatingPlaybooks.map((playbook) => ({
|
|
2988
|
+
slug: playbook.slug,
|
|
2989
|
+
label: playbook.label,
|
|
2990
|
+
quality_gates: playbook.qualityGates,
|
|
2991
|
+
activation_boundary: playbook.activationBoundary
|
|
2992
|
+
})),
|
|
2993
|
+
include_memory: memory.enabled,
|
|
2994
|
+
include_brain: true,
|
|
2995
|
+
include_provider_routes: true,
|
|
2996
|
+
include_failure_patterns: true,
|
|
2997
|
+
include_planned_providers: true,
|
|
2998
|
+
limit: 25
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
3001
|
+
function buildGtmCampaignStrategyMemoryStatusArgs(request, buildRequest) {
|
|
3002
|
+
return compact({
|
|
3003
|
+
query: request.goal,
|
|
3004
|
+
campaign_brief: buildRequest.prompt || request.goal,
|
|
3005
|
+
strategy_template: request.strategyTemplate,
|
|
3006
|
+
target_icp: buildRequest.icp ? buildGtmTargetIcpContext(buildRequest.icp) : void 0,
|
|
3007
|
+
memory_dimension_filters: request.strategyTemplate ? { strategy_template: request.strategyTemplate } : void 0,
|
|
3008
|
+
require_memory_dimension_match: false,
|
|
3009
|
+
include_samples: false,
|
|
3010
|
+
include_sources: true,
|
|
3011
|
+
days: 3650,
|
|
3012
|
+
limit: 25
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
1804
3015
|
function buildGtmMemorySearchArgs(request, routes, query) {
|
|
1805
3016
|
const layers = uniqueStrings(routes.flatMap(gtmLayersForRoute));
|
|
1806
|
-
const providerChain = uniqueStrings(routes.map((route) => route.provider));
|
|
3017
|
+
const providerChain = uniqueStrings([...request.preferredProviders ?? [], ...routes.map((route) => route.provider)]);
|
|
1807
3018
|
return compact({
|
|
1808
3019
|
query: query.query,
|
|
1809
3020
|
limit: query.topK,
|
|
@@ -1825,6 +3036,26 @@ function buildGtmTargetIcpContext(icp) {
|
|
|
1825
3036
|
require_verified_email: icp.requireVerifiedEmail
|
|
1826
3037
|
});
|
|
1827
3038
|
}
|
|
3039
|
+
function mapCampaignBuilderLayerToGtmLayer(layer) {
|
|
3040
|
+
switch (layer) {
|
|
3041
|
+
case "source":
|
|
3042
|
+
return "lead_generation";
|
|
3043
|
+
case "enrichment":
|
|
3044
|
+
return "company_enrichment";
|
|
3045
|
+
case "qualification":
|
|
3046
|
+
return "qualification";
|
|
3047
|
+
case "copy":
|
|
3048
|
+
return "copy_enrichment";
|
|
3049
|
+
case "delivery":
|
|
3050
|
+
return "destination_export";
|
|
3051
|
+
case "feedback":
|
|
3052
|
+
return "feedback";
|
|
3053
|
+
case "approval":
|
|
3054
|
+
return "approval";
|
|
3055
|
+
default:
|
|
3056
|
+
return void 0;
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
1828
3059
|
function buildCampaignArgs(request) {
|
|
1829
3060
|
const args = {
|
|
1830
3061
|
name: request.name,
|
|
@@ -1931,6 +3162,14 @@ function buildExecutionPrepareArgs(request, dryRun, confirmSpend) {
|
|
|
1931
3162
|
enhancers: buildArgs2.enhancers
|
|
1932
3163
|
});
|
|
1933
3164
|
}
|
|
3165
|
+
function buildDeliveryApprovalArgs(request) {
|
|
3166
|
+
if (request.delivery?.enabled === false || request.delivery?.approvalRequired === false) return void 0;
|
|
3167
|
+
return compact({
|
|
3168
|
+
campaign_build_id: "<campaign_build_id_from_approved_build>",
|
|
3169
|
+
destination_type: request.delivery?.destinationType ?? "json",
|
|
3170
|
+
destination_config: request.delivery?.destinationConfig
|
|
3171
|
+
});
|
|
3172
|
+
}
|
|
1934
3173
|
function mapBuildResult(data, dryRun) {
|
|
1935
3174
|
return {
|
|
1936
3175
|
campaignBuildId: data.campaign_build_id ?? null,
|
|
@@ -2005,8 +3244,8 @@ function estimateCredits(request, defaults, targetCount) {
|
|
|
2005
3244
|
}
|
|
2006
3245
|
function buildDescription(request) {
|
|
2007
3246
|
const parts = [
|
|
2008
|
-
request
|
|
2009
|
-
request
|
|
3247
|
+
campaignBuilderAccountLabel(request) ? `Account label: ${campaignBuilderAccountLabel(request)}` : void 0,
|
|
3248
|
+
campaignBuilderAccountContext(request) ? `Context: ${campaignBuilderAccountContext(request)}` : void 0,
|
|
2010
3249
|
request.constraints?.deliverabilityNotes?.length ? `Deliverability: ${request.constraints.deliverabilityNotes.join("; ")}` : void 0,
|
|
2011
3250
|
"Agent-built campaign plan layered on Signaliz kernel and existing MCP tools."
|
|
2012
3251
|
];
|
|
@@ -2029,6 +3268,10 @@ function compact(record) {
|
|
|
2029
3268
|
function asRecord(value) {
|
|
2030
3269
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2031
3270
|
}
|
|
3271
|
+
function asOptionalRecord(value) {
|
|
3272
|
+
const record = asRecord(value);
|
|
3273
|
+
return Object.keys(record).length > 0 ? record : void 0;
|
|
3274
|
+
}
|
|
2032
3275
|
function stringValue(value) {
|
|
2033
3276
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
2034
3277
|
}
|
|
@@ -3773,7 +5016,7 @@ var GtmKernel = class {
|
|
|
3773
5016
|
campaigns: input.campaigns.map(campaignHistoryImportCampaignArgs)
|
|
3774
5017
|
});
|
|
3775
5018
|
}
|
|
3776
|
-
/** Queue a Trigger-backed campaign history import for larger
|
|
5019
|
+
/** Queue a Trigger-backed campaign history import for larger private campaign backfills. */
|
|
3777
5020
|
async importCampaignHistoryRun(input) {
|
|
3778
5021
|
return this.callMcp("gtm_campaign_history_import_run", {
|
|
3779
5022
|
source: input.source,
|
|
@@ -4220,6 +5463,40 @@ var GtmKernel = class {
|
|
|
4220
5463
|
include_layer_catalog: options.includeLayerCatalog
|
|
4221
5464
|
});
|
|
4222
5465
|
}
|
|
5466
|
+
/** List private-safe campaign strategy templates agents can merge into campaign build plans. */
|
|
5467
|
+
async campaignStrategyTemplates(options = {}) {
|
|
5468
|
+
return this.callMcp("gtm_campaign_strategy_templates", {
|
|
5469
|
+
strategy_template: options.strategyTemplate,
|
|
5470
|
+
query: options.query,
|
|
5471
|
+
include_details: options.includeDetails
|
|
5472
|
+
});
|
|
5473
|
+
}
|
|
5474
|
+
/** Build the read-only Memory, Brain, risk, and provider-route runbook needed before planning a campaign. */
|
|
5475
|
+
async campaignStartContext(input = {}) {
|
|
5476
|
+
return this.callMcp("gtm_campaign_start_context", {
|
|
5477
|
+
campaign_id: input.campaignId,
|
|
5478
|
+
campaign_build_id: input.campaignBuildId,
|
|
5479
|
+
campaign_brief: input.campaignBrief,
|
|
5480
|
+
strategy_template: input.strategyTemplate,
|
|
5481
|
+
target_icp: input.targetIcp,
|
|
5482
|
+
lead_count: input.leadCount,
|
|
5483
|
+
layers: input.layers,
|
|
5484
|
+
preferred_providers: input.preferredProviders,
|
|
5485
|
+
memory_dimension_filters: input.memoryDimensionFilters,
|
|
5486
|
+
require_memory_dimension_match: input.requireMemoryDimensionMatch,
|
|
5487
|
+
include_memory: input.includeMemory,
|
|
5488
|
+
include_brain: input.includeBrain,
|
|
5489
|
+
include_provider_routes: input.includeProviderRoutes,
|
|
5490
|
+
include_failure_patterns: input.includeFailurePatterns,
|
|
5491
|
+
include_delivery_risk: input.includeDeliveryRisk,
|
|
5492
|
+
include_global_brain: input.includeGlobalBrain,
|
|
5493
|
+
include_planned_providers: input.includePlannedProviders,
|
|
5494
|
+
days: input.days,
|
|
5495
|
+
min_confidence: input.minConfidence,
|
|
5496
|
+
min_sample_size: input.minSampleSize,
|
|
5497
|
+
limit: input.limit
|
|
5498
|
+
});
|
|
5499
|
+
}
|
|
4223
5500
|
/** Inspect GTM integration activation cards for UI and agent routing without writing state. */
|
|
4224
5501
|
async integrationsActivationStatus(options = {}) {
|
|
4225
5502
|
return this.callMcp("gtm_integrations_activation_status", {
|
|
@@ -4235,10 +5512,16 @@ var GtmKernel = class {
|
|
|
4235
5512
|
campaign_id: input.campaignId,
|
|
4236
5513
|
campaign_build_id: input.campaignBuildId,
|
|
4237
5514
|
campaign_brief: input.campaignBrief,
|
|
5515
|
+
strategy_template: input.strategyTemplate,
|
|
4238
5516
|
target_icp: input.targetIcp,
|
|
4239
5517
|
lead_count: input.leadCount,
|
|
4240
5518
|
layers: input.layers,
|
|
4241
5519
|
preferred_providers: input.preferredProviders,
|
|
5520
|
+
strategy_model: input.strategyModel,
|
|
5521
|
+
include_strategy_patterns: input.includeStrategyPatterns,
|
|
5522
|
+
include_workflow_patterns: input.includeWorkflowPatterns ?? input.includeClayPatterns,
|
|
5523
|
+
include_nango_catalog: input.includeNangoCatalog,
|
|
5524
|
+
partner_ecosystem: input.partnerEcosystem,
|
|
4242
5525
|
memory_dimension_filters: input.memoryDimensionFilters,
|
|
4243
5526
|
require_memory_dimension_match: input.requireMemoryDimensionMatch,
|
|
4244
5527
|
include_memory: input.includeMemory,
|
|
@@ -4250,6 +5533,79 @@ var GtmKernel = class {
|
|
|
4250
5533
|
limit: input.limit
|
|
4251
5534
|
});
|
|
4252
5535
|
}
|
|
5536
|
+
/** Emit reusable CampaignBuilderAgentRequest JSON from hosted MCP strategy-template defaults without spending credits. */
|
|
5537
|
+
async campaignAgentRequestTemplate(input = {}) {
|
|
5538
|
+
return this.callMcp("gtm_campaign_agent_request_template", {
|
|
5539
|
+
goal: input.goal,
|
|
5540
|
+
campaign_brief: input.campaignBrief,
|
|
5541
|
+
campaign_name: input.campaignName,
|
|
5542
|
+
account_label: input.accountLabel,
|
|
5543
|
+
account_context: input.accountContext,
|
|
5544
|
+
strategy_template: input.strategyTemplate,
|
|
5545
|
+
operating_playbooks: input.operatingPlaybooks,
|
|
5546
|
+
target_icp: input.targetIcp,
|
|
5547
|
+
target_count: input.targetCount,
|
|
5548
|
+
builtins: input.builtIns,
|
|
5549
|
+
include_local_leads: input.includeLocalLeads,
|
|
5550
|
+
include_byo_placeholder: input.includeByoPlaceholder,
|
|
5551
|
+
include_nango_catalog: input.includeNangoCatalog,
|
|
5552
|
+
preferred_providers: input.preferredProviders,
|
|
5553
|
+
privacy_mode: input.privacyMode,
|
|
5554
|
+
destination_type: input.destinationType
|
|
5555
|
+
});
|
|
5556
|
+
}
|
|
5557
|
+
/** Compose a one-call read-only strategy-template campaign-agent runbook across built-ins, Memory, Brain, Nango, and BYO routes. */
|
|
5558
|
+
async campaignAgentPlan(input = {}) {
|
|
5559
|
+
return this.callMcp("gtm_campaign_agent_plan", {
|
|
5560
|
+
goal: input.goal,
|
|
5561
|
+
campaign_brief: input.campaignBrief,
|
|
5562
|
+
campaign_name: input.campaignName,
|
|
5563
|
+
campaign_id: input.campaignId,
|
|
5564
|
+
campaign_build_id: input.campaignBuildId,
|
|
5565
|
+
strategy_template: input.strategyTemplate,
|
|
5566
|
+
operating_playbooks: input.operatingPlaybooks,
|
|
5567
|
+
account_context: input.accountContext,
|
|
5568
|
+
target_icp: input.targetIcp,
|
|
5569
|
+
target_count: input.targetCount,
|
|
5570
|
+
lead_count: input.leadCount,
|
|
5571
|
+
builtins: input.builtIns,
|
|
5572
|
+
use_local_leads: input.useLocalLeads,
|
|
5573
|
+
layers: input.layers,
|
|
5574
|
+
preferred_providers: input.preferredProviders,
|
|
5575
|
+
custom_tools: input.customTools,
|
|
5576
|
+
integrations: input.integrations,
|
|
5577
|
+
strategy_model: input.strategyModel,
|
|
5578
|
+
include_strategy_patterns: input.includeStrategyPatterns,
|
|
5579
|
+
include_workflow_patterns: input.includeWorkflowPatterns,
|
|
5580
|
+
include_nango_catalog: input.includeNangoCatalog,
|
|
5581
|
+
partner_ecosystem: input.partnerEcosystem,
|
|
5582
|
+
memory_dimension_filters: input.memoryDimensionFilters,
|
|
5583
|
+
require_memory_dimension_match: input.requireMemoryDimensionMatch,
|
|
5584
|
+
include_memory: input.includeMemory,
|
|
5585
|
+
include_brain: input.includeBrain,
|
|
5586
|
+
include_provider_routes: input.includeProviderRoutes,
|
|
5587
|
+
include_failure_patterns: input.includeFailurePatterns,
|
|
5588
|
+
include_delivery_risk: input.includeDeliveryRisk,
|
|
5589
|
+
include_planned_providers: input.includePlannedProviders,
|
|
5590
|
+
days: input.days,
|
|
5591
|
+
limit: input.limit
|
|
5592
|
+
});
|
|
5593
|
+
}
|
|
5594
|
+
/** Inspect private-safe strategy-template/workflow memory readiness before campaign planning. */
|
|
5595
|
+
async campaignStrategyMemoryStatus(input = {}) {
|
|
5596
|
+
return this.callMcp("gtm_campaign_strategy_memory_status", {
|
|
5597
|
+
strategy_template: input.strategyTemplate,
|
|
5598
|
+
query: input.query,
|
|
5599
|
+
campaign_brief: input.campaignBrief,
|
|
5600
|
+
target_icp: input.targetIcp,
|
|
5601
|
+
memory_dimension_filters: input.memoryDimensionFilters,
|
|
5602
|
+
require_memory_dimension_match: input.requireMemoryDimensionMatch,
|
|
5603
|
+
include_samples: input.includeSamples,
|
|
5604
|
+
include_sources: input.includeSources,
|
|
5605
|
+
days: input.days,
|
|
5606
|
+
limit: input.limit
|
|
5607
|
+
});
|
|
5608
|
+
}
|
|
4253
5609
|
/** Persist a reviewed campaign build plan into a campaign object and audit log. Dry-run first by default. */
|
|
4254
5610
|
async commitCampaignBuildPlan(input = {}) {
|
|
4255
5611
|
return this.callMcp("gtm_campaign_build_plan_commit", {
|
|
@@ -4396,6 +5752,13 @@ var GtmKernel = class {
|
|
|
4396
5752
|
vendor_id: input.vendorId,
|
|
4397
5753
|
service_category: input.serviceCategory,
|
|
4398
5754
|
connection_type: input.connectionType,
|
|
5755
|
+
integration_id: input.integrationId,
|
|
5756
|
+
provider_config_key: input.providerConfigKey,
|
|
5757
|
+
allowed_integrations: input.allowedIntegrations,
|
|
5758
|
+
surface: input.surface,
|
|
5759
|
+
source: input.source,
|
|
5760
|
+
user_email: input.userEmail,
|
|
5761
|
+
user_display_name: input.userDisplayName,
|
|
4399
5762
|
status: input.status,
|
|
4400
5763
|
metadata: input.metadata
|
|
4401
5764
|
});
|
|
@@ -4452,6 +5815,20 @@ var GtmKernel = class {
|
|
|
4452
5815
|
context: input.context
|
|
4453
5816
|
});
|
|
4454
5817
|
}
|
|
5818
|
+
/** Create a short-lived Nango Connect session so a user can authorize a vendor API. */
|
|
5819
|
+
async createNangoConnectSession(input) {
|
|
5820
|
+
return this.callMcp("nango_connect_session_create", {
|
|
5821
|
+
provider_id: input.providerId,
|
|
5822
|
+
integration_id: input.integrationId,
|
|
5823
|
+
provider_display_name: input.providerDisplayName,
|
|
5824
|
+
integration_display_name: input.integrationDisplayName,
|
|
5825
|
+
allowed_integrations: input.allowedIntegrations,
|
|
5826
|
+
surface: input.surface,
|
|
5827
|
+
source: input.source,
|
|
5828
|
+
user_email: input.userEmail,
|
|
5829
|
+
user_display_name: input.userDisplayName
|
|
5830
|
+
});
|
|
5831
|
+
}
|
|
4455
5832
|
/** List Nango-backed action tools for a workspace connection without executing them. */
|
|
4456
5833
|
async listNangoTools(options = {}) {
|
|
4457
5834
|
return this.callMcp("nango_mcp_tools_list", {
|
|
@@ -4795,17 +6172,27 @@ var Signaliz = class {
|
|
|
4795
6172
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4796
6173
|
0 && (module.exports = {
|
|
4797
6174
|
Ai,
|
|
6175
|
+
CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS,
|
|
6176
|
+
CAMPAIGN_BUILDER_STRATEGY_TEMPLATES,
|
|
4798
6177
|
CampaignBuilderAgent,
|
|
4799
6178
|
Campaigns,
|
|
6179
|
+
DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES,
|
|
6180
|
+
DEFAULT_CAMPAIGN_BUILDER_BUILT_INS,
|
|
4800
6181
|
DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS,
|
|
4801
6182
|
GtmKernel,
|
|
4802
6183
|
Icps,
|
|
4803
6184
|
Ops,
|
|
4804
6185
|
Signaliz,
|
|
4805
6186
|
SignalizError,
|
|
6187
|
+
applyCampaignBuilderStrategyTemplate,
|
|
4806
6188
|
collectExecutionReferences,
|
|
4807
6189
|
createCampaignBuilderAgentPlan,
|
|
6190
|
+
createCampaignBuilderAgentRequestTemplate,
|
|
4808
6191
|
createCampaignBuilderApproval,
|
|
6192
|
+
createCampaignBuilderToolRoute,
|
|
6193
|
+
getCampaignBuilderOperatingPlaybook,
|
|
6194
|
+
getCampaignBuilderOperatingPlaybooksForRequest,
|
|
6195
|
+
getCampaignBuilderStrategyTemplate,
|
|
4809
6196
|
getMissingCampaignBuilderApprovals,
|
|
4810
6197
|
normalizeExecutionReference
|
|
4811
6198
|
});
|