@signaliz/sdk 1.0.13 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -99,9 +99,24 @@ const readiness = await signaliz.campaignBuilderAgent.readiness({
99
99
  targetCount: 500,
100
100
  builtIns: ['lead_generation', 'local_leads', 'email_finding', 'email_verification', 'signals'],
101
101
  });
102
+ const proof = await signaliz.campaignBuilderAgent.proof({
103
+ goal: 'Build a strategy-template campaign for mature local operators',
104
+ strategyTemplate: 'non-medical-home-care',
105
+ targetCount: 25,
106
+ builtIns: ['lead_generation', 'local_leads', 'email_finding', 'email_verification', 'signals'],
107
+ });
108
+ const kit = signaliz.campaignBuilderAgent.buildKit({
109
+ goal: 'Build a strategy-template campaign for mature local operators',
110
+ strategyTemplate: 'non-medical-home-care',
111
+ targetCount: 250,
112
+ includeLocalLeads: true,
113
+ includeCustomToolPlaceholder: true,
114
+ });
102
115
 
103
116
  console.log(plan.strategyMemoryStatus?.ready);
104
117
  console.log(readiness.summary.ready);
118
+ console.log(proof.success);
119
+ console.log(kit.mcp_calls.find((call) => call.tool === 'gtm_campaign_agent_proof'));
105
120
  console.log(plan.mcpFlow.filter((step) =>
106
121
  ['gtm_provider_recipe_prepare', 'gtm_provider_route_activate'].includes(step.tool)
107
122
  ));
@@ -130,6 +145,13 @@ npx @signaliz/sdk campaign-agent init \
130
145
  --with-byo-placeholder \
131
146
  --output-file campaign-request.json
132
147
 
148
+ npx @signaliz/sdk campaign-agent kit \
149
+ --strategy-template non-medical-home-care \
150
+ --target-count 250 \
151
+ --use-local-leads \
152
+ --with-byo-placeholder \
153
+ --json
154
+
133
155
  npx @signaliz/sdk campaign-agent plan \
134
156
  --request-file campaign-request.json \
135
157
  --target-count 250 \
@@ -139,6 +161,11 @@ npx @signaliz/sdk campaign-agent doctor \
139
161
  --request-file campaign-request.json \
140
162
  --json
141
163
 
164
+ npx @signaliz/cli build "Build a strategy-template campaign for local operators" \
165
+ --strategy-template non-medical-home-care \
166
+ --target-count 25 \
167
+ --use-local-leads
168
+
142
169
  npx @signaliz/sdk campaign-agent status campaign_build_id --json
143
170
  npx @signaliz/sdk campaign-agent review campaign_build_id --limit 100 --json
144
171
  npx @signaliz/sdk campaign-agent rows campaign_build_id --limit 100 --json
@@ -1698,6 +1698,16 @@ var CampaignBuilderAgent = class {
1698
1698
  const plan = await this.createPlan(request, options);
1699
1699
  return createCampaignBuilderReadiness(plan);
1700
1700
  }
1701
+ async proof(request, options = {}) {
1702
+ const plan = await this.createPlan(request, options);
1703
+ const result = await this.dryRunPlan(plan, {
1704
+ idempotencyKey: options.idempotencyKey
1705
+ });
1706
+ return createCampaignBuilderProofReceipt(plan, result);
1707
+ }
1708
+ buildKit(options = {}) {
1709
+ return createCampaignBuilderBuildKit(options);
1710
+ }
1701
1711
  async commitPlan(plan, options = {}) {
1702
1712
  const writeMode = options.confirm === true && options.dryRun === false;
1703
1713
  if (writeMode && !options.approvedBy) {
@@ -2143,6 +2153,72 @@ function createCampaignBuilderReadiness(plan) {
2143
2153
  nextActions: campaignReadinessNextActions(plan, ready, customRoutes.length)
2144
2154
  };
2145
2155
  }
2156
+ function createCampaignBuilderProofReceipt(plan, result) {
2157
+ const strategyMemory = asRecord(plan.strategyMemoryStatus);
2158
+ const dryRunResult = asRecord(result);
2159
+ const memoryReady = plan.strategyMemoryStatus ? strategyMemory.ready !== false : false;
2160
+ const dryRunCompleted = dryRunResult.dryRun === true || dryRunResult.dry_run === true || dryRunResult.status === "dry_run";
2161
+ const noLaunch = dryRunCompleted && !dryRunResult.campaignBuildId && !dryRunResult.campaign_build_id;
2162
+ const gates = [
2163
+ {
2164
+ id: "strategy_memory_ready",
2165
+ passed: memoryReady,
2166
+ ready: strategyMemory.ready ?? null,
2167
+ blocker_count: Array.isArray(strategyMemory.blockers) ? strategyMemory.blockers.length : 0
2168
+ },
2169
+ {
2170
+ id: "campaign_plan_ready",
2171
+ passed: Boolean(plan.planId && plan.mcpFlow.length > 0),
2172
+ plan_id: plan.planId,
2173
+ flow_steps: plan.mcpFlow.length
2174
+ },
2175
+ {
2176
+ id: "approval_gates_present",
2177
+ passed: plan.approvals.length > 0,
2178
+ approval_types: plan.approvals.map((approval) => approval.type)
2179
+ },
2180
+ {
2181
+ id: "dry_run_completed",
2182
+ passed: dryRunCompleted,
2183
+ status: dryRunResult.status ?? null,
2184
+ current_phase: dryRunResult.currentPhase ?? dryRunResult.current_phase ?? null
2185
+ },
2186
+ {
2187
+ id: "no_spendful_launch",
2188
+ passed: noLaunch,
2189
+ campaign_build_id: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null
2190
+ }
2191
+ ];
2192
+ return {
2193
+ receipt_version: "campaign-agent-proof.v1",
2194
+ source: "signaliz.campaignBuilderAgent.proof",
2195
+ success: gates.every((gate) => gate.passed),
2196
+ safety: {
2197
+ spendful_tools_called: false,
2198
+ external_writes_called: false,
2199
+ sender_loads_called: false,
2200
+ email_sends_called: false,
2201
+ dry_run_only: true
2202
+ },
2203
+ campaign: {
2204
+ plan_id: plan.planId,
2205
+ campaign_name: plan.campaignName,
2206
+ strategy_template: campaignBuilderProofStrategyTemplate(plan),
2207
+ target_count: plan.targetCount,
2208
+ estimated_credits: plan.estimatedCredits,
2209
+ operating_playbooks: plan.operatingPlaybooks.map((playbook) => playbook.slug)
2210
+ },
2211
+ gates,
2212
+ strategy_memory_status: summarizeCampaignBuilderProofStrategyMemory(strategyMemory),
2213
+ dry_run_result: summarizeCampaignBuilderProofDryRun(dryRunResult),
2214
+ recommended_next_actions: [
2215
+ "Review the plan, approvals, and dry-run result.",
2216
+ "Use campaign-agent commit-plan --confirm-write only after review.",
2217
+ "Use campaign-agent build-approved only with --confirm-launch, approval identity, approval types, and spend limit.",
2218
+ "When an approved build reaches pending_approval, review rows and approve delivery through the Campaigns SDK."
2219
+ ]
2220
+ };
2221
+ }
2146
2222
  function getMissingCampaignBuilderApprovals(plan, approval) {
2147
2223
  if (approval.planId !== plan.planId) {
2148
2224
  return plan.approvals;
@@ -2296,6 +2372,156 @@ function createCampaignBuilderAgentRequestTemplate(input = {}) {
2296
2372
  }
2297
2373
  });
2298
2374
  }
2375
+ function createCampaignBuilderBuildKit(input = {}) {
2376
+ const requestFile = input.requestFile || "campaign-request.json";
2377
+ const cliPackage = input.cliPackage || "@signaliz/cli";
2378
+ const sdkPackage = input.sdkPackage || "@signaliz/sdk";
2379
+ const request = createCampaignBuilderAgentRequestTemplate(input);
2380
+ const strategyTemplate = stringValue(request.strategyTemplate) ?? null;
2381
+ const builtIns = request.builtIns ?? DEFAULT_CAMPAIGN_BUILDER_BUILT_INS;
2382
+ const useLocalLeads = builtIns.includes("local_leads");
2383
+ const customRoutes = [
2384
+ ...request.integrations ?? [],
2385
+ ...routesFromCustomerTools(request.customerTools ?? [])
2386
+ ].filter((route) => route.provider !== "signaliz");
2387
+ const strategyFlag = strategyTemplate ? ` --strategy-template ${shellArg(strategyTemplate)}` : "";
2388
+ const targetFlag = request.targetCount ? ` --target-count ${request.targetCount}` : "";
2389
+ const localLeadsFlag = useLocalLeads ? " --use-local-leads" : "";
2390
+ const cliBase = `npx ${cliPackage}`;
2391
+ const sdkCliBase = `npx ${sdkPackage}`;
2392
+ const brief = request.goal || "Build a strategy-template campaign for the target ICP.";
2393
+ const mcpArgs = campaignBuilderBuildKitMcpArgs(request);
2394
+ return {
2395
+ kit_version: "campaign-builder-kit.v1",
2396
+ source: "signaliz.campaignBuilderAgent.buildKit",
2397
+ request_file: requestFile,
2398
+ request,
2399
+ strategy_template: strategyTemplate,
2400
+ built_in_lanes: builtIns,
2401
+ operating_playbooks: getCampaignBuilderOperatingPlaybooksForRequest(request).map((playbook) => playbook.slug),
2402
+ custom_routes: customRoutes.map((route) => ({
2403
+ provider: String(route.provider),
2404
+ layer: String(route.layer),
2405
+ tool: firstNonEmptyString(route.toolName),
2406
+ mcp_server: firstNonEmptyString(route.mcpServerName),
2407
+ mode: route.mode ?? "if_available",
2408
+ approval_required: route.approvalRequired === true || route.mode === "required"
2409
+ })),
2410
+ approval_boundaries: request.approvalPolicy?.requireApprovalFor ?? DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES,
2411
+ byo_tool_pattern: {
2412
+ cli_flag: "--custom-tool provider:layer:tool[:mcp]",
2413
+ request_fragment: createCampaignBuilderToolRoute({
2414
+ provider: "workspace_mcp",
2415
+ layer: "enrichment",
2416
+ gtmLayers: ["company_enrichment"],
2417
+ toolName: "workspace_account_enrich",
2418
+ mcpServerName: "workspace-mcp",
2419
+ label: "Workspace account enrichment",
2420
+ mode: "required",
2421
+ approvalRequired: true
2422
+ })
2423
+ },
2424
+ cli_commands: [
2425
+ {
2426
+ id: "write_request",
2427
+ label: "Write reusable request JSON",
2428
+ command: `${cliBase} campaign-agent init${strategyFlag}${targetFlag}${localLeadsFlag} --output-file ${shellArg(requestFile)}`,
2429
+ safety: "local file only; no MCP calls, credits, provider writes, sender loads, exports, or sends"
2430
+ },
2431
+ {
2432
+ id: "proof_shortcut",
2433
+ label: "Run no-spend campaign-builder proof",
2434
+ command: `${cliBase} build ${shellArg(brief)}${strategyFlag}${targetFlag}${localLeadsFlag} --json`,
2435
+ safety: "strategy memory, Kernel plan, approvals, and forced build_campaign dry-run only"
2436
+ },
2437
+ {
2438
+ id: "plan",
2439
+ label: "Inspect the full campaign-agent plan",
2440
+ command: `${sdkCliBase} campaign-agent plan --request-file ${shellArg(requestFile)} --json`,
2441
+ safety: "read-only MCP planning and provider-route dry-runs"
2442
+ },
2443
+ {
2444
+ id: "doctor",
2445
+ label: "Check readiness gates",
2446
+ command: `${sdkCliBase} campaign-agent doctor --request-file ${shellArg(requestFile)} --json`,
2447
+ safety: "read-only readiness checks for Memory, Brain, built-ins, BYO routes, and approvals"
2448
+ },
2449
+ {
2450
+ id: "commit_preview",
2451
+ label: "Preview GTM campaign object commit",
2452
+ command: `${sdkCliBase} campaign-agent commit-plan --request-file ${shellArg(requestFile)} --json`,
2453
+ safety: "dry-run commit; writes only with --confirm-write and --approved-by"
2454
+ },
2455
+ {
2456
+ id: "approved_launch",
2457
+ label: "Launch after explicit approval",
2458
+ command: `${sdkCliBase} campaign-agent build-approved --request-file ${shellArg(requestFile)} --confirm-launch --approve-all --approved-by operator@example.com --spend-limit ${request.signalizDefaults?.maxCredits ?? 0} --json`,
2459
+ safety: "spendful path; requires human approval identity, approval types, and spend limit"
2460
+ }
2461
+ ],
2462
+ mcp_calls: [
2463
+ {
2464
+ id: "request_template",
2465
+ tool: "gtm_campaign_agent_request_template",
2466
+ arguments: mcpArgs,
2467
+ safety: "read-only reusable request generation"
2468
+ },
2469
+ {
2470
+ id: "readiness",
2471
+ tool: "gtm_campaign_agent_readiness",
2472
+ arguments: mcpArgs,
2473
+ safety: "read-only preflight across strategy memory, Kernel plan, lanes, routes, and approvals"
2474
+ },
2475
+ {
2476
+ id: "proof",
2477
+ tool: "gtm_campaign_agent_proof",
2478
+ arguments: { ...mcpArgs, idempotency_key: "campaign-agent-proof-001" },
2479
+ safety: "forces build_campaign dry_run=true and confirm_spend=false"
2480
+ },
2481
+ {
2482
+ id: "plan",
2483
+ tool: "gtm_campaign_agent_plan",
2484
+ arguments: mcpArgs,
2485
+ safety: "read-only one-call campaign-agent runbook"
2486
+ },
2487
+ {
2488
+ id: "commit_preview",
2489
+ tool: "gtm_campaign_build_plan_commit",
2490
+ arguments: {
2491
+ name: request.campaignName,
2492
+ campaign_brief: request.goal,
2493
+ lead_count: request.targetCount,
2494
+ dry_run: true,
2495
+ confirm: false
2496
+ },
2497
+ safety: "dry-run commit preview only"
2498
+ }
2499
+ ],
2500
+ sdk_example: {
2501
+ language: "typescript",
2502
+ code: campaignBuilderBuildKitSdkExample(request, requestFile)
2503
+ },
2504
+ verification: [
2505
+ `${cliBase} campaign-agent proof --request-file ${shellArg(requestFile)} --json`,
2506
+ `${cliBase} campaign-agent doctor --request-file ${shellArg(requestFile)} --json`,
2507
+ "Confirm proof.success is true and dry_run_result.status is dry_run before any approved launch.",
2508
+ "Confirm no campaign_build_id exists in a proof receipt before moving to approved launch."
2509
+ ],
2510
+ privacy: {
2511
+ client_names_allowed: false,
2512
+ notes: [
2513
+ "Use strategy templates, operating playbooks, and anonymized workflow patterns instead of client names.",
2514
+ "Do not include raw leads, private replies, domains, secrets, or customer account labels in public kit output."
2515
+ ]
2516
+ },
2517
+ next_actions: [
2518
+ `Write or review ${requestFile}.`,
2519
+ "Run the proof command before spending credits or activating provider writes.",
2520
+ "Add BYO integrations with --custom-tool provider:layer:tool[:mcp] or the request_fragment shape.",
2521
+ "Use build-approved only after human approval, spend limit, and delivery review policy are set."
2522
+ ]
2523
+ };
2524
+ }
2299
2525
  function createCampaignBuilderToolRoute(input) {
2300
2526
  return {
2301
2527
  provider: input.provider ?? "custom_mcp",
@@ -2311,6 +2537,63 @@ function createCampaignBuilderToolRoute(input) {
2311
2537
  rationale: `${input.label ?? input.provider ?? "Custom tool"} is a user-provided campaign-builder route for ${input.layer}.`
2312
2538
  };
2313
2539
  }
2540
+ function campaignBuilderBuildKitMcpArgs(request) {
2541
+ return compact({
2542
+ goal: request.goal,
2543
+ campaign_brief: request.goal,
2544
+ campaign_name: request.campaignName,
2545
+ account_label: request.accountLabel,
2546
+ account_context: request.accountContext,
2547
+ strategy_template: request.strategyTemplate,
2548
+ operating_playbooks: request.operatingPlaybooks,
2549
+ target_icp: request.icp,
2550
+ target_count: request.targetCount,
2551
+ builtins: request.builtIns,
2552
+ include_local_leads: request.builtIns?.includes("local_leads") || void 0,
2553
+ preferred_providers: request.preferredProviders,
2554
+ custom_tools: request.integrations?.map((route) => compact({
2555
+ provider: route.provider,
2556
+ layer: route.layer,
2557
+ gtm_layers: route.gtmLayers ?? (route.gtmLayer ? [route.gtmLayer] : void 0),
2558
+ tool: route.toolName,
2559
+ mcp: route.mcpServerName,
2560
+ mode: route.mode,
2561
+ approval_required: route.approvalRequired
2562
+ })),
2563
+ include_nango_catalog: request.agencyContext?.includeNangoCatalog,
2564
+ include_memory: request.memory?.enabled,
2565
+ include_brain: true,
2566
+ include_provider_routes: true,
2567
+ include_delivery_risk: true
2568
+ });
2569
+ }
2570
+ function campaignBuilderBuildKitSdkExample(request, requestFile) {
2571
+ const proofRequest = {
2572
+ goal: request.goal,
2573
+ strategyTemplate: request.strategyTemplate,
2574
+ targetCount: request.targetCount,
2575
+ builtIns: request.builtIns,
2576
+ integrations: request.integrations
2577
+ };
2578
+ return [
2579
+ "import { Signaliz, createCampaignBuilderBuildKit } from '@signaliz/sdk';",
2580
+ "",
2581
+ `const kit = createCampaignBuilderBuildKit({ requestFile: ${JSON.stringify(requestFile)}, ...${JSON.stringify(proofRequest, null, 2)} });`,
2582
+ "console.log(kit.cli_commands.find((command) => command.id === 'proof_shortcut')?.command);",
2583
+ "",
2584
+ "const signaliz = new Signaliz({ apiKey: process.env.SIGNALIZ_API_KEY! });",
2585
+ "const proof = await signaliz.campaignBuilderAgent.proof(kit.request, {",
2586
+ " idempotencyKey: `campaign-agent-proof-${Date.now()}`,",
2587
+ "});",
2588
+ "",
2589
+ 'if (!proof.success || proof.dry_run_result?.status !== "dry_run") {',
2590
+ " throw new Error('Campaign proof failed or launched work unexpectedly');",
2591
+ "}"
2592
+ ].join("\n");
2593
+ }
2594
+ function shellArg(value) {
2595
+ return `'${value.replace(/'/g, "'\\''")}'`;
2596
+ }
2314
2597
  function normalizeTemplateKey(value) {
2315
2598
  return String(value || "").trim().toLowerCase().replace(/[_\s]+/g, "-");
2316
2599
  }
@@ -3585,6 +3868,72 @@ function campaignReadinessNextActions(plan, ready, customRouteCount) {
3585
3868
  ];
3586
3869
  return actions.filter((item) => Boolean(item));
3587
3870
  }
3871
+ function campaignBuilderProofStrategyTemplate(plan) {
3872
+ const buildRequest = asRecord(plan.buildRequest);
3873
+ const strategyMemory = asRecord(plan.strategyMemoryStatus);
3874
+ const statusTemplate = strategyMemory.strategy_template ?? strategyMemory.strategyTemplate;
3875
+ const statusTemplateRecord = asRecord(statusTemplate);
3876
+ const flowTemplate = plan.mcpFlow.map((step) => asRecord(step.arguments).strategy_template ?? asRecord(step.arguments).strategyTemplate).find((value) => typeof value === "string" && value.trim());
3877
+ return firstNonEmptyString(
3878
+ buildRequest.strategyTemplate,
3879
+ buildRequest.strategy_template,
3880
+ statusTemplate,
3881
+ statusTemplateRecord.slug,
3882
+ statusTemplateRecord.id,
3883
+ flowTemplate
3884
+ );
3885
+ }
3886
+ function summarizeCampaignBuilderProofStrategyMemory(strategyMemory) {
3887
+ if (Object.keys(strategyMemory).length === 0) return { ready: false };
3888
+ const template = strategyMemory.strategy_template ?? strategyMemory.strategyTemplate;
3889
+ const templateRecord = asRecord(template);
3890
+ const coverage = asRecord(strategyMemory.coverage);
3891
+ const rawSourceGroups = Array.isArray(strategyMemory.source_groups) ? strategyMemory.source_groups : Array.isArray(strategyMemory.sourceGroups) ? strategyMemory.sourceGroups : [];
3892
+ const sourceGroups = rawSourceGroups.map((group) => {
3893
+ const sourceGroup = asRecord(group);
3894
+ return {
3895
+ id: sourceGroup.id ?? null,
3896
+ required: sourceGroup.required ?? null,
3897
+ ready: sourceGroup.ready ?? null,
3898
+ counts: asRecord(sourceGroup.counts)
3899
+ };
3900
+ });
3901
+ return {
3902
+ ready: strategyMemory.ready ?? null,
3903
+ read_only: strategyMemory.read_only ?? strategyMemory.readOnly ?? null,
3904
+ source_tool: firstNonEmptyString(strategyMemory.source_tool, strategyMemory.sourceTool),
3905
+ strategy_template: {
3906
+ slug: firstNonEmptyString(template, templateRecord.slug, templateRecord.id),
3907
+ label: firstNonEmptyString(templateRecord.label)
3908
+ },
3909
+ coverage: {
3910
+ required_groups_ready: coverage.required_groups_ready ?? coverage.requiredGroupsReady ?? null,
3911
+ required_groups_total: coverage.required_groups_total ?? coverage.requiredGroupsTotal ?? null,
3912
+ source_groups_ready: coverage.source_groups_ready ?? coverage.sourceGroupsReady ?? null,
3913
+ source_groups_total: coverage.source_groups_total ?? coverage.sourceGroupsTotal ?? null,
3914
+ knowledge_docs: coverage.knowledge_docs ?? coverage.knowledgeDocs ?? null,
3915
+ memories: coverage.memories ?? null
3916
+ },
3917
+ source_groups: sourceGroups,
3918
+ blocker_count: Array.isArray(strategyMemory.blockers) ? strategyMemory.blockers.length : 0,
3919
+ warning_count: Array.isArray(strategyMemory.warnings) ? strategyMemory.warnings.length : 0
3920
+ };
3921
+ }
3922
+ function summarizeCampaignBuilderProofDryRun(dryRunResult) {
3923
+ return {
3924
+ dryRun: dryRunResult.dryRun ?? dryRunResult.dry_run ?? null,
3925
+ status: dryRunResult.status ?? null,
3926
+ currentPhase: dryRunResult.currentPhase ?? dryRunResult.current_phase ?? null,
3927
+ campaignBuildId: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null,
3928
+ plannedTargetCount: dryRunResult.plannedTargetCount ?? dryRunResult.planned_target_count ?? null
3929
+ };
3930
+ }
3931
+ function firstNonEmptyString(...values) {
3932
+ for (const value of values) {
3933
+ if (typeof value === "string" && value.trim()) return value;
3934
+ }
3935
+ return null;
3936
+ }
3588
3937
  function diagnosticMessages2(value) {
3589
3938
  if (!Array.isArray(value)) return [];
3590
3939
  return value.map((item) => {
@@ -6596,6 +6945,7 @@ export {
6596
6945
  CampaignBuilderAgent,
6597
6946
  createCampaignBuilderAgentPlan,
6598
6947
  createCampaignBuilderReadiness,
6948
+ createCampaignBuilderProofReceipt,
6599
6949
  getMissingCampaignBuilderApprovals,
6600
6950
  createCampaignBuilderApproval,
6601
6951
  getCampaignBuilderStrategyTemplate,
@@ -6603,6 +6953,7 @@ export {
6603
6953
  getCampaignBuilderOperatingPlaybooksForRequest,
6604
6954
  applyCampaignBuilderStrategyTemplate,
6605
6955
  createCampaignBuilderAgentRequestTemplate,
6956
+ createCampaignBuilderBuildKit,
6606
6957
  createCampaignBuilderToolRoute,
6607
6958
  Icps,
6608
6959
  normalizeExecutionReference,