@signaliz/sdk 1.0.11 → 1.0.13
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 +16 -0
- package/dist/{chunk-QQW6DZQ4.mjs → chunk-DJVOGXVD.mjs} +285 -0
- package/dist/cli.js +389 -6
- package/dist/cli.mjs +106 -7
- package/dist/index.d.mts +78 -1
- package/dist/index.d.ts +78 -1
- package/dist/index.js +286 -0
- package/dist/index.mjs +3 -1
- package/dist/mcp-config.js +284 -0
- package/dist/mcp-config.mjs +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1197,6 +1197,13 @@ var DEFAULT_CAMPAIGN_BUILDER_BUILT_INS = [
|
|
|
1197
1197
|
"email_verification",
|
|
1198
1198
|
"signals"
|
|
1199
1199
|
];
|
|
1200
|
+
var CAMPAIGN_BUILDER_BUILT_IN_ROUTE_IDS = {
|
|
1201
|
+
lead_generation: "signaliz-lead-generation",
|
|
1202
|
+
local_leads: "signaliz-local-leads",
|
|
1203
|
+
email_finding: "signaliz-email-finding",
|
|
1204
|
+
email_verification: "signaliz-email-verification",
|
|
1205
|
+
signals: "signaliz-signals"
|
|
1206
|
+
};
|
|
1200
1207
|
var DEFAULT_CAMPAIGN_BUILDER_APPROVAL_TYPES = [
|
|
1201
1208
|
"memory_retrieval",
|
|
1202
1209
|
"spend",
|
|
@@ -1693,6 +1700,10 @@ var CampaignBuilderAgent = class {
|
|
|
1693
1700
|
}
|
|
1694
1701
|
return plan;
|
|
1695
1702
|
}
|
|
1703
|
+
async readiness(request, options = {}) {
|
|
1704
|
+
const plan = await this.createPlan(request, options);
|
|
1705
|
+
return createCampaignBuilderReadiness(plan);
|
|
1706
|
+
}
|
|
1696
1707
|
async commitPlan(plan, options = {}) {
|
|
1697
1708
|
const writeMode = options.confirm === true && options.dryRun === false;
|
|
1698
1709
|
if (writeMode && !options.approvedBy) {
|
|
@@ -1880,6 +1891,15 @@ var CampaignBuilderAgent = class {
|
|
|
1880
1891
|
async approveDelivery(campaignBuildId, destinationType, options) {
|
|
1881
1892
|
return this.approveCampaignDelivery(campaignBuildId, destinationType, options);
|
|
1882
1893
|
}
|
|
1894
|
+
async reviewBuild(campaignBuildId, options = {}) {
|
|
1895
|
+
const status = await this.getBuildStatus(campaignBuildId);
|
|
1896
|
+
const rows = await this.getBuildRows(campaignBuildId, {
|
|
1897
|
+
...options,
|
|
1898
|
+
limit: options.limit ?? 100
|
|
1899
|
+
});
|
|
1900
|
+
const artifacts = await this.listBuildArtifacts(campaignBuildId);
|
|
1901
|
+
return createCampaignBuilderBuildReview(status, rows, artifacts);
|
|
1902
|
+
}
|
|
1883
1903
|
async getCampaignBuildStatus(campaignBuildId) {
|
|
1884
1904
|
const data = await this.callMcp("get_campaign_build_status", {
|
|
1885
1905
|
campaign_build_id: campaignBuildId
|
|
@@ -2044,6 +2064,91 @@ function createCampaignBuilderAgentPlan(request, context = {}) {
|
|
|
2044
2064
|
warnings: context.warnings ?? []
|
|
2045
2065
|
};
|
|
2046
2066
|
}
|
|
2067
|
+
function createCampaignBuilderReadiness(plan) {
|
|
2068
|
+
const lanes = plan.routes.map((route) => createCampaignBuilderReadinessLane(route, plan));
|
|
2069
|
+
const builtInLanes = lanes.filter((lane) => lane.builtIn);
|
|
2070
|
+
const customRoutes = lanes.filter((lane) => lane.customRoute);
|
|
2071
|
+
const strategyMemory = asRecord(plan.strategyMemoryStatus);
|
|
2072
|
+
const deliveryRisk = asRecord(plan.buildRequest.deliveryRisk);
|
|
2073
|
+
const deliveryRiskBlockers = arrayOfStrings(deliveryRisk.blockers) ?? [];
|
|
2074
|
+
const deliveryRiskValue = asRecord(deliveryRisk.risk);
|
|
2075
|
+
const deliveryRiskLevel = stringValue(deliveryRiskValue.risk_level ?? deliveryRiskValue.riskLevel);
|
|
2076
|
+
const memoryReady = !plan.strategyMemoryStatus || strategyMemory.ready !== false;
|
|
2077
|
+
const kernelPlanReady = Object.keys(asRecord(plan.kernelPlan)).length > 0;
|
|
2078
|
+
const deliveryRiskReady = !plan.buildRequest.deliveryRisk || deliveryRiskBlockers.length === 0 && !["high", "critical", "blocked"].includes(String(deliveryRiskLevel ?? "").toLowerCase());
|
|
2079
|
+
const builtInsReady = builtInLanes.length > 0 && builtInLanes.every((lane) => lane.ready);
|
|
2080
|
+
const customRoutesReady = customRoutes.every((lane) => lane.ready);
|
|
2081
|
+
const approvalGatesReady = plan.approvals.length > 0;
|
|
2082
|
+
const gates = [
|
|
2083
|
+
{
|
|
2084
|
+
id: "campaign_plan_created",
|
|
2085
|
+
label: "Campaign plan created",
|
|
2086
|
+
passed: Boolean(plan.planId && plan.mcpFlow.length > 0),
|
|
2087
|
+
detail: plan.planId ? `Plan ${plan.planId} has ${plan.mcpFlow.length} MCP step(s).` : "No campaign-builder plan was created."
|
|
2088
|
+
},
|
|
2089
|
+
{
|
|
2090
|
+
id: "built_in_lanes_ready",
|
|
2091
|
+
label: "Built-in lanes ready",
|
|
2092
|
+
passed: builtInsReady,
|
|
2093
|
+
detail: `${builtInLanes.filter((lane) => lane.ready).length}/${builtInLanes.length} Signaliz built-in lane(s) are present.`
|
|
2094
|
+
},
|
|
2095
|
+
{
|
|
2096
|
+
id: "strategy_memory_ready",
|
|
2097
|
+
label: "Strategy memory ready",
|
|
2098
|
+
passed: memoryReady,
|
|
2099
|
+
detail: plan.strategyMemoryStatus ? "Strategy memory readiness was checked." : "Strategy memory readiness was not requested."
|
|
2100
|
+
},
|
|
2101
|
+
{
|
|
2102
|
+
id: "kernel_plan_attached",
|
|
2103
|
+
label: "Kernel plan attached",
|
|
2104
|
+
passed: kernelPlanReady,
|
|
2105
|
+
detail: kernelPlanReady ? "Kernel planner evidence is attached." : "Kernel planner evidence is not attached."
|
|
2106
|
+
},
|
|
2107
|
+
{
|
|
2108
|
+
id: "delivery_risk_clear",
|
|
2109
|
+
label: "Delivery risk clear",
|
|
2110
|
+
passed: deliveryRiskReady,
|
|
2111
|
+
detail: plan.buildRequest.deliveryRisk ? `Delivery risk is ${deliveryRiskLevel || "available"} with ${deliveryRiskBlockers.length} blocker(s).` : "Delivery risk preflight was not requested."
|
|
2112
|
+
},
|
|
2113
|
+
{
|
|
2114
|
+
id: "custom_routes_prepared",
|
|
2115
|
+
label: "Custom routes prepared",
|
|
2116
|
+
passed: customRoutesReady,
|
|
2117
|
+
detail: customRoutes.length === 0 ? "No BYO routes were requested." : `${customRoutes.filter((lane) => lane.ready).length}/${customRoutes.length} BYO route(s) have read-only setup steps.`
|
|
2118
|
+
},
|
|
2119
|
+
{
|
|
2120
|
+
id: "approval_gates_present",
|
|
2121
|
+
label: "Approval gates present",
|
|
2122
|
+
passed: approvalGatesReady,
|
|
2123
|
+
detail: approvalGatesReady ? `${plan.approvals.length} approval gate(s) are attached.` : "No approval gates are attached."
|
|
2124
|
+
}
|
|
2125
|
+
];
|
|
2126
|
+
const blockers = [
|
|
2127
|
+
...gates.filter((gate) => !gate.passed).map((gate) => gate.detail),
|
|
2128
|
+
...lanes.flatMap((lane) => lane.blockers)
|
|
2129
|
+
];
|
|
2130
|
+
const score = gates.length === 0 ? 0 : Math.round(gates.filter((gate) => gate.passed).length / gates.length * 100);
|
|
2131
|
+
const ready = blockers.length === 0;
|
|
2132
|
+
return {
|
|
2133
|
+
plan,
|
|
2134
|
+
lanes,
|
|
2135
|
+
gates,
|
|
2136
|
+
summary: {
|
|
2137
|
+
ready,
|
|
2138
|
+
score,
|
|
2139
|
+
targetCount: plan.targetCount,
|
|
2140
|
+
estimatedCredits: plan.estimatedCredits,
|
|
2141
|
+
builtInLanesReady: builtInLanes.filter((lane) => lane.ready).length,
|
|
2142
|
+
builtInLanesTotal: builtInLanes.length,
|
|
2143
|
+
customRoutesReady: customRoutes.filter((lane) => lane.ready).length,
|
|
2144
|
+
customRoutesTotal: customRoutes.length,
|
|
2145
|
+
approvalGateCount: plan.approvals.length,
|
|
2146
|
+
blockers,
|
|
2147
|
+
warnings: plan.warnings
|
|
2148
|
+
},
|
|
2149
|
+
nextActions: campaignReadinessNextActions(plan, ready, customRoutes.length)
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2047
2152
|
function getMissingCampaignBuilderApprovals(plan, approval) {
|
|
2048
2153
|
if (approval.planId !== plan.planId) {
|
|
2049
2154
|
return plan.approvals;
|
|
@@ -3307,6 +3412,185 @@ function mapAgentCampaignArtifact(data) {
|
|
|
3307
3412
|
createdAt: stringValue(data.created_at) ?? ""
|
|
3308
3413
|
};
|
|
3309
3414
|
}
|
|
3415
|
+
function createCampaignBuilderBuildReview(status, rows, artifacts) {
|
|
3416
|
+
const sampledRows = rows.rows.length;
|
|
3417
|
+
const availableRows = rows.count || sampledRows;
|
|
3418
|
+
const qualifiedRows = rows.rows.filter((row) => row.qualified !== false).length;
|
|
3419
|
+
const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
|
|
3420
|
+
const copyReadyRows = rows.rows.filter(campaignReviewRowHasCopy).length;
|
|
3421
|
+
const artifactCount = artifacts.length || status.artifactCount || 0;
|
|
3422
|
+
const gates = [
|
|
3423
|
+
{
|
|
3424
|
+
id: "build_completed",
|
|
3425
|
+
label: "Build completed",
|
|
3426
|
+
passed: status.status === "completed",
|
|
3427
|
+
detail: status.status === "completed" ? "The campaign build is completed." : `The campaign build is ${status.status}; review again after completion.`
|
|
3428
|
+
},
|
|
3429
|
+
{
|
|
3430
|
+
id: "rows_available",
|
|
3431
|
+
label: "Rows available",
|
|
3432
|
+
passed: sampledRows > 0,
|
|
3433
|
+
detail: sampledRows > 0 ? `${sampledRows} sampled row(s) are available for review.` : "No rows were returned for review."
|
|
3434
|
+
},
|
|
3435
|
+
{
|
|
3436
|
+
id: "qualified_sample",
|
|
3437
|
+
label: "Sample rows qualified",
|
|
3438
|
+
passed: sampledRows > 0 && qualifiedRows === sampledRows,
|
|
3439
|
+
detail: sampledRows > 0 ? `${qualifiedRows}/${sampledRows} sampled row(s) are marked qualified.` : "Qualification could not be checked without sampled rows."
|
|
3440
|
+
},
|
|
3441
|
+
{
|
|
3442
|
+
id: "email_coverage",
|
|
3443
|
+
label: "Email coverage",
|
|
3444
|
+
passed: sampledRows > 0 && rowsWithEmail === sampledRows,
|
|
3445
|
+
detail: sampledRows > 0 ? `${rowsWithEmail}/${sampledRows} sampled row(s) include an email.` : "Email coverage could not be checked without sampled rows."
|
|
3446
|
+
},
|
|
3447
|
+
{
|
|
3448
|
+
id: "artifact_available",
|
|
3449
|
+
label: "Artifact available",
|
|
3450
|
+
passed: artifactCount > 0,
|
|
3451
|
+
detail: artifactCount > 0 ? `${artifactCount} artifact(s) are available.` : "No delivery artifact is available yet."
|
|
3452
|
+
},
|
|
3453
|
+
{
|
|
3454
|
+
id: "no_failed_rows",
|
|
3455
|
+
label: "No failed rows",
|
|
3456
|
+
passed: status.recordsFailed === 0,
|
|
3457
|
+
detail: status.recordsFailed === 0 ? "The build reports zero failed rows." : `${status.recordsFailed} row(s) failed during the build.`
|
|
3458
|
+
}
|
|
3459
|
+
];
|
|
3460
|
+
const blockedReasons = gates.filter((gate) => !gate.passed).map((gate) => gate.detail);
|
|
3461
|
+
const warnings = [
|
|
3462
|
+
rows.hasMore ? "This review is based on a row sample; page through remaining rows before final approval." : void 0,
|
|
3463
|
+
sampledRows > 0 && copyReadyRows < sampledRows ? `${copyReadyRows}/${sampledRows} sampled row(s) include generated copy.` : void 0,
|
|
3464
|
+
...status.warnings
|
|
3465
|
+
].filter((item) => Boolean(item));
|
|
3466
|
+
const readyForDeliveryApproval = blockedReasons.length === 0;
|
|
3467
|
+
return {
|
|
3468
|
+
campaignBuildId: status.campaignBuildId || rows.campaignBuildId,
|
|
3469
|
+
status,
|
|
3470
|
+
rows,
|
|
3471
|
+
artifacts,
|
|
3472
|
+
gates,
|
|
3473
|
+
summary: {
|
|
3474
|
+
status: status.status,
|
|
3475
|
+
phase: status.currentPhase,
|
|
3476
|
+
sampledRows,
|
|
3477
|
+
availableRows,
|
|
3478
|
+
qualifiedRows,
|
|
3479
|
+
rowsWithEmail,
|
|
3480
|
+
copyReadyRows,
|
|
3481
|
+
artifactCount,
|
|
3482
|
+
readyForDeliveryApproval,
|
|
3483
|
+
blockedReasons,
|
|
3484
|
+
warnings
|
|
3485
|
+
},
|
|
3486
|
+
nextActions: campaignReviewNextActions(status, readyForDeliveryApproval)
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
function campaignReviewNextActions(status, readyForDeliveryApproval) {
|
|
3490
|
+
const buildId = status.campaignBuildId;
|
|
3491
|
+
if (!buildId) return [];
|
|
3492
|
+
if (status.status === "completed" && readyForDeliveryApproval) {
|
|
3493
|
+
return [
|
|
3494
|
+
`signaliz campaign-agent approve ${buildId} --destination-type json`,
|
|
3495
|
+
`signaliz campaign-agent artifacts ${buildId}`
|
|
3496
|
+
];
|
|
3497
|
+
}
|
|
3498
|
+
if (status.status === "completed") {
|
|
3499
|
+
return [
|
|
3500
|
+
`signaliz campaign-agent rows ${buildId} --limit 100`,
|
|
3501
|
+
`signaliz campaign-agent artifacts ${buildId}`
|
|
3502
|
+
];
|
|
3503
|
+
}
|
|
3504
|
+
if (status.status === "pending_approval") {
|
|
3505
|
+
return [
|
|
3506
|
+
`signaliz campaign-agent rows ${buildId} --limit 100`,
|
|
3507
|
+
`signaliz campaign-agent approve ${buildId} --destination-type json`
|
|
3508
|
+
];
|
|
3509
|
+
}
|
|
3510
|
+
if ((status.status === "queued" || status.status === "running") && status.triggerRunId) {
|
|
3511
|
+
return [`signaliz ops run-status ${status.triggerRunId} --watch`];
|
|
3512
|
+
}
|
|
3513
|
+
return [`signaliz campaign-agent status ${buildId}`];
|
|
3514
|
+
}
|
|
3515
|
+
function campaignReviewRowHasEmail(row) {
|
|
3516
|
+
const data = asRecord(row.data);
|
|
3517
|
+
return Boolean(
|
|
3518
|
+
stringValue(data.email) || stringValue(data.work_email) || stringValue(data.workEmail)
|
|
3519
|
+
);
|
|
3520
|
+
}
|
|
3521
|
+
function campaignReviewRowHasCopy(row) {
|
|
3522
|
+
const data = asRecord(row.data);
|
|
3523
|
+
const copy = asRecord(data.copy);
|
|
3524
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
3525
|
+
return row.status === "copy_ready" || data.copy_ready === true || Boolean(
|
|
3526
|
+
stringValue(data.subject) || stringValue(data.subject_line) || stringValue(data.subjectLine) || stringValue(data.opener) || stringValue(data.body) || stringValue(data.cta) || stringValue(copy.subject) || stringValue(copy.body) || stringValue(rawCopy.subject) || stringValue(rawCopy.body)
|
|
3527
|
+
);
|
|
3528
|
+
}
|
|
3529
|
+
function createCampaignBuilderReadinessLane(route, plan) {
|
|
3530
|
+
const builtIn = campaignBuilderBuiltInForRoute(route);
|
|
3531
|
+
const customRoute = route.provider !== "signaliz" && route.provider !== "csv" && builtIn === void 0;
|
|
3532
|
+
const prepareStep = plan.mcpFlow.find(
|
|
3533
|
+
(step) => step.tool === "gtm_provider_recipe_prepare" && step.arguments.provider_id === route.provider
|
|
3534
|
+
);
|
|
3535
|
+
const activateStep = plan.mcpFlow.find(
|
|
3536
|
+
(step) => step.tool === "gtm_provider_route_activate" && step.arguments.provider_id === route.provider
|
|
3537
|
+
);
|
|
3538
|
+
const readOnlySetup = !customRoute || prepareStep?.readOnly === true && activateStep?.readOnly === true && activateStep.arguments.dry_run === true && activateStep.arguments.confirm === false;
|
|
3539
|
+
const blockers = [
|
|
3540
|
+
customRoute && !prepareStep ? `${route.label ?? route.provider} is missing provider recipe setup.` : void 0,
|
|
3541
|
+
customRoute && !activateStep ? `${route.label ?? route.provider} is missing provider route dry-run setup.` : void 0,
|
|
3542
|
+
customRoute && !readOnlySetup ? `${route.label ?? route.provider} route setup must stay read-only before approval.` : void 0,
|
|
3543
|
+
route.mode === "required" && !route.toolName && customRoute ? `${route.label ?? route.provider} is required but has no tool name.` : void 0
|
|
3544
|
+
].filter((item) => Boolean(item));
|
|
3545
|
+
return {
|
|
3546
|
+
id: route.id ?? `${route.provider}-${route.layer}`,
|
|
3547
|
+
label: route.label ?? readinessLaneLabel(route, builtIn),
|
|
3548
|
+
layer: route.layer,
|
|
3549
|
+
gtmLayers: gtmLayersForRoute(route),
|
|
3550
|
+
provider: route.provider,
|
|
3551
|
+
toolName: route.toolName,
|
|
3552
|
+
mode: route.mode ?? "if_available",
|
|
3553
|
+
builtIn,
|
|
3554
|
+
approvalRequired: route.approvalRequired === true || plan.approvals.some((approval) => approval.routeId === route.id),
|
|
3555
|
+
customRoute,
|
|
3556
|
+
readOnlySetup,
|
|
3557
|
+
ready: blockers.length === 0,
|
|
3558
|
+
blockers,
|
|
3559
|
+
nextAction: customRoute ? `Review ${route.provider} route setup before launch approval.` : void 0
|
|
3560
|
+
};
|
|
3561
|
+
}
|
|
3562
|
+
function campaignBuilderBuiltInForRoute(route) {
|
|
3563
|
+
return Object.entries(CAMPAIGN_BUILDER_BUILT_IN_ROUTE_IDS).find(([, routeId]) => route.id === routeId)?.[0];
|
|
3564
|
+
}
|
|
3565
|
+
function readinessLaneLabel(route, builtIn) {
|
|
3566
|
+
if (builtIn) {
|
|
3567
|
+
const labels = {
|
|
3568
|
+
lead_generation: "Signaliz lead generation",
|
|
3569
|
+
local_leads: "Signaliz local leads",
|
|
3570
|
+
email_finding: "Signaliz email finding",
|
|
3571
|
+
email_verification: "Signaliz email verification",
|
|
3572
|
+
signals: "Signaliz signals"
|
|
3573
|
+
};
|
|
3574
|
+
return labels[builtIn];
|
|
3575
|
+
}
|
|
3576
|
+
return `${route.provider} ${route.layer}`;
|
|
3577
|
+
}
|
|
3578
|
+
function campaignReadinessNextActions(plan, ready, customRouteCount) {
|
|
3579
|
+
const requestHint = "--request-file campaign-request.json";
|
|
3580
|
+
if (ready) {
|
|
3581
|
+
return [
|
|
3582
|
+
`signaliz campaign-agent proof ${requestHint} --json`,
|
|
3583
|
+
`signaliz campaign-agent commit-plan ${requestHint} --json`,
|
|
3584
|
+
`signaliz campaign-agent build-approved ${requestHint} --confirm-launch --approve-all --approved-by operator@example.com --spend-limit ${plan.estimatedCredits}`
|
|
3585
|
+
];
|
|
3586
|
+
}
|
|
3587
|
+
const actions = [
|
|
3588
|
+
plan.strategyMemoryStatus && asRecord(plan.strategyMemoryStatus).ready === false ? "signaliz gtm strategy-memory --strategy-template <strategy_template> --include-samples --json" : void 0,
|
|
3589
|
+
customRouteCount > 0 ? "Review BYO provider recipe and route dry-run steps in the readiness packet." : void 0,
|
|
3590
|
+
`signaliz campaign-agent plan ${requestHint} --json`
|
|
3591
|
+
];
|
|
3592
|
+
return actions.filter((item) => Boolean(item));
|
|
3593
|
+
}
|
|
3310
3594
|
function diagnosticMessages2(value) {
|
|
3311
3595
|
if (!Array.isArray(value)) return [];
|
|
3312
3596
|
return value.map((item) => {
|
|
@@ -6680,17 +6964,18 @@ async function handleCampaignAgentCommand(signaliz, argv) {
|
|
|
6680
6964
|
}
|
|
6681
6965
|
return;
|
|
6682
6966
|
}
|
|
6683
|
-
if (["status", "rows", "artifacts", "approve", "approve-delivery"].includes(subcommand)) {
|
|
6967
|
+
if (["review", "status", "rows", "artifacts", "approve", "approve-delivery"].includes(subcommand)) {
|
|
6684
6968
|
await handleCampaignAgentReviewCommand(signaliz, subcommand, argv.slice(1));
|
|
6685
6969
|
return;
|
|
6686
6970
|
}
|
|
6687
|
-
if (!["plan", "proof", "smoke", "commit-plan", "dry-run", "build-approved", "launch-approved"].includes(subcommand)) {
|
|
6971
|
+
if (!["plan", "doctor", "readiness", "preflight", "proof", "smoke", "commit-plan", "dry-run", "build-approved", "launch-approved"].includes(subcommand)) {
|
|
6688
6972
|
printCampaignAgentHelp();
|
|
6689
6973
|
return;
|
|
6690
6974
|
}
|
|
6691
6975
|
const flags = parseFlags(argv.slice(1));
|
|
6976
|
+
const isDoctor = subcommand === "doctor" || subcommand === "readiness" || subcommand === "preflight";
|
|
6692
6977
|
const requestFromFile = campaignAgentRequestFileFromFlags(flags);
|
|
6693
|
-
const goal = stringFlag(flags, "goal", "brief") ?? stringOrUndefined(requestFromFile?.goal);
|
|
6978
|
+
const goal = stringFlag(flags, "goal", "brief") ?? stringOrUndefined(requestFromFile?.goal) ?? (isDoctor ? "Build a strategy-template campaign for the target ICP." : void 0);
|
|
6694
6979
|
if (!goal) throw new Error(`campaign-agent ${subcommand} requires --goal or a request file with goal`);
|
|
6695
6980
|
const isApprovedBuild = subcommand === "build-approved" || subcommand === "launch-approved";
|
|
6696
6981
|
const isCommitPlan = subcommand === "commit-plan";
|
|
@@ -6709,13 +6994,24 @@ async function handleCampaignAgentCommand(signaliz, argv) {
|
|
|
6709
6994
|
requestFromFile,
|
|
6710
6995
|
campaignAgentRequestFromFlags(goal, flags, { includeDefaults: !requestFromFile })
|
|
6711
6996
|
);
|
|
6712
|
-
const
|
|
6997
|
+
const planOptions = {
|
|
6713
6998
|
discoverCapabilities: !booleanFlag(flags, "skip-discovery"),
|
|
6714
6999
|
scopeCampaign: !booleanFlag(flags, "skip-scope"),
|
|
6715
7000
|
includeStrategyMemoryStatus: !booleanFlag(flags, "no-strategy-memory"),
|
|
6716
7001
|
includeKernelPlan: !booleanFlag(flags, "no-kernel-plan"),
|
|
6717
7002
|
includeDeliveryRisk: !booleanFlag(flags, "no-delivery-risk")
|
|
6718
|
-
}
|
|
7003
|
+
};
|
|
7004
|
+
if (isDoctor) {
|
|
7005
|
+
const readiness = await signaliz.campaignBuilderAgent.readiness(request, planOptions);
|
|
7006
|
+
if (booleanFlag(flags, "json")) {
|
|
7007
|
+
printJson(readiness);
|
|
7008
|
+
} else {
|
|
7009
|
+
printCampaignAgentReadiness(readiness);
|
|
7010
|
+
}
|
|
7011
|
+
if (!readiness.summary.ready) process.exitCode = 1;
|
|
7012
|
+
return;
|
|
7013
|
+
}
|
|
7014
|
+
const plan = await signaliz.campaignBuilderAgent.createPlan(request, planOptions);
|
|
6719
7015
|
if (subcommand === "proof" || subcommand === "smoke") {
|
|
6720
7016
|
const result = await signaliz.campaignBuilderAgent.dryRunPlan(plan, {
|
|
6721
7017
|
idempotencyKey: stringFlag(flags, "idempotency-key")
|
|
@@ -6787,6 +7083,28 @@ async function handleCampaignAgentReviewCommand(signaliz, subcommand, argv) {
|
|
|
6787
7083
|
const flags = parseFlags(argv);
|
|
6788
7084
|
const buildId = argv[0] && !argv[0].startsWith("--") ? argv[0] : stringFlag(flags, "campaign-build-id", "build-id");
|
|
6789
7085
|
if (!buildId) throw new Error(`campaign-agent ${subcommand} requires <campaign_build_id> or --campaign-build-id`);
|
|
7086
|
+
if (subcommand === "review") {
|
|
7087
|
+
const review = await signaliz.campaignBuilderAgent.reviewBuild(buildId, {
|
|
7088
|
+
limit: numberFlag(flags, "limit") ?? 100,
|
|
7089
|
+
cursor: stringFlag(flags, "cursor"),
|
|
7090
|
+
segment: stringFlag(flags, "segment"),
|
|
7091
|
+
rowStatus: stringFlag(flags, "row-status"),
|
|
7092
|
+
qualified: booleanFlag(flags, "qualified") ? true : booleanFlag(flags, "disqualified") ? false : void 0
|
|
7093
|
+
});
|
|
7094
|
+
const operatorReview = {
|
|
7095
|
+
...review,
|
|
7096
|
+
rows: {
|
|
7097
|
+
...review.rows,
|
|
7098
|
+
rows: formatCampaignAgentRows(review.rows.rows)
|
|
7099
|
+
}
|
|
7100
|
+
};
|
|
7101
|
+
if (booleanFlag(flags, "json")) {
|
|
7102
|
+
printJson(operatorReview);
|
|
7103
|
+
} else {
|
|
7104
|
+
printCampaignAgentBuildReview(operatorReview);
|
|
7105
|
+
}
|
|
7106
|
+
return;
|
|
7107
|
+
}
|
|
6790
7108
|
if (subcommand === "status") {
|
|
6791
7109
|
const status = await signaliz.campaignBuilderAgent.getBuildStatus(buildId);
|
|
6792
7110
|
if (booleanFlag(flags, "json")) {
|
|
@@ -7181,6 +7499,39 @@ function printCampaignAgentExecution(payload, flags) {
|
|
|
7181
7499
|
console.log("\nResult:");
|
|
7182
7500
|
printJson(payload.result);
|
|
7183
7501
|
}
|
|
7502
|
+
function printCampaignAgentReadiness(readiness) {
|
|
7503
|
+
const summary = asRecord4(readiness.summary);
|
|
7504
|
+
const plan = readiness.plan;
|
|
7505
|
+
console.log(`Readiness: ${summary.ready === true ? "ready" : "blocked"} (${summary.score ?? 0}%)`);
|
|
7506
|
+
if (plan?.campaignName) console.log(`Campaign: ${plan.campaignName}`);
|
|
7507
|
+
if (summary.targetCount !== void 0) console.log(`Target: ${summary.targetCount}`);
|
|
7508
|
+
if (summary.estimatedCredits !== void 0) console.log(`Estimated credits: ${summary.estimatedCredits}`);
|
|
7509
|
+
console.log(`Built-ins: ${summary.builtInLanesReady ?? 0}/${summary.builtInLanesTotal ?? 0}`);
|
|
7510
|
+
console.log(`BYO routes: ${summary.customRoutesReady ?? 0}/${summary.customRoutesTotal ?? 0}`);
|
|
7511
|
+
console.log(`Approval gates: ${summary.approvalGateCount ?? 0}`);
|
|
7512
|
+
if (Array.isArray(readiness.gates) && readiness.gates.length > 0) {
|
|
7513
|
+
console.log("\nGates:");
|
|
7514
|
+
for (const gate of readiness.gates) {
|
|
7515
|
+
console.log(`- ${gate.passed ? "PASS" : "BLOCKED"} ${gate.label}: ${gate.detail}`);
|
|
7516
|
+
}
|
|
7517
|
+
}
|
|
7518
|
+
if (Array.isArray(readiness.lanes) && readiness.lanes.length > 0) {
|
|
7519
|
+
console.log("\nLanes:");
|
|
7520
|
+
for (const lane of readiness.lanes) {
|
|
7521
|
+
console.log(`- ${lane.ready ? "READY" : "BLOCKED"} ${lane.label}: ${lane.toolName || lane.provider}`);
|
|
7522
|
+
}
|
|
7523
|
+
}
|
|
7524
|
+
const blockers = Array.isArray(summary.blockers) ? summary.blockers : [];
|
|
7525
|
+
if (blockers.length > 0) {
|
|
7526
|
+
console.log("\nBlockers:");
|
|
7527
|
+
for (const blocker of blockers.slice(0, 8)) console.log(`- ${blocker}`);
|
|
7528
|
+
}
|
|
7529
|
+
const nextActions = Array.isArray(readiness.nextActions) ? readiness.nextActions : [];
|
|
7530
|
+
if (nextActions.length > 0) {
|
|
7531
|
+
console.log("\nNext:");
|
|
7532
|
+
for (const action of nextActions) console.log(`- ${action}`);
|
|
7533
|
+
}
|
|
7534
|
+
}
|
|
7184
7535
|
function printCampaignAgentBuildStatus(status) {
|
|
7185
7536
|
console.log(`Campaign: ${status.name || status.campaignBuildId}`);
|
|
7186
7537
|
if (status.campaignId) console.log(`Campaign ID: ${status.campaignId}`);
|
|
@@ -7201,6 +7552,34 @@ function printCampaignAgentBuildStatus(status) {
|
|
|
7201
7552
|
console.log(`Next: signaliz campaign-agent approve ${status.campaignBuildId} --destination-type webhook`);
|
|
7202
7553
|
}
|
|
7203
7554
|
}
|
|
7555
|
+
function printCampaignAgentBuildReview(review) {
|
|
7556
|
+
const summary = asRecord4(review.summary);
|
|
7557
|
+
console.log(`Campaign: ${review.status?.name || review.campaignBuildId}`);
|
|
7558
|
+
console.log(`Status: ${summary.status || review.status?.status}`);
|
|
7559
|
+
console.log(`Phase: ${summary.phase || review.status?.currentPhase || "N/A"}`);
|
|
7560
|
+
console.log(`Rows: ${summary.sampledRows || 0} sampled, ${summary.availableRows || 0} available`);
|
|
7561
|
+
console.log(`Qualified: ${summary.qualifiedRows || 0}`);
|
|
7562
|
+
console.log(`Emails: ${summary.rowsWithEmail || 0}`);
|
|
7563
|
+
console.log(`Copy ready: ${summary.copyReadyRows || 0}`);
|
|
7564
|
+
console.log(`Artifacts: ${summary.artifactCount || 0}`);
|
|
7565
|
+
console.log(`Delivery approval ready: ${summary.readyForDeliveryApproval === true ? "yes" : "no"}`);
|
|
7566
|
+
if (Array.isArray(review.gates) && review.gates.length > 0) {
|
|
7567
|
+
console.log("\nGates:");
|
|
7568
|
+
for (const gate of review.gates) {
|
|
7569
|
+
console.log(`- ${gate.passed ? "PASS" : "BLOCKED"} ${gate.label}: ${gate.detail}`);
|
|
7570
|
+
}
|
|
7571
|
+
}
|
|
7572
|
+
const warnings = Array.isArray(summary.warnings) ? summary.warnings : [];
|
|
7573
|
+
if (warnings.length > 0) {
|
|
7574
|
+
console.log("\nWarnings:");
|
|
7575
|
+
for (const warning of warnings.slice(0, 5)) console.log(`- ${warning}`);
|
|
7576
|
+
}
|
|
7577
|
+
const nextActions = Array.isArray(review.nextActions) ? review.nextActions : [];
|
|
7578
|
+
if (nextActions.length > 0) {
|
|
7579
|
+
console.log("\nNext:");
|
|
7580
|
+
for (const action of nextActions) console.log(`- ${action}`);
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
7204
7583
|
function formatCampaignAgentRows(rows) {
|
|
7205
7584
|
return rows.map((row) => {
|
|
7206
7585
|
const data = asRecord4(row.data);
|
|
@@ -7403,6 +7782,7 @@ Usage:
|
|
|
7403
7782
|
signaliz gtm memory search --query "proof-first vertical gate" --json
|
|
7404
7783
|
signaliz gtm plan --brief "Build 500 verified leads for..." --strategy-template non-medical-home-care --lead-count 500 --json
|
|
7405
7784
|
signaliz campaign-agent init --strategy-template non-medical-home-care --target-count 250 --use-local-leads --json > campaign-request.json
|
|
7785
|
+
signaliz campaign-agent doctor --request-file campaign-request.json --json
|
|
7406
7786
|
signaliz campaign-agent plan --goal "Build a strategy-template campaign..." --strategy-template industrial-ot-resilience --target-count 500 --builtins lead_generation,email_finding,email_verification,signals
|
|
7407
7787
|
signaliz campaign-agent proof --goal "Build a strategy-template campaign..." --strategy-template non-medical-home-care --target-count 100 --json
|
|
7408
7788
|
signaliz campaign-agent plan --request-file examples/campaign-builder-agent-request.json --target-count 250 --json
|
|
@@ -7410,6 +7790,7 @@ Usage:
|
|
|
7410
7790
|
signaliz campaign-agent dry-run --goal "Build a strategy-template campaign..." --target-count 500 --use-local-leads --json
|
|
7411
7791
|
signaliz campaign-agent build-approved --goal "Build a strategy-template campaign..." --confirm-launch --approve-all --approved-by you@example.com --spend-limit 500
|
|
7412
7792
|
signaliz campaign-agent build-approved --request-file campaign-request.json --confirm-launch --approve-all --approved-by you@example.com --spend-limit 500 --wait --approve-delivery --delivery-destination-type json
|
|
7793
|
+
signaliz campaign-agent review <campaign_build_id> --limit 100 --json
|
|
7413
7794
|
signaliz campaign-agent status <campaign_build_id> --json
|
|
7414
7795
|
signaliz campaign-agent rows <campaign_build_id> --limit 100 --json
|
|
7415
7796
|
|
|
@@ -7438,17 +7819,19 @@ function printCampaignAgentHelp() {
|
|
|
7438
7819
|
Signaliz campaign-agent commands:
|
|
7439
7820
|
|
|
7440
7821
|
signaliz campaign-agent init [--goal TEXT] [--strategy-template ID] [--target-count N] [--use-local-leads] [--with-byo-placeholder] [--output-file FILE] [--json]
|
|
7822
|
+
signaliz campaign-agent doctor [--goal TEXT | --request-file FILE] [--strategy-template ID] [--target-count N] [--builtins lead_generation,email_finding,email_verification,signals,local_leads] [--custom-tool provider:layer:tool[:mcp]] [--json]
|
|
7441
7823
|
signaliz campaign-agent plan (--goal TEXT | --request-file FILE) [--campaign-name NAME] [--workspace-label NAME] [--strategy-template industrial-ot-resilience|non-medical-home-care|agency-founder-led|cloud-infrastructure-displacement] [--operating-playbooks proof-first-vertical-gate,signal-led-copy-approval] [--target-count N] [--icp JSON] [--builtins lead_generation,email_finding,email_verification,signals,local_leads] [--use-local-leads] [--custom-tool provider:layer:tool[:mcp]] [--preferred-providers signaliz_native,octave] [--partners clay,instantly,nango] [--no-strategy-memory] [--no-kernel-plan] [--no-delivery-risk] [--json]
|
|
7442
7824
|
signaliz campaign-agent proof (--goal TEXT | --request-file FILE) [--strategy-template ID] [--target-count N] [--use-local-leads] [--custom-tool provider:layer:tool[:mcp]] [--idempotency-key KEY] [--json]
|
|
7443
7825
|
signaliz campaign-agent commit-plan (--goal TEXT | --request-file FILE) [--confirm-write --approved-by EMAIL] [--idempotency-key KEY] [--json]
|
|
7444
7826
|
signaliz campaign-agent dry-run (--goal TEXT | --request-file FILE) [--gtm-campaign-id ID] [--delivery-risk JSON] [--idempotency-key KEY] [--json]
|
|
7445
7827
|
signaliz campaign-agent build-approved (--goal TEXT | --request-file FILE) --confirm-launch --approved-by EMAIL (--approve-all | --approved-types a,b) [--commit-before-launch] [--spend-limit N] [--approved-route-ids a,b] [--wait] [--approve-delivery] [--delivery-destination-type json|csv|webhook] [--idempotency-key KEY] [--json]
|
|
7828
|
+
signaliz campaign-agent review <campaign_build_id> [--limit N] [--qualified|--disqualified] [--json]
|
|
7446
7829
|
signaliz campaign-agent status <campaign_build_id> [--json]
|
|
7447
7830
|
signaliz campaign-agent rows <campaign_build_id> [--limit N] [--cursor CURSOR] [--qualified|--disqualified] [--json]
|
|
7448
7831
|
signaliz campaign-agent artifacts <campaign_build_id> [--json]
|
|
7449
7832
|
signaliz campaign-agent approve <campaign_build_id> --destination-type json|csv|webhook [--destination-config JSON] [--json]
|
|
7450
7833
|
|
|
7451
|
-
The init command emits a reusable JSON CampaignBuilderAgentRequest. The plan command composes an approval-gated strategy-template MCP flow. Proof runs the same plan path plus build_campaign dry_run=true and returns a no-spend receipt. Use --request-file to load a reusable request, then override fields such as --target-count or --strategy-template from the command line. Use --strategy-template to merge a private-safe strategy pattern into the plan without exposing private account labels, and --operating-playbooks to add reusable build-loop gates such as proof-first vertical qualification, net-new suppression, cache-first inventory, and signal-led copy approval. Built-ins map to Signaliz-native tools: lead_generation -> generate_leads, local_leads -> generate_local_leads, email_finding -> find_and_verify_emails, email_verification -> verify_emails, signals -> enrich_company_signals. Add BYO tools with --custom-tool provider:layer:tool[:mcp] or key=value pairs such as provider=apollo,layer=source,tool=apollo_search,mcp=apollo. Use --no-strategy-patterns or --no-workflow-patterns to disable default private strategy memory hints. Commit-plan dry-runs by default and writes only with --confirm-write plus approval identity. Dry-run executes build_campaign with dry_run=true. Approved build requires explicit launch confirmation and approval metadata; add --commit-before-launch to persist the reviewed plan as a GTM campaign before launch, --wait to poll until completion or pending approval, and --approve-delivery to approve reviewed webhook delivery after pending_approval. Use status, rows,
|
|
7834
|
+
The init command emits a reusable JSON CampaignBuilderAgentRequest. Doctor returns a readiness packet for built-in lanes, BYO routes, Memory, Brain, Kernel planning, and approval gates. The plan command composes an approval-gated strategy-template MCP flow. Proof runs the same plan path plus build_campaign dry_run=true and returns a no-spend receipt. Use --request-file to load a reusable request, then override fields such as --target-count or --strategy-template from the command line. Use --strategy-template to merge a private-safe strategy pattern into the plan without exposing private account labels, and --operating-playbooks to add reusable build-loop gates such as proof-first vertical qualification, net-new suppression, cache-first inventory, and signal-led copy approval. Built-ins map to Signaliz-native tools: lead_generation -> generate_leads, local_leads -> generate_local_leads, email_finding -> find_and_verify_emails, email_verification -> verify_emails, signals -> enrich_company_signals. Add BYO tools with --custom-tool provider:layer:tool[:mcp] or key=value pairs such as provider=apollo,layer=source,tool=apollo_search,mcp=apollo. Use --no-strategy-patterns or --no-workflow-patterns to disable default private strategy memory hints. Commit-plan dry-runs by default and writes only with --confirm-write plus approval identity. Dry-run executes build_campaign with dry_run=true. Approved build requires explicit launch confirmation and approval metadata; add --commit-before-launch to persist the reviewed plan as a GTM campaign before launch, --wait to poll until completion or pending approval, and --approve-delivery to approve reviewed webhook delivery after pending_approval. Use review to inspect status, sampled rows, artifacts, and delivery-readiness gates before approving delivery or routing rows to external tools.
|
|
7452
7835
|
`);
|
|
7453
7836
|
}
|
|
7454
7837
|
main().catch((e) => {
|