@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/cli.js
CHANGED
|
@@ -483,6 +483,38 @@ var init_signals = __esm({
|
|
|
483
483
|
constructor(client) {
|
|
484
484
|
this.client = client;
|
|
485
485
|
}
|
|
486
|
+
/** Turn the strongest supported company signal into three complete, evidence-backed emails. */
|
|
487
|
+
async signalToCopy(params) {
|
|
488
|
+
const data = await this.client.post("api/v1/signal-to-copy", {
|
|
489
|
+
company_domain: params.companyDomain,
|
|
490
|
+
person_name: params.personName,
|
|
491
|
+
title: params.title,
|
|
492
|
+
campaign_offer: params.campaignOffer,
|
|
493
|
+
research_prompt: params.researchPrompt
|
|
494
|
+
});
|
|
495
|
+
return {
|
|
496
|
+
success: data.success ?? true,
|
|
497
|
+
strongestSignal: data.strongest_signal ?? "",
|
|
498
|
+
whyNow: data.why_now ?? "",
|
|
499
|
+
subjectLine: data.subject_line ?? "",
|
|
500
|
+
openingLine: data.opening_line ?? "",
|
|
501
|
+
confidence: data.confidence ?? 0,
|
|
502
|
+
evidenceUrl: data.evidence_url ?? "",
|
|
503
|
+
researchPrompt: data.research_prompt,
|
|
504
|
+
variations: (data.variations ?? []).map((v) => ({
|
|
505
|
+
style: v.style,
|
|
506
|
+
subjectLine: v.subject_line ?? "",
|
|
507
|
+
openingLine: v.opening_line ?? "",
|
|
508
|
+
cta: v.cta ?? "",
|
|
509
|
+
prediction: v.prediction,
|
|
510
|
+
email: v.email
|
|
511
|
+
}))
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
/** @deprecated Use signalToCopy. Retained for compatibility. */
|
|
515
|
+
async personalize(params) {
|
|
516
|
+
return this.signalToCopy(params);
|
|
517
|
+
}
|
|
486
518
|
/** Enrich a company with actionable signals (V1) */
|
|
487
519
|
async enrich(params) {
|
|
488
520
|
const args = {
|
|
@@ -491,6 +523,9 @@ var init_signals = __esm({
|
|
|
491
523
|
if (params.domain) args.domain = params.domain;
|
|
492
524
|
if (params.researchPrompt) args.research_prompt = params.researchPrompt;
|
|
493
525
|
if (params.signalTypes) args.signal_types = params.signalTypes;
|
|
526
|
+
if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
|
|
527
|
+
if (params.lookbackDays) args.lookback_days = params.lookbackDays;
|
|
528
|
+
if (params.enableDeepSearch !== void 0) args.enable_deep_search = params.enableDeepSearch;
|
|
494
529
|
const data = await this.client.mcp("tools/call", {
|
|
495
530
|
name: "enrich_company_signals",
|
|
496
531
|
arguments: args
|
|
@@ -500,6 +535,16 @@ var init_signals = __esm({
|
|
|
500
535
|
signals: (data.signals ?? []).map((s) => ({
|
|
501
536
|
title: s.title,
|
|
502
537
|
signalType: s.signal_type,
|
|
538
|
+
sourceType: s.source_type ?? s.signal_classification?.label ?? "unknown",
|
|
539
|
+
sourceProvenance: s.source_provenance ?? s.metadata?.source_provenance ?? null,
|
|
540
|
+
signalFamily: s.signal_family ?? s.signal_type ?? null,
|
|
541
|
+
signalEventType: s.signal_event_type ?? s.signal_classification?.slug ?? null,
|
|
542
|
+
signalEventLabel: s.signal_event_label ?? s.signal_classification?.label ?? null,
|
|
543
|
+
signalClassification: s.signal_classification ? {
|
|
544
|
+
label: s.signal_classification.label,
|
|
545
|
+
slug: s.signal_classification.slug,
|
|
546
|
+
rationale: s.signal_classification.rationale
|
|
547
|
+
} : null,
|
|
503
548
|
confidenceScore: s.confidence_score ?? 0,
|
|
504
549
|
detectedAt: s.detected_at ?? "",
|
|
505
550
|
url: s.url,
|
|
@@ -540,8 +585,17 @@ var init_signals = __esm({
|
|
|
540
585
|
content: s.content ?? "",
|
|
541
586
|
date: s.date ?? null,
|
|
542
587
|
sourceUrl: s.source_url ?? null,
|
|
543
|
-
sourceType: s.source_type ?? "unknown",
|
|
544
|
-
|
|
588
|
+
sourceType: s.source_type ?? s.signal_classification?.label ?? "unknown",
|
|
589
|
+
sourceProvenance: s.source_provenance ?? s.metadata?.source_provenance ?? null,
|
|
590
|
+
signalFamily: s.signal_family ?? s.type ?? null,
|
|
591
|
+
signalEventType: s.signal_event_type ?? s.signal_classification?.slug ?? null,
|
|
592
|
+
signalEventLabel: s.signal_event_label ?? s.signal_classification?.label ?? null,
|
|
593
|
+
confidence: s.confidence ?? null,
|
|
594
|
+
signalClassification: s.signal_classification ? {
|
|
595
|
+
label: s.signal_classification.label,
|
|
596
|
+
slug: s.signal_classification.slug,
|
|
597
|
+
rationale: s.signal_classification.rationale
|
|
598
|
+
} : null
|
|
545
599
|
})),
|
|
546
600
|
signalCount: data.signal_count ?? 0,
|
|
547
601
|
intelligence: data.intelligence ? {
|
|
@@ -584,6 +638,58 @@ var init_signals = __esm({
|
|
|
584
638
|
}
|
|
585
639
|
};
|
|
586
640
|
}
|
|
641
|
+
/** Plan or run experimental Signal Fusion with explicit spend controls. */
|
|
642
|
+
async fusion(params) {
|
|
643
|
+
const args = {};
|
|
644
|
+
if (params.companyName) args.company_name = params.companyName;
|
|
645
|
+
if (params.domain) args.domain = params.domain;
|
|
646
|
+
if (params.companyDomain) args.company_domain = params.companyDomain;
|
|
647
|
+
if (params.linkedinUrl) args.linkedin_url = params.linkedinUrl;
|
|
648
|
+
if (params.companies) args.companies = params.companies;
|
|
649
|
+
if (params.preset) args.preset = params.preset;
|
|
650
|
+
if (params.researchPrompt) args.research_prompt = params.researchPrompt;
|
|
651
|
+
if (params.signalTypes) args.signal_types = params.signalTypes;
|
|
652
|
+
if (params.lookbackDays) args.lookback_days = params.lookbackDays;
|
|
653
|
+
if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
|
|
654
|
+
if (params.maxToolCalls) args.max_tool_calls = params.maxToolCalls;
|
|
655
|
+
if (params.maxTokens) args.max_tokens = params.maxTokens;
|
|
656
|
+
if (params.timeoutMs) args.timeout_ms = params.timeoutMs;
|
|
657
|
+
const dryRun = params.dryRun ?? params.dry_run;
|
|
658
|
+
const confirmSpend = params.confirmSpend ?? params.confirm_spend;
|
|
659
|
+
const maxCredits = params.maxCredits ?? params.max_credits;
|
|
660
|
+
const maxCostUsd = params.maxCostUsd ?? params.max_cost_usd;
|
|
661
|
+
if (dryRun !== void 0) args.dry_run = dryRun;
|
|
662
|
+
if (confirmSpend !== void 0) args.confirm_spend = confirmSpend;
|
|
663
|
+
if (maxCredits !== void 0) args.max_credits = maxCredits;
|
|
664
|
+
if (maxCostUsd !== void 0) args.max_cost_usd = maxCostUsd;
|
|
665
|
+
const data = await this.client.post("signal-fusion", args);
|
|
666
|
+
return {
|
|
667
|
+
success: data.success ?? false,
|
|
668
|
+
capability: data.capability ?? "signal_fusion",
|
|
669
|
+
displayName: data.display_name ?? "Signal Fusion",
|
|
670
|
+
company: data.company,
|
|
671
|
+
signals: (data.signals ?? []).map((s) => ({
|
|
672
|
+
id: s.id,
|
|
673
|
+
title: s.title,
|
|
674
|
+
type: s.type,
|
|
675
|
+
content: s.content ?? "",
|
|
676
|
+
date: s.date ?? null,
|
|
677
|
+
sourceUrl: s.source_url ?? null,
|
|
678
|
+
sourceType: s.source_type ?? "unknown",
|
|
679
|
+
confidence: s.confidence ?? null
|
|
680
|
+
})),
|
|
681
|
+
signalCount: data.signal_count ?? data.signals?.length ?? 0,
|
|
682
|
+
results: data.results ?? [],
|
|
683
|
+
model: data.model,
|
|
684
|
+
fusion: data.fusion,
|
|
685
|
+
costUsd: data.cost_usd ?? 0,
|
|
686
|
+
tokensUsed: data.tokens_used ?? 0,
|
|
687
|
+
costSummary: data.cost_summary,
|
|
688
|
+
creditsUsed: data.total_credits_used ?? data.credits_used ?? 0,
|
|
689
|
+
billingMetadata: data.billing_metadata,
|
|
690
|
+
raw: data
|
|
691
|
+
};
|
|
692
|
+
}
|
|
587
693
|
};
|
|
588
694
|
}
|
|
589
695
|
});
|
|
@@ -835,6 +941,7 @@ function mapCustomerRowCounts(value) {
|
|
|
835
941
|
acceptedRows: numberOrNull(record.accepted_rows) ?? void 0,
|
|
836
942
|
usableRows: numberOrNull(record.usable_rows) ?? void 0,
|
|
837
943
|
copiedRows: numberOrNull(record.copied_rows) ?? void 0,
|
|
944
|
+
copySkippedRows: numberOrNull(record.copy_skipped_rows) ?? void 0,
|
|
838
945
|
approvalReadyRows: numberOrNull(record.approval_ready_rows) ?? void 0,
|
|
839
946
|
qaReadyRows: numberOrNull(record.qa_ready_rows) ?? void 0,
|
|
840
947
|
deliveredRows: numberOrNull(record.delivered_rows) ?? void 0,
|
|
@@ -1071,7 +1178,8 @@ function buildArgs(request) {
|
|
|
1071
1178
|
geographies: request.icp.geographies,
|
|
1072
1179
|
keywords: request.icp.keywords,
|
|
1073
1180
|
exclusions: request.icp.exclusions,
|
|
1074
|
-
require_verified_email: request.icp.requireVerifiedEmail
|
|
1181
|
+
require_verified_email: request.icp.requireVerifiedEmail,
|
|
1182
|
+
persona_expansion_mode: request.icp.personaExpansionMode
|
|
1075
1183
|
};
|
|
1076
1184
|
}
|
|
1077
1185
|
if (request.policy) {
|
|
@@ -1111,6 +1219,7 @@ function buildArgs(request) {
|
|
|
1111
1219
|
} : void 0,
|
|
1112
1220
|
sequence_steps: request.copy.sequenceSteps,
|
|
1113
1221
|
copy_schema: request.copy.copySchema,
|
|
1222
|
+
evidence_mode: request.copy.evidenceMode,
|
|
1114
1223
|
banned_phrases: request.copy.bannedPhrases,
|
|
1115
1224
|
approval_required: request.copy.approvalRequired,
|
|
1116
1225
|
quality_tier: request.copy.qualityTier
|
|
@@ -1376,9 +1485,10 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
|
|
|
1376
1485
|
const estimatedCredits = estimateCredits(resolvedRequest, defaults, targetCount);
|
|
1377
1486
|
const buildRequest = createBuildRequest(resolvedRequest, defaults, targetCount, campaignName, context.scopeBuildArgs, routes, memory, context.scopeBrainPreflight);
|
|
1378
1487
|
const brainPreflight = asRecord(buildRequest.brainPreflight);
|
|
1488
|
+
const evidence = buildRequest.evidence ?? null;
|
|
1379
1489
|
const approvals = deriveApprovals(resolvedRequest, routes, memory, estimatedCredits, defaults.delivery?.approvalRequired !== false);
|
|
1380
1490
|
return {
|
|
1381
|
-
planId: `cbp_${hashString(JSON.stringify({ goal: resolvedRequest.goal, campaignName, targetCount, routes }))}`,
|
|
1491
|
+
planId: `cbp_${hashString(JSON.stringify({ goal: resolvedRequest.goal, campaignName, targetCount, routes, evidence }))}`,
|
|
1382
1492
|
campaignName,
|
|
1383
1493
|
goal: resolvedRequest.goal,
|
|
1384
1494
|
targetCount,
|
|
@@ -1393,6 +1503,7 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
|
|
|
1393
1503
|
approvals,
|
|
1394
1504
|
buildRequest,
|
|
1395
1505
|
brainPreflight,
|
|
1506
|
+
evidence,
|
|
1396
1507
|
operatingPlaybooks,
|
|
1397
1508
|
mcpFlow: createMcpFlow(resolvedRequest, buildRequest, routes, memory, approvals),
|
|
1398
1509
|
estimatedCredits,
|
|
@@ -1484,6 +1595,90 @@ function createCampaignBuilderReadiness(plan) {
|
|
|
1484
1595
|
nextActions: campaignReadinessNextActions(plan, ready, customRoutes.length)
|
|
1485
1596
|
};
|
|
1486
1597
|
}
|
|
1598
|
+
function createCampaignBuilderActiveWorkContext(input) {
|
|
1599
|
+
const plan = input.readiness?.plan ?? input.plan;
|
|
1600
|
+
const remembered = input.remembered ?? {};
|
|
1601
|
+
const lastResult = asRecord(input.lastResult);
|
|
1602
|
+
const readinessBlockers = input.readiness?.summary.blockers ?? [];
|
|
1603
|
+
const explicitBlockers = input.blockers ?? [];
|
|
1604
|
+
const blockers = uniqueStrings([...explicitBlockers, ...readinessBlockers]);
|
|
1605
|
+
const warnings = uniqueStrings([
|
|
1606
|
+
...input.warnings ?? [],
|
|
1607
|
+
...input.readiness?.summary.warnings ?? [],
|
|
1608
|
+
...plan?.warnings ?? []
|
|
1609
|
+
]);
|
|
1610
|
+
const missingApprovals = plan ? (input.approval ? getMissingCampaignBuilderApprovals(plan, input.approval) : plan.approvals.filter((approval) => approval.blocking)).map((approval) => approval.type) : [];
|
|
1611
|
+
const refs = normalizeCampaignBuilderActiveWorkRefs({
|
|
1612
|
+
plan,
|
|
1613
|
+
remembered,
|
|
1614
|
+
refs: input.refs,
|
|
1615
|
+
lastResult
|
|
1616
|
+
});
|
|
1617
|
+
const state = inferCampaignBuilderActiveWorkState({
|
|
1618
|
+
plan,
|
|
1619
|
+
readiness: input.readiness,
|
|
1620
|
+
remembered,
|
|
1621
|
+
lastResult,
|
|
1622
|
+
blockers,
|
|
1623
|
+
missingApprovals
|
|
1624
|
+
});
|
|
1625
|
+
const nextSafeAction = campaignBuilderActiveWorkNextAction(state, blockers, missingApprovals, refs);
|
|
1626
|
+
const approvalPacket = createCampaignBuilderApprovalPacket(plan, input.approval, missingApprovals);
|
|
1627
|
+
const nextSafeMcpAction = campaignBuilderActiveWorkNextMcpAction({
|
|
1628
|
+
state,
|
|
1629
|
+
plan,
|
|
1630
|
+
refs,
|
|
1631
|
+
approvalPacket
|
|
1632
|
+
});
|
|
1633
|
+
const summary = {
|
|
1634
|
+
plan_id: plan?.planId ?? remembered.planId ?? null,
|
|
1635
|
+
campaign_name: plan?.campaignName ?? null,
|
|
1636
|
+
target_count: plan?.targetCount ?? null,
|
|
1637
|
+
gtm_campaign_id: plan?.buildRequest.gtmCampaignId ?? remembered.gtmCampaignId ?? null,
|
|
1638
|
+
campaign_build_id: stringValue(lastResult.campaign_build_id ?? lastResult.campaignBuildId) ?? remembered.campaignBuildId ?? null,
|
|
1639
|
+
provider_campaign_id: remembered.providerCampaignId ?? null
|
|
1640
|
+
};
|
|
1641
|
+
const approvalBoundary = campaignBuilderActiveWorkApprovalBoundary(missingApprovals, state);
|
|
1642
|
+
const conversationStarters = campaignBuilderActiveWorkConversationStarters({
|
|
1643
|
+
state,
|
|
1644
|
+
blockers,
|
|
1645
|
+
missingApprovals,
|
|
1646
|
+
refs,
|
|
1647
|
+
nextSafeAction
|
|
1648
|
+
});
|
|
1649
|
+
return {
|
|
1650
|
+
packet_version: "campaign-builder-active-work-context.v1",
|
|
1651
|
+
read_only: true,
|
|
1652
|
+
no_spend: true,
|
|
1653
|
+
no_provider_writes: true,
|
|
1654
|
+
private_safe: true,
|
|
1655
|
+
state,
|
|
1656
|
+
summary,
|
|
1657
|
+
refs,
|
|
1658
|
+
blockers,
|
|
1659
|
+
warnings,
|
|
1660
|
+
missing_approval_types: missingApprovals,
|
|
1661
|
+
approval_packet: approvalPacket,
|
|
1662
|
+
approval_boundary: approvalBoundary,
|
|
1663
|
+
next_safe_action: nextSafeAction,
|
|
1664
|
+
next_safe_mcp_action: nextSafeMcpAction,
|
|
1665
|
+
conversation_starters: conversationStarters,
|
|
1666
|
+
openai_agent_handoff: createCampaignBuilderOpenAiAgentHandoff({
|
|
1667
|
+
plan,
|
|
1668
|
+
state,
|
|
1669
|
+
summary,
|
|
1670
|
+
refs,
|
|
1671
|
+
blockers,
|
|
1672
|
+
warnings,
|
|
1673
|
+
missingApprovals,
|
|
1674
|
+
approvalPacket,
|
|
1675
|
+
approvalBoundary,
|
|
1676
|
+
nextSafeAction,
|
|
1677
|
+
nextSafeMcpAction,
|
|
1678
|
+
conversationStarters
|
|
1679
|
+
})
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1487
1682
|
function createCampaignBuilderProofReceipt(plan, result) {
|
|
1488
1683
|
const strategyMemory = asRecord(plan.strategyMemoryStatus);
|
|
1489
1684
|
const dryRunResult = asRecord(result);
|
|
@@ -1542,6 +1737,7 @@ function createCampaignBuilderProofReceipt(plan, result) {
|
|
|
1542
1737
|
estimated_credits: plan.estimatedCredits,
|
|
1543
1738
|
operating_playbooks: plan.operatingPlaybooks.map((playbook) => playbook.slug)
|
|
1544
1739
|
},
|
|
1740
|
+
evidence: plan.evidence,
|
|
1545
1741
|
gates,
|
|
1546
1742
|
strategy_memory_status: summarizeCampaignBuilderProofStrategyMemory(strategyMemory),
|
|
1547
1743
|
dry_run_result: summarizeCampaignBuilderProofDryRun(dryRunResult),
|
|
@@ -1597,6 +1793,56 @@ function getCampaignBuilderOperatingPlaybooksForRequest(request) {
|
|
|
1597
1793
|
]);
|
|
1598
1794
|
return slugs.map(getCampaignBuilderOperatingPlaybook).filter((playbook) => Boolean(playbook));
|
|
1599
1795
|
}
|
|
1796
|
+
function normalizeCampaignBuilderEvidence(evidence) {
|
|
1797
|
+
if (!evidence) return null;
|
|
1798
|
+
const attachmentSummary = (evidence.attachments ?? []).filter((attachment) => stringValue(attachment.name)).slice(0, 5).map((attachment) => ({
|
|
1799
|
+
name: stringValue(attachment.name) ?? "attachment",
|
|
1800
|
+
kind: stringValue(attachment.kind) ?? null,
|
|
1801
|
+
media_type: stringValue(attachment.mediaType) ?? null,
|
|
1802
|
+
redacted: attachment.redacted !== false,
|
|
1803
|
+
columns: uniqueStrings(attachment.columns ?? []).slice(0, 25),
|
|
1804
|
+
row_count: numberOrUndefined2(attachment.rowCount) ?? null,
|
|
1805
|
+
content_summary: stringValue(attachment.contentSummary)?.slice(0, 500) ?? null,
|
|
1806
|
+
evidence_fields: uniqueStrings(attachment.evidenceFields ?? []).slice(0, 25)
|
|
1807
|
+
}));
|
|
1808
|
+
const urlSummary = (evidence.urls ?? []).filter((url) => stringValue(url.url)).slice(0, 8).map((url) => {
|
|
1809
|
+
const rawUrl = stringValue(url.url) ?? "";
|
|
1810
|
+
return {
|
|
1811
|
+
url: rawUrl,
|
|
1812
|
+
host: stringValue(url.host) ?? hostFromUrl(rawUrl) ?? null,
|
|
1813
|
+
type: stringValue(url.type) ?? null,
|
|
1814
|
+
label: stringValue(url.label) ?? null,
|
|
1815
|
+
summary: stringValue(url.summary)?.slice(0, 500) ?? null,
|
|
1816
|
+
redacted: url.redacted === true
|
|
1817
|
+
};
|
|
1818
|
+
});
|
|
1819
|
+
const operatorNotes = uniqueStrings(evidence.notes ?? []).map((note) => note.slice(0, 240)).slice(0, 5);
|
|
1820
|
+
if (!attachmentSummary.length && !urlSummary.length && !operatorNotes.length) return null;
|
|
1821
|
+
return {
|
|
1822
|
+
packet_version: "campaign-builder-evidence.v1",
|
|
1823
|
+
private_safe: true,
|
|
1824
|
+
attachment_summary: attachmentSummary,
|
|
1825
|
+
url_summary: urlSummary,
|
|
1826
|
+
operator_notes: operatorNotes,
|
|
1827
|
+
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.",
|
|
1828
|
+
raw_private_fields_withheld: [
|
|
1829
|
+
"raw_private_attachment_text",
|
|
1830
|
+
"raw_attachment_rows",
|
|
1831
|
+
"raw_leads",
|
|
1832
|
+
"email_addresses",
|
|
1833
|
+
"provider_auth_payloads",
|
|
1834
|
+
"copy_bodies",
|
|
1835
|
+
"secrets"
|
|
1836
|
+
]
|
|
1837
|
+
};
|
|
1838
|
+
}
|
|
1839
|
+
function hostFromUrl(value) {
|
|
1840
|
+
try {
|
|
1841
|
+
return new URL(value).hostname || void 0;
|
|
1842
|
+
} catch {
|
|
1843
|
+
return void 0;
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1600
1846
|
function applyCampaignBuilderStrategyTemplate(request) {
|
|
1601
1847
|
const template = getCampaignBuilderStrategyTemplate(request.strategyTemplate);
|
|
1602
1848
|
if (!template) return request;
|
|
@@ -2288,7 +2534,7 @@ function normalizeMemory(request) {
|
|
|
2288
2534
|
};
|
|
2289
2535
|
}
|
|
2290
2536
|
function defaultAgencyMemoryQueries(request, configured) {
|
|
2291
|
-
const operatingPlaybookTerms = getCampaignBuilderOperatingPlaybooksForRequest(request).flatMap((playbook) => [playbook.label, ...playbook.memoryKeywords]).join(" ");
|
|
2537
|
+
const operatingPlaybookTerms = getCampaignBuilderOperatingPlaybooksForRequest(request).flatMap((playbook) => [playbook.label, ...playbook.memoryKeywords, ...playbook.knowledgeSources]).join(" ");
|
|
2292
2538
|
const queries = [{
|
|
2293
2539
|
query: request.goal,
|
|
2294
2540
|
scopes: ["workspace", configured.useNetworkPatterns ? "network_patterns" : "operator_notes"],
|
|
@@ -2499,6 +2745,8 @@ function createBuildRequest(request, defaults, targetCount, campaignName, scopeB
|
|
|
2499
2745
|
fillPolicy: "aggressive"
|
|
2500
2746
|
}
|
|
2501
2747
|
};
|
|
2748
|
+
const evidence = normalizeCampaignBuilderEvidence(request.evidence);
|
|
2749
|
+
if (evidence) buildRequest.evidence = evidence;
|
|
2502
2750
|
const scoped = asRecord(scopeBuildArgs);
|
|
2503
2751
|
buildRequest.gtmCampaignId = request.gtmCampaignId ?? stringValue(scoped.gtm_campaign_id ?? scoped.gtmCampaignId);
|
|
2504
2752
|
buildRequest.learningHoldout = normalizeCampaignBuilderLearningHoldout(
|
|
@@ -2530,6 +2778,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
2530
2778
|
memory.enabled ? "feedback" : void 0
|
|
2531
2779
|
]);
|
|
2532
2780
|
const providerChain = uniqueStrings(["signaliz", ...request.preferredProviders ?? [], ...routes.map((route) => route.provider)]);
|
|
2781
|
+
const evidence = buildRequest.evidence ?? normalizeCampaignBuilderEvidence(request.evidence);
|
|
2533
2782
|
const targetIcp = compact({
|
|
2534
2783
|
personas: buildRequest.icp?.personas,
|
|
2535
2784
|
industries: buildRequest.icp?.industries,
|
|
@@ -2542,6 +2791,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
2542
2791
|
const learningArgs = compact({
|
|
2543
2792
|
campaign_brief: request.goal,
|
|
2544
2793
|
target_icp: targetIcp,
|
|
2794
|
+
evidence_context: evidence,
|
|
2545
2795
|
layers,
|
|
2546
2796
|
provider_chain: providerChain,
|
|
2547
2797
|
lead_source: providerChain[0] ?? "signaliz",
|
|
@@ -2553,6 +2803,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
2553
2803
|
const defaultsArgs = compact({
|
|
2554
2804
|
campaign_brief: request.goal,
|
|
2555
2805
|
target_icp: targetIcp,
|
|
2806
|
+
evidence_context: evidence,
|
|
2556
2807
|
layers,
|
|
2557
2808
|
include_global: memory.useNetworkPatterns,
|
|
2558
2809
|
include_memory: memory.enabled,
|
|
@@ -2563,6 +2814,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
2563
2814
|
provider_chain: providerChain,
|
|
2564
2815
|
lead_source: providerChain[0] ?? "signaliz",
|
|
2565
2816
|
target_icp: targetIcp,
|
|
2817
|
+
evidence_context: evidence,
|
|
2566
2818
|
include_global: memory.useNetworkPatterns,
|
|
2567
2819
|
limit: 25
|
|
2568
2820
|
});
|
|
@@ -2575,9 +2827,11 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
2575
2827
|
label: playbook.label,
|
|
2576
2828
|
quality_gates: playbook.qualityGates,
|
|
2577
2829
|
required_fields: playbook.requiredFields,
|
|
2578
|
-
activation_boundary: playbook.activationBoundary
|
|
2830
|
+
activation_boundary: playbook.activationBoundary,
|
|
2831
|
+
knowledge_sources: playbook.knowledgeSources
|
|
2579
2832
|
})),
|
|
2580
2833
|
target_icp: targetIcp,
|
|
2834
|
+
evidence_context: evidence,
|
|
2581
2835
|
provider_chain: providerChain,
|
|
2582
2836
|
lead_source: providerChain[0] ?? "signaliz",
|
|
2583
2837
|
learning_holdout: buildRequest.learningHoldout,
|
|
@@ -2850,7 +3104,7 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
|
|
|
2850
3104
|
phase: "plan",
|
|
2851
3105
|
tool: "nango_mcp_tools_list",
|
|
2852
3106
|
arguments: {
|
|
2853
|
-
format: "
|
|
3107
|
+
format: "openai"
|
|
2854
3108
|
},
|
|
2855
3109
|
readOnly: true,
|
|
2856
3110
|
approvalRequired: false
|
|
@@ -3159,6 +3413,7 @@ function buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory) {
|
|
|
3159
3413
|
layers: layers.length > 0 ? layers : void 0,
|
|
3160
3414
|
preferred_providers: preferredProviders.length > 0 ? preferredProviders : void 0,
|
|
3161
3415
|
strategy_model: strategyModel,
|
|
3416
|
+
evidence_context: buildRequest.evidence ?? normalizeCampaignBuilderEvidence(request.evidence),
|
|
3162
3417
|
include_strategy_patterns: campaignBuilderStrategyPatternsEnabled(agencyContext),
|
|
3163
3418
|
include_workflow_patterns: campaignBuilderWorkflowPatternsEnabled(agencyContext),
|
|
3164
3419
|
include_nango_catalog: agencyContext.includeNangoCatalog !== false,
|
|
@@ -3167,7 +3422,8 @@ function buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory) {
|
|
|
3167
3422
|
slug: playbook.slug,
|
|
3168
3423
|
label: playbook.label,
|
|
3169
3424
|
quality_gates: playbook.qualityGates,
|
|
3170
|
-
activation_boundary: playbook.activationBoundary
|
|
3425
|
+
activation_boundary: playbook.activationBoundary,
|
|
3426
|
+
knowledge_sources: playbook.knowledgeSources
|
|
3171
3427
|
})),
|
|
3172
3428
|
include_memory: memory.enabled,
|
|
3173
3429
|
include_brain: true,
|
|
@@ -3260,6 +3516,7 @@ function buildCampaignArgs(request) {
|
|
|
3260
3516
|
}
|
|
3261
3517
|
if (request.campaignStrategyContext) args.campaign_strategy_context = request.campaignStrategyContext;
|
|
3262
3518
|
if (request.deliveryRisk) args.delivery_risk = request.deliveryRisk;
|
|
3519
|
+
if (request.evidence) args.evidence_context = request.evidence;
|
|
3263
3520
|
if (request.icp) {
|
|
3264
3521
|
args.icp = compact({
|
|
3265
3522
|
personas: request.icp.personas,
|
|
@@ -3309,7 +3566,8 @@ function buildCampaignArgs(request) {
|
|
|
3309
3566
|
max_body_words: request.copy.maxBodyWords,
|
|
3310
3567
|
sender_context: request.copy.senderContext,
|
|
3311
3568
|
offer_context: request.copy.offerContext,
|
|
3312
|
-
model: request.copy.model
|
|
3569
|
+
model: request.copy.model,
|
|
3570
|
+
evidence_mode: request.copy.evidenceMode
|
|
3313
3571
|
});
|
|
3314
3572
|
}
|
|
3315
3573
|
if (request.delivery) {
|
|
@@ -3584,6 +3842,7 @@ function mapAgentCustomerRowCounts(value) {
|
|
|
3584
3842
|
acceptedRows: numberOrUndefined2(record.accepted_rows),
|
|
3585
3843
|
usableRows: numberOrUndefined2(record.usable_rows),
|
|
3586
3844
|
copiedRows: numberOrUndefined2(record.copied_rows),
|
|
3845
|
+
copySkippedRows: numberOrUndefined2(record.copy_skipped_rows),
|
|
3587
3846
|
approvalReadyRows: numberOrUndefined2(record.approval_ready_rows),
|
|
3588
3847
|
qaReadyRows: numberOrUndefined2(record.qa_ready_rows),
|
|
3589
3848
|
deliveredRows: numberOrUndefined2(record.delivered_rows),
|
|
@@ -3685,7 +3944,7 @@ function createCampaignBuilderNorthStarScorecard(status, rows, artifacts, termin
|
|
|
3685
3944
|
const sampledRows = rows.rows.length;
|
|
3686
3945
|
const rowData = rows.rows.map((row) => asRecord(row.data));
|
|
3687
3946
|
const requestedTarget = status.customerRowCounts?.requestedTarget ?? status.recordsTotal ?? rows.count;
|
|
3688
|
-
const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
|
|
3947
|
+
const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copySkippedRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
|
|
3689
3948
|
const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
|
|
3690
3949
|
const verifiedEmailRows = rowData.filter(campaignReviewDataHasVerifiedEmail).length;
|
|
3691
3950
|
const uniqueEmails = new Set(rowData.map(campaignReviewDataEmail).filter(Boolean)).size;
|
|
@@ -4176,6 +4435,342 @@ function createCampaignBuilderReadinessLane(route, plan) {
|
|
|
4176
4435
|
nextAction: customRoute ? `Review ${route.provider} route setup before launch approval.` : void 0
|
|
4177
4436
|
};
|
|
4178
4437
|
}
|
|
4438
|
+
function createCampaignBuilderApprovalPacket(plan, approval, missingTypes) {
|
|
4439
|
+
const requestedTypes = plan ? uniqueStrings(plan.approvals.filter((item) => item.blocking).map((item) => item.type)) : [];
|
|
4440
|
+
const approvalMatchesPlan = Boolean(plan && approval?.planId === plan.planId);
|
|
4441
|
+
const approvedTypes = approvalMatchesPlan ? approval?.approvedTypes ?? [] : [];
|
|
4442
|
+
const approvedRoutes = approvalMatchesPlan ? approval?.approvedRouteIds ?? [] : [];
|
|
4443
|
+
const missingIds = new Set(
|
|
4444
|
+
plan && approvalMatchesPlan && approval ? getMissingCampaignBuilderApprovals(plan, approval).map((item) => item.id) : plan?.approvals.filter((item) => item.blocking).map((item) => item.id) ?? []
|
|
4445
|
+
);
|
|
4446
|
+
const routeIdsRequired = plan ? uniqueStrings(plan.approvals.map((item) => item.routeId).filter((id) => Boolean(id))) : [];
|
|
4447
|
+
const spendLimitRequired = plan ? Math.max(0, ...plan.approvals.filter((item) => item.type === "spend" && item.blocking).map((item) => item.estimatedCredits ?? plan.estimatedCredits)) : 0;
|
|
4448
|
+
const normalizedSpendLimit = spendLimitRequired > 0 ? spendLimitRequired : null;
|
|
4449
|
+
const approvalState = !plan ? "unscoped" : missingTypes.length > 0 ? "requires_approval" : "approved";
|
|
4450
|
+
const approvalInput = {
|
|
4451
|
+
approved_by: approval?.approvedBy ?? null,
|
|
4452
|
+
approved_at: approval?.approvedAt ?? null,
|
|
4453
|
+
approved_types: approvedTypes,
|
|
4454
|
+
approved_route_ids: approvedRoutes,
|
|
4455
|
+
spend_limit_credits: approval?.spendLimitCredits ?? null,
|
|
4456
|
+
notes: approval?.notes
|
|
4457
|
+
};
|
|
4458
|
+
return {
|
|
4459
|
+
packet_version: "campaign-builder-approval-packet.v1",
|
|
4460
|
+
read_only: true,
|
|
4461
|
+
no_spend: true,
|
|
4462
|
+
no_provider_writes: true,
|
|
4463
|
+
private_safe: true,
|
|
4464
|
+
approval_state: approvalState,
|
|
4465
|
+
plan_id: plan?.planId ?? null,
|
|
4466
|
+
campaign_name: plan?.campaignName ?? null,
|
|
4467
|
+
requested_approval_types: requestedTypes,
|
|
4468
|
+
missing_approval_types: uniqueStrings(missingTypes),
|
|
4469
|
+
spend_limit_credits_required: normalizedSpendLimit,
|
|
4470
|
+
route_ids_required: routeIdsRequired,
|
|
4471
|
+
required_approvals: (plan?.approvals ?? []).map((item) => compact({
|
|
4472
|
+
id: item.id,
|
|
4473
|
+
type: item.type,
|
|
4474
|
+
label: item.label,
|
|
4475
|
+
reason: item.reason,
|
|
4476
|
+
blocking: item.blocking,
|
|
4477
|
+
route_id: item.routeId,
|
|
4478
|
+
provider: item.provider,
|
|
4479
|
+
estimated_credits: item.estimatedCredits,
|
|
4480
|
+
status: missingIds.has(item.id) ? "missing" : "approved"
|
|
4481
|
+
})),
|
|
4482
|
+
approval_input: approvalInput,
|
|
4483
|
+
cli_handoff: plan ? {
|
|
4484
|
+
command: campaignBuilderApprovalCliHandoff(requestedTypes, routeIdsRequired, normalizedSpendLimit),
|
|
4485
|
+
safety: "Template only: run after explicit human approval identity, approved types, route scope, and spend limit are filled in."
|
|
4486
|
+
} : null,
|
|
4487
|
+
sdk_handoff: plan ? {
|
|
4488
|
+
method: "campaignBuilderAgent.buildApprovedPlan",
|
|
4489
|
+
approval: compact({
|
|
4490
|
+
approvedBy: approval?.approvedBy ?? "<operator-email>",
|
|
4491
|
+
approvedTypes: requestedTypes,
|
|
4492
|
+
approvedRouteIds: routeIdsRequired,
|
|
4493
|
+
spendLimitCredits: normalizedSpendLimit ?? void 0,
|
|
4494
|
+
notes: approval?.notes
|
|
4495
|
+
}),
|
|
4496
|
+
options: {
|
|
4497
|
+
idempotencyKey: "<set-before-execution>"
|
|
4498
|
+
},
|
|
4499
|
+
safety: "Call only after the approval packet is accepted; this helper does not execute writes or spend."
|
|
4500
|
+
} : null,
|
|
4501
|
+
mcp_handoffs: plan ? campaignBuilderApprovalMcpHandoffs(plan, requestedTypes, routeIdsRequired, normalizedSpendLimit) : [],
|
|
4502
|
+
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."
|
|
4503
|
+
};
|
|
4504
|
+
}
|
|
4505
|
+
function campaignBuilderApprovalCliHandoff(requestedTypes, routeIds, spendLimit) {
|
|
4506
|
+
return [
|
|
4507
|
+
"signaliz campaign-agent build-approved --request-file campaign-request.json --confirm-launch",
|
|
4508
|
+
requestedTypes.length > 0 ? `--approved-types ${shellArg(requestedTypes.join(","))}` : "--approve-all",
|
|
4509
|
+
"--approved-by <operator-email>",
|
|
4510
|
+
spendLimit !== null ? `--spend-limit ${spendLimit}` : void 0,
|
|
4511
|
+
routeIds.length > 0 ? `--approved-route-ids ${shellArg(routeIds.join(","))}` : void 0
|
|
4512
|
+
].filter(Boolean).join(" ");
|
|
4513
|
+
}
|
|
4514
|
+
function campaignBuilderApprovalMcpHandoffs(plan, requestedTypes, routeIds, spendLimit) {
|
|
4515
|
+
const approvalContext = compact({
|
|
4516
|
+
plan_id: plan.planId,
|
|
4517
|
+
approval_types: requestedTypes,
|
|
4518
|
+
approved_route_ids: routeIds,
|
|
4519
|
+
spend_limit_credits: spendLimit,
|
|
4520
|
+
approved_by: "<operator-email>"
|
|
4521
|
+
});
|
|
4522
|
+
return plan.mcpFlow.filter((step) => ["execution-prepare", "approved-build", "delivery-approval"].includes(step.id)).map((step) => ({
|
|
4523
|
+
id: step.id,
|
|
4524
|
+
tool: step.tool,
|
|
4525
|
+
arguments: step.id === "approved-build" ? compact({ ...step.arguments, approval_context: approvalContext }) : step.arguments,
|
|
4526
|
+
read_only: step.readOnly,
|
|
4527
|
+
approval_required: step.approvalRequired,
|
|
4528
|
+
safety: step.readOnly ? "Read-only readiness handoff; safe to inspect before approval." : "Write-capable handoff; run only after the approval packet is accepted."
|
|
4529
|
+
}));
|
|
4530
|
+
}
|
|
4531
|
+
function campaignBuilderActiveWorkNextMcpAction(input) {
|
|
4532
|
+
const campaignBuildRef = input.refs.find((ref) => ref.kind === "campaign_build" && ref.id);
|
|
4533
|
+
if (campaignBuildRef) {
|
|
4534
|
+
return {
|
|
4535
|
+
id: "check-campaign-build-status",
|
|
4536
|
+
tool: "get_campaign_build_status",
|
|
4537
|
+
arguments: { campaign_build_id: campaignBuildRef.id },
|
|
4538
|
+
read_only: true,
|
|
4539
|
+
approval_required: false,
|
|
4540
|
+
safety: "Read-only status check for the remembered campaign build; does not spend, write, export, send, or approve anything."
|
|
4541
|
+
};
|
|
4542
|
+
}
|
|
4543
|
+
const campaignRef = input.refs.find((ref) => ref.kind === "gtm_campaign" && ref.id);
|
|
4544
|
+
if (campaignRef) {
|
|
4545
|
+
return {
|
|
4546
|
+
id: "check-gtm-campaign-status",
|
|
4547
|
+
tool: "gtm_campaign_execution_status",
|
|
4548
|
+
arguments: { campaign_id: campaignRef.id },
|
|
4549
|
+
read_only: true,
|
|
4550
|
+
approval_required: false,
|
|
4551
|
+
safety: "Read-only campaign execution status check; does not start or mutate the campaign."
|
|
4552
|
+
};
|
|
4553
|
+
}
|
|
4554
|
+
const preferredStepId = input.state === "ready_for_dry_run" ? "dry-run-build" : input.state === "planning" || input.state === "blocked" ? "agency-campaign-build-plan" : null;
|
|
4555
|
+
const preferredStep = preferredStepId ? input.plan?.mcpFlow.find((step) => step.id === preferredStepId && step.readOnly) : void 0;
|
|
4556
|
+
if (preferredStep) return campaignBuilderMcpStepToActiveWorkAction(preferredStep, "Read-only continuation from the saved campaign-agent plan.");
|
|
4557
|
+
const readOnlyApprovalHandoff = input.approvalPacket.mcp_handoffs.find((handoff) => handoff.read_only && !handoff.approval_required);
|
|
4558
|
+
if (readOnlyApprovalHandoff) return readOnlyApprovalHandoff;
|
|
4559
|
+
const firstReadOnlyPlanStep = input.plan?.mcpFlow.find((step) => step.readOnly && !step.approvalRequired);
|
|
4560
|
+
return firstReadOnlyPlanStep ? campaignBuilderMcpStepToActiveWorkAction(firstReadOnlyPlanStep, "Read-only saved plan check; safe before approvals or writes.") : null;
|
|
4561
|
+
}
|
|
4562
|
+
function campaignBuilderMcpStepToActiveWorkAction(step, safety) {
|
|
4563
|
+
return {
|
|
4564
|
+
id: step.id,
|
|
4565
|
+
tool: step.tool,
|
|
4566
|
+
arguments: step.arguments,
|
|
4567
|
+
read_only: step.readOnly,
|
|
4568
|
+
approval_required: step.approvalRequired,
|
|
4569
|
+
safety
|
|
4570
|
+
};
|
|
4571
|
+
}
|
|
4572
|
+
function normalizeCampaignBuilderActiveWorkRefs(input) {
|
|
4573
|
+
const refs = [];
|
|
4574
|
+
const pushRef = (ref) => {
|
|
4575
|
+
if (!ref?.id) return;
|
|
4576
|
+
refs.push(ref);
|
|
4577
|
+
};
|
|
4578
|
+
pushRef(input.plan?.planId ? { kind: "plan", id: input.plan.planId, label: input.plan.campaignName, source: "plan" } : void 0);
|
|
4579
|
+
pushRef(input.remembered.planId ? { kind: "plan", id: input.remembered.planId, source: "remembered" } : void 0);
|
|
4580
|
+
pushRef(
|
|
4581
|
+
input.plan?.buildRequest.gtmCampaignId ?? input.remembered.gtmCampaignId ? {
|
|
4582
|
+
kind: "gtm_campaign",
|
|
4583
|
+
id: input.plan?.buildRequest.gtmCampaignId ?? input.remembered.gtmCampaignId,
|
|
4584
|
+
label: input.plan?.campaignName,
|
|
4585
|
+
source: input.plan?.buildRequest.gtmCampaignId ? "plan" : "remembered"
|
|
4586
|
+
} : void 0
|
|
4587
|
+
);
|
|
4588
|
+
const campaignBuildId = stringValue(input.lastResult.campaign_build_id ?? input.lastResult.campaignBuildId) ?? input.remembered.campaignBuildId;
|
|
4589
|
+
pushRef(campaignBuildId ? { kind: "campaign_build", id: campaignBuildId, status: activeWorkStatus(input.lastResult) ?? input.remembered.status, source: "result" } : void 0);
|
|
4590
|
+
pushRef(
|
|
4591
|
+
input.remembered.providerCampaignId ? {
|
|
4592
|
+
kind: "provider_campaign",
|
|
4593
|
+
id: input.remembered.providerCampaignId,
|
|
4594
|
+
label: input.remembered.provider,
|
|
4595
|
+
status: input.remembered.status,
|
|
4596
|
+
source: "remembered"
|
|
4597
|
+
} : void 0
|
|
4598
|
+
);
|
|
4599
|
+
for (const ref of input.remembered.refs ?? []) pushRef(ref);
|
|
4600
|
+
for (const ref of input.refs ?? []) pushRef(ref);
|
|
4601
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4602
|
+
return refs.filter((ref) => {
|
|
4603
|
+
const key = `${ref.kind}:${ref.id}`;
|
|
4604
|
+
if (seen.has(key)) return false;
|
|
4605
|
+
seen.add(key);
|
|
4606
|
+
return true;
|
|
4607
|
+
});
|
|
4608
|
+
}
|
|
4609
|
+
function inferCampaignBuilderActiveWorkState(input) {
|
|
4610
|
+
if (input.blockers.length > 0) return "blocked";
|
|
4611
|
+
const status = activeWorkStatus(input.lastResult) ?? input.remembered.status;
|
|
4612
|
+
const normalized = status?.toLowerCase();
|
|
4613
|
+
if (normalized && ["completed", "complete", "succeeded", "success", "done"].includes(normalized)) return "completed";
|
|
4614
|
+
if (normalized && ["queued", "running", "in_progress", "processing", "pending"].includes(normalized)) return "queued_or_running";
|
|
4615
|
+
const dryRunComplete = input.lastResult.dry_run === true || input.lastResult.dryRun === true || normalized === "dry_run";
|
|
4616
|
+
if (dryRunComplete) return input.missingApprovals.length > 0 ? "needs_approval" : "dry_run_complete";
|
|
4617
|
+
if (input.missingApprovals.length > 0) return "needs_approval";
|
|
4618
|
+
if (input.readiness?.summary.ready === true) return "ready_for_dry_run";
|
|
4619
|
+
if (input.plan) return "planning";
|
|
4620
|
+
return "unknown";
|
|
4621
|
+
}
|
|
4622
|
+
function campaignBuilderActiveWorkApprovalBoundary(missingApprovals, state) {
|
|
4623
|
+
if (missingApprovals.length > 0) {
|
|
4624
|
+
return `Blocked before spend, provider writes, delivery, or launch until approval covers: ${uniqueStrings(missingApprovals).join(", ")}.`;
|
|
4625
|
+
}
|
|
4626
|
+
if (state === "dry_run_complete" || state === "ready_for_dry_run") {
|
|
4627
|
+
return "Read-only planning and dry-runs are allowed; spend, provider writes, sender loading, delivery, and launch still require explicit approval.";
|
|
4628
|
+
}
|
|
4629
|
+
return "This packet is read-only and does not authorize spend, provider writes, sender loading, delivery, or launch.";
|
|
4630
|
+
}
|
|
4631
|
+
function campaignBuilderActiveWorkNextAction(state, blockers, missingApprovals, refs) {
|
|
4632
|
+
if (blockers.length > 0) return `Resolve blocker: ${blockers[0]}`;
|
|
4633
|
+
if (missingApprovals.length > 0) return `Ask the operator to approve ${uniqueStrings(missingApprovals).join(", ")} before any write or spend action.`;
|
|
4634
|
+
if (state === "ready_for_dry_run") return "Run or inspect the read-only campaign dry-run, then return the receipt for approval review.";
|
|
4635
|
+
if (state === "dry_run_complete") return "Review the dry-run receipt and collect explicit launch or delivery approval before any write action.";
|
|
4636
|
+
if (state === "queued_or_running") return "Poll the remembered campaign build or provider job status; do not start a duplicate job.";
|
|
4637
|
+
if (state === "completed") return "Review final artifacts and delivery gates before export, sync, sender load, or launch.";
|
|
4638
|
+
if (refs.length > 0) return "Use the remembered refs to fetch current read-only status before asking the operator for IDs.";
|
|
4639
|
+
return "Create or refresh a campaign-builder plan before taking any spendful or write action.";
|
|
4640
|
+
}
|
|
4641
|
+
function campaignBuilderActiveWorkConversationStarters(input) {
|
|
4642
|
+
const starters = [];
|
|
4643
|
+
if (input.blockers.length > 0) {
|
|
4644
|
+
starters.push(
|
|
4645
|
+
`I found a blocker: ${input.blockers[0]}. Want me to stay in read-only diagnostics and prepare the fix path?`
|
|
4646
|
+
);
|
|
4647
|
+
}
|
|
4648
|
+
if (input.missingApprovals.length > 0) {
|
|
4649
|
+
starters.push(
|
|
4650
|
+
`You still owe approval for ${uniqueStrings(input.missingApprovals).join(", ")}. Want the exact approval packet before anything writes or spends?`
|
|
4651
|
+
);
|
|
4652
|
+
}
|
|
4653
|
+
if (input.state === "queued_or_running") {
|
|
4654
|
+
const buildRef = input.refs.find((ref) => ref.kind === "campaign_build");
|
|
4655
|
+
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.");
|
|
4656
|
+
}
|
|
4657
|
+
if (input.state === "dry_run_complete") {
|
|
4658
|
+
starters.push("The dry run is complete. Want me to summarize blockers, artifacts, and the approval handoff?");
|
|
4659
|
+
}
|
|
4660
|
+
if (input.state === "ready_for_dry_run") {
|
|
4661
|
+
starters.push("Everything is ready for a safe dry run. Want me to run the no-spend preview first?");
|
|
4662
|
+
}
|
|
4663
|
+
if (input.state === "completed") {
|
|
4664
|
+
starters.push("The build looks complete. Want me to review rows, artifacts, and delivery gates before export or send approval?");
|
|
4665
|
+
}
|
|
4666
|
+
starters.push(`Next safe action: ${input.nextSafeAction}`);
|
|
4667
|
+
return uniqueStrings(starters).slice(0, 4);
|
|
4668
|
+
}
|
|
4669
|
+
function createCampaignBuilderOpenAiAgentHandoff(input) {
|
|
4670
|
+
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.")) ?? [];
|
|
4671
|
+
const routeSetupActions = readOnlyPlanActions.filter(
|
|
4672
|
+
(action) => action.tool === "gtm_provider_recipe_prepare" || action.tool === "gtm_provider_route_activate"
|
|
4673
|
+
);
|
|
4674
|
+
const safeReadActions = uniqueCampaignBuilderActiveWorkActions([
|
|
4675
|
+
input.nextSafeMcpAction,
|
|
4676
|
+
...routeSetupActions,
|
|
4677
|
+
...readOnlyPlanActions
|
|
4678
|
+
]);
|
|
4679
|
+
const approvalGatedActions = uniqueCampaignBuilderActiveWorkActions([
|
|
4680
|
+
...input.approvalPacket.mcp_handoffs.filter((action) => action.approval_required || !action.read_only),
|
|
4681
|
+
...input.plan?.mcpFlow.filter((step) => step.approvalRequired || !step.readOnly).map((step) => campaignBuilderMcpStepToActiveWorkAction(step, "Approval-gated Signaliz MCP continuation for the saved campaign-agent plan.")) ?? []
|
|
4682
|
+
]);
|
|
4683
|
+
const approvalTypes = uniqueStrings([
|
|
4684
|
+
...input.missingApprovals,
|
|
4685
|
+
...input.approvalPacket.requested_approval_types
|
|
4686
|
+
]);
|
|
4687
|
+
return {
|
|
4688
|
+
packet_version: "campaign-builder-openai-agent-handoff.v1",
|
|
4689
|
+
surface: "openai_agents_sdk",
|
|
4690
|
+
agent: {
|
|
4691
|
+
name: "Signaliz GTM Campaign Agent",
|
|
4692
|
+
handoff_description: "Owns safe, conversational GTM campaign planning and continuation across Signaliz MCP, SDK, attachments, URLs, customer tools, approvals, and sender/export gates.",
|
|
4693
|
+
instructions: [
|
|
4694
|
+
"Be warm, direct, and expert-level GTM. Translate the current state into plain operator language before proposing work.",
|
|
4695
|
+
"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.",
|
|
4696
|
+
"Use attachment_summary, url_summary, and operator_notes as first-class planning evidence, while honoring the evidence privacy_boundary and withheld raw fields.",
|
|
4697
|
+
"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.",
|
|
4698
|
+
"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.",
|
|
4699
|
+
"When approval is missing, show the approval_packet and the exact missing approval scope before any side-effecting step."
|
|
4700
|
+
],
|
|
4701
|
+
output_contract: [
|
|
4702
|
+
"current_state: one concise sentence describing where the campaign work stands.",
|
|
4703
|
+
"evidence_used: attachment, URL, memory, route, or integration evidence used without exposing private raw rows or secrets.",
|
|
4704
|
+
"next_safe_mcp_action: the read-only Signaliz MCP action to run next, or null when none is safe.",
|
|
4705
|
+
"approval_boundary: the human approval scope required before spend, provider writes, delivery, export, sender load, or launch.",
|
|
4706
|
+
"operator_reply: conversational GTM guidance with blockers, risks, and the safest next move."
|
|
4707
|
+
]
|
|
4708
|
+
},
|
|
4709
|
+
context: {
|
|
4710
|
+
state: input.state,
|
|
4711
|
+
summary: input.summary,
|
|
4712
|
+
refs: input.refs,
|
|
4713
|
+
blockers: input.blockers,
|
|
4714
|
+
warnings: input.warnings,
|
|
4715
|
+
evidence_context: input.plan?.evidence ?? null,
|
|
4716
|
+
approval_packet: input.approvalPacket,
|
|
4717
|
+
approval_boundary: input.approvalBoundary,
|
|
4718
|
+
next_safe_action: input.nextSafeAction,
|
|
4719
|
+
conversation_starters: input.conversationStarters
|
|
4720
|
+
},
|
|
4721
|
+
tools: {
|
|
4722
|
+
mcp_server_label: "signaliz",
|
|
4723
|
+
remote_mcp_compatible: true,
|
|
4724
|
+
next_safe_mcp_action: input.nextSafeMcpAction,
|
|
4725
|
+
safe_read_tools: safeReadActions.map(
|
|
4726
|
+
(action) => campaignBuilderOpenAiAgentTool(action, "Safe read-only Signaliz MCP action available before approval.")
|
|
4727
|
+
),
|
|
4728
|
+
approval_gated_tools: approvalGatedActions.map(
|
|
4729
|
+
(action) => campaignBuilderOpenAiAgentTool(action, "Requires explicit human review before execution.")
|
|
4730
|
+
)
|
|
4731
|
+
},
|
|
4732
|
+
guardrails: {
|
|
4733
|
+
input: [
|
|
4734
|
+
"Reject or pause requests to expose raw private attachment text, raw rows, leads, emails, provider payloads, copy bodies, API keys, or secrets.",
|
|
4735
|
+
"Pause when the user asks to spend credits, write to a provider, export, load a sender, deliver, or launch without explicit approval scope."
|
|
4736
|
+
],
|
|
4737
|
+
tool: [
|
|
4738
|
+
"Read-only tools may run when they match safe_read_tools and their arguments match this packet.",
|
|
4739
|
+
"Any tool with approval_required=true or read_only=false requires human review and the approval_packet scope first."
|
|
4740
|
+
],
|
|
4741
|
+
human_review_required_for: approvalTypes,
|
|
4742
|
+
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."
|
|
4743
|
+
}
|
|
4744
|
+
};
|
|
4745
|
+
}
|
|
4746
|
+
function campaignBuilderOpenAiAgentTool(action, purpose) {
|
|
4747
|
+
return {
|
|
4748
|
+
id: action.id,
|
|
4749
|
+
type: "mcp",
|
|
4750
|
+
server_label: "signaliz",
|
|
4751
|
+
name: action.tool,
|
|
4752
|
+
arguments: action.arguments,
|
|
4753
|
+
read_only: action.read_only,
|
|
4754
|
+
approval_required: action.approval_required,
|
|
4755
|
+
purpose,
|
|
4756
|
+
safety: action.safety
|
|
4757
|
+
};
|
|
4758
|
+
}
|
|
4759
|
+
function uniqueCampaignBuilderActiveWorkActions(actions) {
|
|
4760
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4761
|
+
const unique = [];
|
|
4762
|
+
for (const action of actions) {
|
|
4763
|
+
if (!action) continue;
|
|
4764
|
+
const key = `${action.id}:${action.tool}`;
|
|
4765
|
+
if (seen.has(key)) continue;
|
|
4766
|
+
seen.add(key);
|
|
4767
|
+
unique.push(action);
|
|
4768
|
+
}
|
|
4769
|
+
return unique;
|
|
4770
|
+
}
|
|
4771
|
+
function activeWorkStatus(record) {
|
|
4772
|
+
return stringValue(record.status ?? record.state ?? record.phase);
|
|
4773
|
+
}
|
|
4179
4774
|
function campaignBuilderBuiltInForRoute(route) {
|
|
4180
4775
|
return Object.entries(CAMPAIGN_BUILDER_BUILT_IN_ROUTE_IDS).find(([, routeId]) => route.id === routeId)?.[0];
|
|
4181
4776
|
}
|
|
@@ -4463,7 +5058,8 @@ var init_campaign_builder_agent = __esm({
|
|
|
4463
5058
|
copy: {
|
|
4464
5059
|
enabled: true,
|
|
4465
5060
|
tone: "direct",
|
|
4466
|
-
maxBodyWords: 125
|
|
5061
|
+
maxBodyWords: 125,
|
|
5062
|
+
evidenceMode: "signal_led"
|
|
4467
5063
|
},
|
|
4468
5064
|
delivery: {
|
|
4469
5065
|
enabled: true,
|
|
@@ -4520,7 +5116,8 @@ var init_campaign_builder_agent = __esm({
|
|
|
4520
5116
|
"Block export when required identity, company, or email fields are missing."
|
|
4521
5117
|
],
|
|
4522
5118
|
activationBoundary: "Cache inventory is read-only. Fresh sourcing, cache writes, export, and sender loading require explicit approval.",
|
|
4523
|
-
memoryKeywords: ["cache inventory", "large list", "unique emails", "top-up sourcing", "source metadata"]
|
|
5119
|
+
memoryKeywords: ["cache inventory", "large list", "unique emails", "top-up sourcing", "source metadata"],
|
|
5120
|
+
knowledgeSources: ["data-ops/contact-data-lifecycle", "data-ops/credit-optimization-guide", "gtm/data-quality-ops", "gtm/lead-generation-strategies"]
|
|
4524
5121
|
},
|
|
4525
5122
|
{
|
|
4526
5123
|
slug: "net-new-suppressed-list",
|
|
@@ -4545,7 +5142,8 @@ var init_campaign_builder_agent = __esm({
|
|
|
4545
5142
|
"Do not describe rows as fully qualified when the approved path only proves net-new email status."
|
|
4546
5143
|
],
|
|
4547
5144
|
activationBoundary: "Suppression review must pass before export, upload, CRM sync, sender load, or sequence launch.",
|
|
4548
|
-
memoryKeywords: ["suppression", "net-new", "prior email overlap", "domain review", "provenance-rich QA"]
|
|
5145
|
+
memoryKeywords: ["suppression", "net-new", "prior email overlap", "domain review", "provenance-rich QA"],
|
|
5146
|
+
knowledgeSources: ["gtm/data-quality-ops", "data-ops/contact-data-lifecycle", "gtm/outbound-sequencing"]
|
|
4549
5147
|
},
|
|
4550
5148
|
{
|
|
4551
5149
|
slug: "proof-first-vertical-gate",
|
|
@@ -4570,7 +5168,8 @@ var init_campaign_builder_agent = __esm({
|
|
|
4570
5168
|
"Contact fit should meet the configured threshold before email finding or copy generation."
|
|
4571
5169
|
],
|
|
4572
5170
|
activationBoundary: "Proof gates are required before contact spend, copy, export, or external writes.",
|
|
4573
|
-
memoryKeywords: ["proof gate", "vertical exclusion", "company before contact", "pass review fail", "fit threshold"]
|
|
5171
|
+
memoryKeywords: ["proof gate", "vertical exclusion", "company before contact", "pass review fail", "fit threshold"],
|
|
5172
|
+
knowledgeSources: ["gtm/icp-design-framework", "gtm/strategy/scoring.yaml", "gtm/advanced/account-prioritization-frameworks", "gtm/advanced/predictive-lead-scoring", "gtm/verticals"]
|
|
4574
5173
|
},
|
|
4575
5174
|
{
|
|
4576
5175
|
slug: "signal-led-copy-approval",
|
|
@@ -4595,7 +5194,8 @@ var init_campaign_builder_agent = __esm({
|
|
|
4595
5194
|
"Destination fields must remain blocked until approval metadata is present."
|
|
4596
5195
|
],
|
|
4597
5196
|
activationBoundary: "Copy readiness is not delivery approval. Export, sync, sender load, and launch require a separate human-approved gate.",
|
|
4598
|
-
memoryKeywords: ["company signals", "evidence-fed copy", "why now", "copy blocker", "approval gate"]
|
|
5197
|
+
memoryKeywords: ["company signals", "evidence-fed copy", "why now", "copy blocker", "approval gate"],
|
|
5198
|
+
knowledgeSources: ["gtm/email-personalization", "gtm/signal-based-selling", "gtm/signal-combination-matrix", "gtm/advanced/buyer-journey-mapping"]
|
|
4599
5199
|
},
|
|
4600
5200
|
{
|
|
4601
5201
|
slug: "domain-first-recovery",
|
|
@@ -4620,7 +5220,8 @@ var init_campaign_builder_agent = __esm({
|
|
|
4620
5220
|
"Target count means final held rows, not raw sourced rows."
|
|
4621
5221
|
],
|
|
4622
5222
|
activationBoundary: "Domain recovery informs sourcing. Contact enrichment, paid qualification, and export still require approved gates.",
|
|
4623
|
-
memoryKeywords: ["domain-first", "yield modeling", "attrition", "accepted domains", "gap fill"]
|
|
5223
|
+
memoryKeywords: ["domain-first", "yield modeling", "attrition", "accepted domains", "gap fill"],
|
|
5224
|
+
knowledgeSources: ["gtm/lead-generation-strategies", "data-ops/enrichment-waterfall-strategy", "data-ops/credit-optimization-guide", "gtm/territory-account-planning"]
|
|
4624
5225
|
},
|
|
4625
5226
|
{
|
|
4626
5227
|
slug: "table-workflow-handoff",
|
|
@@ -4645,7 +5246,112 @@ var init_campaign_builder_agent = __esm({
|
|
|
4645
5246
|
"Provider route activation must dry-run before any external write."
|
|
4646
5247
|
],
|
|
4647
5248
|
activationBoundary: "MCP, webhook, managed integration, and destination routes remain dry-run until the reviewed route and campaign are approved.",
|
|
4648
|
-
memoryKeywords: ["table workflow", "request ready", "provider status", "export blocker", "BYO integration"]
|
|
5249
|
+
memoryKeywords: ["table workflow", "request ready", "provider status", "export blocker", "BYO integration"],
|
|
5250
|
+
knowledgeSources: ["gtm/multi-channel-orchestration", "data-ops/enrichment-waterfall-strategy", "recipes/clay-gtm-webhook-recipe", "systems/blueprints/multi-channel-orchestration"]
|
|
5251
|
+
},
|
|
5252
|
+
{
|
|
5253
|
+
slug: "icp-persona-segmentation",
|
|
5254
|
+
label: "ICP And Persona Segmentation",
|
|
5255
|
+
whenToUse: [
|
|
5256
|
+
"The brief has a broad market, multiple personas, or unclear buying committee.",
|
|
5257
|
+
"The campaign should rank account tiers, persona fit, vertical nuance, and exclusions before sourcing at scale."
|
|
5258
|
+
],
|
|
5259
|
+
sequence: [
|
|
5260
|
+
"Convert the brief into account tiers, persona roles, buying committee influence, and explicit exclusions.",
|
|
5261
|
+
"Choose vertical guidance only from the customer-safe GTM library and keep internal platform docs out of prompts.",
|
|
5262
|
+
"Score accounts before contacts, then score contacts against persona, seniority, function, geography, and intent fit.",
|
|
5263
|
+
"Return segment counts and review buckets before spend, copy, export, or launch."
|
|
5264
|
+
],
|
|
5265
|
+
requiredFields: {
|
|
5266
|
+
segment: ["segment_name", "tier", "persona_priority", "buying_committee_role", "fit_reason", "exclusion_reason"],
|
|
5267
|
+
scoring: ["account_fit_score", "persona_fit_score", "segment_confidence", "review_bucket"]
|
|
5268
|
+
},
|
|
5269
|
+
qualityGates: [
|
|
5270
|
+
"Do not treat adjacent personas or verticals as matches unless the brief allows them.",
|
|
5271
|
+
"Keep ICP, persona, and exclusion evidence visible in the proof packet.",
|
|
5272
|
+
"Low-confidence segments route to review before contact discovery or copy."
|
|
5273
|
+
],
|
|
5274
|
+
activationBoundary: "Segmentation is planning guidance. Paid sourcing, enrichment, export, and launch require the normal approval gates.",
|
|
5275
|
+
memoryKeywords: ["ICP design", "persona segmentation", "buying committee", "account tiers", "fit scoring", "vertical nuance"],
|
|
5276
|
+
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"]
|
|
5277
|
+
},
|
|
5278
|
+
{
|
|
5279
|
+
slug: "buying-signal-prioritization",
|
|
5280
|
+
label: "Buying Signal Prioritization",
|
|
5281
|
+
whenToUse: [
|
|
5282
|
+
"The campaign depends on timing, intent, trigger events, or account prioritization.",
|
|
5283
|
+
"The operator wants why-now proof instead of generic list generation."
|
|
5284
|
+
],
|
|
5285
|
+
sequence: [
|
|
5286
|
+
"Map the campaign goal to signal families, trigger freshness, and buyer-journey stage.",
|
|
5287
|
+
"Rank signals by relevance, recency, source quality, and persona-specific actionability.",
|
|
5288
|
+
"Attach evidence URLs or evidence summaries without exposing private memory rows.",
|
|
5289
|
+
"Use signal strength to decide source order, copy angle, and review priority."
|
|
5290
|
+
],
|
|
5291
|
+
requiredFields: {
|
|
5292
|
+
signal: ["signal_type", "signal_date", "signal_source", "why_now", "signal_confidence", "buyer_stage"],
|
|
5293
|
+
prioritization: ["priority_score", "priority_reason", "next_best_action", "review_reason"]
|
|
5294
|
+
},
|
|
5295
|
+
qualityGates: [
|
|
5296
|
+
"Do not use stale, unsupported, or weak signals as personalization proof.",
|
|
5297
|
+
"Signal fit cannot override hard ICP, geography, suppression, or verified-email gates.",
|
|
5298
|
+
"Rows with uncertain why-now evidence must stay review-only."
|
|
5299
|
+
],
|
|
5300
|
+
activationBoundary: "Signal ranking can prioritize review and copy. It does not approve outreach, sender loading, exports, or sends.",
|
|
5301
|
+
memoryKeywords: ["buying signals", "intent data", "funding trigger", "new executive", "tech adoption", "buyer journey", "why now"],
|
|
5302
|
+
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"]
|
|
5303
|
+
},
|
|
5304
|
+
{
|
|
5305
|
+
slug: "multi-channel-sequence-fit",
|
|
5306
|
+
label: "Multi-Channel Sequence Fit",
|
|
5307
|
+
whenToUse: [
|
|
5308
|
+
"The campaign needs email, LinkedIn, call, webhook, CRM, or sequencer coordination.",
|
|
5309
|
+
"Copy and delivery should adapt by persona, channel, deliverability risk, and proof strength."
|
|
5310
|
+
],
|
|
5311
|
+
sequence: [
|
|
5312
|
+
"Choose channel mix from persona, deal motion, evidence strength, deliverability constraints, and connected destination readiness.",
|
|
5313
|
+
"Draft sequence logic with email, LinkedIn, call, and task handoffs only where supported by the approved destination.",
|
|
5314
|
+
"Keep copy concise, proof-backed, channel-specific, and reviewable before delivery.",
|
|
5315
|
+
"Run deliverability and destination readiness checks before sender load or launch approval."
|
|
5316
|
+
],
|
|
5317
|
+
requiredFields: {
|
|
5318
|
+
channel: ["channel", "touch_number", "persona_context", "message_angle", "channel_blocker", "approval_status"],
|
|
5319
|
+
deliverability: ["verified_email", "domain_risk", "send_window", "unsubscribe_risk", "sender_ready"]
|
|
5320
|
+
},
|
|
5321
|
+
qualityGates: [
|
|
5322
|
+
"Email copy must be row-supported and under the configured campaign tone/length limits.",
|
|
5323
|
+
"LinkedIn, phone, CRM, webhook, and sequencer actions remain destination-locked until approved.",
|
|
5324
|
+
"Deliverability risk or missing sender readiness blocks launch even when rows are qualified."
|
|
5325
|
+
],
|
|
5326
|
+
activationBoundary: "Sequence strategy is draft-only. External writes, sender loading, launch, and sending need separate explicit approval.",
|
|
5327
|
+
memoryKeywords: ["outbound sequencing", "email personalization", "LinkedIn outreach", "cold calling", "multi-channel orchestration", "deliverability"],
|
|
5328
|
+
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"]
|
|
5329
|
+
},
|
|
5330
|
+
{
|
|
5331
|
+
slug: "revops-feedback-loop",
|
|
5332
|
+
label: "RevOps Feedback Loop",
|
|
5333
|
+
whenToUse: [
|
|
5334
|
+
"The campaign should improve from replies, meetings, delivery results, CRM outcomes, or operator QA.",
|
|
5335
|
+
"The operator needs post-build monitoring, governance, or continuous ops follow-up."
|
|
5336
|
+
],
|
|
5337
|
+
sequence: [
|
|
5338
|
+
"Define success metrics, guardrails, and feedback sources before launch.",
|
|
5339
|
+
"Collect aggregate outcomes, QA blockers, delivery health, and operator edits after each campaign phase.",
|
|
5340
|
+
"Separate workspace-private evidence from public-safe learnings and Brain defaults.",
|
|
5341
|
+
"Feed approved aggregate learnings back into future sourcing, qualification, copy, and suppression rules."
|
|
5342
|
+
],
|
|
5343
|
+
requiredFields: {
|
|
5344
|
+
feedback: ["source", "event_type", "metric", "sample_size", "confidence", "learning_candidate"],
|
|
5345
|
+
governance: ["approval_owner", "last_reviewed_at", "risk_flag", "next_review_action"]
|
|
5346
|
+
},
|
|
5347
|
+
qualityGates: [
|
|
5348
|
+
"Do not write memory or Brain learnings from raw replies, private labels, or provider payloads without approved redaction.",
|
|
5349
|
+
"Use holdouts or pre/post comparisons before claiming causal lift.",
|
|
5350
|
+
"Delivery, suppression, and opt-out signals must update future gates before scale-up."
|
|
5351
|
+
],
|
|
5352
|
+
activationBoundary: "Feedback review is read-only until memory writes, Brain writes, CRM updates, or campaign changes are explicitly approved.",
|
|
5353
|
+
memoryKeywords: ["RevOps", "feedback loop", "campaign learning", "reply outcomes", "sales marketing alignment", "data hygiene", "holdout"],
|
|
5354
|
+
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"]
|
|
4649
5355
|
}
|
|
4650
5356
|
];
|
|
4651
5357
|
CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
@@ -4732,7 +5438,15 @@ var init_campaign_builder_agent = __esm({
|
|
|
4732
5438
|
agencyContext: {
|
|
4733
5439
|
partnerEcosystem: ["signaliz", "instantly", "nango"]
|
|
4734
5440
|
},
|
|
4735
|
-
operatingPlaybookSlugs: [
|
|
5441
|
+
operatingPlaybookSlugs: [
|
|
5442
|
+
"net-new-suppressed-list",
|
|
5443
|
+
"proof-first-vertical-gate",
|
|
5444
|
+
"signal-led-copy-approval",
|
|
5445
|
+
"icp-persona-segmentation",
|
|
5446
|
+
"buying-signal-prioritization",
|
|
5447
|
+
"multi-channel-sequence-fit",
|
|
5448
|
+
"revops-feedback-loop"
|
|
5449
|
+
]
|
|
4736
5450
|
},
|
|
4737
5451
|
{
|
|
4738
5452
|
slug: "non-medical-home-care",
|
|
@@ -4805,7 +5519,15 @@ var init_campaign_builder_agent = __esm({
|
|
|
4805
5519
|
agencyContext: {
|
|
4806
5520
|
partnerEcosystem: ["clay", "octave", "signaliz", "instantly", "nango"]
|
|
4807
5521
|
},
|
|
4808
|
-
operatingPlaybookSlugs: [
|
|
5522
|
+
operatingPlaybookSlugs: [
|
|
5523
|
+
"proof-first-vertical-gate",
|
|
5524
|
+
"domain-first-recovery",
|
|
5525
|
+
"table-workflow-handoff",
|
|
5526
|
+
"icp-persona-segmentation",
|
|
5527
|
+
"buying-signal-prioritization",
|
|
5528
|
+
"multi-channel-sequence-fit",
|
|
5529
|
+
"revops-feedback-loop"
|
|
5530
|
+
]
|
|
4809
5531
|
},
|
|
4810
5532
|
{
|
|
4811
5533
|
slug: "agency-founder-led",
|
|
@@ -4866,7 +5588,15 @@ var init_campaign_builder_agent = __esm({
|
|
|
4866
5588
|
agencyContext: {
|
|
4867
5589
|
partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
|
|
4868
5590
|
},
|
|
4869
|
-
operatingPlaybookSlugs: [
|
|
5591
|
+
operatingPlaybookSlugs: [
|
|
5592
|
+
"net-new-suppressed-list",
|
|
5593
|
+
"signal-led-copy-approval",
|
|
5594
|
+
"table-workflow-handoff",
|
|
5595
|
+
"icp-persona-segmentation",
|
|
5596
|
+
"buying-signal-prioritization",
|
|
5597
|
+
"multi-channel-sequence-fit",
|
|
5598
|
+
"revops-feedback-loop"
|
|
5599
|
+
]
|
|
4870
5600
|
},
|
|
4871
5601
|
{
|
|
4872
5602
|
slug: "cloud-infrastructure-displacement",
|
|
@@ -4953,7 +5683,15 @@ var init_campaign_builder_agent = __esm({
|
|
|
4953
5683
|
agencyContext: {
|
|
4954
5684
|
partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
|
|
4955
5685
|
},
|
|
4956
|
-
operatingPlaybookSlugs: [
|
|
5686
|
+
operatingPlaybookSlugs: [
|
|
5687
|
+
"proof-first-vertical-gate",
|
|
5688
|
+
"domain-first-recovery",
|
|
5689
|
+
"signal-led-copy-approval",
|
|
5690
|
+
"icp-persona-segmentation",
|
|
5691
|
+
"buying-signal-prioritization",
|
|
5692
|
+
"multi-channel-sequence-fit",
|
|
5693
|
+
"revops-feedback-loop"
|
|
5694
|
+
]
|
|
4957
5695
|
}
|
|
4958
5696
|
];
|
|
4959
5697
|
CampaignBuilderAgent = class {
|
|
@@ -4984,6 +5722,9 @@ var init_campaign_builder_agent = __esm({
|
|
|
4984
5722
|
const plan = await this.createPlan(request, options);
|
|
4985
5723
|
return createCampaignBuilderReadiness(plan);
|
|
4986
5724
|
}
|
|
5725
|
+
activeWorkContext(input) {
|
|
5726
|
+
return createCampaignBuilderActiveWorkContext(input);
|
|
5727
|
+
}
|
|
4987
5728
|
async proof(request, options = {}) {
|
|
4988
5729
|
const plan = await this.createPlan(request, options);
|
|
4989
5730
|
const result = await this.dryRunPlan(plan, {
|
|
@@ -7924,6 +8665,36 @@ function recordsFromParams(params) {
|
|
|
7924
8665
|
if (params.input) return { input: params.input };
|
|
7925
8666
|
return { input: {} };
|
|
7926
8667
|
}
|
|
8668
|
+
function toFusionConfig(params) {
|
|
8669
|
+
return {
|
|
8670
|
+
system_prompt: params.systemPrompt || params.system_prompt,
|
|
8671
|
+
user_template: params.userTemplate || params.user_template || params.prompt,
|
|
8672
|
+
preset: params.preset,
|
|
8673
|
+
temperature: params.temperature,
|
|
8674
|
+
max_tool_calls: params.maxToolCalls || params.max_tool_calls,
|
|
8675
|
+
max_tokens: params.maxTokens || params.max_tokens,
|
|
8676
|
+
timeout_ms: params.timeoutMs || params.timeout_ms,
|
|
8677
|
+
output_fields: params.outputFields || params.output_fields || [{ name: "response", type: "text", description: "Structured Fusion enrichment result" }]
|
|
8678
|
+
};
|
|
8679
|
+
}
|
|
8680
|
+
function toFusionSpendControls(params) {
|
|
8681
|
+
const controls = {};
|
|
8682
|
+
const dryRun = params.dryRun ?? params.dry_run;
|
|
8683
|
+
const confirmSpend = params.confirmSpend ?? params.confirm_spend;
|
|
8684
|
+
const maxCredits = params.maxCredits ?? params.max_credits;
|
|
8685
|
+
const maxCostUsd = params.maxCostUsd ?? params.max_cost_usd;
|
|
8686
|
+
if (dryRun !== void 0) controls.dry_run = dryRun;
|
|
8687
|
+
if (confirmSpend !== void 0) controls.confirm_spend = confirmSpend;
|
|
8688
|
+
if (maxCredits !== void 0) controls.max_credits = maxCredits;
|
|
8689
|
+
if (maxCostUsd !== void 0) controls.max_cost_usd = maxCostUsd;
|
|
8690
|
+
return controls;
|
|
8691
|
+
}
|
|
8692
|
+
function fusionRecordsFromParams(params) {
|
|
8693
|
+
const records = params.records || params.inputs;
|
|
8694
|
+
if (records?.length) return { records };
|
|
8695
|
+
if (params.input) return { input: params.input };
|
|
8696
|
+
return { input: {} };
|
|
8697
|
+
}
|
|
7927
8698
|
var Ai;
|
|
7928
8699
|
var init_ai = __esm({
|
|
7929
8700
|
"src/resources/ai.ts"() {
|
|
@@ -7961,6 +8732,33 @@ var init_ai = __esm({
|
|
|
7961
8732
|
raw: data
|
|
7962
8733
|
};
|
|
7963
8734
|
}
|
|
8735
|
+
/**
|
|
8736
|
+
* Plan or run experimental AI Enrichment Fusion with explicit spend controls.
|
|
8737
|
+
*/
|
|
8738
|
+
async fusion(params) {
|
|
8739
|
+
if (!params.prompt && !params.userTemplate && !params.user_template) {
|
|
8740
|
+
throw new Error("prompt or userTemplate is required.");
|
|
8741
|
+
}
|
|
8742
|
+
const data = await this.client.post("ai-enrichment-fusion", {
|
|
8743
|
+
...fusionRecordsFromParams(params),
|
|
8744
|
+
config: toFusionConfig(params),
|
|
8745
|
+
...toFusionSpendControls(params)
|
|
8746
|
+
});
|
|
8747
|
+
return {
|
|
8748
|
+
success: data.success ?? false,
|
|
8749
|
+
capability: data.capability ?? "ai_enrichment_fusion",
|
|
8750
|
+
displayName: data.display_name ?? "AI Enrichment Fusion",
|
|
8751
|
+
results: data.results ?? [],
|
|
8752
|
+
creditsUsed: data.total_credits_used ?? data.credits_used ?? 0,
|
|
8753
|
+
model: data.model,
|
|
8754
|
+
fusion: data.fusion,
|
|
8755
|
+
tokensUsed: data.tokens_used ?? 0,
|
|
8756
|
+
costUsd: data.cost_usd ?? 0,
|
|
8757
|
+
costSummary: data.cost_summary,
|
|
8758
|
+
billingMetadata: data.billing_metadata,
|
|
8759
|
+
raw: data
|
|
8760
|
+
};
|
|
8761
|
+
}
|
|
7964
8762
|
};
|
|
7965
8763
|
}
|
|
7966
8764
|
});
|
|
@@ -8623,6 +9421,24 @@ var init_gtm_kernel = __esm({
|
|
|
8623
9421
|
limit: input.limit
|
|
8624
9422
|
});
|
|
8625
9423
|
}
|
|
9424
|
+
/** Predict booked-meeting likelihood for uploaded, inline, or MCP-sourced lead rows without persisting raw rows. */
|
|
9425
|
+
async predictMeetingLikelihood(input) {
|
|
9426
|
+
return this.callMcp("gtm_predict_meeting_likelihood", {
|
|
9427
|
+
lead_rows: input.leadRows,
|
|
9428
|
+
input_source: input.inputSource,
|
|
9429
|
+
campaign_id: input.campaignId,
|
|
9430
|
+
campaign_build_id: input.campaignBuildId,
|
|
9431
|
+
days: input.days,
|
|
9432
|
+
feedback_limit: input.feedbackLimit,
|
|
9433
|
+
include_features: input.includeFeatures,
|
|
9434
|
+
include_global: input.includeGlobal,
|
|
9435
|
+
min_feedback_events: input.minFeedbackEvents,
|
|
9436
|
+
min_historical_feature_sample_size: input.minHistoricalFeatureSampleSize,
|
|
9437
|
+
min_workspace_count: input.minWorkspaceCount,
|
|
9438
|
+
min_privacy_k: input.minPrivacyK,
|
|
9439
|
+
limit: input.limit
|
|
9440
|
+
});
|
|
9441
|
+
}
|
|
8626
9442
|
/** Rank provider-chain, ICP, source, copy, and sequence failure patterns without writing raw lead data. */
|
|
8627
9443
|
async failurePatterns(options = {}) {
|
|
8628
9444
|
return this.callMcp("gtm_brain_failure_patterns", {
|
|
@@ -9123,6 +9939,76 @@ var init_gtm_kernel = __esm({
|
|
|
9123
9939
|
}
|
|
9124
9940
|
});
|
|
9125
9941
|
|
|
9942
|
+
// src/resources/public-ground-truth.ts
|
|
9943
|
+
var PublicGroundTruth;
|
|
9944
|
+
var init_public_ground_truth = __esm({
|
|
9945
|
+
"src/resources/public-ground-truth.ts"() {
|
|
9946
|
+
"use strict";
|
|
9947
|
+
PublicGroundTruth = class {
|
|
9948
|
+
constructor(client) {
|
|
9949
|
+
this.client = client;
|
|
9950
|
+
}
|
|
9951
|
+
/**
|
|
9952
|
+
* Search the public-ground-truth cache by company/name/domain/native ID,
|
|
9953
|
+
* or by plain-language industry + location.
|
|
9954
|
+
* Results use the same snake_case wire shape returned by the hosted MCP API.
|
|
9955
|
+
*/
|
|
9956
|
+
async search(params) {
|
|
9957
|
+
return this.client.mcp("tools/call", {
|
|
9958
|
+
name: "search_public_ground_truth",
|
|
9959
|
+
arguments: {
|
|
9960
|
+
query: params.query ?? params.search,
|
|
9961
|
+
industry: params.industry,
|
|
9962
|
+
location: params.location,
|
|
9963
|
+
source_id: params.sourceId ?? params.source_id,
|
|
9964
|
+
entity_type: params.entityType ?? params.entity_type,
|
|
9965
|
+
native_id: params.nativeId ?? params.native_id,
|
|
9966
|
+
entity_name: params.entityName ?? params.entity_name,
|
|
9967
|
+
domain: params.domain,
|
|
9968
|
+
website_url: params.websiteUrl ?? params.website_url,
|
|
9969
|
+
phone: params.phone,
|
|
9970
|
+
email: params.email,
|
|
9971
|
+
city: params.city,
|
|
9972
|
+
state: params.state,
|
|
9973
|
+
postal_code: params.postalCode ?? params.postal_code,
|
|
9974
|
+
country: params.country,
|
|
9975
|
+
source_url: params.sourceUrl ?? params.source_url,
|
|
9976
|
+
join_keys: params.joinKeys ?? params.join_keys,
|
|
9977
|
+
row_data: params.rowData ?? params.row_data,
|
|
9978
|
+
naics: params.naics,
|
|
9979
|
+
industry_code: params.industryCode ?? params.industry_code,
|
|
9980
|
+
industry_type: params.industryType ?? params.industry_type,
|
|
9981
|
+
year: params.year,
|
|
9982
|
+
quarter: params.quarter,
|
|
9983
|
+
area_fips: params.areaFips ?? params.area_fips,
|
|
9984
|
+
geo_id: params.geoId ?? params.geo_id,
|
|
9985
|
+
own_code: params.ownCode ?? params.own_code,
|
|
9986
|
+
source_updated_after: params.sourceUpdatedAfter ?? params.source_updated_after,
|
|
9987
|
+
source_updated_before: params.sourceUpdatedBefore ?? params.source_updated_before,
|
|
9988
|
+
observed_after: params.observedAfter ?? params.observed_after,
|
|
9989
|
+
observed_before: params.observedBefore ?? params.observed_before,
|
|
9990
|
+
limit: params.limit,
|
|
9991
|
+
offset: params.offset
|
|
9992
|
+
}
|
|
9993
|
+
});
|
|
9994
|
+
}
|
|
9995
|
+
/**
|
|
9996
|
+
* List available public-ground-truth cache sources and their join-key metadata.
|
|
9997
|
+
*/
|
|
9998
|
+
async listSources(params = {}) {
|
|
9999
|
+
return this.client.mcp("tools/call", {
|
|
10000
|
+
name: "list_public_ground_truth_sources",
|
|
10001
|
+
arguments: {
|
|
10002
|
+
query: params.query ?? params.search,
|
|
10003
|
+
status: params.status,
|
|
10004
|
+
limit: params.limit
|
|
10005
|
+
}
|
|
10006
|
+
});
|
|
10007
|
+
}
|
|
10008
|
+
};
|
|
10009
|
+
}
|
|
10010
|
+
});
|
|
10011
|
+
|
|
9126
10012
|
// src/index.ts
|
|
9127
10013
|
var index_exports = {};
|
|
9128
10014
|
__export(index_exports, {
|
|
@@ -9137,10 +10023,12 @@ __export(index_exports, {
|
|
|
9137
10023
|
GtmKernel: () => GtmKernel,
|
|
9138
10024
|
Icps: () => Icps,
|
|
9139
10025
|
Ops: () => Ops,
|
|
10026
|
+
PublicGroundTruth: () => PublicGroundTruth,
|
|
9140
10027
|
Signaliz: () => Signaliz,
|
|
9141
10028
|
SignalizError: () => SignalizError,
|
|
9142
10029
|
applyCampaignBuilderStrategyTemplate: () => applyCampaignBuilderStrategyTemplate,
|
|
9143
10030
|
collectExecutionReferences: () => collectExecutionReferences,
|
|
10031
|
+
createCampaignBuilderActiveWorkContext: () => createCampaignBuilderActiveWorkContext,
|
|
9144
10032
|
createCampaignBuilderAgentPlan: () => createCampaignBuilderAgentPlan,
|
|
9145
10033
|
createCampaignBuilderAgentRequestTemplate: () => createCampaignBuilderAgentRequestTemplate,
|
|
9146
10034
|
createCampaignBuilderApproval: () => createCampaignBuilderApproval,
|
|
@@ -9195,6 +10083,7 @@ function inferMcpToolCategory(toolName) {
|
|
|
9195
10083
|
}
|
|
9196
10084
|
if (toolName.includes("icp")) return "icp";
|
|
9197
10085
|
if (toolName.startsWith("ai_clean_")) return "data_cleaning";
|
|
10086
|
+
if (toolName.includes("public_ground_truth")) return "public_data";
|
|
9198
10087
|
if (toolName.includes("system") || toolName.includes("workflow")) return "automation";
|
|
9199
10088
|
if (toolName.includes("agent") || toolName.includes("platform_health") || toolName === "discover_capabilities") return "observability";
|
|
9200
10089
|
return void 0;
|
|
@@ -9248,9 +10137,11 @@ var init_index = __esm({
|
|
|
9248
10137
|
init_ops();
|
|
9249
10138
|
init_ai();
|
|
9250
10139
|
init_gtm_kernel();
|
|
10140
|
+
init_public_ground_truth();
|
|
9251
10141
|
init_errors();
|
|
9252
10142
|
init_ai();
|
|
9253
10143
|
init_gtm_kernel();
|
|
10144
|
+
init_public_ground_truth();
|
|
9254
10145
|
init_campaigns();
|
|
9255
10146
|
init_campaign_builder_agent();
|
|
9256
10147
|
init_icps();
|
|
@@ -9272,6 +10163,7 @@ var init_index = __esm({
|
|
|
9272
10163
|
this.ops = new Ops(this.client);
|
|
9273
10164
|
this.ai = new Ai(this.client);
|
|
9274
10165
|
this.gtm = new GtmKernel(this.client);
|
|
10166
|
+
this.publicGroundTruth = new PublicGroundTruth(this.client);
|
|
9275
10167
|
}
|
|
9276
10168
|
/** Get current workspace info including credits */
|
|
9277
10169
|
async getWorkspace() {
|
|
@@ -9430,6 +10322,13 @@ async function main() {
|
|
|
9430
10322
|
await handleGtmCommand(signaliz, process.argv.slice(3));
|
|
9431
10323
|
break;
|
|
9432
10324
|
}
|
|
10325
|
+
case "public-data":
|
|
10326
|
+
case "ground-truth":
|
|
10327
|
+
case "public-ground-truth": {
|
|
10328
|
+
const signaliz = await createSignalizClient();
|
|
10329
|
+
await handlePublicGroundTruthCommand(signaliz, process.argv.slice(3));
|
|
10330
|
+
break;
|
|
10331
|
+
}
|
|
9433
10332
|
case "campaign-agent":
|
|
9434
10333
|
case "campaign-builder": {
|
|
9435
10334
|
await handleCampaignAgentCommand(createSignalizClient, process.argv.slice(3));
|
|
@@ -9439,6 +10338,51 @@ async function main() {
|
|
|
9439
10338
|
printHelp();
|
|
9440
10339
|
}
|
|
9441
10340
|
}
|
|
10341
|
+
async function handlePublicGroundTruthCommand(signaliz, argv) {
|
|
10342
|
+
const subcommand = argv[0] && !argv[0].startsWith("--") ? argv[0] : "search";
|
|
10343
|
+
if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
|
|
10344
|
+
printPublicGroundTruthHelp();
|
|
10345
|
+
return;
|
|
10346
|
+
}
|
|
10347
|
+
if (subcommand === "sources" || subcommand === "list-sources") {
|
|
10348
|
+
const flags2 = parseFlags(argv.slice(subcommand === argv[0] ? 1 : 0));
|
|
10349
|
+
const result2 = await signaliz.publicGroundTruth.listSources({
|
|
10350
|
+
query: stringFlag(flags2, "query", "q", "search"),
|
|
10351
|
+
status: stringFlag(flags2, "status"),
|
|
10352
|
+
limit: numberFlag(flags2, "limit")
|
|
10353
|
+
});
|
|
10354
|
+
if (booleanFlag(flags2, "json")) {
|
|
10355
|
+
printJson(result2);
|
|
10356
|
+
} else {
|
|
10357
|
+
printPublicGroundTruthSources(result2);
|
|
10358
|
+
}
|
|
10359
|
+
return;
|
|
10360
|
+
}
|
|
10361
|
+
if (subcommand !== "search") {
|
|
10362
|
+
throw new Error(`Unknown public-data command: ${subcommand}`);
|
|
10363
|
+
}
|
|
10364
|
+
const flags = parseFlags(argv.slice(subcommand === argv[0] ? 1 : 0));
|
|
10365
|
+
const query = stringFlag(flags, "query", "q", "search");
|
|
10366
|
+
const sourceId = stringFlag(flags, "source-id", "sourceId");
|
|
10367
|
+
const entityType = stringFlag(flags, "entity-type", "entityType");
|
|
10368
|
+
const filters = publicGroundTruthFiltersFromFlags(flags);
|
|
10369
|
+
if (!query && !sourceId && !entityType && Object.keys(filters).length === 0) {
|
|
10370
|
+
throw new Error("public-data search requires --query or at least one filter");
|
|
10371
|
+
}
|
|
10372
|
+
const result = await signaliz.publicGroundTruth.search({
|
|
10373
|
+
query,
|
|
10374
|
+
sourceId,
|
|
10375
|
+
entityType,
|
|
10376
|
+
...filters,
|
|
10377
|
+
limit: numberFlag(flags, "limit"),
|
|
10378
|
+
offset: numberFlag(flags, "offset")
|
|
10379
|
+
});
|
|
10380
|
+
if (booleanFlag(flags, "json")) {
|
|
10381
|
+
printJson(result);
|
|
10382
|
+
} else {
|
|
10383
|
+
printPublicGroundTruthSearch(result);
|
|
10384
|
+
}
|
|
10385
|
+
}
|
|
9442
10386
|
async function handleGtmCommand(signaliz, argv) {
|
|
9443
10387
|
const subcommand = argv[0];
|
|
9444
10388
|
if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
|
|
@@ -10425,6 +11369,69 @@ function jsonObjectFromString(value, label) {
|
|
|
10425
11369
|
}
|
|
10426
11370
|
return parsed;
|
|
10427
11371
|
}
|
|
11372
|
+
var PUBLIC_GROUND_TRUTH_CLI_FILTERS = [
|
|
11373
|
+
["industry", "industry"],
|
|
11374
|
+
["location", "location"],
|
|
11375
|
+
["nativeId", "native-id", "nativeId"],
|
|
11376
|
+
["entityName", "entity-name", "entityName"],
|
|
11377
|
+
["domain", "domain"],
|
|
11378
|
+
["websiteUrl", "website-url", "websiteUrl"],
|
|
11379
|
+
["phone", "phone"],
|
|
11380
|
+
["email", "email"],
|
|
11381
|
+
["city", "city"],
|
|
11382
|
+
["state", "state"],
|
|
11383
|
+
["postalCode", "postal-code", "postalCode"],
|
|
11384
|
+
["country", "country"],
|
|
11385
|
+
["sourceUrl", "source-url", "sourceUrl"],
|
|
11386
|
+
["naics", "naics"],
|
|
11387
|
+
["industryCode", "industry-code", "industryCode"],
|
|
11388
|
+
["industryType", "industry-type", "industryType"],
|
|
11389
|
+
["year", "year"],
|
|
11390
|
+
["quarter", "quarter"],
|
|
11391
|
+
["areaFips", "area-fips", "areaFips"],
|
|
11392
|
+
["geoId", "geo-id", "geoId"],
|
|
11393
|
+
["ownCode", "own-code", "ownCode"],
|
|
11394
|
+
["sourceUpdatedAfter", "source-updated-after", "sourceUpdatedAfter"],
|
|
11395
|
+
["sourceUpdatedBefore", "source-updated-before", "sourceUpdatedBefore"],
|
|
11396
|
+
["observedAfter", "observed-after", "observedAfter"],
|
|
11397
|
+
["observedBefore", "observed-before", "observedBefore"]
|
|
11398
|
+
];
|
|
11399
|
+
function objectFromKeyValueFlags(flags, keyValueNames, jsonNames) {
|
|
11400
|
+
const object = {};
|
|
11401
|
+
for (const jsonName of jsonNames) {
|
|
11402
|
+
const parsed = jsonObjectFlag(flags, jsonName);
|
|
11403
|
+
if (parsed) Object.assign(object, parsed);
|
|
11404
|
+
}
|
|
11405
|
+
for (const pair of repeatedStringFlag(flags, ...keyValueNames)) {
|
|
11406
|
+
const eq = pair.indexOf("=");
|
|
11407
|
+
if (eq <= 0) throw new Error(`Expected key=value for --${keyValueNames[0]}`);
|
|
11408
|
+
const key = pair.slice(0, eq).trim();
|
|
11409
|
+
const value = pair.slice(eq + 1).trim();
|
|
11410
|
+
if (!key) throw new Error(`Expected non-empty key for --${keyValueNames[0]}`);
|
|
11411
|
+
object[key] = value;
|
|
11412
|
+
}
|
|
11413
|
+
return Object.keys(object).length > 0 ? object : void 0;
|
|
11414
|
+
}
|
|
11415
|
+
function publicGroundTruthFiltersFromFlags(flags) {
|
|
11416
|
+
const filters = {};
|
|
11417
|
+
for (const [paramName, ...flagNames] of PUBLIC_GROUND_TRUTH_CLI_FILTERS) {
|
|
11418
|
+
const value = stringFlag(flags, ...flagNames);
|
|
11419
|
+
if (value) filters[paramName] = value;
|
|
11420
|
+
}
|
|
11421
|
+
const joinKeys = objectFromKeyValueFlags(
|
|
11422
|
+
flags,
|
|
11423
|
+
["join-key", "joinKey"],
|
|
11424
|
+
["join-keys-json", "joinKeysJson"]
|
|
11425
|
+
);
|
|
11426
|
+
const rowData = objectFromKeyValueFlags(
|
|
11427
|
+
flags,
|
|
11428
|
+
["row-data", "rowData"],
|
|
11429
|
+
["row-data-json", "rowDataJson"]
|
|
11430
|
+
);
|
|
11431
|
+
if (joinKeys) filters.joinKeys = joinKeys;
|
|
11432
|
+
if (rowData) filters.rowData = rowData;
|
|
11433
|
+
return filters;
|
|
11434
|
+
}
|
|
10428
11435
|
function printResult(result, flags) {
|
|
10429
11436
|
if (booleanFlag(flags, "json")) {
|
|
10430
11437
|
printJson(result);
|
|
@@ -10501,10 +11508,59 @@ function printCampaignAgentExecution(payload, flags) {
|
|
|
10501
11508
|
printJson(payload);
|
|
10502
11509
|
return;
|
|
10503
11510
|
}
|
|
11511
|
+
printCampaignAgentOperatorVerdict(payload);
|
|
10504
11512
|
printCampaignAgentPlan(payload.plan);
|
|
10505
11513
|
console.log("\nResult:");
|
|
10506
11514
|
printJson(payload.result);
|
|
10507
11515
|
}
|
|
11516
|
+
function printCampaignAgentOperatorVerdict(payload) {
|
|
11517
|
+
const result = asRecord4(payload.result);
|
|
11518
|
+
const build = hasRecordKeys(asRecord4(result.build)) ? asRecord4(result.build) : result;
|
|
11519
|
+
const finalStatus = asRecord4(result.finalStatus);
|
|
11520
|
+
const deliveryApproval = asRecord4(result.deliveryApproval);
|
|
11521
|
+
const status = textFromRecord(finalStatus, "status") ?? textFromRecord(build, "status") ?? "unknown";
|
|
11522
|
+
const dryRun = build.dryRun === true || build.dry_run === true || status === "dry_run";
|
|
11523
|
+
const campaignBuildId = textFromRecord(build, "campaignBuildId", "campaign_build_id") ?? textFromRecord(finalStatus, "campaignBuildId", "campaign_build_id");
|
|
11524
|
+
const campaignId = textFromRecord(build, "campaignId", "campaign_id") ?? textFromRecord(finalStatus, "campaignId", "campaign_id");
|
|
11525
|
+
if (dryRun) {
|
|
11526
|
+
console.log("Operator verdict: dry run complete; nothing launched.");
|
|
11527
|
+
console.log("Safety: Dry-run only. No spend, provider write, sender load, delivery, or launch ran.");
|
|
11528
|
+
} else if (textFromRecord(finalStatus, "status") === "completed") {
|
|
11529
|
+
console.log("Operator verdict: approved campaign build completed.");
|
|
11530
|
+
console.log("Safety: Approved build path. Review rows and artifacts before any delivery expansion.");
|
|
11531
|
+
} else {
|
|
11532
|
+
console.log(`Operator verdict: approved campaign build ${status}.`);
|
|
11533
|
+
console.log("Safety: Approved build path. Spend and provider writes require the supplied approval packet; delivery remains separately gated.");
|
|
11534
|
+
}
|
|
11535
|
+
console.log(`Approval state: ${campaignAgentApprovalState(payload)}`);
|
|
11536
|
+
if (campaignId) console.log(`Campaign ID: ${campaignId}`);
|
|
11537
|
+
if (campaignBuildId) console.log(`Campaign build ID: ${campaignBuildId}`);
|
|
11538
|
+
if (hasRecordKeys(finalStatus)) console.log(`Final status: ${textFromRecord(finalStatus, "status") ?? "unknown"}`);
|
|
11539
|
+
if (hasRecordKeys(deliveryApproval)) console.log(`Delivery approval: ${textFromRecord(deliveryApproval, "status") ?? "unknown"}`);
|
|
11540
|
+
console.log(`Next safe command: ${campaignAgentNextSafeCommand(payload.plan, dryRun, campaignBuildId)}`);
|
|
11541
|
+
console.log("");
|
|
11542
|
+
}
|
|
11543
|
+
function campaignAgentApprovalState(payload) {
|
|
11544
|
+
if (payload.approval) return "approval packet supplied";
|
|
11545
|
+
const required = payload.plan.approvals.map((item) => item.type);
|
|
11546
|
+
return required.length ? `missing ${required.join(", ")}` : "no explicit approvals required";
|
|
11547
|
+
}
|
|
11548
|
+
function campaignAgentNextSafeCommand(plan, dryRun, campaignBuildId) {
|
|
11549
|
+
if (campaignBuildId) return `signaliz campaign-agent review ${campaignBuildId} --limit 100`;
|
|
11550
|
+
if (!dryRun) return "signaliz campaign-agent status <campaign-build-id>";
|
|
11551
|
+
return [
|
|
11552
|
+
"signaliz campaign-agent build-approved",
|
|
11553
|
+
"--goal",
|
|
11554
|
+
shellQuote(plan.campaignName),
|
|
11555
|
+
"--target-count",
|
|
11556
|
+
String(plan.targetCount),
|
|
11557
|
+
"--confirm-launch",
|
|
11558
|
+
"--approve-all",
|
|
11559
|
+
"--approved-by <operator-email>",
|
|
11560
|
+
"--spend-limit",
|
|
11561
|
+
String(plan.estimatedCredits)
|
|
11562
|
+
].join(" ");
|
|
11563
|
+
}
|
|
10508
11564
|
function printCampaignAgentReadiness(readiness) {
|
|
10509
11565
|
const summary = asRecord4(readiness.summary);
|
|
10510
11566
|
const plan = readiness.plan;
|
|
@@ -10580,7 +11636,10 @@ function printCampaignCustomerRowCounts(status) {
|
|
|
10580
11636
|
if (!counts || typeof counts !== "object") return;
|
|
10581
11637
|
const value = (camel, snake) => counts[camel] ?? counts[snake] ?? "n/a";
|
|
10582
11638
|
const requested = value("requestedTarget", "requested_target");
|
|
10583
|
-
|
|
11639
|
+
const copied = value("copiedRows", "copied_rows");
|
|
11640
|
+
const copySkipped = value("copySkippedRows", "copy_skipped_rows");
|
|
11641
|
+
const copyLabel = typeof copySkipped === "number" && copySkipped > 0 && (!copied || copied === "n/a") ? `copy-skipped ${copySkipped}` : `copied ${copied}`;
|
|
11642
|
+
console.log(`Customer rows: accepted ${value("acceptedRows", "accepted_rows")}/${requested}, ${copyLabel}, approval-ready ${value("approvalReadyRows", "approval_ready_rows")}, QA-ready ${value("qaReadyRows", "qa_ready_rows")}, delivered ${value("deliveredRows", "delivered_rows")}`);
|
|
10584
11643
|
const shortfalls = [
|
|
10585
11644
|
["accepted", value("acceptedShortfall", "accepted_shortfall")],
|
|
10586
11645
|
["usable", value("usableShortfall", "usable_shortfall")],
|
|
@@ -10715,6 +11774,20 @@ function printCampaignAgentCopySnippets(rows, limit = 5) {
|
|
|
10715
11774
|
function asRecord4(value) {
|
|
10716
11775
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
10717
11776
|
}
|
|
11777
|
+
function hasRecordKeys(value) {
|
|
11778
|
+
return Object.keys(value).length > 0;
|
|
11779
|
+
}
|
|
11780
|
+
function textFromRecord(record, ...keys) {
|
|
11781
|
+
for (const key of keys) {
|
|
11782
|
+
const value = record[key];
|
|
11783
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
11784
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
11785
|
+
}
|
|
11786
|
+
return void 0;
|
|
11787
|
+
}
|
|
11788
|
+
function shellQuote(value) {
|
|
11789
|
+
return `'${String(value || "").replace(/'/g, `'\\''`)}'`;
|
|
11790
|
+
}
|
|
10718
11791
|
function printCampaignAgentProof(proof) {
|
|
10719
11792
|
console.log(`Campaign-agent proof: ${proof.success ? "passed" : "failed"}`);
|
|
10720
11793
|
const campaign = asRecord4(proof.campaign);
|
|
@@ -10732,6 +11805,51 @@ function printCampaignAgentProof(proof) {
|
|
|
10732
11805
|
function printJson(value) {
|
|
10733
11806
|
console.log(JSON.stringify(value, null, 2));
|
|
10734
11807
|
}
|
|
11808
|
+
function truncateCell(value, width) {
|
|
11809
|
+
const text = String(value ?? "").replace(/\s+/g, " ").trim();
|
|
11810
|
+
return text.length > width ? `${text.slice(0, Math.max(width - 3, 0))}...` : text;
|
|
11811
|
+
}
|
|
11812
|
+
function printPublicGroundTruthSearch(result) {
|
|
11813
|
+
const records = Array.isArray(result.records) ? result.records : [];
|
|
11814
|
+
console.log(`Public data search: ${result.total_count ?? 0} matches (${records.length} returned)`);
|
|
11815
|
+
if (result.query) console.log(`Query: ${result.query}`);
|
|
11816
|
+
if (result.source_id) console.log(`Source: ${result.source_id}`);
|
|
11817
|
+
if (result.entity_type) console.log(`Entity type: ${result.entity_type}`);
|
|
11818
|
+
if (!records.length) {
|
|
11819
|
+
console.log("No records matched.");
|
|
11820
|
+
return;
|
|
11821
|
+
}
|
|
11822
|
+
console.log("");
|
|
11823
|
+
console.log("Source".padEnd(22) + "Native ID".padEnd(22) + "Name".padEnd(42) + "Industry".padEnd(28) + "Domain".padEnd(24) + "Loc".padEnd(12) + "Match");
|
|
11824
|
+
console.log("-".repeat(160));
|
|
11825
|
+
for (const record of records) {
|
|
11826
|
+
const loc = [record.city, record.state].filter(Boolean).join(", ");
|
|
11827
|
+
const industry = [record.industry_code, record.industry_name].filter(Boolean).join(" ");
|
|
11828
|
+
console.log(
|
|
11829
|
+
truncateCell(record.source_id, 21).padEnd(22) + truncateCell(record.native_id, 21).padEnd(22) + truncateCell(record.entity_name, 41).padEnd(42) + truncateCell(industry, 27).padEnd(28) + truncateCell(record.domain, 23).padEnd(24) + truncateCell(loc, 11).padEnd(12) + truncateCell(record.match_type, 16)
|
|
11830
|
+
);
|
|
11831
|
+
}
|
|
11832
|
+
if (result.next_offset !== null && result.next_offset !== void 0) {
|
|
11833
|
+
console.log(`
|
|
11834
|
+
Next page: --offset ${result.next_offset}`);
|
|
11835
|
+
}
|
|
11836
|
+
}
|
|
11837
|
+
function printPublicGroundTruthSources(result) {
|
|
11838
|
+
const sources = Array.isArray(result.sources) ? result.sources : [];
|
|
11839
|
+
console.log(`Public data sources: ${sources.length}/${result.total ?? sources.length}`);
|
|
11840
|
+
if (!sources.length) {
|
|
11841
|
+
console.log("No sources matched.");
|
|
11842
|
+
return;
|
|
11843
|
+
}
|
|
11844
|
+
console.log("");
|
|
11845
|
+
console.log("Source ID".padEnd(30) + "Status".padEnd(12) + "Rung".padEnd(7) + "Join key".padEnd(20) + "Cadence".padEnd(16) + "Name");
|
|
11846
|
+
console.log("-".repeat(120));
|
|
11847
|
+
for (const source of sources) {
|
|
11848
|
+
console.log(
|
|
11849
|
+
truncateCell(source.id, 29).padEnd(30) + truncateCell(source.ingestion_status, 11).padEnd(12) + String(source.ground_truth_rung ?? "").padEnd(7) + truncateCell(source.primary_join_key || source.join_key_quality, 19).padEnd(20) + truncateCell(source.update_cadence, 15).padEnd(16) + truncateCell(source.name, 40)
|
|
11850
|
+
);
|
|
11851
|
+
}
|
|
11852
|
+
}
|
|
10735
11853
|
function printHelp() {
|
|
10736
11854
|
console.log(`
|
|
10737
11855
|
Signaliz CLI v1.0.0
|
|
@@ -10739,6 +11857,8 @@ Signaliz CLI v1.0.0
|
|
|
10739
11857
|
Usage:
|
|
10740
11858
|
signaliz test Verify API connectivity
|
|
10741
11859
|
signaliz tools List all available MCP tools
|
|
11860
|
+
signaliz public-data search --query "swift transportation" --limit 10
|
|
11861
|
+
signaliz public-data sources --status ready
|
|
10742
11862
|
signaliz gtm context --json Load GTM Kernel workspace context
|
|
10743
11863
|
signaliz gtm bootstrap --json Inspect GTM Kernel readiness
|
|
10744
11864
|
signaliz gtm templates --json List private-safe campaign strategy templates
|
|
@@ -10769,6 +11889,25 @@ Environment:
|
|
|
10769
11889
|
SIGNALIZ_BASE_URL Optional API base URL override
|
|
10770
11890
|
`);
|
|
10771
11891
|
}
|
|
11892
|
+
function printPublicGroundTruthHelp() {
|
|
11893
|
+
console.log(`
|
|
11894
|
+
Signaliz public-data commands:
|
|
11895
|
+
|
|
11896
|
+
signaliz public-data search [--query TEXT] [--industry TEXT] [--location TEXT] [--source-id ID] [--domain DOMAIN] [--naics CODE] [--state ST] [--year YYYY] [--join-key k=v] [--row-data k=v] [--limit N] [--offset N] [--json]
|
|
11897
|
+
signaliz public-data sources [--query TEXT] [--status ready|partial|blocked|planned] [--limit N] [--json]
|
|
11898
|
+
|
|
11899
|
+
Aliases:
|
|
11900
|
+
signaliz ground-truth search ...
|
|
11901
|
+
|
|
11902
|
+
Examples:
|
|
11903
|
+
signaliz public-data search --query "swift transportation" --source-id fmcsa_company_census --limit 10
|
|
11904
|
+
signaliz public-data search --industry "software publishers" --location CA --limit 25 --json
|
|
11905
|
+
signaliz public-data search --source-id bls_qcew --naics 541511 --state CA --year 2025 --json
|
|
11906
|
+
signaliz public-data search --domain swifttrans.com --json
|
|
11907
|
+
signaliz public-data search --join-key ein=123456789 --json
|
|
11908
|
+
signaliz public-data sources --status ready --json
|
|
11909
|
+
`);
|
|
11910
|
+
}
|
|
10772
11911
|
function printGtmHelp() {
|
|
10773
11912
|
console.log(`
|
|
10774
11913
|
Signaliz GTM commands:
|