@signaliz/sdk 1.0.18 → 1.0.19
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/dist/{chunk-VFBQCWOM.mjs → chunk-PBJFIO72.mjs} +905 -21
- package/dist/cli.js +1161 -22
- package/dist/cli.mjs +248 -1
- package/dist/index.d.mts +555 -4
- package/dist/index.d.ts +555 -4
- package/dist/index.js +907 -21
- package/dist/index.mjs +5 -1
- package/dist/mcp-config.js +903 -21
- package/dist/mcp-config.mjs +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -31,10 +31,12 @@ __export(index_exports, {
|
|
|
31
31
|
GtmKernel: () => GtmKernel,
|
|
32
32
|
Icps: () => Icps,
|
|
33
33
|
Ops: () => Ops,
|
|
34
|
+
PublicGroundTruth: () => PublicGroundTruth,
|
|
34
35
|
Signaliz: () => Signaliz,
|
|
35
36
|
SignalizError: () => SignalizError,
|
|
36
37
|
applyCampaignBuilderStrategyTemplate: () => applyCampaignBuilderStrategyTemplate,
|
|
37
38
|
collectExecutionReferences: () => collectExecutionReferences,
|
|
39
|
+
createCampaignBuilderActiveWorkContext: () => createCampaignBuilderActiveWorkContext,
|
|
38
40
|
createCampaignBuilderAgentPlan: () => createCampaignBuilderAgentPlan,
|
|
39
41
|
createCampaignBuilderAgentRequestTemplate: () => createCampaignBuilderAgentRequestTemplate,
|
|
40
42
|
createCampaignBuilderApproval: () => createCampaignBuilderApproval,
|
|
@@ -501,6 +503,38 @@ var Signals = class {
|
|
|
501
503
|
constructor(client) {
|
|
502
504
|
this.client = client;
|
|
503
505
|
}
|
|
506
|
+
/** Turn the strongest supported company signal into three complete, evidence-backed emails. */
|
|
507
|
+
async signalToCopy(params) {
|
|
508
|
+
const data = await this.client.post("api/v1/signal-to-copy", {
|
|
509
|
+
company_domain: params.companyDomain,
|
|
510
|
+
person_name: params.personName,
|
|
511
|
+
title: params.title,
|
|
512
|
+
campaign_offer: params.campaignOffer,
|
|
513
|
+
research_prompt: params.researchPrompt
|
|
514
|
+
});
|
|
515
|
+
return {
|
|
516
|
+
success: data.success ?? true,
|
|
517
|
+
strongestSignal: data.strongest_signal ?? "",
|
|
518
|
+
whyNow: data.why_now ?? "",
|
|
519
|
+
subjectLine: data.subject_line ?? "",
|
|
520
|
+
openingLine: data.opening_line ?? "",
|
|
521
|
+
confidence: data.confidence ?? 0,
|
|
522
|
+
evidenceUrl: data.evidence_url ?? "",
|
|
523
|
+
researchPrompt: data.research_prompt,
|
|
524
|
+
variations: (data.variations ?? []).map((v) => ({
|
|
525
|
+
style: v.style,
|
|
526
|
+
subjectLine: v.subject_line ?? "",
|
|
527
|
+
openingLine: v.opening_line ?? "",
|
|
528
|
+
cta: v.cta ?? "",
|
|
529
|
+
prediction: v.prediction,
|
|
530
|
+
email: v.email
|
|
531
|
+
}))
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
/** @deprecated Use signalToCopy. Retained for compatibility. */
|
|
535
|
+
async personalize(params) {
|
|
536
|
+
return this.signalToCopy(params);
|
|
537
|
+
}
|
|
504
538
|
/** Enrich a company with actionable signals (V1) */
|
|
505
539
|
async enrich(params) {
|
|
506
540
|
const args = {
|
|
@@ -509,6 +543,9 @@ var Signals = class {
|
|
|
509
543
|
if (params.domain) args.domain = params.domain;
|
|
510
544
|
if (params.researchPrompt) args.research_prompt = params.researchPrompt;
|
|
511
545
|
if (params.signalTypes) args.signal_types = params.signalTypes;
|
|
546
|
+
if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
|
|
547
|
+
if (params.lookbackDays) args.lookback_days = params.lookbackDays;
|
|
548
|
+
if (params.enableDeepSearch !== void 0) args.enable_deep_search = params.enableDeepSearch;
|
|
512
549
|
const data = await this.client.mcp("tools/call", {
|
|
513
550
|
name: "enrich_company_signals",
|
|
514
551
|
arguments: args
|
|
@@ -518,6 +555,16 @@ var Signals = class {
|
|
|
518
555
|
signals: (data.signals ?? []).map((s) => ({
|
|
519
556
|
title: s.title,
|
|
520
557
|
signalType: s.signal_type,
|
|
558
|
+
sourceType: s.source_type ?? s.signal_classification?.label ?? "unknown",
|
|
559
|
+
sourceProvenance: s.source_provenance ?? s.metadata?.source_provenance ?? null,
|
|
560
|
+
signalFamily: s.signal_family ?? s.signal_type ?? null,
|
|
561
|
+
signalEventType: s.signal_event_type ?? s.signal_classification?.slug ?? null,
|
|
562
|
+
signalEventLabel: s.signal_event_label ?? s.signal_classification?.label ?? null,
|
|
563
|
+
signalClassification: s.signal_classification ? {
|
|
564
|
+
label: s.signal_classification.label,
|
|
565
|
+
slug: s.signal_classification.slug,
|
|
566
|
+
rationale: s.signal_classification.rationale
|
|
567
|
+
} : null,
|
|
521
568
|
confidenceScore: s.confidence_score ?? 0,
|
|
522
569
|
detectedAt: s.detected_at ?? "",
|
|
523
570
|
url: s.url,
|
|
@@ -558,8 +605,17 @@ var Signals = class {
|
|
|
558
605
|
content: s.content ?? "",
|
|
559
606
|
date: s.date ?? null,
|
|
560
607
|
sourceUrl: s.source_url ?? null,
|
|
561
|
-
sourceType: s.source_type ?? "unknown",
|
|
562
|
-
|
|
608
|
+
sourceType: s.source_type ?? s.signal_classification?.label ?? "unknown",
|
|
609
|
+
sourceProvenance: s.source_provenance ?? s.metadata?.source_provenance ?? null,
|
|
610
|
+
signalFamily: s.signal_family ?? s.type ?? null,
|
|
611
|
+
signalEventType: s.signal_event_type ?? s.signal_classification?.slug ?? null,
|
|
612
|
+
signalEventLabel: s.signal_event_label ?? s.signal_classification?.label ?? null,
|
|
613
|
+
confidence: s.confidence ?? null,
|
|
614
|
+
signalClassification: s.signal_classification ? {
|
|
615
|
+
label: s.signal_classification.label,
|
|
616
|
+
slug: s.signal_classification.slug,
|
|
617
|
+
rationale: s.signal_classification.rationale
|
|
618
|
+
} : null
|
|
563
619
|
})),
|
|
564
620
|
signalCount: data.signal_count ?? 0,
|
|
565
621
|
intelligence: data.intelligence ? {
|
|
@@ -602,6 +658,58 @@ var Signals = class {
|
|
|
602
658
|
}
|
|
603
659
|
};
|
|
604
660
|
}
|
|
661
|
+
/** Plan or run experimental Signal Fusion with explicit spend controls. */
|
|
662
|
+
async fusion(params) {
|
|
663
|
+
const args = {};
|
|
664
|
+
if (params.companyName) args.company_name = params.companyName;
|
|
665
|
+
if (params.domain) args.domain = params.domain;
|
|
666
|
+
if (params.companyDomain) args.company_domain = params.companyDomain;
|
|
667
|
+
if (params.linkedinUrl) args.linkedin_url = params.linkedinUrl;
|
|
668
|
+
if (params.companies) args.companies = params.companies;
|
|
669
|
+
if (params.preset) args.preset = params.preset;
|
|
670
|
+
if (params.researchPrompt) args.research_prompt = params.researchPrompt;
|
|
671
|
+
if (params.signalTypes) args.signal_types = params.signalTypes;
|
|
672
|
+
if (params.lookbackDays) args.lookback_days = params.lookbackDays;
|
|
673
|
+
if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
|
|
674
|
+
if (params.maxToolCalls) args.max_tool_calls = params.maxToolCalls;
|
|
675
|
+
if (params.maxTokens) args.max_tokens = params.maxTokens;
|
|
676
|
+
if (params.timeoutMs) args.timeout_ms = params.timeoutMs;
|
|
677
|
+
const dryRun = params.dryRun ?? params.dry_run;
|
|
678
|
+
const confirmSpend = params.confirmSpend ?? params.confirm_spend;
|
|
679
|
+
const maxCredits = params.maxCredits ?? params.max_credits;
|
|
680
|
+
const maxCostUsd = params.maxCostUsd ?? params.max_cost_usd;
|
|
681
|
+
if (dryRun !== void 0) args.dry_run = dryRun;
|
|
682
|
+
if (confirmSpend !== void 0) args.confirm_spend = confirmSpend;
|
|
683
|
+
if (maxCredits !== void 0) args.max_credits = maxCredits;
|
|
684
|
+
if (maxCostUsd !== void 0) args.max_cost_usd = maxCostUsd;
|
|
685
|
+
const data = await this.client.post("signal-fusion", args);
|
|
686
|
+
return {
|
|
687
|
+
success: data.success ?? false,
|
|
688
|
+
capability: data.capability ?? "signal_fusion",
|
|
689
|
+
displayName: data.display_name ?? "Signal Fusion",
|
|
690
|
+
company: data.company,
|
|
691
|
+
signals: (data.signals ?? []).map((s) => ({
|
|
692
|
+
id: s.id,
|
|
693
|
+
title: s.title,
|
|
694
|
+
type: s.type,
|
|
695
|
+
content: s.content ?? "",
|
|
696
|
+
date: s.date ?? null,
|
|
697
|
+
sourceUrl: s.source_url ?? null,
|
|
698
|
+
sourceType: s.source_type ?? "unknown",
|
|
699
|
+
confidence: s.confidence ?? null
|
|
700
|
+
})),
|
|
701
|
+
signalCount: data.signal_count ?? data.signals?.length ?? 0,
|
|
702
|
+
results: data.results ?? [],
|
|
703
|
+
model: data.model,
|
|
704
|
+
fusion: data.fusion,
|
|
705
|
+
costUsd: data.cost_usd ?? 0,
|
|
706
|
+
tokensUsed: data.tokens_used ?? 0,
|
|
707
|
+
costSummary: data.cost_summary,
|
|
708
|
+
creditsUsed: data.total_credits_used ?? data.credits_used ?? 0,
|
|
709
|
+
billingMetadata: data.billing_metadata,
|
|
710
|
+
raw: data
|
|
711
|
+
};
|
|
712
|
+
}
|
|
605
713
|
};
|
|
606
714
|
|
|
607
715
|
// src/resources/systems.ts
|
|
@@ -1040,6 +1148,7 @@ function mapCustomerRowCounts(value) {
|
|
|
1040
1148
|
acceptedRows: numberOrNull(record.accepted_rows) ?? void 0,
|
|
1041
1149
|
usableRows: numberOrNull(record.usable_rows) ?? void 0,
|
|
1042
1150
|
copiedRows: numberOrNull(record.copied_rows) ?? void 0,
|
|
1151
|
+
copySkippedRows: numberOrNull(record.copy_skipped_rows) ?? void 0,
|
|
1043
1152
|
approvalReadyRows: numberOrNull(record.approval_ready_rows) ?? void 0,
|
|
1044
1153
|
qaReadyRows: numberOrNull(record.qa_ready_rows) ?? void 0,
|
|
1045
1154
|
deliveredRows: numberOrNull(record.delivered_rows) ?? void 0,
|
|
@@ -1276,7 +1385,8 @@ function buildArgs(request) {
|
|
|
1276
1385
|
geographies: request.icp.geographies,
|
|
1277
1386
|
keywords: request.icp.keywords,
|
|
1278
1387
|
exclusions: request.icp.exclusions,
|
|
1279
|
-
require_verified_email: request.icp.requireVerifiedEmail
|
|
1388
|
+
require_verified_email: request.icp.requireVerifiedEmail,
|
|
1389
|
+
persona_expansion_mode: request.icp.personaExpansionMode
|
|
1280
1390
|
};
|
|
1281
1391
|
}
|
|
1282
1392
|
if (request.policy) {
|
|
@@ -1316,6 +1426,7 @@ function buildArgs(request) {
|
|
|
1316
1426
|
} : void 0,
|
|
1317
1427
|
sequence_steps: request.copy.sequenceSteps,
|
|
1318
1428
|
copy_schema: request.copy.copySchema,
|
|
1429
|
+
evidence_mode: request.copy.evidenceMode,
|
|
1319
1430
|
banned_phrases: request.copy.bannedPhrases,
|
|
1320
1431
|
approval_required: request.copy.approvalRequired,
|
|
1321
1432
|
quality_tier: request.copy.qualityTier
|
|
@@ -1372,7 +1483,8 @@ var DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS = {
|
|
|
1372
1483
|
copy: {
|
|
1373
1484
|
enabled: true,
|
|
1374
1485
|
tone: "direct",
|
|
1375
|
-
maxBodyWords: 125
|
|
1486
|
+
maxBodyWords: 125,
|
|
1487
|
+
evidenceMode: "signal_led"
|
|
1376
1488
|
},
|
|
1377
1489
|
delivery: {
|
|
1378
1490
|
enabled: true,
|
|
@@ -1429,7 +1541,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1429
1541
|
"Block export when required identity, company, or email fields are missing."
|
|
1430
1542
|
],
|
|
1431
1543
|
activationBoundary: "Cache inventory is read-only. Fresh sourcing, cache writes, export, and sender loading require explicit approval.",
|
|
1432
|
-
memoryKeywords: ["cache inventory", "large list", "unique emails", "top-up sourcing", "source metadata"]
|
|
1544
|
+
memoryKeywords: ["cache inventory", "large list", "unique emails", "top-up sourcing", "source metadata"],
|
|
1545
|
+
knowledgeSources: ["data-ops/contact-data-lifecycle", "data-ops/credit-optimization-guide", "gtm/data-quality-ops", "gtm/lead-generation-strategies"]
|
|
1433
1546
|
},
|
|
1434
1547
|
{
|
|
1435
1548
|
slug: "net-new-suppressed-list",
|
|
@@ -1454,7 +1567,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1454
1567
|
"Do not describe rows as fully qualified when the approved path only proves net-new email status."
|
|
1455
1568
|
],
|
|
1456
1569
|
activationBoundary: "Suppression review must pass before export, upload, CRM sync, sender load, or sequence launch.",
|
|
1457
|
-
memoryKeywords: ["suppression", "net-new", "prior email overlap", "domain review", "provenance-rich QA"]
|
|
1570
|
+
memoryKeywords: ["suppression", "net-new", "prior email overlap", "domain review", "provenance-rich QA"],
|
|
1571
|
+
knowledgeSources: ["gtm/data-quality-ops", "data-ops/contact-data-lifecycle", "gtm/outbound-sequencing"]
|
|
1458
1572
|
},
|
|
1459
1573
|
{
|
|
1460
1574
|
slug: "proof-first-vertical-gate",
|
|
@@ -1479,7 +1593,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1479
1593
|
"Contact fit should meet the configured threshold before email finding or copy generation."
|
|
1480
1594
|
],
|
|
1481
1595
|
activationBoundary: "Proof gates are required before contact spend, copy, export, or external writes.",
|
|
1482
|
-
memoryKeywords: ["proof gate", "vertical exclusion", "company before contact", "pass review fail", "fit threshold"]
|
|
1596
|
+
memoryKeywords: ["proof gate", "vertical exclusion", "company before contact", "pass review fail", "fit threshold"],
|
|
1597
|
+
knowledgeSources: ["gtm/icp-design-framework", "gtm/strategy/scoring.yaml", "gtm/advanced/account-prioritization-frameworks", "gtm/advanced/predictive-lead-scoring", "gtm/verticals"]
|
|
1483
1598
|
},
|
|
1484
1599
|
{
|
|
1485
1600
|
slug: "signal-led-copy-approval",
|
|
@@ -1504,7 +1619,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1504
1619
|
"Destination fields must remain blocked until approval metadata is present."
|
|
1505
1620
|
],
|
|
1506
1621
|
activationBoundary: "Copy readiness is not delivery approval. Export, sync, sender load, and launch require a separate human-approved gate.",
|
|
1507
|
-
memoryKeywords: ["company signals", "evidence-fed copy", "why now", "copy blocker", "approval gate"]
|
|
1622
|
+
memoryKeywords: ["company signals", "evidence-fed copy", "why now", "copy blocker", "approval gate"],
|
|
1623
|
+
knowledgeSources: ["gtm/email-personalization", "gtm/signal-based-selling", "gtm/signal-combination-matrix", "gtm/advanced/buyer-journey-mapping"]
|
|
1508
1624
|
},
|
|
1509
1625
|
{
|
|
1510
1626
|
slug: "domain-first-recovery",
|
|
@@ -1529,7 +1645,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1529
1645
|
"Target count means final held rows, not raw sourced rows."
|
|
1530
1646
|
],
|
|
1531
1647
|
activationBoundary: "Domain recovery informs sourcing. Contact enrichment, paid qualification, and export still require approved gates.",
|
|
1532
|
-
memoryKeywords: ["domain-first", "yield modeling", "attrition", "accepted domains", "gap fill"]
|
|
1648
|
+
memoryKeywords: ["domain-first", "yield modeling", "attrition", "accepted domains", "gap fill"],
|
|
1649
|
+
knowledgeSources: ["gtm/lead-generation-strategies", "data-ops/enrichment-waterfall-strategy", "data-ops/credit-optimization-guide", "gtm/territory-account-planning"]
|
|
1533
1650
|
},
|
|
1534
1651
|
{
|
|
1535
1652
|
slug: "table-workflow-handoff",
|
|
@@ -1554,7 +1671,112 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1554
1671
|
"Provider route activation must dry-run before any external write."
|
|
1555
1672
|
],
|
|
1556
1673
|
activationBoundary: "MCP, webhook, managed integration, and destination routes remain dry-run until the reviewed route and campaign are approved.",
|
|
1557
|
-
memoryKeywords: ["table workflow", "request ready", "provider status", "export blocker", "BYO integration"]
|
|
1674
|
+
memoryKeywords: ["table workflow", "request ready", "provider status", "export blocker", "BYO integration"],
|
|
1675
|
+
knowledgeSources: ["gtm/multi-channel-orchestration", "data-ops/enrichment-waterfall-strategy", "recipes/clay-gtm-webhook-recipe", "systems/blueprints/multi-channel-orchestration"]
|
|
1676
|
+
},
|
|
1677
|
+
{
|
|
1678
|
+
slug: "icp-persona-segmentation",
|
|
1679
|
+
label: "ICP And Persona Segmentation",
|
|
1680
|
+
whenToUse: [
|
|
1681
|
+
"The brief has a broad market, multiple personas, or unclear buying committee.",
|
|
1682
|
+
"The campaign should rank account tiers, persona fit, vertical nuance, and exclusions before sourcing at scale."
|
|
1683
|
+
],
|
|
1684
|
+
sequence: [
|
|
1685
|
+
"Convert the brief into account tiers, persona roles, buying committee influence, and explicit exclusions.",
|
|
1686
|
+
"Choose vertical guidance only from the customer-safe GTM library and keep internal platform docs out of prompts.",
|
|
1687
|
+
"Score accounts before contacts, then score contacts against persona, seniority, function, geography, and intent fit.",
|
|
1688
|
+
"Return segment counts and review buckets before spend, copy, export, or launch."
|
|
1689
|
+
],
|
|
1690
|
+
requiredFields: {
|
|
1691
|
+
segment: ["segment_name", "tier", "persona_priority", "buying_committee_role", "fit_reason", "exclusion_reason"],
|
|
1692
|
+
scoring: ["account_fit_score", "persona_fit_score", "segment_confidence", "review_bucket"]
|
|
1693
|
+
},
|
|
1694
|
+
qualityGates: [
|
|
1695
|
+
"Do not treat adjacent personas or verticals as matches unless the brief allows them.",
|
|
1696
|
+
"Keep ICP, persona, and exclusion evidence visible in the proof packet.",
|
|
1697
|
+
"Low-confidence segments route to review before contact discovery or copy."
|
|
1698
|
+
],
|
|
1699
|
+
activationBoundary: "Segmentation is planning guidance. Paid sourcing, enrichment, export, and launch require the normal approval gates.",
|
|
1700
|
+
memoryKeywords: ["ICP design", "persona segmentation", "buying committee", "account tiers", "fit scoring", "vertical nuance"],
|
|
1701
|
+
knowledgeSources: ["gtm/icp-design-framework", "gtm/personas/sdr.yaml", "gtm/personas/ae.yaml", "gtm/personas/cro.yaml", "gtm/personas/revops.yaml", "gtm/advanced/account-prioritization-frameworks", "gtm/verticals"]
|
|
1702
|
+
},
|
|
1703
|
+
{
|
|
1704
|
+
slug: "buying-signal-prioritization",
|
|
1705
|
+
label: "Buying Signal Prioritization",
|
|
1706
|
+
whenToUse: [
|
|
1707
|
+
"The campaign depends on timing, intent, trigger events, or account prioritization.",
|
|
1708
|
+
"The operator wants why-now proof instead of generic list generation."
|
|
1709
|
+
],
|
|
1710
|
+
sequence: [
|
|
1711
|
+
"Map the campaign goal to signal families, trigger freshness, and buyer-journey stage.",
|
|
1712
|
+
"Rank signals by relevance, recency, source quality, and persona-specific actionability.",
|
|
1713
|
+
"Attach evidence URLs or evidence summaries without exposing private memory rows.",
|
|
1714
|
+
"Use signal strength to decide source order, copy angle, and review priority."
|
|
1715
|
+
],
|
|
1716
|
+
requiredFields: {
|
|
1717
|
+
signal: ["signal_type", "signal_date", "signal_source", "why_now", "signal_confidence", "buyer_stage"],
|
|
1718
|
+
prioritization: ["priority_score", "priority_reason", "next_best_action", "review_reason"]
|
|
1719
|
+
},
|
|
1720
|
+
qualityGates: [
|
|
1721
|
+
"Do not use stale, unsupported, or weak signals as personalization proof.",
|
|
1722
|
+
"Signal fit cannot override hard ICP, geography, suppression, or verified-email gates.",
|
|
1723
|
+
"Rows with uncertain why-now evidence must stay review-only."
|
|
1724
|
+
],
|
|
1725
|
+
activationBoundary: "Signal ranking can prioritize review and copy. It does not approve outreach, sender loading, exports, or sends.",
|
|
1726
|
+
memoryKeywords: ["buying signals", "intent data", "funding trigger", "new executive", "tech adoption", "buyer journey", "why now"],
|
|
1727
|
+
knowledgeSources: ["gtm/signal-based-selling", "gtm/signal-combination-matrix", "gtm/advanced/intent-data-strategies", "gtm/advanced/buyer-journey-mapping", "gtm/signals/funding-round", "gtm/signals/new-executive", "gtm/signals/tech-adoption", "recipes/funding-trigger-outreach", "recipes/new-hire-outreach"]
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
slug: "multi-channel-sequence-fit",
|
|
1731
|
+
label: "Multi-Channel Sequence Fit",
|
|
1732
|
+
whenToUse: [
|
|
1733
|
+
"The campaign needs email, LinkedIn, call, webhook, CRM, or sequencer coordination.",
|
|
1734
|
+
"Copy and delivery should adapt by persona, channel, deliverability risk, and proof strength."
|
|
1735
|
+
],
|
|
1736
|
+
sequence: [
|
|
1737
|
+
"Choose channel mix from persona, deal motion, evidence strength, deliverability constraints, and connected destination readiness.",
|
|
1738
|
+
"Draft sequence logic with email, LinkedIn, call, and task handoffs only where supported by the approved destination.",
|
|
1739
|
+
"Keep copy concise, proof-backed, channel-specific, and reviewable before delivery.",
|
|
1740
|
+
"Run deliverability and destination readiness checks before sender load or launch approval."
|
|
1741
|
+
],
|
|
1742
|
+
requiredFields: {
|
|
1743
|
+
channel: ["channel", "touch_number", "persona_context", "message_angle", "channel_blocker", "approval_status"],
|
|
1744
|
+
deliverability: ["verified_email", "domain_risk", "send_window", "unsubscribe_risk", "sender_ready"]
|
|
1745
|
+
},
|
|
1746
|
+
qualityGates: [
|
|
1747
|
+
"Email copy must be row-supported and under the configured campaign tone/length limits.",
|
|
1748
|
+
"LinkedIn, phone, CRM, webhook, and sequencer actions remain destination-locked until approved.",
|
|
1749
|
+
"Deliverability risk or missing sender readiness blocks launch even when rows are qualified."
|
|
1750
|
+
],
|
|
1751
|
+
activationBoundary: "Sequence strategy is draft-only. External writes, sender loading, launch, and sending need separate explicit approval.",
|
|
1752
|
+
memoryKeywords: ["outbound sequencing", "email personalization", "LinkedIn outreach", "cold calling", "multi-channel orchestration", "deliverability"],
|
|
1753
|
+
knowledgeSources: ["gtm/outbound-sequencing", "gtm/email-personalization", "gtm/linkedin-outreach-strategies", "gtm/cold-calling-frameworks", "gtm/multi-channel-orchestration", "gtm/advanced/email-deliverability", "systems/blueprints/multi-channel-orchestration"]
|
|
1754
|
+
},
|
|
1755
|
+
{
|
|
1756
|
+
slug: "revops-feedback-loop",
|
|
1757
|
+
label: "RevOps Feedback Loop",
|
|
1758
|
+
whenToUse: [
|
|
1759
|
+
"The campaign should improve from replies, meetings, delivery results, CRM outcomes, or operator QA.",
|
|
1760
|
+
"The operator needs post-build monitoring, governance, or continuous ops follow-up."
|
|
1761
|
+
],
|
|
1762
|
+
sequence: [
|
|
1763
|
+
"Define success metrics, guardrails, and feedback sources before launch.",
|
|
1764
|
+
"Collect aggregate outcomes, QA blockers, delivery health, and operator edits after each campaign phase.",
|
|
1765
|
+
"Separate workspace-private evidence from public-safe learnings and Brain defaults.",
|
|
1766
|
+
"Feed approved aggregate learnings back into future sourcing, qualification, copy, and suppression rules."
|
|
1767
|
+
],
|
|
1768
|
+
requiredFields: {
|
|
1769
|
+
feedback: ["source", "event_type", "metric", "sample_size", "confidence", "learning_candidate"],
|
|
1770
|
+
governance: ["approval_owner", "last_reviewed_at", "risk_flag", "next_review_action"]
|
|
1771
|
+
},
|
|
1772
|
+
qualityGates: [
|
|
1773
|
+
"Do not write memory or Brain learnings from raw replies, private labels, or provider payloads without approved redaction.",
|
|
1774
|
+
"Use holdouts or pre/post comparisons before claiming causal lift.",
|
|
1775
|
+
"Delivery, suppression, and opt-out signals must update future gates before scale-up."
|
|
1776
|
+
],
|
|
1777
|
+
activationBoundary: "Feedback review is read-only until memory writes, Brain writes, CRM updates, or campaign changes are explicitly approved.",
|
|
1778
|
+
memoryKeywords: ["RevOps", "feedback loop", "campaign learning", "reply outcomes", "sales marketing alignment", "data hygiene", "holdout"],
|
|
1779
|
+
knowledgeSources: ["gtm/revenue-operations", "gtm/advanced/sales-marketing-alignment", "gtm/advanced/predictive-lead-scoring", "gtm/data-quality-ops", "data-ops/contact-data-lifecycle", "recipes/crm-data-hygiene", "gtm/playbooks/revops-automation-playbook"]
|
|
1558
1780
|
}
|
|
1559
1781
|
];
|
|
1560
1782
|
var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
@@ -1641,7 +1863,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1641
1863
|
agencyContext: {
|
|
1642
1864
|
partnerEcosystem: ["signaliz", "instantly", "nango"]
|
|
1643
1865
|
},
|
|
1644
|
-
operatingPlaybookSlugs: [
|
|
1866
|
+
operatingPlaybookSlugs: [
|
|
1867
|
+
"net-new-suppressed-list",
|
|
1868
|
+
"proof-first-vertical-gate",
|
|
1869
|
+
"signal-led-copy-approval",
|
|
1870
|
+
"icp-persona-segmentation",
|
|
1871
|
+
"buying-signal-prioritization",
|
|
1872
|
+
"multi-channel-sequence-fit",
|
|
1873
|
+
"revops-feedback-loop"
|
|
1874
|
+
]
|
|
1645
1875
|
},
|
|
1646
1876
|
{
|
|
1647
1877
|
slug: "non-medical-home-care",
|
|
@@ -1714,7 +1944,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1714
1944
|
agencyContext: {
|
|
1715
1945
|
partnerEcosystem: ["clay", "octave", "signaliz", "instantly", "nango"]
|
|
1716
1946
|
},
|
|
1717
|
-
operatingPlaybookSlugs: [
|
|
1947
|
+
operatingPlaybookSlugs: [
|
|
1948
|
+
"proof-first-vertical-gate",
|
|
1949
|
+
"domain-first-recovery",
|
|
1950
|
+
"table-workflow-handoff",
|
|
1951
|
+
"icp-persona-segmentation",
|
|
1952
|
+
"buying-signal-prioritization",
|
|
1953
|
+
"multi-channel-sequence-fit",
|
|
1954
|
+
"revops-feedback-loop"
|
|
1955
|
+
]
|
|
1718
1956
|
},
|
|
1719
1957
|
{
|
|
1720
1958
|
slug: "agency-founder-led",
|
|
@@ -1775,7 +2013,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1775
2013
|
agencyContext: {
|
|
1776
2014
|
partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
|
|
1777
2015
|
},
|
|
1778
|
-
operatingPlaybookSlugs: [
|
|
2016
|
+
operatingPlaybookSlugs: [
|
|
2017
|
+
"net-new-suppressed-list",
|
|
2018
|
+
"signal-led-copy-approval",
|
|
2019
|
+
"table-workflow-handoff",
|
|
2020
|
+
"icp-persona-segmentation",
|
|
2021
|
+
"buying-signal-prioritization",
|
|
2022
|
+
"multi-channel-sequence-fit",
|
|
2023
|
+
"revops-feedback-loop"
|
|
2024
|
+
]
|
|
1779
2025
|
},
|
|
1780
2026
|
{
|
|
1781
2027
|
slug: "cloud-infrastructure-displacement",
|
|
@@ -1862,7 +2108,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1862
2108
|
agencyContext: {
|
|
1863
2109
|
partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
|
|
1864
2110
|
},
|
|
1865
|
-
operatingPlaybookSlugs: [
|
|
2111
|
+
operatingPlaybookSlugs: [
|
|
2112
|
+
"proof-first-vertical-gate",
|
|
2113
|
+
"domain-first-recovery",
|
|
2114
|
+
"signal-led-copy-approval",
|
|
2115
|
+
"icp-persona-segmentation",
|
|
2116
|
+
"buying-signal-prioritization",
|
|
2117
|
+
"multi-channel-sequence-fit",
|
|
2118
|
+
"revops-feedback-loop"
|
|
2119
|
+
]
|
|
1866
2120
|
}
|
|
1867
2121
|
];
|
|
1868
2122
|
var CampaignBuilderAgent = class {
|
|
@@ -1893,6 +2147,9 @@ var CampaignBuilderAgent = class {
|
|
|
1893
2147
|
const plan = await this.createPlan(request, options);
|
|
1894
2148
|
return createCampaignBuilderReadiness(plan);
|
|
1895
2149
|
}
|
|
2150
|
+
activeWorkContext(input) {
|
|
2151
|
+
return createCampaignBuilderActiveWorkContext(input);
|
|
2152
|
+
}
|
|
1896
2153
|
async proof(request, options = {}) {
|
|
1897
2154
|
const plan = await this.createPlan(request, options);
|
|
1898
2155
|
const result = await this.dryRunPlan(plan, {
|
|
@@ -2277,9 +2534,10 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
|
|
|
2277
2534
|
const estimatedCredits = estimateCredits(resolvedRequest, defaults, targetCount);
|
|
2278
2535
|
const buildRequest = createBuildRequest(resolvedRequest, defaults, targetCount, campaignName, context.scopeBuildArgs, routes, memory, context.scopeBrainPreflight);
|
|
2279
2536
|
const brainPreflight = asRecord(buildRequest.brainPreflight);
|
|
2537
|
+
const evidence = buildRequest.evidence ?? null;
|
|
2280
2538
|
const approvals = deriveApprovals(resolvedRequest, routes, memory, estimatedCredits, defaults.delivery?.approvalRequired !== false);
|
|
2281
2539
|
return {
|
|
2282
|
-
planId: `cbp_${hashString(JSON.stringify({ goal: resolvedRequest.goal, campaignName, targetCount, routes }))}`,
|
|
2540
|
+
planId: `cbp_${hashString(JSON.stringify({ goal: resolvedRequest.goal, campaignName, targetCount, routes, evidence }))}`,
|
|
2283
2541
|
campaignName,
|
|
2284
2542
|
goal: resolvedRequest.goal,
|
|
2285
2543
|
targetCount,
|
|
@@ -2294,6 +2552,7 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
|
|
|
2294
2552
|
approvals,
|
|
2295
2553
|
buildRequest,
|
|
2296
2554
|
brainPreflight,
|
|
2555
|
+
evidence,
|
|
2297
2556
|
operatingPlaybooks,
|
|
2298
2557
|
mcpFlow: createMcpFlow(resolvedRequest, buildRequest, routes, memory, approvals),
|
|
2299
2558
|
estimatedCredits,
|
|
@@ -2385,6 +2644,90 @@ function createCampaignBuilderReadiness(plan) {
|
|
|
2385
2644
|
nextActions: campaignReadinessNextActions(plan, ready, customRoutes.length)
|
|
2386
2645
|
};
|
|
2387
2646
|
}
|
|
2647
|
+
function createCampaignBuilderActiveWorkContext(input) {
|
|
2648
|
+
const plan = input.readiness?.plan ?? input.plan;
|
|
2649
|
+
const remembered = input.remembered ?? {};
|
|
2650
|
+
const lastResult = asRecord(input.lastResult);
|
|
2651
|
+
const readinessBlockers = input.readiness?.summary.blockers ?? [];
|
|
2652
|
+
const explicitBlockers = input.blockers ?? [];
|
|
2653
|
+
const blockers = uniqueStrings([...explicitBlockers, ...readinessBlockers]);
|
|
2654
|
+
const warnings = uniqueStrings([
|
|
2655
|
+
...input.warnings ?? [],
|
|
2656
|
+
...input.readiness?.summary.warnings ?? [],
|
|
2657
|
+
...plan?.warnings ?? []
|
|
2658
|
+
]);
|
|
2659
|
+
const missingApprovals = plan ? (input.approval ? getMissingCampaignBuilderApprovals(plan, input.approval) : plan.approvals.filter((approval) => approval.blocking)).map((approval) => approval.type) : [];
|
|
2660
|
+
const refs = normalizeCampaignBuilderActiveWorkRefs({
|
|
2661
|
+
plan,
|
|
2662
|
+
remembered,
|
|
2663
|
+
refs: input.refs,
|
|
2664
|
+
lastResult
|
|
2665
|
+
});
|
|
2666
|
+
const state = inferCampaignBuilderActiveWorkState({
|
|
2667
|
+
plan,
|
|
2668
|
+
readiness: input.readiness,
|
|
2669
|
+
remembered,
|
|
2670
|
+
lastResult,
|
|
2671
|
+
blockers,
|
|
2672
|
+
missingApprovals
|
|
2673
|
+
});
|
|
2674
|
+
const nextSafeAction = campaignBuilderActiveWorkNextAction(state, blockers, missingApprovals, refs);
|
|
2675
|
+
const approvalPacket = createCampaignBuilderApprovalPacket(plan, input.approval, missingApprovals);
|
|
2676
|
+
const nextSafeMcpAction = campaignBuilderActiveWorkNextMcpAction({
|
|
2677
|
+
state,
|
|
2678
|
+
plan,
|
|
2679
|
+
refs,
|
|
2680
|
+
approvalPacket
|
|
2681
|
+
});
|
|
2682
|
+
const summary = {
|
|
2683
|
+
plan_id: plan?.planId ?? remembered.planId ?? null,
|
|
2684
|
+
campaign_name: plan?.campaignName ?? null,
|
|
2685
|
+
target_count: plan?.targetCount ?? null,
|
|
2686
|
+
gtm_campaign_id: plan?.buildRequest.gtmCampaignId ?? remembered.gtmCampaignId ?? null,
|
|
2687
|
+
campaign_build_id: stringValue(lastResult.campaign_build_id ?? lastResult.campaignBuildId) ?? remembered.campaignBuildId ?? null,
|
|
2688
|
+
provider_campaign_id: remembered.providerCampaignId ?? null
|
|
2689
|
+
};
|
|
2690
|
+
const approvalBoundary = campaignBuilderActiveWorkApprovalBoundary(missingApprovals, state);
|
|
2691
|
+
const conversationStarters = campaignBuilderActiveWorkConversationStarters({
|
|
2692
|
+
state,
|
|
2693
|
+
blockers,
|
|
2694
|
+
missingApprovals,
|
|
2695
|
+
refs,
|
|
2696
|
+
nextSafeAction
|
|
2697
|
+
});
|
|
2698
|
+
return {
|
|
2699
|
+
packet_version: "campaign-builder-active-work-context.v1",
|
|
2700
|
+
read_only: true,
|
|
2701
|
+
no_spend: true,
|
|
2702
|
+
no_provider_writes: true,
|
|
2703
|
+
private_safe: true,
|
|
2704
|
+
state,
|
|
2705
|
+
summary,
|
|
2706
|
+
refs,
|
|
2707
|
+
blockers,
|
|
2708
|
+
warnings,
|
|
2709
|
+
missing_approval_types: missingApprovals,
|
|
2710
|
+
approval_packet: approvalPacket,
|
|
2711
|
+
approval_boundary: approvalBoundary,
|
|
2712
|
+
next_safe_action: nextSafeAction,
|
|
2713
|
+
next_safe_mcp_action: nextSafeMcpAction,
|
|
2714
|
+
conversation_starters: conversationStarters,
|
|
2715
|
+
openai_agent_handoff: createCampaignBuilderOpenAiAgentHandoff({
|
|
2716
|
+
plan,
|
|
2717
|
+
state,
|
|
2718
|
+
summary,
|
|
2719
|
+
refs,
|
|
2720
|
+
blockers,
|
|
2721
|
+
warnings,
|
|
2722
|
+
missingApprovals,
|
|
2723
|
+
approvalPacket,
|
|
2724
|
+
approvalBoundary,
|
|
2725
|
+
nextSafeAction,
|
|
2726
|
+
nextSafeMcpAction,
|
|
2727
|
+
conversationStarters
|
|
2728
|
+
})
|
|
2729
|
+
};
|
|
2730
|
+
}
|
|
2388
2731
|
function createCampaignBuilderProofReceipt(plan, result) {
|
|
2389
2732
|
const strategyMemory = asRecord(plan.strategyMemoryStatus);
|
|
2390
2733
|
const dryRunResult = asRecord(result);
|
|
@@ -2443,6 +2786,7 @@ function createCampaignBuilderProofReceipt(plan, result) {
|
|
|
2443
2786
|
estimated_credits: plan.estimatedCredits,
|
|
2444
2787
|
operating_playbooks: plan.operatingPlaybooks.map((playbook) => playbook.slug)
|
|
2445
2788
|
},
|
|
2789
|
+
evidence: plan.evidence,
|
|
2446
2790
|
gates,
|
|
2447
2791
|
strategy_memory_status: summarizeCampaignBuilderProofStrategyMemory(strategyMemory),
|
|
2448
2792
|
dry_run_result: summarizeCampaignBuilderProofDryRun(dryRunResult),
|
|
@@ -2498,6 +2842,56 @@ function getCampaignBuilderOperatingPlaybooksForRequest(request) {
|
|
|
2498
2842
|
]);
|
|
2499
2843
|
return slugs.map(getCampaignBuilderOperatingPlaybook).filter((playbook) => Boolean(playbook));
|
|
2500
2844
|
}
|
|
2845
|
+
function normalizeCampaignBuilderEvidence(evidence) {
|
|
2846
|
+
if (!evidence) return null;
|
|
2847
|
+
const attachmentSummary = (evidence.attachments ?? []).filter((attachment) => stringValue(attachment.name)).slice(0, 5).map((attachment) => ({
|
|
2848
|
+
name: stringValue(attachment.name) ?? "attachment",
|
|
2849
|
+
kind: stringValue(attachment.kind) ?? null,
|
|
2850
|
+
media_type: stringValue(attachment.mediaType) ?? null,
|
|
2851
|
+
redacted: attachment.redacted !== false,
|
|
2852
|
+
columns: uniqueStrings(attachment.columns ?? []).slice(0, 25),
|
|
2853
|
+
row_count: numberOrUndefined2(attachment.rowCount) ?? null,
|
|
2854
|
+
content_summary: stringValue(attachment.contentSummary)?.slice(0, 500) ?? null,
|
|
2855
|
+
evidence_fields: uniqueStrings(attachment.evidenceFields ?? []).slice(0, 25)
|
|
2856
|
+
}));
|
|
2857
|
+
const urlSummary = (evidence.urls ?? []).filter((url) => stringValue(url.url)).slice(0, 8).map((url) => {
|
|
2858
|
+
const rawUrl = stringValue(url.url) ?? "";
|
|
2859
|
+
return {
|
|
2860
|
+
url: rawUrl,
|
|
2861
|
+
host: stringValue(url.host) ?? hostFromUrl(rawUrl) ?? null,
|
|
2862
|
+
type: stringValue(url.type) ?? null,
|
|
2863
|
+
label: stringValue(url.label) ?? null,
|
|
2864
|
+
summary: stringValue(url.summary)?.slice(0, 500) ?? null,
|
|
2865
|
+
redacted: url.redacted === true
|
|
2866
|
+
};
|
|
2867
|
+
});
|
|
2868
|
+
const operatorNotes = uniqueStrings(evidence.notes ?? []).map((note) => note.slice(0, 240)).slice(0, 5);
|
|
2869
|
+
if (!attachmentSummary.length && !urlSummary.length && !operatorNotes.length) return null;
|
|
2870
|
+
return {
|
|
2871
|
+
packet_version: "campaign-builder-evidence.v1",
|
|
2872
|
+
private_safe: true,
|
|
2873
|
+
attachment_summary: attachmentSummary,
|
|
2874
|
+
url_summary: urlSummary,
|
|
2875
|
+
operator_notes: operatorNotes,
|
|
2876
|
+
privacy_boundary: "Use these attachment and URL summaries as planning evidence only. Do not expose raw private attachment text, raw rows, leads, emails, provider payloads, copy bodies, or secrets.",
|
|
2877
|
+
raw_private_fields_withheld: [
|
|
2878
|
+
"raw_private_attachment_text",
|
|
2879
|
+
"raw_attachment_rows",
|
|
2880
|
+
"raw_leads",
|
|
2881
|
+
"email_addresses",
|
|
2882
|
+
"provider_auth_payloads",
|
|
2883
|
+
"copy_bodies",
|
|
2884
|
+
"secrets"
|
|
2885
|
+
]
|
|
2886
|
+
};
|
|
2887
|
+
}
|
|
2888
|
+
function hostFromUrl(value) {
|
|
2889
|
+
try {
|
|
2890
|
+
return new URL(value).hostname || void 0;
|
|
2891
|
+
} catch {
|
|
2892
|
+
return void 0;
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2501
2895
|
function applyCampaignBuilderStrategyTemplate(request) {
|
|
2502
2896
|
const template = getCampaignBuilderStrategyTemplate(request.strategyTemplate);
|
|
2503
2897
|
if (!template) return request;
|
|
@@ -3189,7 +3583,7 @@ function normalizeMemory(request) {
|
|
|
3189
3583
|
};
|
|
3190
3584
|
}
|
|
3191
3585
|
function defaultAgencyMemoryQueries(request, configured) {
|
|
3192
|
-
const operatingPlaybookTerms = getCampaignBuilderOperatingPlaybooksForRequest(request).flatMap((playbook) => [playbook.label, ...playbook.memoryKeywords]).join(" ");
|
|
3586
|
+
const operatingPlaybookTerms = getCampaignBuilderOperatingPlaybooksForRequest(request).flatMap((playbook) => [playbook.label, ...playbook.memoryKeywords, ...playbook.knowledgeSources]).join(" ");
|
|
3193
3587
|
const queries = [{
|
|
3194
3588
|
query: request.goal,
|
|
3195
3589
|
scopes: ["workspace", configured.useNetworkPatterns ? "network_patterns" : "operator_notes"],
|
|
@@ -3400,6 +3794,8 @@ function createBuildRequest(request, defaults, targetCount, campaignName, scopeB
|
|
|
3400
3794
|
fillPolicy: "aggressive"
|
|
3401
3795
|
}
|
|
3402
3796
|
};
|
|
3797
|
+
const evidence = normalizeCampaignBuilderEvidence(request.evidence);
|
|
3798
|
+
if (evidence) buildRequest.evidence = evidence;
|
|
3403
3799
|
const scoped = asRecord(scopeBuildArgs);
|
|
3404
3800
|
buildRequest.gtmCampaignId = request.gtmCampaignId ?? stringValue(scoped.gtm_campaign_id ?? scoped.gtmCampaignId);
|
|
3405
3801
|
buildRequest.learningHoldout = normalizeCampaignBuilderLearningHoldout(
|
|
@@ -3431,6 +3827,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
3431
3827
|
memory.enabled ? "feedback" : void 0
|
|
3432
3828
|
]);
|
|
3433
3829
|
const providerChain = uniqueStrings(["signaliz", ...request.preferredProviders ?? [], ...routes.map((route) => route.provider)]);
|
|
3830
|
+
const evidence = buildRequest.evidence ?? normalizeCampaignBuilderEvidence(request.evidence);
|
|
3434
3831
|
const targetIcp = compact({
|
|
3435
3832
|
personas: buildRequest.icp?.personas,
|
|
3436
3833
|
industries: buildRequest.icp?.industries,
|
|
@@ -3443,6 +3840,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
3443
3840
|
const learningArgs = compact({
|
|
3444
3841
|
campaign_brief: request.goal,
|
|
3445
3842
|
target_icp: targetIcp,
|
|
3843
|
+
evidence_context: evidence,
|
|
3446
3844
|
layers,
|
|
3447
3845
|
provider_chain: providerChain,
|
|
3448
3846
|
lead_source: providerChain[0] ?? "signaliz",
|
|
@@ -3454,6 +3852,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
3454
3852
|
const defaultsArgs = compact({
|
|
3455
3853
|
campaign_brief: request.goal,
|
|
3456
3854
|
target_icp: targetIcp,
|
|
3855
|
+
evidence_context: evidence,
|
|
3457
3856
|
layers,
|
|
3458
3857
|
include_global: memory.useNetworkPatterns,
|
|
3459
3858
|
include_memory: memory.enabled,
|
|
@@ -3464,6 +3863,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
3464
3863
|
provider_chain: providerChain,
|
|
3465
3864
|
lead_source: providerChain[0] ?? "signaliz",
|
|
3466
3865
|
target_icp: targetIcp,
|
|
3866
|
+
evidence_context: evidence,
|
|
3467
3867
|
include_global: memory.useNetworkPatterns,
|
|
3468
3868
|
limit: 25
|
|
3469
3869
|
});
|
|
@@ -3476,9 +3876,11 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
3476
3876
|
label: playbook.label,
|
|
3477
3877
|
quality_gates: playbook.qualityGates,
|
|
3478
3878
|
required_fields: playbook.requiredFields,
|
|
3479
|
-
activation_boundary: playbook.activationBoundary
|
|
3879
|
+
activation_boundary: playbook.activationBoundary,
|
|
3880
|
+
knowledge_sources: playbook.knowledgeSources
|
|
3480
3881
|
})),
|
|
3481
3882
|
target_icp: targetIcp,
|
|
3883
|
+
evidence_context: evidence,
|
|
3482
3884
|
provider_chain: providerChain,
|
|
3483
3885
|
lead_source: providerChain[0] ?? "signaliz",
|
|
3484
3886
|
learning_holdout: buildRequest.learningHoldout,
|
|
@@ -3751,7 +4153,7 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
|
|
|
3751
4153
|
phase: "plan",
|
|
3752
4154
|
tool: "nango_mcp_tools_list",
|
|
3753
4155
|
arguments: {
|
|
3754
|
-
format: "
|
|
4156
|
+
format: "openai"
|
|
3755
4157
|
},
|
|
3756
4158
|
readOnly: true,
|
|
3757
4159
|
approvalRequired: false
|
|
@@ -4060,6 +4462,7 @@ function buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory) {
|
|
|
4060
4462
|
layers: layers.length > 0 ? layers : void 0,
|
|
4061
4463
|
preferred_providers: preferredProviders.length > 0 ? preferredProviders : void 0,
|
|
4062
4464
|
strategy_model: strategyModel,
|
|
4465
|
+
evidence_context: buildRequest.evidence ?? normalizeCampaignBuilderEvidence(request.evidence),
|
|
4063
4466
|
include_strategy_patterns: campaignBuilderStrategyPatternsEnabled(agencyContext),
|
|
4064
4467
|
include_workflow_patterns: campaignBuilderWorkflowPatternsEnabled(agencyContext),
|
|
4065
4468
|
include_nango_catalog: agencyContext.includeNangoCatalog !== false,
|
|
@@ -4068,7 +4471,8 @@ function buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory) {
|
|
|
4068
4471
|
slug: playbook.slug,
|
|
4069
4472
|
label: playbook.label,
|
|
4070
4473
|
quality_gates: playbook.qualityGates,
|
|
4071
|
-
activation_boundary: playbook.activationBoundary
|
|
4474
|
+
activation_boundary: playbook.activationBoundary,
|
|
4475
|
+
knowledge_sources: playbook.knowledgeSources
|
|
4072
4476
|
})),
|
|
4073
4477
|
include_memory: memory.enabled,
|
|
4074
4478
|
include_brain: true,
|
|
@@ -4161,6 +4565,7 @@ function buildCampaignArgs(request) {
|
|
|
4161
4565
|
}
|
|
4162
4566
|
if (request.campaignStrategyContext) args.campaign_strategy_context = request.campaignStrategyContext;
|
|
4163
4567
|
if (request.deliveryRisk) args.delivery_risk = request.deliveryRisk;
|
|
4568
|
+
if (request.evidence) args.evidence_context = request.evidence;
|
|
4164
4569
|
if (request.icp) {
|
|
4165
4570
|
args.icp = compact({
|
|
4166
4571
|
personas: request.icp.personas,
|
|
@@ -4210,7 +4615,8 @@ function buildCampaignArgs(request) {
|
|
|
4210
4615
|
max_body_words: request.copy.maxBodyWords,
|
|
4211
4616
|
sender_context: request.copy.senderContext,
|
|
4212
4617
|
offer_context: request.copy.offerContext,
|
|
4213
|
-
model: request.copy.model
|
|
4618
|
+
model: request.copy.model,
|
|
4619
|
+
evidence_mode: request.copy.evidenceMode
|
|
4214
4620
|
});
|
|
4215
4621
|
}
|
|
4216
4622
|
if (request.delivery) {
|
|
@@ -4487,6 +4893,7 @@ function mapAgentCustomerRowCounts(value) {
|
|
|
4487
4893
|
acceptedRows: numberOrUndefined2(record.accepted_rows),
|
|
4488
4894
|
usableRows: numberOrUndefined2(record.usable_rows),
|
|
4489
4895
|
copiedRows: numberOrUndefined2(record.copied_rows),
|
|
4896
|
+
copySkippedRows: numberOrUndefined2(record.copy_skipped_rows),
|
|
4490
4897
|
approvalReadyRows: numberOrUndefined2(record.approval_ready_rows),
|
|
4491
4898
|
qaReadyRows: numberOrUndefined2(record.qa_ready_rows),
|
|
4492
4899
|
deliveredRows: numberOrUndefined2(record.delivered_rows),
|
|
@@ -4597,7 +5004,7 @@ function createCampaignBuilderNorthStarScorecard(status, rows, artifacts, termin
|
|
|
4597
5004
|
const sampledRows = rows.rows.length;
|
|
4598
5005
|
const rowData = rows.rows.map((row) => asRecord(row.data));
|
|
4599
5006
|
const requestedTarget = status.customerRowCounts?.requestedTarget ?? status.recordsTotal ?? rows.count;
|
|
4600
|
-
const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
|
|
5007
|
+
const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copySkippedRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
|
|
4601
5008
|
const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
|
|
4602
5009
|
const verifiedEmailRows = rowData.filter(campaignReviewDataHasVerifiedEmail).length;
|
|
4603
5010
|
const uniqueEmails = new Set(rowData.map(campaignReviewDataEmail).filter(Boolean)).size;
|
|
@@ -5088,6 +5495,342 @@ function createCampaignBuilderReadinessLane(route, plan) {
|
|
|
5088
5495
|
nextAction: customRoute ? `Review ${route.provider} route setup before launch approval.` : void 0
|
|
5089
5496
|
};
|
|
5090
5497
|
}
|
|
5498
|
+
function createCampaignBuilderApprovalPacket(plan, approval, missingTypes) {
|
|
5499
|
+
const requestedTypes = plan ? uniqueStrings(plan.approvals.filter((item) => item.blocking).map((item) => item.type)) : [];
|
|
5500
|
+
const approvalMatchesPlan = Boolean(plan && approval?.planId === plan.planId);
|
|
5501
|
+
const approvedTypes = approvalMatchesPlan ? approval?.approvedTypes ?? [] : [];
|
|
5502
|
+
const approvedRoutes = approvalMatchesPlan ? approval?.approvedRouteIds ?? [] : [];
|
|
5503
|
+
const missingIds = new Set(
|
|
5504
|
+
plan && approvalMatchesPlan && approval ? getMissingCampaignBuilderApprovals(plan, approval).map((item) => item.id) : plan?.approvals.filter((item) => item.blocking).map((item) => item.id) ?? []
|
|
5505
|
+
);
|
|
5506
|
+
const routeIdsRequired = plan ? uniqueStrings(plan.approvals.map((item) => item.routeId).filter((id) => Boolean(id))) : [];
|
|
5507
|
+
const spendLimitRequired = plan ? Math.max(0, ...plan.approvals.filter((item) => item.type === "spend" && item.blocking).map((item) => item.estimatedCredits ?? plan.estimatedCredits)) : 0;
|
|
5508
|
+
const normalizedSpendLimit = spendLimitRequired > 0 ? spendLimitRequired : null;
|
|
5509
|
+
const approvalState = !plan ? "unscoped" : missingTypes.length > 0 ? "requires_approval" : "approved";
|
|
5510
|
+
const approvalInput = {
|
|
5511
|
+
approved_by: approval?.approvedBy ?? null,
|
|
5512
|
+
approved_at: approval?.approvedAt ?? null,
|
|
5513
|
+
approved_types: approvedTypes,
|
|
5514
|
+
approved_route_ids: approvedRoutes,
|
|
5515
|
+
spend_limit_credits: approval?.spendLimitCredits ?? null,
|
|
5516
|
+
notes: approval?.notes
|
|
5517
|
+
};
|
|
5518
|
+
return {
|
|
5519
|
+
packet_version: "campaign-builder-approval-packet.v1",
|
|
5520
|
+
read_only: true,
|
|
5521
|
+
no_spend: true,
|
|
5522
|
+
no_provider_writes: true,
|
|
5523
|
+
private_safe: true,
|
|
5524
|
+
approval_state: approvalState,
|
|
5525
|
+
plan_id: plan?.planId ?? null,
|
|
5526
|
+
campaign_name: plan?.campaignName ?? null,
|
|
5527
|
+
requested_approval_types: requestedTypes,
|
|
5528
|
+
missing_approval_types: uniqueStrings(missingTypes),
|
|
5529
|
+
spend_limit_credits_required: normalizedSpendLimit,
|
|
5530
|
+
route_ids_required: routeIdsRequired,
|
|
5531
|
+
required_approvals: (plan?.approvals ?? []).map((item) => compact({
|
|
5532
|
+
id: item.id,
|
|
5533
|
+
type: item.type,
|
|
5534
|
+
label: item.label,
|
|
5535
|
+
reason: item.reason,
|
|
5536
|
+
blocking: item.blocking,
|
|
5537
|
+
route_id: item.routeId,
|
|
5538
|
+
provider: item.provider,
|
|
5539
|
+
estimated_credits: item.estimatedCredits,
|
|
5540
|
+
status: missingIds.has(item.id) ? "missing" : "approved"
|
|
5541
|
+
})),
|
|
5542
|
+
approval_input: approvalInput,
|
|
5543
|
+
cli_handoff: plan ? {
|
|
5544
|
+
command: campaignBuilderApprovalCliHandoff(requestedTypes, routeIdsRequired, normalizedSpendLimit),
|
|
5545
|
+
safety: "Template only: run after explicit human approval identity, approved types, route scope, and spend limit are filled in."
|
|
5546
|
+
} : null,
|
|
5547
|
+
sdk_handoff: plan ? {
|
|
5548
|
+
method: "campaignBuilderAgent.buildApprovedPlan",
|
|
5549
|
+
approval: compact({
|
|
5550
|
+
approvedBy: approval?.approvedBy ?? "<operator-email>",
|
|
5551
|
+
approvedTypes: requestedTypes,
|
|
5552
|
+
approvedRouteIds: routeIdsRequired,
|
|
5553
|
+
spendLimitCredits: normalizedSpendLimit ?? void 0,
|
|
5554
|
+
notes: approval?.notes
|
|
5555
|
+
}),
|
|
5556
|
+
options: {
|
|
5557
|
+
idempotencyKey: "<set-before-execution>"
|
|
5558
|
+
},
|
|
5559
|
+
safety: "Call only after the approval packet is accepted; this helper does not execute writes or spend."
|
|
5560
|
+
} : null,
|
|
5561
|
+
mcp_handoffs: plan ? campaignBuilderApprovalMcpHandoffs(plan, requestedTypes, routeIdsRequired, normalizedSpendLimit) : [],
|
|
5562
|
+
safety_boundary: "This approval packet is a reusable request for human approval; it is not an approval grant and it does not authorize spend, provider writes, sender loading, delivery, or launch by itself."
|
|
5563
|
+
};
|
|
5564
|
+
}
|
|
5565
|
+
function campaignBuilderApprovalCliHandoff(requestedTypes, routeIds, spendLimit) {
|
|
5566
|
+
return [
|
|
5567
|
+
"signaliz campaign-agent build-approved --request-file campaign-request.json --confirm-launch",
|
|
5568
|
+
requestedTypes.length > 0 ? `--approved-types ${shellArg(requestedTypes.join(","))}` : "--approve-all",
|
|
5569
|
+
"--approved-by <operator-email>",
|
|
5570
|
+
spendLimit !== null ? `--spend-limit ${spendLimit}` : void 0,
|
|
5571
|
+
routeIds.length > 0 ? `--approved-route-ids ${shellArg(routeIds.join(","))}` : void 0
|
|
5572
|
+
].filter(Boolean).join(" ");
|
|
5573
|
+
}
|
|
5574
|
+
function campaignBuilderApprovalMcpHandoffs(plan, requestedTypes, routeIds, spendLimit) {
|
|
5575
|
+
const approvalContext = compact({
|
|
5576
|
+
plan_id: plan.planId,
|
|
5577
|
+
approval_types: requestedTypes,
|
|
5578
|
+
approved_route_ids: routeIds,
|
|
5579
|
+
spend_limit_credits: spendLimit,
|
|
5580
|
+
approved_by: "<operator-email>"
|
|
5581
|
+
});
|
|
5582
|
+
return plan.mcpFlow.filter((step) => ["execution-prepare", "approved-build", "delivery-approval"].includes(step.id)).map((step) => ({
|
|
5583
|
+
id: step.id,
|
|
5584
|
+
tool: step.tool,
|
|
5585
|
+
arguments: step.id === "approved-build" ? compact({ ...step.arguments, approval_context: approvalContext }) : step.arguments,
|
|
5586
|
+
read_only: step.readOnly,
|
|
5587
|
+
approval_required: step.approvalRequired,
|
|
5588
|
+
safety: step.readOnly ? "Read-only readiness handoff; safe to inspect before approval." : "Write-capable handoff; run only after the approval packet is accepted."
|
|
5589
|
+
}));
|
|
5590
|
+
}
|
|
5591
|
+
function campaignBuilderActiveWorkNextMcpAction(input) {
|
|
5592
|
+
const campaignBuildRef = input.refs.find((ref) => ref.kind === "campaign_build" && ref.id);
|
|
5593
|
+
if (campaignBuildRef) {
|
|
5594
|
+
return {
|
|
5595
|
+
id: "check-campaign-build-status",
|
|
5596
|
+
tool: "get_campaign_build_status",
|
|
5597
|
+
arguments: { campaign_build_id: campaignBuildRef.id },
|
|
5598
|
+
read_only: true,
|
|
5599
|
+
approval_required: false,
|
|
5600
|
+
safety: "Read-only status check for the remembered campaign build; does not spend, write, export, send, or approve anything."
|
|
5601
|
+
};
|
|
5602
|
+
}
|
|
5603
|
+
const campaignRef = input.refs.find((ref) => ref.kind === "gtm_campaign" && ref.id);
|
|
5604
|
+
if (campaignRef) {
|
|
5605
|
+
return {
|
|
5606
|
+
id: "check-gtm-campaign-status",
|
|
5607
|
+
tool: "gtm_campaign_execution_status",
|
|
5608
|
+
arguments: { campaign_id: campaignRef.id },
|
|
5609
|
+
read_only: true,
|
|
5610
|
+
approval_required: false,
|
|
5611
|
+
safety: "Read-only campaign execution status check; does not start or mutate the campaign."
|
|
5612
|
+
};
|
|
5613
|
+
}
|
|
5614
|
+
const preferredStepId = input.state === "ready_for_dry_run" ? "dry-run-build" : input.state === "planning" || input.state === "blocked" ? "agency-campaign-build-plan" : null;
|
|
5615
|
+
const preferredStep = preferredStepId ? input.plan?.mcpFlow.find((step) => step.id === preferredStepId && step.readOnly) : void 0;
|
|
5616
|
+
if (preferredStep) return campaignBuilderMcpStepToActiveWorkAction(preferredStep, "Read-only continuation from the saved campaign-agent plan.");
|
|
5617
|
+
const readOnlyApprovalHandoff = input.approvalPacket.mcp_handoffs.find((handoff) => handoff.read_only && !handoff.approval_required);
|
|
5618
|
+
if (readOnlyApprovalHandoff) return readOnlyApprovalHandoff;
|
|
5619
|
+
const firstReadOnlyPlanStep = input.plan?.mcpFlow.find((step) => step.readOnly && !step.approvalRequired);
|
|
5620
|
+
return firstReadOnlyPlanStep ? campaignBuilderMcpStepToActiveWorkAction(firstReadOnlyPlanStep, "Read-only saved plan check; safe before approvals or writes.") : null;
|
|
5621
|
+
}
|
|
5622
|
+
function campaignBuilderMcpStepToActiveWorkAction(step, safety) {
|
|
5623
|
+
return {
|
|
5624
|
+
id: step.id,
|
|
5625
|
+
tool: step.tool,
|
|
5626
|
+
arguments: step.arguments,
|
|
5627
|
+
read_only: step.readOnly,
|
|
5628
|
+
approval_required: step.approvalRequired,
|
|
5629
|
+
safety
|
|
5630
|
+
};
|
|
5631
|
+
}
|
|
5632
|
+
function normalizeCampaignBuilderActiveWorkRefs(input) {
|
|
5633
|
+
const refs = [];
|
|
5634
|
+
const pushRef = (ref) => {
|
|
5635
|
+
if (!ref?.id) return;
|
|
5636
|
+
refs.push(ref);
|
|
5637
|
+
};
|
|
5638
|
+
pushRef(input.plan?.planId ? { kind: "plan", id: input.plan.planId, label: input.plan.campaignName, source: "plan" } : void 0);
|
|
5639
|
+
pushRef(input.remembered.planId ? { kind: "plan", id: input.remembered.planId, source: "remembered" } : void 0);
|
|
5640
|
+
pushRef(
|
|
5641
|
+
input.plan?.buildRequest.gtmCampaignId ?? input.remembered.gtmCampaignId ? {
|
|
5642
|
+
kind: "gtm_campaign",
|
|
5643
|
+
id: input.plan?.buildRequest.gtmCampaignId ?? input.remembered.gtmCampaignId,
|
|
5644
|
+
label: input.plan?.campaignName,
|
|
5645
|
+
source: input.plan?.buildRequest.gtmCampaignId ? "plan" : "remembered"
|
|
5646
|
+
} : void 0
|
|
5647
|
+
);
|
|
5648
|
+
const campaignBuildId = stringValue(input.lastResult.campaign_build_id ?? input.lastResult.campaignBuildId) ?? input.remembered.campaignBuildId;
|
|
5649
|
+
pushRef(campaignBuildId ? { kind: "campaign_build", id: campaignBuildId, status: activeWorkStatus(input.lastResult) ?? input.remembered.status, source: "result" } : void 0);
|
|
5650
|
+
pushRef(
|
|
5651
|
+
input.remembered.providerCampaignId ? {
|
|
5652
|
+
kind: "provider_campaign",
|
|
5653
|
+
id: input.remembered.providerCampaignId,
|
|
5654
|
+
label: input.remembered.provider,
|
|
5655
|
+
status: input.remembered.status,
|
|
5656
|
+
source: "remembered"
|
|
5657
|
+
} : void 0
|
|
5658
|
+
);
|
|
5659
|
+
for (const ref of input.remembered.refs ?? []) pushRef(ref);
|
|
5660
|
+
for (const ref of input.refs ?? []) pushRef(ref);
|
|
5661
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5662
|
+
return refs.filter((ref) => {
|
|
5663
|
+
const key = `${ref.kind}:${ref.id}`;
|
|
5664
|
+
if (seen.has(key)) return false;
|
|
5665
|
+
seen.add(key);
|
|
5666
|
+
return true;
|
|
5667
|
+
});
|
|
5668
|
+
}
|
|
5669
|
+
function inferCampaignBuilderActiveWorkState(input) {
|
|
5670
|
+
if (input.blockers.length > 0) return "blocked";
|
|
5671
|
+
const status = activeWorkStatus(input.lastResult) ?? input.remembered.status;
|
|
5672
|
+
const normalized = status?.toLowerCase();
|
|
5673
|
+
if (normalized && ["completed", "complete", "succeeded", "success", "done"].includes(normalized)) return "completed";
|
|
5674
|
+
if (normalized && ["queued", "running", "in_progress", "processing", "pending"].includes(normalized)) return "queued_or_running";
|
|
5675
|
+
const dryRunComplete = input.lastResult.dry_run === true || input.lastResult.dryRun === true || normalized === "dry_run";
|
|
5676
|
+
if (dryRunComplete) return input.missingApprovals.length > 0 ? "needs_approval" : "dry_run_complete";
|
|
5677
|
+
if (input.missingApprovals.length > 0) return "needs_approval";
|
|
5678
|
+
if (input.readiness?.summary.ready === true) return "ready_for_dry_run";
|
|
5679
|
+
if (input.plan) return "planning";
|
|
5680
|
+
return "unknown";
|
|
5681
|
+
}
|
|
5682
|
+
function campaignBuilderActiveWorkApprovalBoundary(missingApprovals, state) {
|
|
5683
|
+
if (missingApprovals.length > 0) {
|
|
5684
|
+
return `Blocked before spend, provider writes, delivery, or launch until approval covers: ${uniqueStrings(missingApprovals).join(", ")}.`;
|
|
5685
|
+
}
|
|
5686
|
+
if (state === "dry_run_complete" || state === "ready_for_dry_run") {
|
|
5687
|
+
return "Read-only planning and dry-runs are allowed; spend, provider writes, sender loading, delivery, and launch still require explicit approval.";
|
|
5688
|
+
}
|
|
5689
|
+
return "This packet is read-only and does not authorize spend, provider writes, sender loading, delivery, or launch.";
|
|
5690
|
+
}
|
|
5691
|
+
function campaignBuilderActiveWorkNextAction(state, blockers, missingApprovals, refs) {
|
|
5692
|
+
if (blockers.length > 0) return `Resolve blocker: ${blockers[0]}`;
|
|
5693
|
+
if (missingApprovals.length > 0) return `Ask the operator to approve ${uniqueStrings(missingApprovals).join(", ")} before any write or spend action.`;
|
|
5694
|
+
if (state === "ready_for_dry_run") return "Run or inspect the read-only campaign dry-run, then return the receipt for approval review.";
|
|
5695
|
+
if (state === "dry_run_complete") return "Review the dry-run receipt and collect explicit launch or delivery approval before any write action.";
|
|
5696
|
+
if (state === "queued_or_running") return "Poll the remembered campaign build or provider job status; do not start a duplicate job.";
|
|
5697
|
+
if (state === "completed") return "Review final artifacts and delivery gates before export, sync, sender load, or launch.";
|
|
5698
|
+
if (refs.length > 0) return "Use the remembered refs to fetch current read-only status before asking the operator for IDs.";
|
|
5699
|
+
return "Create or refresh a campaign-builder plan before taking any spendful or write action.";
|
|
5700
|
+
}
|
|
5701
|
+
function campaignBuilderActiveWorkConversationStarters(input) {
|
|
5702
|
+
const starters = [];
|
|
5703
|
+
if (input.blockers.length > 0) {
|
|
5704
|
+
starters.push(
|
|
5705
|
+
`I found a blocker: ${input.blockers[0]}. Want me to stay in read-only diagnostics and prepare the fix path?`
|
|
5706
|
+
);
|
|
5707
|
+
}
|
|
5708
|
+
if (input.missingApprovals.length > 0) {
|
|
5709
|
+
starters.push(
|
|
5710
|
+
`You still owe approval for ${uniqueStrings(input.missingApprovals).join(", ")}. Want the exact approval packet before anything writes or spends?`
|
|
5711
|
+
);
|
|
5712
|
+
}
|
|
5713
|
+
if (input.state === "queued_or_running") {
|
|
5714
|
+
const buildRef = input.refs.find((ref) => ref.kind === "campaign_build");
|
|
5715
|
+
starters.push(buildRef ? `I can check campaign build ${buildRef.id} now and avoid starting a duplicate job.` : "I can check the running job status now and avoid starting duplicate work.");
|
|
5716
|
+
}
|
|
5717
|
+
if (input.state === "dry_run_complete") {
|
|
5718
|
+
starters.push("The dry run is complete. Want me to summarize blockers, artifacts, and the approval handoff?");
|
|
5719
|
+
}
|
|
5720
|
+
if (input.state === "ready_for_dry_run") {
|
|
5721
|
+
starters.push("Everything is ready for a safe dry run. Want me to run the no-spend preview first?");
|
|
5722
|
+
}
|
|
5723
|
+
if (input.state === "completed") {
|
|
5724
|
+
starters.push("The build looks complete. Want me to review rows, artifacts, and delivery gates before export or send approval?");
|
|
5725
|
+
}
|
|
5726
|
+
starters.push(`Next safe action: ${input.nextSafeAction}`);
|
|
5727
|
+
return uniqueStrings(starters).slice(0, 4);
|
|
5728
|
+
}
|
|
5729
|
+
function createCampaignBuilderOpenAiAgentHandoff(input) {
|
|
5730
|
+
const readOnlyPlanActions = input.plan?.mcpFlow.filter((step) => step.readOnly && !step.approvalRequired).map((step) => campaignBuilderMcpStepToActiveWorkAction(step, "Read-only Signaliz MCP continuation for the saved campaign-agent plan.")) ?? [];
|
|
5731
|
+
const routeSetupActions = readOnlyPlanActions.filter(
|
|
5732
|
+
(action) => action.tool === "gtm_provider_recipe_prepare" || action.tool === "gtm_provider_route_activate"
|
|
5733
|
+
);
|
|
5734
|
+
const safeReadActions = uniqueCampaignBuilderActiveWorkActions([
|
|
5735
|
+
input.nextSafeMcpAction,
|
|
5736
|
+
...routeSetupActions,
|
|
5737
|
+
...readOnlyPlanActions
|
|
5738
|
+
]);
|
|
5739
|
+
const approvalGatedActions = uniqueCampaignBuilderActiveWorkActions([
|
|
5740
|
+
...input.approvalPacket.mcp_handoffs.filter((action) => action.approval_required || !action.read_only),
|
|
5741
|
+
...input.plan?.mcpFlow.filter((step) => step.approvalRequired || !step.readOnly).map((step) => campaignBuilderMcpStepToActiveWorkAction(step, "Approval-gated Signaliz MCP continuation for the saved campaign-agent plan.")) ?? []
|
|
5742
|
+
]);
|
|
5743
|
+
const approvalTypes = uniqueStrings([
|
|
5744
|
+
...input.missingApprovals,
|
|
5745
|
+
...input.approvalPacket.requested_approval_types
|
|
5746
|
+
]);
|
|
5747
|
+
return {
|
|
5748
|
+
packet_version: "campaign-builder-openai-agent-handoff.v1",
|
|
5749
|
+
surface: "openai_agents_sdk",
|
|
5750
|
+
agent: {
|
|
5751
|
+
name: "Signaliz GTM Campaign Agent",
|
|
5752
|
+
handoff_description: "Owns safe, conversational GTM campaign planning and continuation across Signaliz MCP, SDK, attachments, URLs, customer tools, approvals, and sender/export gates.",
|
|
5753
|
+
instructions: [
|
|
5754
|
+
"Be warm, direct, and expert-level GTM. Translate the current state into plain operator language before proposing work.",
|
|
5755
|
+
"Start from the packet state, refs, evidence_context, approval_boundary, and next_safe_action. Do not ask for IDs already present in refs or summary.",
|
|
5756
|
+
"Use attachment_summary, url_summary, and operator_notes as first-class planning evidence, while honoring the evidence privacy_boundary and withheld raw fields.",
|
|
5757
|
+
"Prefer Signaliz-native, cached, remembered, and read-only MCP actions before provider calls. Never start duplicate jobs when a campaign_build or provider job is queued or running.",
|
|
5758
|
+
"Call only tools listed in safe_read_tools without approval. Treat approval_gated_tools as human-review surfaces, not permission to spend, write, export, load senders, deliver, or launch.",
|
|
5759
|
+
"When approval is missing, show the approval_packet and the exact missing approval scope before any side-effecting step."
|
|
5760
|
+
],
|
|
5761
|
+
output_contract: [
|
|
5762
|
+
"current_state: one concise sentence describing where the campaign work stands.",
|
|
5763
|
+
"evidence_used: attachment, URL, memory, route, or integration evidence used without exposing private raw rows or secrets.",
|
|
5764
|
+
"next_safe_mcp_action: the read-only Signaliz MCP action to run next, or null when none is safe.",
|
|
5765
|
+
"approval_boundary: the human approval scope required before spend, provider writes, delivery, export, sender load, or launch.",
|
|
5766
|
+
"operator_reply: conversational GTM guidance with blockers, risks, and the safest next move."
|
|
5767
|
+
]
|
|
5768
|
+
},
|
|
5769
|
+
context: {
|
|
5770
|
+
state: input.state,
|
|
5771
|
+
summary: input.summary,
|
|
5772
|
+
refs: input.refs,
|
|
5773
|
+
blockers: input.blockers,
|
|
5774
|
+
warnings: input.warnings,
|
|
5775
|
+
evidence_context: input.plan?.evidence ?? null,
|
|
5776
|
+
approval_packet: input.approvalPacket,
|
|
5777
|
+
approval_boundary: input.approvalBoundary,
|
|
5778
|
+
next_safe_action: input.nextSafeAction,
|
|
5779
|
+
conversation_starters: input.conversationStarters
|
|
5780
|
+
},
|
|
5781
|
+
tools: {
|
|
5782
|
+
mcp_server_label: "signaliz",
|
|
5783
|
+
remote_mcp_compatible: true,
|
|
5784
|
+
next_safe_mcp_action: input.nextSafeMcpAction,
|
|
5785
|
+
safe_read_tools: safeReadActions.map(
|
|
5786
|
+
(action) => campaignBuilderOpenAiAgentTool(action, "Safe read-only Signaliz MCP action available before approval.")
|
|
5787
|
+
),
|
|
5788
|
+
approval_gated_tools: approvalGatedActions.map(
|
|
5789
|
+
(action) => campaignBuilderOpenAiAgentTool(action, "Requires explicit human review before execution.")
|
|
5790
|
+
)
|
|
5791
|
+
},
|
|
5792
|
+
guardrails: {
|
|
5793
|
+
input: [
|
|
5794
|
+
"Reject or pause requests to expose raw private attachment text, raw rows, leads, emails, provider payloads, copy bodies, API keys, or secrets.",
|
|
5795
|
+
"Pause when the user asks to spend credits, write to a provider, export, load a sender, deliver, or launch without explicit approval scope."
|
|
5796
|
+
],
|
|
5797
|
+
tool: [
|
|
5798
|
+
"Read-only tools may run when they match safe_read_tools and their arguments match this packet.",
|
|
5799
|
+
"Any tool with approval_required=true or read_only=false requires human review and the approval_packet scope first."
|
|
5800
|
+
],
|
|
5801
|
+
human_review_required_for: approvalTypes,
|
|
5802
|
+
privacy: input.plan?.evidence?.privacy_boundary ?? "Use summarized context only. Do not expose raw private attachment text, raw rows, leads, emails, provider payloads, copy bodies, secrets, or credentials."
|
|
5803
|
+
}
|
|
5804
|
+
};
|
|
5805
|
+
}
|
|
5806
|
+
function campaignBuilderOpenAiAgentTool(action, purpose) {
|
|
5807
|
+
return {
|
|
5808
|
+
id: action.id,
|
|
5809
|
+
type: "mcp",
|
|
5810
|
+
server_label: "signaliz",
|
|
5811
|
+
name: action.tool,
|
|
5812
|
+
arguments: action.arguments,
|
|
5813
|
+
read_only: action.read_only,
|
|
5814
|
+
approval_required: action.approval_required,
|
|
5815
|
+
purpose,
|
|
5816
|
+
safety: action.safety
|
|
5817
|
+
};
|
|
5818
|
+
}
|
|
5819
|
+
function uniqueCampaignBuilderActiveWorkActions(actions) {
|
|
5820
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5821
|
+
const unique = [];
|
|
5822
|
+
for (const action of actions) {
|
|
5823
|
+
if (!action) continue;
|
|
5824
|
+
const key = `${action.id}:${action.tool}`;
|
|
5825
|
+
if (seen.has(key)) continue;
|
|
5826
|
+
seen.add(key);
|
|
5827
|
+
unique.push(action);
|
|
5828
|
+
}
|
|
5829
|
+
return unique;
|
|
5830
|
+
}
|
|
5831
|
+
function activeWorkStatus(record) {
|
|
5832
|
+
return stringValue(record.status ?? record.state ?? record.phase);
|
|
5833
|
+
}
|
|
5091
5834
|
function campaignBuilderBuiltInForRoute(route) {
|
|
5092
5835
|
return Object.entries(CAMPAIGN_BUILDER_BUILT_IN_ROUTE_IDS).find(([, routeId]) => route.id === routeId)?.[0];
|
|
5093
5836
|
}
|
|
@@ -7884,6 +8627,36 @@ function recordsFromParams(params) {
|
|
|
7884
8627
|
if (params.input) return { input: params.input };
|
|
7885
8628
|
return { input: {} };
|
|
7886
8629
|
}
|
|
8630
|
+
function toFusionConfig(params) {
|
|
8631
|
+
return {
|
|
8632
|
+
system_prompt: params.systemPrompt || params.system_prompt,
|
|
8633
|
+
user_template: params.userTemplate || params.user_template || params.prompt,
|
|
8634
|
+
preset: params.preset,
|
|
8635
|
+
temperature: params.temperature,
|
|
8636
|
+
max_tool_calls: params.maxToolCalls || params.max_tool_calls,
|
|
8637
|
+
max_tokens: params.maxTokens || params.max_tokens,
|
|
8638
|
+
timeout_ms: params.timeoutMs || params.timeout_ms,
|
|
8639
|
+
output_fields: params.outputFields || params.output_fields || [{ name: "response", type: "text", description: "Structured Fusion enrichment result" }]
|
|
8640
|
+
};
|
|
8641
|
+
}
|
|
8642
|
+
function toFusionSpendControls(params) {
|
|
8643
|
+
const controls = {};
|
|
8644
|
+
const dryRun = params.dryRun ?? params.dry_run;
|
|
8645
|
+
const confirmSpend = params.confirmSpend ?? params.confirm_spend;
|
|
8646
|
+
const maxCredits = params.maxCredits ?? params.max_credits;
|
|
8647
|
+
const maxCostUsd = params.maxCostUsd ?? params.max_cost_usd;
|
|
8648
|
+
if (dryRun !== void 0) controls.dry_run = dryRun;
|
|
8649
|
+
if (confirmSpend !== void 0) controls.confirm_spend = confirmSpend;
|
|
8650
|
+
if (maxCredits !== void 0) controls.max_credits = maxCredits;
|
|
8651
|
+
if (maxCostUsd !== void 0) controls.max_cost_usd = maxCostUsd;
|
|
8652
|
+
return controls;
|
|
8653
|
+
}
|
|
8654
|
+
function fusionRecordsFromParams(params) {
|
|
8655
|
+
const records = params.records || params.inputs;
|
|
8656
|
+
if (records?.length) return { records };
|
|
8657
|
+
if (params.input) return { input: params.input };
|
|
8658
|
+
return { input: {} };
|
|
8659
|
+
}
|
|
7887
8660
|
var Ai = class {
|
|
7888
8661
|
constructor(client) {
|
|
7889
8662
|
this.client = client;
|
|
@@ -7917,6 +8690,33 @@ var Ai = class {
|
|
|
7917
8690
|
raw: data
|
|
7918
8691
|
};
|
|
7919
8692
|
}
|
|
8693
|
+
/**
|
|
8694
|
+
* Plan or run experimental AI Enrichment Fusion with explicit spend controls.
|
|
8695
|
+
*/
|
|
8696
|
+
async fusion(params) {
|
|
8697
|
+
if (!params.prompt && !params.userTemplate && !params.user_template) {
|
|
8698
|
+
throw new Error("prompt or userTemplate is required.");
|
|
8699
|
+
}
|
|
8700
|
+
const data = await this.client.post("ai-enrichment-fusion", {
|
|
8701
|
+
...fusionRecordsFromParams(params),
|
|
8702
|
+
config: toFusionConfig(params),
|
|
8703
|
+
...toFusionSpendControls(params)
|
|
8704
|
+
});
|
|
8705
|
+
return {
|
|
8706
|
+
success: data.success ?? false,
|
|
8707
|
+
capability: data.capability ?? "ai_enrichment_fusion",
|
|
8708
|
+
displayName: data.display_name ?? "AI Enrichment Fusion",
|
|
8709
|
+
results: data.results ?? [],
|
|
8710
|
+
creditsUsed: data.total_credits_used ?? data.credits_used ?? 0,
|
|
8711
|
+
model: data.model,
|
|
8712
|
+
fusion: data.fusion,
|
|
8713
|
+
tokensUsed: data.tokens_used ?? 0,
|
|
8714
|
+
costUsd: data.cost_usd ?? 0,
|
|
8715
|
+
costSummary: data.cost_summary,
|
|
8716
|
+
billingMetadata: data.billing_metadata,
|
|
8717
|
+
raw: data
|
|
8718
|
+
};
|
|
8719
|
+
}
|
|
7920
8720
|
};
|
|
7921
8721
|
|
|
7922
8722
|
// src/resources/gtm-kernel.ts
|
|
@@ -8456,6 +9256,24 @@ var GtmKernel = class {
|
|
|
8456
9256
|
limit: input.limit
|
|
8457
9257
|
});
|
|
8458
9258
|
}
|
|
9259
|
+
/** Predict booked-meeting likelihood for uploaded, inline, or MCP-sourced lead rows without persisting raw rows. */
|
|
9260
|
+
async predictMeetingLikelihood(input) {
|
|
9261
|
+
return this.callMcp("gtm_predict_meeting_likelihood", {
|
|
9262
|
+
lead_rows: input.leadRows,
|
|
9263
|
+
input_source: input.inputSource,
|
|
9264
|
+
campaign_id: input.campaignId,
|
|
9265
|
+
campaign_build_id: input.campaignBuildId,
|
|
9266
|
+
days: input.days,
|
|
9267
|
+
feedback_limit: input.feedbackLimit,
|
|
9268
|
+
include_features: input.includeFeatures,
|
|
9269
|
+
include_global: input.includeGlobal,
|
|
9270
|
+
min_feedback_events: input.minFeedbackEvents,
|
|
9271
|
+
min_historical_feature_sample_size: input.minHistoricalFeatureSampleSize,
|
|
9272
|
+
min_workspace_count: input.minWorkspaceCount,
|
|
9273
|
+
min_privacy_k: input.minPrivacyK,
|
|
9274
|
+
limit: input.limit
|
|
9275
|
+
});
|
|
9276
|
+
}
|
|
8459
9277
|
/** Rank provider-chain, ICP, source, copy, and sequence failure patterns without writing raw lead data. */
|
|
8460
9278
|
async failurePatterns(options = {}) {
|
|
8461
9279
|
return this.callMcp("gtm_brain_failure_patterns", {
|
|
@@ -9071,6 +9889,70 @@ function compact2(value) {
|
|
|
9071
9889
|
return out;
|
|
9072
9890
|
}
|
|
9073
9891
|
|
|
9892
|
+
// src/resources/public-ground-truth.ts
|
|
9893
|
+
var PublicGroundTruth = class {
|
|
9894
|
+
constructor(client) {
|
|
9895
|
+
this.client = client;
|
|
9896
|
+
}
|
|
9897
|
+
/**
|
|
9898
|
+
* Search the public-ground-truth cache by company/name/domain/native ID,
|
|
9899
|
+
* or by plain-language industry + location.
|
|
9900
|
+
* Results use the same snake_case wire shape returned by the hosted MCP API.
|
|
9901
|
+
*/
|
|
9902
|
+
async search(params) {
|
|
9903
|
+
return this.client.mcp("tools/call", {
|
|
9904
|
+
name: "search_public_ground_truth",
|
|
9905
|
+
arguments: {
|
|
9906
|
+
query: params.query ?? params.search,
|
|
9907
|
+
industry: params.industry,
|
|
9908
|
+
location: params.location,
|
|
9909
|
+
source_id: params.sourceId ?? params.source_id,
|
|
9910
|
+
entity_type: params.entityType ?? params.entity_type,
|
|
9911
|
+
native_id: params.nativeId ?? params.native_id,
|
|
9912
|
+
entity_name: params.entityName ?? params.entity_name,
|
|
9913
|
+
domain: params.domain,
|
|
9914
|
+
website_url: params.websiteUrl ?? params.website_url,
|
|
9915
|
+
phone: params.phone,
|
|
9916
|
+
email: params.email,
|
|
9917
|
+
city: params.city,
|
|
9918
|
+
state: params.state,
|
|
9919
|
+
postal_code: params.postalCode ?? params.postal_code,
|
|
9920
|
+
country: params.country,
|
|
9921
|
+
source_url: params.sourceUrl ?? params.source_url,
|
|
9922
|
+
join_keys: params.joinKeys ?? params.join_keys,
|
|
9923
|
+
row_data: params.rowData ?? params.row_data,
|
|
9924
|
+
naics: params.naics,
|
|
9925
|
+
industry_code: params.industryCode ?? params.industry_code,
|
|
9926
|
+
industry_type: params.industryType ?? params.industry_type,
|
|
9927
|
+
year: params.year,
|
|
9928
|
+
quarter: params.quarter,
|
|
9929
|
+
area_fips: params.areaFips ?? params.area_fips,
|
|
9930
|
+
geo_id: params.geoId ?? params.geo_id,
|
|
9931
|
+
own_code: params.ownCode ?? params.own_code,
|
|
9932
|
+
source_updated_after: params.sourceUpdatedAfter ?? params.source_updated_after,
|
|
9933
|
+
source_updated_before: params.sourceUpdatedBefore ?? params.source_updated_before,
|
|
9934
|
+
observed_after: params.observedAfter ?? params.observed_after,
|
|
9935
|
+
observed_before: params.observedBefore ?? params.observed_before,
|
|
9936
|
+
limit: params.limit,
|
|
9937
|
+
offset: params.offset
|
|
9938
|
+
}
|
|
9939
|
+
});
|
|
9940
|
+
}
|
|
9941
|
+
/**
|
|
9942
|
+
* List available public-ground-truth cache sources and their join-key metadata.
|
|
9943
|
+
*/
|
|
9944
|
+
async listSources(params = {}) {
|
|
9945
|
+
return this.client.mcp("tools/call", {
|
|
9946
|
+
name: "list_public_ground_truth_sources",
|
|
9947
|
+
arguments: {
|
|
9948
|
+
query: params.query ?? params.search,
|
|
9949
|
+
status: params.status,
|
|
9950
|
+
limit: params.limit
|
|
9951
|
+
}
|
|
9952
|
+
});
|
|
9953
|
+
}
|
|
9954
|
+
};
|
|
9955
|
+
|
|
9074
9956
|
// src/index.ts
|
|
9075
9957
|
var MCP_TOOL_CACHE_TTL_MS = 3e4;
|
|
9076
9958
|
function inferMcpToolCategory(toolName) {
|
|
@@ -9113,6 +9995,7 @@ function inferMcpToolCategory(toolName) {
|
|
|
9113
9995
|
}
|
|
9114
9996
|
if (toolName.includes("icp")) return "icp";
|
|
9115
9997
|
if (toolName.startsWith("ai_clean_")) return "data_cleaning";
|
|
9998
|
+
if (toolName.includes("public_ground_truth")) return "public_data";
|
|
9116
9999
|
if (toolName.includes("system") || toolName.includes("workflow")) return "automation";
|
|
9117
10000
|
if (toolName.includes("agent") || toolName.includes("platform_health") || toolName === "discover_capabilities") return "observability";
|
|
9118
10001
|
return void 0;
|
|
@@ -9164,6 +10047,7 @@ var Signaliz = class {
|
|
|
9164
10047
|
this.ops = new Ops(this.client);
|
|
9165
10048
|
this.ai = new Ai(this.client);
|
|
9166
10049
|
this.gtm = new GtmKernel(this.client);
|
|
10050
|
+
this.publicGroundTruth = new PublicGroundTruth(this.client);
|
|
9167
10051
|
}
|
|
9168
10052
|
/** Get current workspace info including credits */
|
|
9169
10053
|
async getWorkspace() {
|
|
@@ -9270,10 +10154,12 @@ var Signaliz = class {
|
|
|
9270
10154
|
GtmKernel,
|
|
9271
10155
|
Icps,
|
|
9272
10156
|
Ops,
|
|
10157
|
+
PublicGroundTruth,
|
|
9273
10158
|
Signaliz,
|
|
9274
10159
|
SignalizError,
|
|
9275
10160
|
applyCampaignBuilderStrategyTemplate,
|
|
9276
10161
|
collectExecutionReferences,
|
|
10162
|
+
createCampaignBuilderActiveWorkContext,
|
|
9277
10163
|
createCampaignBuilderAgentPlan,
|
|
9278
10164
|
createCampaignBuilderAgentRequestTemplate,
|
|
9279
10165
|
createCampaignBuilderApproval,
|