@signaliz/sdk 1.0.18 → 1.0.20

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.
@@ -479,6 +479,38 @@ var Signals = class {
479
479
  constructor(client) {
480
480
  this.client = client;
481
481
  }
482
+ /** Turn the strongest supported company signal into three complete, evidence-backed emails. */
483
+ async signalToCopy(params) {
484
+ const data = await this.client.post("api/v1/signal-to-copy", {
485
+ company_domain: params.companyDomain,
486
+ person_name: params.personName,
487
+ title: params.title,
488
+ campaign_offer: params.campaignOffer,
489
+ research_prompt: params.researchPrompt
490
+ });
491
+ return {
492
+ success: data.success ?? true,
493
+ strongestSignal: data.strongest_signal ?? "",
494
+ whyNow: data.why_now ?? "",
495
+ subjectLine: data.subject_line ?? "",
496
+ openingLine: data.opening_line ?? "",
497
+ confidence: data.confidence ?? 0,
498
+ evidenceUrl: data.evidence_url ?? "",
499
+ researchPrompt: data.research_prompt,
500
+ variations: (data.variations ?? []).map((v) => ({
501
+ style: v.style,
502
+ subjectLine: v.subject_line ?? "",
503
+ openingLine: v.opening_line ?? "",
504
+ cta: v.cta ?? "",
505
+ prediction: v.prediction,
506
+ email: v.email
507
+ }))
508
+ };
509
+ }
510
+ /** @deprecated Use signalToCopy. Retained for compatibility. */
511
+ async personalize(params) {
512
+ return this.signalToCopy(params);
513
+ }
482
514
  /** Enrich a company with actionable signals (V1) */
483
515
  async enrich(params) {
484
516
  const args = {
@@ -487,6 +519,9 @@ var Signals = class {
487
519
  if (params.domain) args.domain = params.domain;
488
520
  if (params.researchPrompt) args.research_prompt = params.researchPrompt;
489
521
  if (params.signalTypes) args.signal_types = params.signalTypes;
522
+ if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
523
+ if (params.lookbackDays) args.lookback_days = params.lookbackDays;
524
+ if (params.enableDeepSearch !== void 0) args.enable_deep_search = params.enableDeepSearch;
490
525
  const data = await this.client.mcp("tools/call", {
491
526
  name: "enrich_company_signals",
492
527
  arguments: args
@@ -496,6 +531,16 @@ var Signals = class {
496
531
  signals: (data.signals ?? []).map((s) => ({
497
532
  title: s.title,
498
533
  signalType: s.signal_type,
534
+ sourceType: s.source_type ?? s.signal_classification?.label ?? "unknown",
535
+ sourceProvenance: s.source_provenance ?? s.metadata?.source_provenance ?? null,
536
+ signalFamily: s.signal_family ?? s.signal_type ?? null,
537
+ signalEventType: s.signal_event_type ?? s.signal_classification?.slug ?? null,
538
+ signalEventLabel: s.signal_event_label ?? s.signal_classification?.label ?? null,
539
+ signalClassification: s.signal_classification ? {
540
+ label: s.signal_classification.label,
541
+ slug: s.signal_classification.slug,
542
+ rationale: s.signal_classification.rationale
543
+ } : null,
499
544
  confidenceScore: s.confidence_score ?? 0,
500
545
  detectedAt: s.detected_at ?? "",
501
546
  url: s.url,
@@ -536,8 +581,17 @@ var Signals = class {
536
581
  content: s.content ?? "",
537
582
  date: s.date ?? null,
538
583
  sourceUrl: s.source_url ?? null,
539
- sourceType: s.source_type ?? "unknown",
540
- confidence: s.confidence ?? null
584
+ sourceType: s.source_type ?? s.signal_classification?.label ?? "unknown",
585
+ sourceProvenance: s.source_provenance ?? s.metadata?.source_provenance ?? null,
586
+ signalFamily: s.signal_family ?? s.type ?? null,
587
+ signalEventType: s.signal_event_type ?? s.signal_classification?.slug ?? null,
588
+ signalEventLabel: s.signal_event_label ?? s.signal_classification?.label ?? null,
589
+ confidence: s.confidence ?? null,
590
+ signalClassification: s.signal_classification ? {
591
+ label: s.signal_classification.label,
592
+ slug: s.signal_classification.slug,
593
+ rationale: s.signal_classification.rationale
594
+ } : null
541
595
  })),
542
596
  signalCount: data.signal_count ?? 0,
543
597
  intelligence: data.intelligence ? {
@@ -580,6 +634,58 @@ var Signals = class {
580
634
  }
581
635
  };
582
636
  }
637
+ /** Plan or run experimental Signal Fusion with explicit spend controls. */
638
+ async fusion(params) {
639
+ const args = {};
640
+ if (params.companyName) args.company_name = params.companyName;
641
+ if (params.domain) args.domain = params.domain;
642
+ if (params.companyDomain) args.company_domain = params.companyDomain;
643
+ if (params.linkedinUrl) args.linkedin_url = params.linkedinUrl;
644
+ if (params.companies) args.companies = params.companies;
645
+ if (params.preset) args.preset = params.preset;
646
+ if (params.researchPrompt) args.research_prompt = params.researchPrompt;
647
+ if (params.signalTypes) args.signal_types = params.signalTypes;
648
+ if (params.lookbackDays) args.lookback_days = params.lookbackDays;
649
+ if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
650
+ if (params.maxToolCalls) args.max_tool_calls = params.maxToolCalls;
651
+ if (params.maxTokens) args.max_tokens = params.maxTokens;
652
+ if (params.timeoutMs) args.timeout_ms = params.timeoutMs;
653
+ const dryRun = params.dryRun ?? params.dry_run;
654
+ const confirmSpend = params.confirmSpend ?? params.confirm_spend;
655
+ const maxCredits = params.maxCredits ?? params.max_credits;
656
+ const maxCostUsd = params.maxCostUsd ?? params.max_cost_usd;
657
+ if (dryRun !== void 0) args.dry_run = dryRun;
658
+ if (confirmSpend !== void 0) args.confirm_spend = confirmSpend;
659
+ if (maxCredits !== void 0) args.max_credits = maxCredits;
660
+ if (maxCostUsd !== void 0) args.max_cost_usd = maxCostUsd;
661
+ const data = await this.client.post("signal-fusion", args);
662
+ return {
663
+ success: data.success ?? false,
664
+ capability: data.capability ?? "signal_fusion",
665
+ displayName: data.display_name ?? "Signal Fusion",
666
+ company: data.company,
667
+ signals: (data.signals ?? []).map((s) => ({
668
+ id: s.id,
669
+ title: s.title,
670
+ type: s.type,
671
+ content: s.content ?? "",
672
+ date: s.date ?? null,
673
+ sourceUrl: s.source_url ?? null,
674
+ sourceType: s.source_type ?? "unknown",
675
+ confidence: s.confidence ?? null
676
+ })),
677
+ signalCount: data.signal_count ?? data.signals?.length ?? 0,
678
+ results: data.results ?? [],
679
+ model: data.model,
680
+ fusion: data.fusion,
681
+ costUsd: data.cost_usd ?? 0,
682
+ tokensUsed: data.tokens_used ?? 0,
683
+ costSummary: data.cost_summary,
684
+ creditsUsed: data.total_credits_used ?? data.credits_used ?? 0,
685
+ billingMetadata: data.billing_metadata,
686
+ raw: data
687
+ };
688
+ }
583
689
  };
584
690
 
585
691
  // src/resources/systems.ts
@@ -1018,6 +1124,7 @@ function mapCustomerRowCounts(value) {
1018
1124
  acceptedRows: numberOrNull(record.accepted_rows) ?? void 0,
1019
1125
  usableRows: numberOrNull(record.usable_rows) ?? void 0,
1020
1126
  copiedRows: numberOrNull(record.copied_rows) ?? void 0,
1127
+ copySkippedRows: numberOrNull(record.copy_skipped_rows) ?? void 0,
1021
1128
  approvalReadyRows: numberOrNull(record.approval_ready_rows) ?? void 0,
1022
1129
  qaReadyRows: numberOrNull(record.qa_ready_rows) ?? void 0,
1023
1130
  deliveredRows: numberOrNull(record.delivered_rows) ?? void 0,
@@ -1254,7 +1361,8 @@ function buildArgs(request) {
1254
1361
  geographies: request.icp.geographies,
1255
1362
  keywords: request.icp.keywords,
1256
1363
  exclusions: request.icp.exclusions,
1257
- require_verified_email: request.icp.requireVerifiedEmail
1364
+ require_verified_email: request.icp.requireVerifiedEmail,
1365
+ persona_expansion_mode: request.icp.personaExpansionMode
1258
1366
  };
1259
1367
  }
1260
1368
  if (request.policy) {
@@ -1294,6 +1402,7 @@ function buildArgs(request) {
1294
1402
  } : void 0,
1295
1403
  sequence_steps: request.copy.sequenceSteps,
1296
1404
  copy_schema: request.copy.copySchema,
1405
+ evidence_mode: request.copy.evidenceMode,
1297
1406
  banned_phrases: request.copy.bannedPhrases,
1298
1407
  approval_required: request.copy.approvalRequired,
1299
1408
  quality_tier: request.copy.qualityTier
@@ -1350,7 +1459,8 @@ var DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS = {
1350
1459
  copy: {
1351
1460
  enabled: true,
1352
1461
  tone: "direct",
1353
- maxBodyWords: 125
1462
+ maxBodyWords: 125,
1463
+ evidenceMode: "signal_led"
1354
1464
  },
1355
1465
  delivery: {
1356
1466
  enabled: true,
@@ -1407,7 +1517,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
1407
1517
  "Block export when required identity, company, or email fields are missing."
1408
1518
  ],
1409
1519
  activationBoundary: "Cache inventory is read-only. Fresh sourcing, cache writes, export, and sender loading require explicit approval.",
1410
- memoryKeywords: ["cache inventory", "large list", "unique emails", "top-up sourcing", "source metadata"]
1520
+ memoryKeywords: ["cache inventory", "large list", "unique emails", "top-up sourcing", "source metadata"],
1521
+ knowledgeSources: ["data-ops/contact-data-lifecycle", "data-ops/credit-optimization-guide", "gtm/data-quality-ops", "gtm/lead-generation-strategies"]
1411
1522
  },
1412
1523
  {
1413
1524
  slug: "net-new-suppressed-list",
@@ -1432,7 +1543,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
1432
1543
  "Do not describe rows as fully qualified when the approved path only proves net-new email status."
1433
1544
  ],
1434
1545
  activationBoundary: "Suppression review must pass before export, upload, CRM sync, sender load, or sequence launch.",
1435
- memoryKeywords: ["suppression", "net-new", "prior email overlap", "domain review", "provenance-rich QA"]
1546
+ memoryKeywords: ["suppression", "net-new", "prior email overlap", "domain review", "provenance-rich QA"],
1547
+ knowledgeSources: ["gtm/data-quality-ops", "data-ops/contact-data-lifecycle", "gtm/outbound-sequencing"]
1436
1548
  },
1437
1549
  {
1438
1550
  slug: "proof-first-vertical-gate",
@@ -1457,7 +1569,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
1457
1569
  "Contact fit should meet the configured threshold before email finding or copy generation."
1458
1570
  ],
1459
1571
  activationBoundary: "Proof gates are required before contact spend, copy, export, or external writes.",
1460
- memoryKeywords: ["proof gate", "vertical exclusion", "company before contact", "pass review fail", "fit threshold"]
1572
+ memoryKeywords: ["proof gate", "vertical exclusion", "company before contact", "pass review fail", "fit threshold"],
1573
+ knowledgeSources: ["gtm/icp-design-framework", "gtm/strategy/scoring.yaml", "gtm/advanced/account-prioritization-frameworks", "gtm/advanced/predictive-lead-scoring", "gtm/verticals"]
1461
1574
  },
1462
1575
  {
1463
1576
  slug: "signal-led-copy-approval",
@@ -1482,7 +1595,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
1482
1595
  "Destination fields must remain blocked until approval metadata is present."
1483
1596
  ],
1484
1597
  activationBoundary: "Copy readiness is not delivery approval. Export, sync, sender load, and launch require a separate human-approved gate.",
1485
- memoryKeywords: ["company signals", "evidence-fed copy", "why now", "copy blocker", "approval gate"]
1598
+ memoryKeywords: ["company signals", "evidence-fed copy", "why now", "copy blocker", "approval gate"],
1599
+ knowledgeSources: ["gtm/email-personalization", "gtm/signal-based-selling", "gtm/signal-combination-matrix", "gtm/advanced/buyer-journey-mapping"]
1486
1600
  },
1487
1601
  {
1488
1602
  slug: "domain-first-recovery",
@@ -1507,7 +1621,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
1507
1621
  "Target count means final held rows, not raw sourced rows."
1508
1622
  ],
1509
1623
  activationBoundary: "Domain recovery informs sourcing. Contact enrichment, paid qualification, and export still require approved gates.",
1510
- memoryKeywords: ["domain-first", "yield modeling", "attrition", "accepted domains", "gap fill"]
1624
+ memoryKeywords: ["domain-first", "yield modeling", "attrition", "accepted domains", "gap fill"],
1625
+ knowledgeSources: ["gtm/lead-generation-strategies", "data-ops/enrichment-waterfall-strategy", "data-ops/credit-optimization-guide", "gtm/territory-account-planning"]
1511
1626
  },
1512
1627
  {
1513
1628
  slug: "table-workflow-handoff",
@@ -1532,7 +1647,112 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
1532
1647
  "Provider route activation must dry-run before any external write."
1533
1648
  ],
1534
1649
  activationBoundary: "MCP, webhook, managed integration, and destination routes remain dry-run until the reviewed route and campaign are approved.",
1535
- memoryKeywords: ["table workflow", "request ready", "provider status", "export blocker", "BYO integration"]
1650
+ memoryKeywords: ["table workflow", "request ready", "provider status", "export blocker", "BYO integration"],
1651
+ knowledgeSources: ["gtm/multi-channel-orchestration", "data-ops/enrichment-waterfall-strategy", "recipes/clay-gtm-webhook-recipe", "systems/blueprints/multi-channel-orchestration"]
1652
+ },
1653
+ {
1654
+ slug: "icp-persona-segmentation",
1655
+ label: "ICP And Persona Segmentation",
1656
+ whenToUse: [
1657
+ "The brief has a broad market, multiple personas, or unclear buying committee.",
1658
+ "The campaign should rank account tiers, persona fit, vertical nuance, and exclusions before sourcing at scale."
1659
+ ],
1660
+ sequence: [
1661
+ "Convert the brief into account tiers, persona roles, buying committee influence, and explicit exclusions.",
1662
+ "Choose vertical guidance only from the customer-safe GTM library and keep internal platform docs out of prompts.",
1663
+ "Score accounts before contacts, then score contacts against persona, seniority, function, geography, and intent fit.",
1664
+ "Return segment counts and review buckets before spend, copy, export, or launch."
1665
+ ],
1666
+ requiredFields: {
1667
+ segment: ["segment_name", "tier", "persona_priority", "buying_committee_role", "fit_reason", "exclusion_reason"],
1668
+ scoring: ["account_fit_score", "persona_fit_score", "segment_confidence", "review_bucket"]
1669
+ },
1670
+ qualityGates: [
1671
+ "Do not treat adjacent personas or verticals as matches unless the brief allows them.",
1672
+ "Keep ICP, persona, and exclusion evidence visible in the proof packet.",
1673
+ "Low-confidence segments route to review before contact discovery or copy."
1674
+ ],
1675
+ activationBoundary: "Segmentation is planning guidance. Paid sourcing, enrichment, export, and launch require the normal approval gates.",
1676
+ memoryKeywords: ["ICP design", "persona segmentation", "buying committee", "account tiers", "fit scoring", "vertical nuance"],
1677
+ 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"]
1678
+ },
1679
+ {
1680
+ slug: "buying-signal-prioritization",
1681
+ label: "Buying Signal Prioritization",
1682
+ whenToUse: [
1683
+ "The campaign depends on timing, intent, trigger events, or account prioritization.",
1684
+ "The operator wants why-now proof instead of generic list generation."
1685
+ ],
1686
+ sequence: [
1687
+ "Map the campaign goal to signal families, trigger freshness, and buyer-journey stage.",
1688
+ "Rank signals by relevance, recency, source quality, and persona-specific actionability.",
1689
+ "Attach evidence URLs or evidence summaries without exposing private memory rows.",
1690
+ "Use signal strength to decide source order, copy angle, and review priority."
1691
+ ],
1692
+ requiredFields: {
1693
+ signal: ["signal_type", "signal_date", "signal_source", "why_now", "signal_confidence", "buyer_stage"],
1694
+ prioritization: ["priority_score", "priority_reason", "next_best_action", "review_reason"]
1695
+ },
1696
+ qualityGates: [
1697
+ "Do not use stale, unsupported, or weak signals as personalization proof.",
1698
+ "Signal fit cannot override hard ICP, geography, suppression, or verified-email gates.",
1699
+ "Rows with uncertain why-now evidence must stay review-only."
1700
+ ],
1701
+ activationBoundary: "Signal ranking can prioritize review and copy. It does not approve outreach, sender loading, exports, or sends.",
1702
+ memoryKeywords: ["buying signals", "intent data", "funding trigger", "new executive", "tech adoption", "buyer journey", "why now"],
1703
+ 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"]
1704
+ },
1705
+ {
1706
+ slug: "multi-channel-sequence-fit",
1707
+ label: "Multi-Channel Sequence Fit",
1708
+ whenToUse: [
1709
+ "The campaign needs email, LinkedIn, call, webhook, CRM, or sequencer coordination.",
1710
+ "Copy and delivery should adapt by persona, channel, deliverability risk, and proof strength."
1711
+ ],
1712
+ sequence: [
1713
+ "Choose channel mix from persona, deal motion, evidence strength, deliverability constraints, and connected destination readiness.",
1714
+ "Draft sequence logic with email, LinkedIn, call, and task handoffs only where supported by the approved destination.",
1715
+ "Keep copy concise, proof-backed, channel-specific, and reviewable before delivery.",
1716
+ "Run deliverability and destination readiness checks before sender load or launch approval."
1717
+ ],
1718
+ requiredFields: {
1719
+ channel: ["channel", "touch_number", "persona_context", "message_angle", "channel_blocker", "approval_status"],
1720
+ deliverability: ["verified_email", "domain_risk", "send_window", "unsubscribe_risk", "sender_ready"]
1721
+ },
1722
+ qualityGates: [
1723
+ "Email copy must be row-supported and under the configured campaign tone/length limits.",
1724
+ "LinkedIn, phone, CRM, webhook, and sequencer actions remain destination-locked until approved.",
1725
+ "Deliverability risk or missing sender readiness blocks launch even when rows are qualified."
1726
+ ],
1727
+ activationBoundary: "Sequence strategy is draft-only. External writes, sender loading, launch, and sending need separate explicit approval.",
1728
+ memoryKeywords: ["outbound sequencing", "email personalization", "LinkedIn outreach", "cold calling", "multi-channel orchestration", "deliverability"],
1729
+ 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"]
1730
+ },
1731
+ {
1732
+ slug: "revops-feedback-loop",
1733
+ label: "RevOps Feedback Loop",
1734
+ whenToUse: [
1735
+ "The campaign should improve from replies, meetings, delivery results, CRM outcomes, or operator QA.",
1736
+ "The operator needs post-build monitoring, governance, or continuous ops follow-up."
1737
+ ],
1738
+ sequence: [
1739
+ "Define success metrics, guardrails, and feedback sources before launch.",
1740
+ "Collect aggregate outcomes, QA blockers, delivery health, and operator edits after each campaign phase.",
1741
+ "Separate workspace-private evidence from public-safe learnings and Brain defaults.",
1742
+ "Feed approved aggregate learnings back into future sourcing, qualification, copy, and suppression rules."
1743
+ ],
1744
+ requiredFields: {
1745
+ feedback: ["source", "event_type", "metric", "sample_size", "confidence", "learning_candidate"],
1746
+ governance: ["approval_owner", "last_reviewed_at", "risk_flag", "next_review_action"]
1747
+ },
1748
+ qualityGates: [
1749
+ "Do not write memory or Brain learnings from raw replies, private labels, or provider payloads without approved redaction.",
1750
+ "Use holdouts or pre/post comparisons before claiming causal lift.",
1751
+ "Delivery, suppression, and opt-out signals must update future gates before scale-up."
1752
+ ],
1753
+ activationBoundary: "Feedback review is read-only until memory writes, Brain writes, CRM updates, or campaign changes are explicitly approved.",
1754
+ memoryKeywords: ["RevOps", "feedback loop", "campaign learning", "reply outcomes", "sales marketing alignment", "data hygiene", "holdout"],
1755
+ 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"]
1536
1756
  }
1537
1757
  ];
1538
1758
  var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
@@ -1619,7 +1839,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
1619
1839
  agencyContext: {
1620
1840
  partnerEcosystem: ["signaliz", "instantly", "nango"]
1621
1841
  },
1622
- operatingPlaybookSlugs: ["net-new-suppressed-list", "proof-first-vertical-gate", "signal-led-copy-approval"]
1842
+ operatingPlaybookSlugs: [
1843
+ "net-new-suppressed-list",
1844
+ "proof-first-vertical-gate",
1845
+ "signal-led-copy-approval",
1846
+ "icp-persona-segmentation",
1847
+ "buying-signal-prioritization",
1848
+ "multi-channel-sequence-fit",
1849
+ "revops-feedback-loop"
1850
+ ]
1623
1851
  },
1624
1852
  {
1625
1853
  slug: "non-medical-home-care",
@@ -1692,7 +1920,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
1692
1920
  agencyContext: {
1693
1921
  partnerEcosystem: ["clay", "octave", "signaliz", "instantly", "nango"]
1694
1922
  },
1695
- operatingPlaybookSlugs: ["proof-first-vertical-gate", "domain-first-recovery", "table-workflow-handoff"]
1923
+ operatingPlaybookSlugs: [
1924
+ "proof-first-vertical-gate",
1925
+ "domain-first-recovery",
1926
+ "table-workflow-handoff",
1927
+ "icp-persona-segmentation",
1928
+ "buying-signal-prioritization",
1929
+ "multi-channel-sequence-fit",
1930
+ "revops-feedback-loop"
1931
+ ]
1696
1932
  },
1697
1933
  {
1698
1934
  slug: "agency-founder-led",
@@ -1753,7 +1989,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
1753
1989
  agencyContext: {
1754
1990
  partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
1755
1991
  },
1756
- operatingPlaybookSlugs: ["net-new-suppressed-list", "signal-led-copy-approval", "table-workflow-handoff"]
1992
+ operatingPlaybookSlugs: [
1993
+ "net-new-suppressed-list",
1994
+ "signal-led-copy-approval",
1995
+ "table-workflow-handoff",
1996
+ "icp-persona-segmentation",
1997
+ "buying-signal-prioritization",
1998
+ "multi-channel-sequence-fit",
1999
+ "revops-feedback-loop"
2000
+ ]
1757
2001
  },
1758
2002
  {
1759
2003
  slug: "cloud-infrastructure-displacement",
@@ -1840,7 +2084,15 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
1840
2084
  agencyContext: {
1841
2085
  partnerEcosystem: ["signaliz", "octave", "instantly", "nango"]
1842
2086
  },
1843
- operatingPlaybookSlugs: ["proof-first-vertical-gate", "domain-first-recovery", "signal-led-copy-approval"]
2087
+ operatingPlaybookSlugs: [
2088
+ "proof-first-vertical-gate",
2089
+ "domain-first-recovery",
2090
+ "signal-led-copy-approval",
2091
+ "icp-persona-segmentation",
2092
+ "buying-signal-prioritization",
2093
+ "multi-channel-sequence-fit",
2094
+ "revops-feedback-loop"
2095
+ ]
1844
2096
  }
1845
2097
  ];
1846
2098
  var CampaignBuilderAgent = class {
@@ -1871,6 +2123,9 @@ var CampaignBuilderAgent = class {
1871
2123
  const plan = await this.createPlan(request, options);
1872
2124
  return createCampaignBuilderReadiness(plan);
1873
2125
  }
2126
+ activeWorkContext(input) {
2127
+ return createCampaignBuilderActiveWorkContext(input);
2128
+ }
1874
2129
  async proof(request, options = {}) {
1875
2130
  const plan = await this.createPlan(request, options);
1876
2131
  const result = await this.dryRunPlan(plan, {
@@ -2255,9 +2510,10 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
2255
2510
  const estimatedCredits = estimateCredits(resolvedRequest, defaults, targetCount);
2256
2511
  const buildRequest = createBuildRequest(resolvedRequest, defaults, targetCount, campaignName, context.scopeBuildArgs, routes, memory, context.scopeBrainPreflight);
2257
2512
  const brainPreflight = asRecord(buildRequest.brainPreflight);
2513
+ const evidence = buildRequest.evidence ?? null;
2258
2514
  const approvals = deriveApprovals(resolvedRequest, routes, memory, estimatedCredits, defaults.delivery?.approvalRequired !== false);
2259
2515
  return {
2260
- planId: `cbp_${hashString(JSON.stringify({ goal: resolvedRequest.goal, campaignName, targetCount, routes }))}`,
2516
+ planId: `cbp_${hashString(JSON.stringify({ goal: resolvedRequest.goal, campaignName, targetCount, routes, evidence }))}`,
2261
2517
  campaignName,
2262
2518
  goal: resolvedRequest.goal,
2263
2519
  targetCount,
@@ -2272,6 +2528,7 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
2272
2528
  approvals,
2273
2529
  buildRequest,
2274
2530
  brainPreflight,
2531
+ evidence,
2275
2532
  operatingPlaybooks,
2276
2533
  mcpFlow: createMcpFlow(resolvedRequest, buildRequest, routes, memory, approvals),
2277
2534
  estimatedCredits,
@@ -2363,6 +2620,90 @@ function createCampaignBuilderReadiness(plan) {
2363
2620
  nextActions: campaignReadinessNextActions(plan, ready, customRoutes.length)
2364
2621
  };
2365
2622
  }
2623
+ function createCampaignBuilderActiveWorkContext(input) {
2624
+ const plan = input.readiness?.plan ?? input.plan;
2625
+ const remembered = input.remembered ?? {};
2626
+ const lastResult = asRecord(input.lastResult);
2627
+ const readinessBlockers = input.readiness?.summary.blockers ?? [];
2628
+ const explicitBlockers = input.blockers ?? [];
2629
+ const blockers = uniqueStrings([...explicitBlockers, ...readinessBlockers]);
2630
+ const warnings = uniqueStrings([
2631
+ ...input.warnings ?? [],
2632
+ ...input.readiness?.summary.warnings ?? [],
2633
+ ...plan?.warnings ?? []
2634
+ ]);
2635
+ const missingApprovals = plan ? (input.approval ? getMissingCampaignBuilderApprovals(plan, input.approval) : plan.approvals.filter((approval) => approval.blocking)).map((approval) => approval.type) : [];
2636
+ const refs = normalizeCampaignBuilderActiveWorkRefs({
2637
+ plan,
2638
+ remembered,
2639
+ refs: input.refs,
2640
+ lastResult
2641
+ });
2642
+ const state = inferCampaignBuilderActiveWorkState({
2643
+ plan,
2644
+ readiness: input.readiness,
2645
+ remembered,
2646
+ lastResult,
2647
+ blockers,
2648
+ missingApprovals
2649
+ });
2650
+ const nextSafeAction = campaignBuilderActiveWorkNextAction(state, blockers, missingApprovals, refs);
2651
+ const approvalPacket = createCampaignBuilderApprovalPacket(plan, input.approval, missingApprovals);
2652
+ const nextSafeMcpAction = campaignBuilderActiveWorkNextMcpAction({
2653
+ state,
2654
+ plan,
2655
+ refs,
2656
+ approvalPacket
2657
+ });
2658
+ const summary = {
2659
+ plan_id: plan?.planId ?? remembered.planId ?? null,
2660
+ campaign_name: plan?.campaignName ?? null,
2661
+ target_count: plan?.targetCount ?? null,
2662
+ gtm_campaign_id: plan?.buildRequest.gtmCampaignId ?? remembered.gtmCampaignId ?? null,
2663
+ campaign_build_id: stringValue(lastResult.campaign_build_id ?? lastResult.campaignBuildId) ?? remembered.campaignBuildId ?? null,
2664
+ provider_campaign_id: remembered.providerCampaignId ?? null
2665
+ };
2666
+ const approvalBoundary = campaignBuilderActiveWorkApprovalBoundary(missingApprovals, state);
2667
+ const conversationStarters = campaignBuilderActiveWorkConversationStarters({
2668
+ state,
2669
+ blockers,
2670
+ missingApprovals,
2671
+ refs,
2672
+ nextSafeAction
2673
+ });
2674
+ return {
2675
+ packet_version: "campaign-builder-active-work-context.v1",
2676
+ read_only: true,
2677
+ no_spend: true,
2678
+ no_provider_writes: true,
2679
+ private_safe: true,
2680
+ state,
2681
+ summary,
2682
+ refs,
2683
+ blockers,
2684
+ warnings,
2685
+ missing_approval_types: missingApprovals,
2686
+ approval_packet: approvalPacket,
2687
+ approval_boundary: approvalBoundary,
2688
+ next_safe_action: nextSafeAction,
2689
+ next_safe_mcp_action: nextSafeMcpAction,
2690
+ conversation_starters: conversationStarters,
2691
+ openai_agent_handoff: createCampaignBuilderOpenAiAgentHandoff({
2692
+ plan,
2693
+ state,
2694
+ summary,
2695
+ refs,
2696
+ blockers,
2697
+ warnings,
2698
+ missingApprovals,
2699
+ approvalPacket,
2700
+ approvalBoundary,
2701
+ nextSafeAction,
2702
+ nextSafeMcpAction,
2703
+ conversationStarters
2704
+ })
2705
+ };
2706
+ }
2366
2707
  function createCampaignBuilderProofReceipt(plan, result) {
2367
2708
  const strategyMemory = asRecord(plan.strategyMemoryStatus);
2368
2709
  const dryRunResult = asRecord(result);
@@ -2421,6 +2762,7 @@ function createCampaignBuilderProofReceipt(plan, result) {
2421
2762
  estimated_credits: plan.estimatedCredits,
2422
2763
  operating_playbooks: plan.operatingPlaybooks.map((playbook) => playbook.slug)
2423
2764
  },
2765
+ evidence: plan.evidence,
2424
2766
  gates,
2425
2767
  strategy_memory_status: summarizeCampaignBuilderProofStrategyMemory(strategyMemory),
2426
2768
  dry_run_result: summarizeCampaignBuilderProofDryRun(dryRunResult),
@@ -2469,6 +2811,56 @@ function getCampaignBuilderOperatingPlaybooksForRequest(request) {
2469
2811
  ]);
2470
2812
  return slugs.map(getCampaignBuilderOperatingPlaybook).filter((playbook) => Boolean(playbook));
2471
2813
  }
2814
+ function normalizeCampaignBuilderEvidence(evidence) {
2815
+ if (!evidence) return null;
2816
+ const attachmentSummary = (evidence.attachments ?? []).filter((attachment) => stringValue(attachment.name)).slice(0, 5).map((attachment) => ({
2817
+ name: stringValue(attachment.name) ?? "attachment",
2818
+ kind: stringValue(attachment.kind) ?? null,
2819
+ media_type: stringValue(attachment.mediaType) ?? null,
2820
+ redacted: attachment.redacted !== false,
2821
+ columns: uniqueStrings(attachment.columns ?? []).slice(0, 25),
2822
+ row_count: numberOrUndefined2(attachment.rowCount) ?? null,
2823
+ content_summary: stringValue(attachment.contentSummary)?.slice(0, 500) ?? null,
2824
+ evidence_fields: uniqueStrings(attachment.evidenceFields ?? []).slice(0, 25)
2825
+ }));
2826
+ const urlSummary = (evidence.urls ?? []).filter((url) => stringValue(url.url)).slice(0, 8).map((url) => {
2827
+ const rawUrl = stringValue(url.url) ?? "";
2828
+ return {
2829
+ url: rawUrl,
2830
+ host: stringValue(url.host) ?? hostFromUrl(rawUrl) ?? null,
2831
+ type: stringValue(url.type) ?? null,
2832
+ label: stringValue(url.label) ?? null,
2833
+ summary: stringValue(url.summary)?.slice(0, 500) ?? null,
2834
+ redacted: url.redacted === true
2835
+ };
2836
+ });
2837
+ const operatorNotes = uniqueStrings(evidence.notes ?? []).map((note) => note.slice(0, 240)).slice(0, 5);
2838
+ if (!attachmentSummary.length && !urlSummary.length && !operatorNotes.length) return null;
2839
+ return {
2840
+ packet_version: "campaign-builder-evidence.v1",
2841
+ private_safe: true,
2842
+ attachment_summary: attachmentSummary,
2843
+ url_summary: urlSummary,
2844
+ operator_notes: operatorNotes,
2845
+ 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.",
2846
+ raw_private_fields_withheld: [
2847
+ "raw_private_attachment_text",
2848
+ "raw_attachment_rows",
2849
+ "raw_leads",
2850
+ "email_addresses",
2851
+ "provider_auth_payloads",
2852
+ "copy_bodies",
2853
+ "secrets"
2854
+ ]
2855
+ };
2856
+ }
2857
+ function hostFromUrl(value) {
2858
+ try {
2859
+ return new URL(value).hostname || void 0;
2860
+ } catch {
2861
+ return void 0;
2862
+ }
2863
+ }
2472
2864
  function applyCampaignBuilderStrategyTemplate(request) {
2473
2865
  const template = getCampaignBuilderStrategyTemplate(request.strategyTemplate);
2474
2866
  if (!template) return request;
@@ -3160,7 +3552,7 @@ function normalizeMemory(request) {
3160
3552
  };
3161
3553
  }
3162
3554
  function defaultAgencyMemoryQueries(request, configured) {
3163
- const operatingPlaybookTerms = getCampaignBuilderOperatingPlaybooksForRequest(request).flatMap((playbook) => [playbook.label, ...playbook.memoryKeywords]).join(" ");
3555
+ const operatingPlaybookTerms = getCampaignBuilderOperatingPlaybooksForRequest(request).flatMap((playbook) => [playbook.label, ...playbook.memoryKeywords, ...playbook.knowledgeSources]).join(" ");
3164
3556
  const queries = [{
3165
3557
  query: request.goal,
3166
3558
  scopes: ["workspace", configured.useNetworkPatterns ? "network_patterns" : "operator_notes"],
@@ -3371,6 +3763,8 @@ function createBuildRequest(request, defaults, targetCount, campaignName, scopeB
3371
3763
  fillPolicy: "aggressive"
3372
3764
  }
3373
3765
  };
3766
+ const evidence = normalizeCampaignBuilderEvidence(request.evidence);
3767
+ if (evidence) buildRequest.evidence = evidence;
3374
3768
  const scoped = asRecord(scopeBuildArgs);
3375
3769
  buildRequest.gtmCampaignId = request.gtmCampaignId ?? stringValue(scoped.gtm_campaign_id ?? scoped.gtmCampaignId);
3376
3770
  buildRequest.learningHoldout = normalizeCampaignBuilderLearningHoldout(
@@ -3402,6 +3796,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
3402
3796
  memory.enabled ? "feedback" : void 0
3403
3797
  ]);
3404
3798
  const providerChain = uniqueStrings(["signaliz", ...request.preferredProviders ?? [], ...routes.map((route) => route.provider)]);
3799
+ const evidence = buildRequest.evidence ?? normalizeCampaignBuilderEvidence(request.evidence);
3405
3800
  const targetIcp = compact({
3406
3801
  personas: buildRequest.icp?.personas,
3407
3802
  industries: buildRequest.icp?.industries,
@@ -3414,6 +3809,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
3414
3809
  const learningArgs = compact({
3415
3810
  campaign_brief: request.goal,
3416
3811
  target_icp: targetIcp,
3812
+ evidence_context: evidence,
3417
3813
  layers,
3418
3814
  provider_chain: providerChain,
3419
3815
  lead_source: providerChain[0] ?? "signaliz",
@@ -3425,6 +3821,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
3425
3821
  const defaultsArgs = compact({
3426
3822
  campaign_brief: request.goal,
3427
3823
  target_icp: targetIcp,
3824
+ evidence_context: evidence,
3428
3825
  layers,
3429
3826
  include_global: memory.useNetworkPatterns,
3430
3827
  include_memory: memory.enabled,
@@ -3435,6 +3832,7 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
3435
3832
  provider_chain: providerChain,
3436
3833
  lead_source: providerChain[0] ?? "signaliz",
3437
3834
  target_icp: targetIcp,
3835
+ evidence_context: evidence,
3438
3836
  include_global: memory.useNetworkPatterns,
3439
3837
  limit: 25
3440
3838
  });
@@ -3447,9 +3845,11 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
3447
3845
  label: playbook.label,
3448
3846
  quality_gates: playbook.qualityGates,
3449
3847
  required_fields: playbook.requiredFields,
3450
- activation_boundary: playbook.activationBoundary
3848
+ activation_boundary: playbook.activationBoundary,
3849
+ knowledge_sources: playbook.knowledgeSources
3451
3850
  })),
3452
3851
  target_icp: targetIcp,
3852
+ evidence_context: evidence,
3453
3853
  provider_chain: providerChain,
3454
3854
  lead_source: providerChain[0] ?? "signaliz",
3455
3855
  learning_holdout: buildRequest.learningHoldout,
@@ -3722,7 +4122,7 @@ function createMcpFlow(request, buildRequest, routes, memory, approvals) {
3722
4122
  phase: "plan",
3723
4123
  tool: "nango_mcp_tools_list",
3724
4124
  arguments: {
3725
- format: "mcp"
4125
+ format: "openai"
3726
4126
  },
3727
4127
  readOnly: true,
3728
4128
  approvalRequired: false
@@ -4031,6 +4431,7 @@ function buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory) {
4031
4431
  layers: layers.length > 0 ? layers : void 0,
4032
4432
  preferred_providers: preferredProviders.length > 0 ? preferredProviders : void 0,
4033
4433
  strategy_model: strategyModel,
4434
+ evidence_context: buildRequest.evidence ?? normalizeCampaignBuilderEvidence(request.evidence),
4034
4435
  include_strategy_patterns: campaignBuilderStrategyPatternsEnabled(agencyContext),
4035
4436
  include_workflow_patterns: campaignBuilderWorkflowPatternsEnabled(agencyContext),
4036
4437
  include_nango_catalog: agencyContext.includeNangoCatalog !== false,
@@ -4039,7 +4440,8 @@ function buildGtmCampaignBuildPlanArgs(request, buildRequest, routes, memory) {
4039
4440
  slug: playbook.slug,
4040
4441
  label: playbook.label,
4041
4442
  quality_gates: playbook.qualityGates,
4042
- activation_boundary: playbook.activationBoundary
4443
+ activation_boundary: playbook.activationBoundary,
4444
+ knowledge_sources: playbook.knowledgeSources
4043
4445
  })),
4044
4446
  include_memory: memory.enabled,
4045
4447
  include_brain: true,
@@ -4132,6 +4534,7 @@ function buildCampaignArgs(request) {
4132
4534
  }
4133
4535
  if (request.campaignStrategyContext) args.campaign_strategy_context = request.campaignStrategyContext;
4134
4536
  if (request.deliveryRisk) args.delivery_risk = request.deliveryRisk;
4537
+ if (request.evidence) args.evidence_context = request.evidence;
4135
4538
  if (request.icp) {
4136
4539
  args.icp = compact({
4137
4540
  personas: request.icp.personas,
@@ -4181,7 +4584,8 @@ function buildCampaignArgs(request) {
4181
4584
  max_body_words: request.copy.maxBodyWords,
4182
4585
  sender_context: request.copy.senderContext,
4183
4586
  offer_context: request.copy.offerContext,
4184
- model: request.copy.model
4587
+ model: request.copy.model,
4588
+ evidence_mode: request.copy.evidenceMode
4185
4589
  });
4186
4590
  }
4187
4591
  if (request.delivery) {
@@ -4458,6 +4862,7 @@ function mapAgentCustomerRowCounts(value) {
4458
4862
  acceptedRows: numberOrUndefined2(record.accepted_rows),
4459
4863
  usableRows: numberOrUndefined2(record.usable_rows),
4460
4864
  copiedRows: numberOrUndefined2(record.copied_rows),
4865
+ copySkippedRows: numberOrUndefined2(record.copy_skipped_rows),
4461
4866
  approvalReadyRows: numberOrUndefined2(record.approval_ready_rows),
4462
4867
  qaReadyRows: numberOrUndefined2(record.qa_ready_rows),
4463
4868
  deliveredRows: numberOrUndefined2(record.delivered_rows),
@@ -4568,7 +4973,7 @@ function createCampaignBuilderNorthStarScorecard(status, rows, artifacts, termin
4568
4973
  const sampledRows = rows.rows.length;
4569
4974
  const rowData = rows.rows.map((row) => asRecord(row.data));
4570
4975
  const requestedTarget = status.customerRowCounts?.requestedTarget ?? status.recordsTotal ?? rows.count;
4571
- const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
4976
+ const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copySkippedRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
4572
4977
  const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
4573
4978
  const verifiedEmailRows = rowData.filter(campaignReviewDataHasVerifiedEmail).length;
4574
4979
  const uniqueEmails = new Set(rowData.map(campaignReviewDataEmail).filter(Boolean)).size;
@@ -5059,6 +5464,342 @@ function createCampaignBuilderReadinessLane(route, plan) {
5059
5464
  nextAction: customRoute ? `Review ${route.provider} route setup before launch approval.` : void 0
5060
5465
  };
5061
5466
  }
5467
+ function createCampaignBuilderApprovalPacket(plan, approval, missingTypes) {
5468
+ const requestedTypes = plan ? uniqueStrings(plan.approvals.filter((item) => item.blocking).map((item) => item.type)) : [];
5469
+ const approvalMatchesPlan = Boolean(plan && approval?.planId === plan.planId);
5470
+ const approvedTypes = approvalMatchesPlan ? approval?.approvedTypes ?? [] : [];
5471
+ const approvedRoutes = approvalMatchesPlan ? approval?.approvedRouteIds ?? [] : [];
5472
+ const missingIds = new Set(
5473
+ plan && approvalMatchesPlan && approval ? getMissingCampaignBuilderApprovals(plan, approval).map((item) => item.id) : plan?.approvals.filter((item) => item.blocking).map((item) => item.id) ?? []
5474
+ );
5475
+ const routeIdsRequired = plan ? uniqueStrings(plan.approvals.map((item) => item.routeId).filter((id) => Boolean(id))) : [];
5476
+ const spendLimitRequired = plan ? Math.max(0, ...plan.approvals.filter((item) => item.type === "spend" && item.blocking).map((item) => item.estimatedCredits ?? plan.estimatedCredits)) : 0;
5477
+ const normalizedSpendLimit = spendLimitRequired > 0 ? spendLimitRequired : null;
5478
+ const approvalState = !plan ? "unscoped" : missingTypes.length > 0 ? "requires_approval" : "approved";
5479
+ const approvalInput = {
5480
+ approved_by: approval?.approvedBy ?? null,
5481
+ approved_at: approval?.approvedAt ?? null,
5482
+ approved_types: approvedTypes,
5483
+ approved_route_ids: approvedRoutes,
5484
+ spend_limit_credits: approval?.spendLimitCredits ?? null,
5485
+ notes: approval?.notes
5486
+ };
5487
+ return {
5488
+ packet_version: "campaign-builder-approval-packet.v1",
5489
+ read_only: true,
5490
+ no_spend: true,
5491
+ no_provider_writes: true,
5492
+ private_safe: true,
5493
+ approval_state: approvalState,
5494
+ plan_id: plan?.planId ?? null,
5495
+ campaign_name: plan?.campaignName ?? null,
5496
+ requested_approval_types: requestedTypes,
5497
+ missing_approval_types: uniqueStrings(missingTypes),
5498
+ spend_limit_credits_required: normalizedSpendLimit,
5499
+ route_ids_required: routeIdsRequired,
5500
+ required_approvals: (plan?.approvals ?? []).map((item) => compact({
5501
+ id: item.id,
5502
+ type: item.type,
5503
+ label: item.label,
5504
+ reason: item.reason,
5505
+ blocking: item.blocking,
5506
+ route_id: item.routeId,
5507
+ provider: item.provider,
5508
+ estimated_credits: item.estimatedCredits,
5509
+ status: missingIds.has(item.id) ? "missing" : "approved"
5510
+ })),
5511
+ approval_input: approvalInput,
5512
+ cli_handoff: plan ? {
5513
+ command: campaignBuilderApprovalCliHandoff(requestedTypes, routeIdsRequired, normalizedSpendLimit),
5514
+ safety: "Template only: run after explicit human approval identity, approved types, route scope, and spend limit are filled in."
5515
+ } : null,
5516
+ sdk_handoff: plan ? {
5517
+ method: "campaignBuilderAgent.buildApprovedPlan",
5518
+ approval: compact({
5519
+ approvedBy: approval?.approvedBy ?? "<operator-email>",
5520
+ approvedTypes: requestedTypes,
5521
+ approvedRouteIds: routeIdsRequired,
5522
+ spendLimitCredits: normalizedSpendLimit ?? void 0,
5523
+ notes: approval?.notes
5524
+ }),
5525
+ options: {
5526
+ idempotencyKey: "<set-before-execution>"
5527
+ },
5528
+ safety: "Call only after the approval packet is accepted; this helper does not execute writes or spend."
5529
+ } : null,
5530
+ mcp_handoffs: plan ? campaignBuilderApprovalMcpHandoffs(plan, requestedTypes, routeIdsRequired, normalizedSpendLimit) : [],
5531
+ 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."
5532
+ };
5533
+ }
5534
+ function campaignBuilderApprovalCliHandoff(requestedTypes, routeIds, spendLimit) {
5535
+ return [
5536
+ "signaliz campaign-agent build-approved --request-file campaign-request.json --confirm-launch",
5537
+ requestedTypes.length > 0 ? `--approved-types ${shellArg(requestedTypes.join(","))}` : "--approve-all",
5538
+ "--approved-by <operator-email>",
5539
+ spendLimit !== null ? `--spend-limit ${spendLimit}` : void 0,
5540
+ routeIds.length > 0 ? `--approved-route-ids ${shellArg(routeIds.join(","))}` : void 0
5541
+ ].filter(Boolean).join(" ");
5542
+ }
5543
+ function campaignBuilderApprovalMcpHandoffs(plan, requestedTypes, routeIds, spendLimit) {
5544
+ const approvalContext = compact({
5545
+ plan_id: plan.planId,
5546
+ approval_types: requestedTypes,
5547
+ approved_route_ids: routeIds,
5548
+ spend_limit_credits: spendLimit,
5549
+ approved_by: "<operator-email>"
5550
+ });
5551
+ return plan.mcpFlow.filter((step) => ["execution-prepare", "approved-build", "delivery-approval"].includes(step.id)).map((step) => ({
5552
+ id: step.id,
5553
+ tool: step.tool,
5554
+ arguments: step.id === "approved-build" ? compact({ ...step.arguments, approval_context: approvalContext }) : step.arguments,
5555
+ read_only: step.readOnly,
5556
+ approval_required: step.approvalRequired,
5557
+ safety: step.readOnly ? "Read-only readiness handoff; safe to inspect before approval." : "Write-capable handoff; run only after the approval packet is accepted."
5558
+ }));
5559
+ }
5560
+ function campaignBuilderActiveWorkNextMcpAction(input) {
5561
+ const campaignBuildRef = input.refs.find((ref) => ref.kind === "campaign_build" && ref.id);
5562
+ if (campaignBuildRef) {
5563
+ return {
5564
+ id: "check-campaign-build-status",
5565
+ tool: "get_campaign_build_status",
5566
+ arguments: { campaign_build_id: campaignBuildRef.id },
5567
+ read_only: true,
5568
+ approval_required: false,
5569
+ safety: "Read-only status check for the remembered campaign build; does not spend, write, export, send, or approve anything."
5570
+ };
5571
+ }
5572
+ const campaignRef = input.refs.find((ref) => ref.kind === "gtm_campaign" && ref.id);
5573
+ if (campaignRef) {
5574
+ return {
5575
+ id: "check-gtm-campaign-status",
5576
+ tool: "gtm_campaign_execution_status",
5577
+ arguments: { campaign_id: campaignRef.id },
5578
+ read_only: true,
5579
+ approval_required: false,
5580
+ safety: "Read-only campaign execution status check; does not start or mutate the campaign."
5581
+ };
5582
+ }
5583
+ const preferredStepId = input.state === "ready_for_dry_run" ? "dry-run-build" : input.state === "planning" || input.state === "blocked" ? "agency-campaign-build-plan" : null;
5584
+ const preferredStep = preferredStepId ? input.plan?.mcpFlow.find((step) => step.id === preferredStepId && step.readOnly) : void 0;
5585
+ if (preferredStep) return campaignBuilderMcpStepToActiveWorkAction(preferredStep, "Read-only continuation from the saved campaign-agent plan.");
5586
+ const readOnlyApprovalHandoff = input.approvalPacket.mcp_handoffs.find((handoff) => handoff.read_only && !handoff.approval_required);
5587
+ if (readOnlyApprovalHandoff) return readOnlyApprovalHandoff;
5588
+ const firstReadOnlyPlanStep = input.plan?.mcpFlow.find((step) => step.readOnly && !step.approvalRequired);
5589
+ return firstReadOnlyPlanStep ? campaignBuilderMcpStepToActiveWorkAction(firstReadOnlyPlanStep, "Read-only saved plan check; safe before approvals or writes.") : null;
5590
+ }
5591
+ function campaignBuilderMcpStepToActiveWorkAction(step, safety) {
5592
+ return {
5593
+ id: step.id,
5594
+ tool: step.tool,
5595
+ arguments: step.arguments,
5596
+ read_only: step.readOnly,
5597
+ approval_required: step.approvalRequired,
5598
+ safety
5599
+ };
5600
+ }
5601
+ function normalizeCampaignBuilderActiveWorkRefs(input) {
5602
+ const refs = [];
5603
+ const pushRef = (ref) => {
5604
+ if (!ref?.id) return;
5605
+ refs.push(ref);
5606
+ };
5607
+ pushRef(input.plan?.planId ? { kind: "plan", id: input.plan.planId, label: input.plan.campaignName, source: "plan" } : void 0);
5608
+ pushRef(input.remembered.planId ? { kind: "plan", id: input.remembered.planId, source: "remembered" } : void 0);
5609
+ pushRef(
5610
+ input.plan?.buildRequest.gtmCampaignId ?? input.remembered.gtmCampaignId ? {
5611
+ kind: "gtm_campaign",
5612
+ id: input.plan?.buildRequest.gtmCampaignId ?? input.remembered.gtmCampaignId,
5613
+ label: input.plan?.campaignName,
5614
+ source: input.plan?.buildRequest.gtmCampaignId ? "plan" : "remembered"
5615
+ } : void 0
5616
+ );
5617
+ const campaignBuildId = stringValue(input.lastResult.campaign_build_id ?? input.lastResult.campaignBuildId) ?? input.remembered.campaignBuildId;
5618
+ pushRef(campaignBuildId ? { kind: "campaign_build", id: campaignBuildId, status: activeWorkStatus(input.lastResult) ?? input.remembered.status, source: "result" } : void 0);
5619
+ pushRef(
5620
+ input.remembered.providerCampaignId ? {
5621
+ kind: "provider_campaign",
5622
+ id: input.remembered.providerCampaignId,
5623
+ label: input.remembered.provider,
5624
+ status: input.remembered.status,
5625
+ source: "remembered"
5626
+ } : void 0
5627
+ );
5628
+ for (const ref of input.remembered.refs ?? []) pushRef(ref);
5629
+ for (const ref of input.refs ?? []) pushRef(ref);
5630
+ const seen = /* @__PURE__ */ new Set();
5631
+ return refs.filter((ref) => {
5632
+ const key = `${ref.kind}:${ref.id}`;
5633
+ if (seen.has(key)) return false;
5634
+ seen.add(key);
5635
+ return true;
5636
+ });
5637
+ }
5638
+ function inferCampaignBuilderActiveWorkState(input) {
5639
+ if (input.blockers.length > 0) return "blocked";
5640
+ const status = activeWorkStatus(input.lastResult) ?? input.remembered.status;
5641
+ const normalized = status?.toLowerCase();
5642
+ if (normalized && ["completed", "complete", "succeeded", "success", "done"].includes(normalized)) return "completed";
5643
+ if (normalized && ["queued", "running", "in_progress", "processing", "pending"].includes(normalized)) return "queued_or_running";
5644
+ const dryRunComplete = input.lastResult.dry_run === true || input.lastResult.dryRun === true || normalized === "dry_run";
5645
+ if (dryRunComplete) return input.missingApprovals.length > 0 ? "needs_approval" : "dry_run_complete";
5646
+ if (input.missingApprovals.length > 0) return "needs_approval";
5647
+ if (input.readiness?.summary.ready === true) return "ready_for_dry_run";
5648
+ if (input.plan) return "planning";
5649
+ return "unknown";
5650
+ }
5651
+ function campaignBuilderActiveWorkApprovalBoundary(missingApprovals, state) {
5652
+ if (missingApprovals.length > 0) {
5653
+ return `Blocked before spend, provider writes, delivery, or launch until approval covers: ${uniqueStrings(missingApprovals).join(", ")}.`;
5654
+ }
5655
+ if (state === "dry_run_complete" || state === "ready_for_dry_run") {
5656
+ return "Read-only planning and dry-runs are allowed; spend, provider writes, sender loading, delivery, and launch still require explicit approval.";
5657
+ }
5658
+ return "This packet is read-only and does not authorize spend, provider writes, sender loading, delivery, or launch.";
5659
+ }
5660
+ function campaignBuilderActiveWorkNextAction(state, blockers, missingApprovals, refs) {
5661
+ if (blockers.length > 0) return `Resolve blocker: ${blockers[0]}`;
5662
+ if (missingApprovals.length > 0) return `Ask the operator to approve ${uniqueStrings(missingApprovals).join(", ")} before any write or spend action.`;
5663
+ if (state === "ready_for_dry_run") return "Run or inspect the read-only campaign dry-run, then return the receipt for approval review.";
5664
+ if (state === "dry_run_complete") return "Review the dry-run receipt and collect explicit launch or delivery approval before any write action.";
5665
+ if (state === "queued_or_running") return "Poll the remembered campaign build or provider job status; do not start a duplicate job.";
5666
+ if (state === "completed") return "Review final artifacts and delivery gates before export, sync, sender load, or launch.";
5667
+ if (refs.length > 0) return "Use the remembered refs to fetch current read-only status before asking the operator for IDs.";
5668
+ return "Create or refresh a campaign-builder plan before taking any spendful or write action.";
5669
+ }
5670
+ function campaignBuilderActiveWorkConversationStarters(input) {
5671
+ const starters = [];
5672
+ if (input.blockers.length > 0) {
5673
+ starters.push(
5674
+ `I found a blocker: ${input.blockers[0]}. Want me to stay in read-only diagnostics and prepare the fix path?`
5675
+ );
5676
+ }
5677
+ if (input.missingApprovals.length > 0) {
5678
+ starters.push(
5679
+ `You still owe approval for ${uniqueStrings(input.missingApprovals).join(", ")}. Want the exact approval packet before anything writes or spends?`
5680
+ );
5681
+ }
5682
+ if (input.state === "queued_or_running") {
5683
+ const buildRef = input.refs.find((ref) => ref.kind === "campaign_build");
5684
+ 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.");
5685
+ }
5686
+ if (input.state === "dry_run_complete") {
5687
+ starters.push("The dry run is complete. Want me to summarize blockers, artifacts, and the approval handoff?");
5688
+ }
5689
+ if (input.state === "ready_for_dry_run") {
5690
+ starters.push("Everything is ready for a safe dry run. Want me to run the no-spend preview first?");
5691
+ }
5692
+ if (input.state === "completed") {
5693
+ starters.push("The build looks complete. Want me to review rows, artifacts, and delivery gates before export or send approval?");
5694
+ }
5695
+ starters.push(`Next safe action: ${input.nextSafeAction}`);
5696
+ return uniqueStrings(starters).slice(0, 4);
5697
+ }
5698
+ function createCampaignBuilderOpenAiAgentHandoff(input) {
5699
+ 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.")) ?? [];
5700
+ const routeSetupActions = readOnlyPlanActions.filter(
5701
+ (action) => action.tool === "gtm_provider_recipe_prepare" || action.tool === "gtm_provider_route_activate"
5702
+ );
5703
+ const safeReadActions = uniqueCampaignBuilderActiveWorkActions([
5704
+ input.nextSafeMcpAction,
5705
+ ...routeSetupActions,
5706
+ ...readOnlyPlanActions
5707
+ ]);
5708
+ const approvalGatedActions = uniqueCampaignBuilderActiveWorkActions([
5709
+ ...input.approvalPacket.mcp_handoffs.filter((action) => action.approval_required || !action.read_only),
5710
+ ...input.plan?.mcpFlow.filter((step) => step.approvalRequired || !step.readOnly).map((step) => campaignBuilderMcpStepToActiveWorkAction(step, "Approval-gated Signaliz MCP continuation for the saved campaign-agent plan.")) ?? []
5711
+ ]);
5712
+ const approvalTypes = uniqueStrings([
5713
+ ...input.missingApprovals,
5714
+ ...input.approvalPacket.requested_approval_types
5715
+ ]);
5716
+ return {
5717
+ packet_version: "campaign-builder-openai-agent-handoff.v1",
5718
+ surface: "openai_agents_sdk",
5719
+ agent: {
5720
+ name: "Signaliz GTM Campaign Agent",
5721
+ handoff_description: "Owns safe, conversational GTM campaign planning and continuation across Signaliz MCP, SDK, attachments, URLs, customer tools, approvals, and sender/export gates.",
5722
+ instructions: [
5723
+ "Be warm, direct, and expert-level GTM. Translate the current state into plain operator language before proposing work.",
5724
+ "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.",
5725
+ "Use attachment_summary, url_summary, and operator_notes as first-class planning evidence, while honoring the evidence privacy_boundary and withheld raw fields.",
5726
+ "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.",
5727
+ "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.",
5728
+ "When approval is missing, show the approval_packet and the exact missing approval scope before any side-effecting step."
5729
+ ],
5730
+ output_contract: [
5731
+ "current_state: one concise sentence describing where the campaign work stands.",
5732
+ "evidence_used: attachment, URL, memory, route, or integration evidence used without exposing private raw rows or secrets.",
5733
+ "next_safe_mcp_action: the read-only Signaliz MCP action to run next, or null when none is safe.",
5734
+ "approval_boundary: the human approval scope required before spend, provider writes, delivery, export, sender load, or launch.",
5735
+ "operator_reply: conversational GTM guidance with blockers, risks, and the safest next move."
5736
+ ]
5737
+ },
5738
+ context: {
5739
+ state: input.state,
5740
+ summary: input.summary,
5741
+ refs: input.refs,
5742
+ blockers: input.blockers,
5743
+ warnings: input.warnings,
5744
+ evidence_context: input.plan?.evidence ?? null,
5745
+ approval_packet: input.approvalPacket,
5746
+ approval_boundary: input.approvalBoundary,
5747
+ next_safe_action: input.nextSafeAction,
5748
+ conversation_starters: input.conversationStarters
5749
+ },
5750
+ tools: {
5751
+ mcp_server_label: "signaliz",
5752
+ remote_mcp_compatible: true,
5753
+ next_safe_mcp_action: input.nextSafeMcpAction,
5754
+ safe_read_tools: safeReadActions.map(
5755
+ (action) => campaignBuilderOpenAiAgentTool(action, "Safe read-only Signaliz MCP action available before approval.")
5756
+ ),
5757
+ approval_gated_tools: approvalGatedActions.map(
5758
+ (action) => campaignBuilderOpenAiAgentTool(action, "Requires explicit human review before execution.")
5759
+ )
5760
+ },
5761
+ guardrails: {
5762
+ input: [
5763
+ "Reject or pause requests to expose raw private attachment text, raw rows, leads, emails, provider payloads, copy bodies, API keys, or secrets.",
5764
+ "Pause when the user asks to spend credits, write to a provider, export, load a sender, deliver, or launch without explicit approval scope."
5765
+ ],
5766
+ tool: [
5767
+ "Read-only tools may run when they match safe_read_tools and their arguments match this packet.",
5768
+ "Any tool with approval_required=true or read_only=false requires human review and the approval_packet scope first."
5769
+ ],
5770
+ human_review_required_for: approvalTypes,
5771
+ 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."
5772
+ }
5773
+ };
5774
+ }
5775
+ function campaignBuilderOpenAiAgentTool(action, purpose) {
5776
+ return {
5777
+ id: action.id,
5778
+ type: "mcp",
5779
+ server_label: "signaliz",
5780
+ name: action.tool,
5781
+ arguments: action.arguments,
5782
+ read_only: action.read_only,
5783
+ approval_required: action.approval_required,
5784
+ purpose,
5785
+ safety: action.safety
5786
+ };
5787
+ }
5788
+ function uniqueCampaignBuilderActiveWorkActions(actions) {
5789
+ const seen = /* @__PURE__ */ new Set();
5790
+ const unique = [];
5791
+ for (const action of actions) {
5792
+ if (!action) continue;
5793
+ const key = `${action.id}:${action.tool}`;
5794
+ if (seen.has(key)) continue;
5795
+ seen.add(key);
5796
+ unique.push(action);
5797
+ }
5798
+ return unique;
5799
+ }
5800
+ function activeWorkStatus(record) {
5801
+ return stringValue(record.status ?? record.state ?? record.phase);
5802
+ }
5062
5803
  function campaignBuilderBuiltInForRoute(route) {
5063
5804
  return Object.entries(CAMPAIGN_BUILDER_BUILT_IN_ROUTE_IDS).find(([, routeId]) => route.id === routeId)?.[0];
5064
5805
  }
@@ -7855,6 +8596,36 @@ function recordsFromParams(params) {
7855
8596
  if (params.input) return { input: params.input };
7856
8597
  return { input: {} };
7857
8598
  }
8599
+ function toFusionConfig(params) {
8600
+ return {
8601
+ system_prompt: params.systemPrompt || params.system_prompt,
8602
+ user_template: params.userTemplate || params.user_template || params.prompt,
8603
+ preset: params.preset,
8604
+ temperature: params.temperature,
8605
+ max_tool_calls: params.maxToolCalls || params.max_tool_calls,
8606
+ max_tokens: params.maxTokens || params.max_tokens,
8607
+ timeout_ms: params.timeoutMs || params.timeout_ms,
8608
+ output_fields: params.outputFields || params.output_fields || [{ name: "response", type: "text", description: "Structured Fusion enrichment result" }]
8609
+ };
8610
+ }
8611
+ function toFusionSpendControls(params) {
8612
+ const controls = {};
8613
+ const dryRun = params.dryRun ?? params.dry_run;
8614
+ const confirmSpend = params.confirmSpend ?? params.confirm_spend;
8615
+ const maxCredits = params.maxCredits ?? params.max_credits;
8616
+ const maxCostUsd = params.maxCostUsd ?? params.max_cost_usd;
8617
+ if (dryRun !== void 0) controls.dry_run = dryRun;
8618
+ if (confirmSpend !== void 0) controls.confirm_spend = confirmSpend;
8619
+ if (maxCredits !== void 0) controls.max_credits = maxCredits;
8620
+ if (maxCostUsd !== void 0) controls.max_cost_usd = maxCostUsd;
8621
+ return controls;
8622
+ }
8623
+ function fusionRecordsFromParams(params) {
8624
+ const records = params.records || params.inputs;
8625
+ if (records?.length) return { records };
8626
+ if (params.input) return { input: params.input };
8627
+ return { input: {} };
8628
+ }
7858
8629
  var Ai = class {
7859
8630
  constructor(client) {
7860
8631
  this.client = client;
@@ -7888,6 +8659,33 @@ var Ai = class {
7888
8659
  raw: data
7889
8660
  };
7890
8661
  }
8662
+ /**
8663
+ * Plan or run experimental AI Enrichment Fusion with explicit spend controls.
8664
+ */
8665
+ async fusion(params) {
8666
+ if (!params.prompt && !params.userTemplate && !params.user_template) {
8667
+ throw new Error("prompt or userTemplate is required.");
8668
+ }
8669
+ const data = await this.client.post("ai-enrichment-fusion", {
8670
+ ...fusionRecordsFromParams(params),
8671
+ config: toFusionConfig(params),
8672
+ ...toFusionSpendControls(params)
8673
+ });
8674
+ return {
8675
+ success: data.success ?? false,
8676
+ capability: data.capability ?? "ai_enrichment_fusion",
8677
+ displayName: data.display_name ?? "AI Enrichment Fusion",
8678
+ results: data.results ?? [],
8679
+ creditsUsed: data.total_credits_used ?? data.credits_used ?? 0,
8680
+ model: data.model,
8681
+ fusion: data.fusion,
8682
+ tokensUsed: data.tokens_used ?? 0,
8683
+ costUsd: data.cost_usd ?? 0,
8684
+ costSummary: data.cost_summary,
8685
+ billingMetadata: data.billing_metadata,
8686
+ raw: data
8687
+ };
8688
+ }
7891
8689
  };
7892
8690
 
7893
8691
  // src/resources/gtm-kernel.ts
@@ -8427,6 +9225,24 @@ var GtmKernel = class {
8427
9225
  limit: input.limit
8428
9226
  });
8429
9227
  }
9228
+ /** Predict booked-meeting likelihood for uploaded, inline, or MCP-sourced lead rows without persisting raw rows. */
9229
+ async predictMeetingLikelihood(input) {
9230
+ return this.callMcp("gtm_predict_meeting_likelihood", {
9231
+ lead_rows: input.leadRows,
9232
+ input_source: input.inputSource,
9233
+ campaign_id: input.campaignId,
9234
+ campaign_build_id: input.campaignBuildId,
9235
+ days: input.days,
9236
+ feedback_limit: input.feedbackLimit,
9237
+ include_features: input.includeFeatures,
9238
+ include_global: input.includeGlobal,
9239
+ min_feedback_events: input.minFeedbackEvents,
9240
+ min_historical_feature_sample_size: input.minHistoricalFeatureSampleSize,
9241
+ min_workspace_count: input.minWorkspaceCount,
9242
+ min_privacy_k: input.minPrivacyK,
9243
+ limit: input.limit
9244
+ });
9245
+ }
8430
9246
  /** Rank provider-chain, ICP, source, copy, and sequence failure patterns without writing raw lead data. */
8431
9247
  async failurePatterns(options = {}) {
8432
9248
  return this.callMcp("gtm_brain_failure_patterns", {
@@ -9042,6 +9858,70 @@ function compact2(value) {
9042
9858
  return out;
9043
9859
  }
9044
9860
 
9861
+ // src/resources/public-ground-truth.ts
9862
+ var PublicGroundTruth = class {
9863
+ constructor(client) {
9864
+ this.client = client;
9865
+ }
9866
+ /**
9867
+ * Search the public-ground-truth cache by company/name/domain/native ID,
9868
+ * or by plain-language industry + location.
9869
+ * Results use the same snake_case wire shape returned by the hosted MCP API.
9870
+ */
9871
+ async search(params) {
9872
+ return this.client.mcp("tools/call", {
9873
+ name: "search_public_ground_truth",
9874
+ arguments: {
9875
+ query: params.query ?? params.search,
9876
+ industry: params.industry,
9877
+ location: params.location,
9878
+ source_id: params.sourceId ?? params.source_id,
9879
+ entity_type: params.entityType ?? params.entity_type,
9880
+ native_id: params.nativeId ?? params.native_id,
9881
+ entity_name: params.entityName ?? params.entity_name,
9882
+ domain: params.domain,
9883
+ website_url: params.websiteUrl ?? params.website_url,
9884
+ phone: params.phone,
9885
+ email: params.email,
9886
+ city: params.city,
9887
+ state: params.state,
9888
+ postal_code: params.postalCode ?? params.postal_code,
9889
+ country: params.country,
9890
+ source_url: params.sourceUrl ?? params.source_url,
9891
+ join_keys: params.joinKeys ?? params.join_keys,
9892
+ row_data: params.rowData ?? params.row_data,
9893
+ naics: params.naics,
9894
+ industry_code: params.industryCode ?? params.industry_code,
9895
+ industry_type: params.industryType ?? params.industry_type,
9896
+ year: params.year,
9897
+ quarter: params.quarter,
9898
+ area_fips: params.areaFips ?? params.area_fips,
9899
+ geo_id: params.geoId ?? params.geo_id,
9900
+ own_code: params.ownCode ?? params.own_code,
9901
+ source_updated_after: params.sourceUpdatedAfter ?? params.source_updated_after,
9902
+ source_updated_before: params.sourceUpdatedBefore ?? params.source_updated_before,
9903
+ observed_after: params.observedAfter ?? params.observed_after,
9904
+ observed_before: params.observedBefore ?? params.observed_before,
9905
+ limit: params.limit,
9906
+ offset: params.offset
9907
+ }
9908
+ });
9909
+ }
9910
+ /**
9911
+ * List available public-ground-truth cache sources and their join-key metadata.
9912
+ */
9913
+ async listSources(params = {}) {
9914
+ return this.client.mcp("tools/call", {
9915
+ name: "list_public_ground_truth_sources",
9916
+ arguments: {
9917
+ query: params.query ?? params.search,
9918
+ status: params.status,
9919
+ limit: params.limit
9920
+ }
9921
+ });
9922
+ }
9923
+ };
9924
+
9045
9925
  // src/index.ts
9046
9926
  var MCP_TOOL_CACHE_TTL_MS = 3e4;
9047
9927
  function inferMcpToolCategory(toolName) {
@@ -9084,6 +9964,7 @@ function inferMcpToolCategory(toolName) {
9084
9964
  }
9085
9965
  if (toolName.includes("icp")) return "icp";
9086
9966
  if (toolName.startsWith("ai_clean_")) return "data_cleaning";
9967
+ if (toolName.includes("public_ground_truth")) return "public_data";
9087
9968
  if (toolName.includes("system") || toolName.includes("workflow")) return "automation";
9088
9969
  if (toolName.includes("agent") || toolName.includes("platform_health") || toolName === "discover_capabilities") return "observability";
9089
9970
  return void 0;
@@ -9135,6 +10016,7 @@ var Signaliz = class {
9135
10016
  this.ops = new Ops(this.client);
9136
10017
  this.ai = new Ai(this.client);
9137
10018
  this.gtm = new GtmKernel(this.client);
10019
+ this.publicGroundTruth = new PublicGroundTruth(this.client);
9138
10020
  }
9139
10021
  /** Get current workspace info including credits */
9140
10022
  async getWorkspace() {