@signaliz/sdk 1.0.16 → 1.0.18
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 +120 -12
- package/dist/{chunk-5JNKSMNW.mjs → chunk-VFBQCWOM.mjs} +2211 -169
- package/dist/cli.js +5700 -3280
- package/dist/cli.mjs +237 -24
- package/dist/index.d.mts +2634 -1939
- package/dist/index.d.ts +2634 -1939
- package/dist/index.js +2211 -169
- package/dist/index.mjs +1 -1
- package/dist/mcp-config.js +2211 -169
- package/dist/mcp-config.mjs +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -265,25 +265,31 @@ var HttpClient = class {
|
|
|
265
265
|
async getToken() {
|
|
266
266
|
if (this.apiKey) return this.apiKey;
|
|
267
267
|
if (this.accessToken) return this.accessToken;
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
throw new SignalizError({
|
|
279
|
-
code: "AUTH_FAILED",
|
|
280
|
-
message: "Failed to obtain access token",
|
|
281
|
-
errorType: "auth_expired"
|
|
268
|
+
if (this.accessTokenPromise) return this.accessTokenPromise;
|
|
269
|
+
this.accessTokenPromise = (async () => {
|
|
270
|
+
const res = await fetch("https://api.signaliz.com/token", {
|
|
271
|
+
method: "POST",
|
|
272
|
+
headers: { "Content-Type": "application/json" },
|
|
273
|
+
body: JSON.stringify({
|
|
274
|
+
grant_type: "client_credentials",
|
|
275
|
+
client_id: this.clientId,
|
|
276
|
+
client_secret: this.clientSecret
|
|
277
|
+
})
|
|
282
278
|
});
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
279
|
+
if (!res.ok) {
|
|
280
|
+
throw new SignalizError({
|
|
281
|
+
code: "AUTH_FAILED",
|
|
282
|
+
message: "Failed to obtain access token",
|
|
283
|
+
errorType: "auth_expired"
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
const data = await res.json();
|
|
287
|
+
this.accessToken = data.access_token;
|
|
288
|
+
return this.accessToken;
|
|
289
|
+
})().finally(() => {
|
|
290
|
+
this.accessTokenPromise = void 0;
|
|
291
|
+
});
|
|
292
|
+
return this.accessTokenPromise;
|
|
287
293
|
}
|
|
288
294
|
};
|
|
289
295
|
function sleep(ms) {
|
|
@@ -532,7 +538,6 @@ var Signals = class {
|
|
|
532
538
|
if (params.online !== void 0) args.online = params.online;
|
|
533
539
|
if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
|
|
534
540
|
if (params.lookbackDays) args.lookback_days = params.lookbackDays;
|
|
535
|
-
if (params.model) args.model = params.model;
|
|
536
541
|
if (params.enableDeepSearch) args.enable_deep_search = params.enableDeepSearch;
|
|
537
542
|
if (params.enableOutreachIntelligence) args.enable_outreach_intelligence = params.enableOutreachIntelligence;
|
|
538
543
|
if (params.enablePredictiveIntelligence) args.enable_predictive_intelligence = params.enablePredictiveIntelligence;
|
|
@@ -827,6 +832,10 @@ var Campaigns = class {
|
|
|
827
832
|
async artifacts(campaignBuildId) {
|
|
828
833
|
return this.listCampaignBuildArtifacts(campaignBuildId);
|
|
829
834
|
}
|
|
835
|
+
/** Generate fresh signed URLs for a downloadable campaign artifact. */
|
|
836
|
+
async downloadArtifact(campaignBuildId, options) {
|
|
837
|
+
return this.downloadCampaignArtifact(campaignBuildId, options);
|
|
838
|
+
}
|
|
830
839
|
/** Cancel a queued or running build. */
|
|
831
840
|
async cancel(campaignBuildId, reason) {
|
|
832
841
|
return this.cancelCampaignBuild(campaignBuildId, reason);
|
|
@@ -871,13 +880,21 @@ var Campaigns = class {
|
|
|
871
880
|
dryRun: isDryRun,
|
|
872
881
|
requestedTargetCount: data.requested_target_count,
|
|
873
882
|
plannedTargetCount: data.planned_target_count,
|
|
883
|
+
acquisitionMode: data.acquisition_mode,
|
|
884
|
+
acquisitionSource: data.acquisition_source,
|
|
885
|
+
cacheReusePolicy: data.cache_reuse_policy,
|
|
874
886
|
estimatedCredits: data.estimated_credits,
|
|
875
887
|
estimatedDurationSeconds: data.estimated_duration_seconds,
|
|
876
888
|
targetLimitApplied: data.target_limit_applied,
|
|
877
889
|
targetLimitReason: data.target_limit_reason,
|
|
878
890
|
maxSupportedTargetCount: data.max_supported_target_count,
|
|
879
891
|
brainContext: data.brain_context ?? {},
|
|
880
|
-
|
|
892
|
+
learningHoldout: data.learning_holdout ?? {},
|
|
893
|
+
providerRoute: mapProviderRoute(data),
|
|
894
|
+
effectiveSourceRouting: recordOrNull(data.effective_source_routing ?? data.source_routing),
|
|
895
|
+
sourcePlan: recordOrNull(data.source_plan ?? data.plan?.source_plan),
|
|
896
|
+
sourceRoutes: recordArray(data.source_routes ?? data.source_plan?.routes ?? data.plan?.source_plan?.routes),
|
|
897
|
+
sourceShards: recordArray(data.source_shards ?? data.source_plan?.shards ?? data.plan?.source_plan?.shards)
|
|
881
898
|
};
|
|
882
899
|
}
|
|
883
900
|
async getCampaignBuildStatus(campaignBuildId) {
|
|
@@ -892,14 +909,24 @@ var Campaigns = class {
|
|
|
892
909
|
});
|
|
893
910
|
return (data.artifacts ?? []).map(mapArtifact);
|
|
894
911
|
}
|
|
912
|
+
async downloadCampaignArtifact(campaignBuildId, options) {
|
|
913
|
+
const args = { campaign_build_id: campaignBuildId };
|
|
914
|
+
if (options?.format) args.format = options.format;
|
|
915
|
+
const data = await this.callMcp("download_campaign_artifact", args);
|
|
916
|
+
return mapArtifactDownloadResult(data);
|
|
917
|
+
}
|
|
895
918
|
async getCampaignBuildRows(campaignBuildId, options) {
|
|
896
919
|
const args = { campaign_build_id: campaignBuildId };
|
|
897
920
|
if (options?.limit) args.page_size = options.limit;
|
|
898
921
|
if (options?.cursor) args.cursor = options.cursor;
|
|
922
|
+
if (options?.includeData !== void 0) args.include_data = options.includeData;
|
|
923
|
+
if (options?.includeRaw !== void 0) args.include_raw = options.includeRaw;
|
|
899
924
|
const filters = {};
|
|
900
925
|
if (options?.segment) filters.segment = options.segment;
|
|
901
926
|
if (options?.rowStatus) filters.row_status = options.rowStatus;
|
|
902
927
|
if (options?.qualified !== void 0) filters.qualified = options.qualified;
|
|
928
|
+
if (options?.cached !== void 0) filters.cached = options.cached;
|
|
929
|
+
if (options?.exportReady !== void 0) filters.export_ready = options.exportReady;
|
|
903
930
|
if (Object.keys(filters).length > 0) args.filters = filters;
|
|
904
931
|
const data = await this.callMcp("get_campaign_build_rows", args);
|
|
905
932
|
return {
|
|
@@ -924,6 +951,7 @@ var Campaigns = class {
|
|
|
924
951
|
};
|
|
925
952
|
if (options?.destinationId) args.destination_id = options.destinationId;
|
|
926
953
|
if (options?.destinationConfig) args.destination_config = options.destinationConfig;
|
|
954
|
+
if (options?.allowPartialDelivery === true) args.allow_partial_delivery = true;
|
|
927
955
|
const data = await this.callMcp("approve_campaign_delivery", args);
|
|
928
956
|
return {
|
|
929
957
|
campaignBuildId: data.campaign_build_id,
|
|
@@ -932,7 +960,10 @@ var Campaigns = class {
|
|
|
932
960
|
message: data.message ?? "",
|
|
933
961
|
deliveryId: data.delivery_id,
|
|
934
962
|
deliveryIds: data.delivery_ids,
|
|
935
|
-
approvedCount: data.approved_count
|
|
963
|
+
approvedCount: data.approved_count,
|
|
964
|
+
partialDelivery: data.partial_delivery,
|
|
965
|
+
effectiveTargetCount: data.effective_target_count,
|
|
966
|
+
requestedTargetCount: data.requested_target_count
|
|
936
967
|
};
|
|
937
968
|
}
|
|
938
969
|
async cancelCampaignBuild(campaignBuildId, reason) {
|
|
@@ -985,17 +1016,50 @@ function mapStatus(data) {
|
|
|
985
1016
|
warnings: diagnosticMessages(data.warnings),
|
|
986
1017
|
errors: diagnosticMessages(data.errors),
|
|
987
1018
|
artifactCount: data.artifact_count ?? 0,
|
|
1019
|
+
artifactDownloads: Array.isArray(data.artifact_downloads) ? data.artifact_downloads.map(mapArtifactDownload) : [],
|
|
1020
|
+
customerRowCounts: mapCustomerRowCounts(data.customer_row_counts),
|
|
1021
|
+
phaseAttemptTotals: recordOrNull(data.phase_attempt_totals) ?? void 0,
|
|
988
1022
|
providerRoute: mapProviderRoute(data),
|
|
989
1023
|
triggerRunId: typeof data.trigger_run_id === "string" ? data.trigger_run_id : null,
|
|
990
1024
|
staleRunningPhase: data.stale_running_phase === true,
|
|
991
1025
|
phaseAgeSeconds: numberOrNull(data.phase_age_seconds),
|
|
992
1026
|
diagnostics: recordOrNull(data.diagnostics) ?? {},
|
|
993
1027
|
nextAction: formatNextAction(data.next_action),
|
|
1028
|
+
approvalAction: formatNextAction(data.approval_action),
|
|
994
1029
|
createdAt: data.created_at,
|
|
995
1030
|
updatedAt: data.updated_at,
|
|
996
1031
|
completedAt: data.completed_at
|
|
997
1032
|
};
|
|
998
1033
|
}
|
|
1034
|
+
function mapCustomerRowCounts(value) {
|
|
1035
|
+
const record = recordOrNull(value);
|
|
1036
|
+
if (!record) return void 0;
|
|
1037
|
+
return {
|
|
1038
|
+
requestedTarget: numberOrNull(record.requested_target),
|
|
1039
|
+
acquiredRows: numberOrNull(record.acquired_rows) ?? void 0,
|
|
1040
|
+
acceptedRows: numberOrNull(record.accepted_rows) ?? void 0,
|
|
1041
|
+
usableRows: numberOrNull(record.usable_rows) ?? void 0,
|
|
1042
|
+
copiedRows: numberOrNull(record.copied_rows) ?? void 0,
|
|
1043
|
+
approvalReadyRows: numberOrNull(record.approval_ready_rows) ?? void 0,
|
|
1044
|
+
qaReadyRows: numberOrNull(record.qa_ready_rows) ?? void 0,
|
|
1045
|
+
deliveredRows: numberOrNull(record.delivered_rows) ?? void 0,
|
|
1046
|
+
disqualifiedRows: numberOrNull(record.disqualified_rows) ?? void 0,
|
|
1047
|
+
reviewableRows: numberOrNull(record.reviewable_rows) ?? void 0,
|
|
1048
|
+
rowFailures: numberOrNull(record.row_failures) ?? void 0,
|
|
1049
|
+
acceptedShortfall: numberOrNull(record.accepted_shortfall),
|
|
1050
|
+
usableShortfall: numberOrNull(record.usable_shortfall),
|
|
1051
|
+
qaReadyShortfall: numberOrNull(record.qa_ready_shortfall),
|
|
1052
|
+
deliveryShortfall: numberOrNull(record.delivery_shortfall),
|
|
1053
|
+
fillRatio: numberOrNull(record.fill_ratio),
|
|
1054
|
+
qaReadyFillRatio: numberOrNull(record.qa_ready_fill_ratio),
|
|
1055
|
+
deliveredFillRatio: numberOrNull(record.delivered_fill_ratio),
|
|
1056
|
+
terminalReason: typeof record.terminal_reason === "string" ? record.terminal_reason : null,
|
|
1057
|
+
acceptedShortfallReason: typeof record.accepted_shortfall_reason === "string" ? record.accepted_shortfall_reason : null,
|
|
1058
|
+
usableShortfallReason: typeof record.usable_shortfall_reason === "string" ? record.usable_shortfall_reason : null,
|
|
1059
|
+
qaReadyShortfallReason: typeof record.qa_ready_shortfall_reason === "string" ? record.qa_ready_shortfall_reason : null,
|
|
1060
|
+
deliveryShortfallReason: typeof record.delivery_shortfall_reason === "string" ? record.delivery_shortfall_reason : null
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
999
1063
|
function mapProviderRoute(data) {
|
|
1000
1064
|
const brainContext = recordOrNull(data?.brain_context);
|
|
1001
1065
|
const plan = recordOrNull(data?.provider_route_plan) ?? recordOrNull(brainContext?.provider_route_plan);
|
|
@@ -1022,6 +1086,9 @@ function recordOrNull(value) {
|
|
|
1022
1086
|
function stringArray(value) {
|
|
1023
1087
|
return Array.isArray(value) ? value.map((item) => String(item || "").trim()).filter(Boolean) : [];
|
|
1024
1088
|
}
|
|
1089
|
+
function recordArray(value) {
|
|
1090
|
+
return Array.isArray(value) ? value.map(recordOrNull).filter((item) => Boolean(item)) : [];
|
|
1091
|
+
}
|
|
1025
1092
|
function diagnosticMessages(value) {
|
|
1026
1093
|
if (!Array.isArray(value)) return [];
|
|
1027
1094
|
return value.map((item) => {
|
|
@@ -1073,13 +1140,56 @@ function mapArtifact(a) {
|
|
|
1073
1140
|
artifactType: a.artifact_type,
|
|
1074
1141
|
destination: a.destination,
|
|
1075
1142
|
storagePath: a.storage_path,
|
|
1143
|
+
format: a.format ?? null,
|
|
1076
1144
|
signedUrl: a.signed_url,
|
|
1145
|
+
downloadUrl: a.download_url ?? null,
|
|
1146
|
+
manifestUrl: a.manifest_url ?? null,
|
|
1147
|
+
expiresAt: a.expires_at ?? null,
|
|
1077
1148
|
rowCount: a.row_count ?? 0,
|
|
1078
1149
|
checksum: a.checksum,
|
|
1079
1150
|
metadata: a.metadata ?? {},
|
|
1080
1151
|
createdAt: a.created_at
|
|
1081
1152
|
};
|
|
1082
1153
|
}
|
|
1154
|
+
function mapArtifactDownload(data) {
|
|
1155
|
+
return {
|
|
1156
|
+
id: data.id,
|
|
1157
|
+
artifactType: data.artifact_type ?? null,
|
|
1158
|
+
format: data.format ?? null,
|
|
1159
|
+
rowCount: data.row_count ?? 0,
|
|
1160
|
+
signedUrl: data.signed_url ?? null,
|
|
1161
|
+
downloadUrl: data.download_url ?? null,
|
|
1162
|
+
manifestUrl: data.manifest_url ?? null,
|
|
1163
|
+
expiresAt: data.expires_at ?? null
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
function mapArtifactDownloadResult(data) {
|
|
1167
|
+
return {
|
|
1168
|
+
campaignBuildId: data.campaign_build_id,
|
|
1169
|
+
artifactId: data.artifact_id,
|
|
1170
|
+
format: data.format,
|
|
1171
|
+
rowCount: data.row_count ?? 0,
|
|
1172
|
+
byteSize: numberOrNull(data.byte_size),
|
|
1173
|
+
partCount: data.part_count ?? 0,
|
|
1174
|
+
checksum: data.checksum ?? null,
|
|
1175
|
+
signedUrl: data.signed_url ?? null,
|
|
1176
|
+
downloadUrl: data.download_url ?? null,
|
|
1177
|
+
manifestUrl: data.manifest_url ?? null,
|
|
1178
|
+
expiresAt: data.expires_at ?? null,
|
|
1179
|
+
parts: Array.isArray(data.parts) ? data.parts.map(mapArtifactDownloadPart) : [],
|
|
1180
|
+
downloadCommands: recordOrNull(data.download_commands) ?? {},
|
|
1181
|
+
expiresInSeconds: numberOrNull(data.expires_in_seconds)
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
function mapArtifactDownloadPart(data) {
|
|
1185
|
+
return {
|
|
1186
|
+
partIndex: data.part_index ?? 0,
|
|
1187
|
+
rowCount: data.row_count ?? 0,
|
|
1188
|
+
byteSize: numberOrNull(data.byte_size),
|
|
1189
|
+
checksum: data.checksum ?? null,
|
|
1190
|
+
signedUrl: data.signed_url ?? null
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1083
1193
|
function mapScope(data) {
|
|
1084
1194
|
return {
|
|
1085
1195
|
campaignScopeId: data.campaign_scope_id,
|
|
@@ -1133,8 +1243,30 @@ function buildArgs(request) {
|
|
|
1133
1243
|
if (request.allowDownscale !== void 0) args.allow_downscale = request.allowDownscale;
|
|
1134
1244
|
if (request.confirmSpend !== void 0) args.confirm_spend = request.confirmSpend;
|
|
1135
1245
|
if (request.dedupKeys) args.dedup_keys = request.dedupKeys;
|
|
1246
|
+
if (request.acquisitionMode) args.acquisition_mode = request.acquisitionMode;
|
|
1247
|
+
if (request.cacheReusePolicy) {
|
|
1248
|
+
args.cache_reuse_policy = {
|
|
1249
|
+
allow_verified_cache: request.cacheReusePolicy.allowVerifiedCache,
|
|
1250
|
+
suppress_prior_campaign_ids: request.cacheReusePolicy.suppressPriorCampaignIds,
|
|
1251
|
+
suppress_prior_list_ids: request.cacheReusePolicy.suppressPriorListIds,
|
|
1252
|
+
uniqueness: request.cacheReusePolicy.uniqueness,
|
|
1253
|
+
require_usage_metadata: request.cacheReusePolicy.requireUsageMetadata,
|
|
1254
|
+
verified_cache_ttl_days: request.cacheReusePolicy.verifiedCacheTtlDays
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1136
1257
|
if (request.brainPreflight) args.brain_preflight = request.brainPreflight;
|
|
1137
1258
|
if (request.brainDefaults) args.brain_defaults = request.brainDefaults;
|
|
1259
|
+
if (request.learningHoldout) {
|
|
1260
|
+
args.learning_holdout = {
|
|
1261
|
+
enabled: request.learningHoldout.enabled,
|
|
1262
|
+
control_percentage: request.learningHoldout.controlPercentage,
|
|
1263
|
+
min_control_size: request.learningHoldout.minControlSize,
|
|
1264
|
+
experiment_key: request.learningHoldout.experimentKey,
|
|
1265
|
+
source_campaign_id: request.learningHoldout.sourceCampaignId,
|
|
1266
|
+
primary_metric: request.learningHoldout.primaryMetric
|
|
1267
|
+
};
|
|
1268
|
+
}
|
|
1269
|
+
if (request.campaignStrategyContext) args.campaign_strategy_context = request.campaignStrategyContext;
|
|
1138
1270
|
if (request.deliveryRisk) args.delivery_risk = request.deliveryRisk;
|
|
1139
1271
|
if (request.icp) {
|
|
1140
1272
|
args.icp = {
|
|
@@ -1176,7 +1308,17 @@ function buildArgs(request) {
|
|
|
1176
1308
|
max_body_words: request.copy.maxBodyWords,
|
|
1177
1309
|
sender_context: request.copy.senderContext,
|
|
1178
1310
|
offer_context: request.copy.offerContext,
|
|
1179
|
-
model: request.copy.model
|
|
1311
|
+
model: request.copy.model,
|
|
1312
|
+
style_source: request.copy.styleSource ? {
|
|
1313
|
+
sample_text: request.copy.styleSource.sampleText,
|
|
1314
|
+
campaign_ids: request.copy.styleSource.campaignIds,
|
|
1315
|
+
artifact_ids: request.copy.styleSource.artifactIds
|
|
1316
|
+
} : void 0,
|
|
1317
|
+
sequence_steps: request.copy.sequenceSteps,
|
|
1318
|
+
copy_schema: request.copy.copySchema,
|
|
1319
|
+
banned_phrases: request.copy.bannedPhrases,
|
|
1320
|
+
approval_required: request.copy.approvalRequired,
|
|
1321
|
+
quality_tier: request.copy.qualityTier
|
|
1180
1322
|
};
|
|
1181
1323
|
}
|
|
1182
1324
|
if (request.delivery) {
|
|
@@ -1239,6 +1381,8 @@ var DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS = {
|
|
|
1239
1381
|
}
|
|
1240
1382
|
};
|
|
1241
1383
|
var DEFAULT_CAMPAIGN_BUILDER_BUILT_INS = [
|
|
1384
|
+
"company_discovery",
|
|
1385
|
+
"people_discovery",
|
|
1242
1386
|
"lead_generation",
|
|
1243
1387
|
"email_finding",
|
|
1244
1388
|
"email_verification",
|
|
@@ -1247,6 +1391,8 @@ var DEFAULT_CAMPAIGN_BUILDER_BUILT_INS = [
|
|
|
1247
1391
|
var CAMPAIGN_BUILDER_BUILT_IN_ROUTE_IDS = {
|
|
1248
1392
|
lead_generation: "signaliz-lead-generation",
|
|
1249
1393
|
local_leads: "signaliz-local-leads",
|
|
1394
|
+
company_discovery: "signaliz-company-discovery",
|
|
1395
|
+
people_discovery: "signaliz-people-discovery",
|
|
1250
1396
|
email_finding: "signaliz-email-finding",
|
|
1251
1397
|
email_verification: "signaliz-email-verification",
|
|
1252
1398
|
signals: "signaliz-signals"
|
|
@@ -1264,8 +1410,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1264
1410
|
slug: "cache-first-large-list",
|
|
1265
1411
|
label: "Cache-First Large List",
|
|
1266
1412
|
whenToUse: [
|
|
1267
|
-
"The
|
|
1268
|
-
"The deliverable is a
|
|
1413
|
+
"The operator explicitly references a previous campaign, prior list, seed list, or suppression baseline.",
|
|
1414
|
+
"The deliverable is a top-up, continuation, or backfill where prior campaign context should guide reuse."
|
|
1269
1415
|
],
|
|
1270
1416
|
sequence: [
|
|
1271
1417
|
"Inventory reusable cache before paid sourcing.",
|
|
@@ -1471,7 +1617,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1471
1617
|
],
|
|
1472
1618
|
requireVerifiedEmail: true
|
|
1473
1619
|
},
|
|
1474
|
-
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1620
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "email_finding", "email_verification", "signals"],
|
|
1475
1621
|
preferredProviders: ["signaliz_native"],
|
|
1476
1622
|
memoryQueries: [{
|
|
1477
1623
|
query: "industrial OT net-new prior email suppression verified manufacturing embedded systems field service cyber resilience business continuity",
|
|
@@ -1545,7 +1691,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1545
1691
|
],
|
|
1546
1692
|
requireVerifiedEmail: true
|
|
1547
1693
|
},
|
|
1548
|
-
builtIns: ["lead_generation", "local_leads", "email_finding", "email_verification", "signals"],
|
|
1694
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "local_leads", "email_finding", "email_verification", "signals"],
|
|
1549
1695
|
preferredProviders: ["signaliz_native", "octave", "clay_webhook", "apify"],
|
|
1550
1696
|
memoryQueries: [{
|
|
1551
1697
|
query: "mature non-medical home care agencies billable hours franchise caregiver recruiting proof gate qualification export approval",
|
|
@@ -1611,7 +1757,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1611
1757
|
exclusions: ["enterprise holding company", "staffing", "recruiting", "software-only vendor", "freelancer-only profile"],
|
|
1612
1758
|
requireVerifiedEmail: true
|
|
1613
1759
|
},
|
|
1614
|
-
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1760
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "email_finding", "email_verification", "signals"],
|
|
1615
1761
|
preferredProviders: ["signaliz_native", "octave"],
|
|
1616
1762
|
memoryQueries: [{
|
|
1617
1763
|
query: "agency founder owner CEO marketing services suppression domain pool email verification final approval gate",
|
|
@@ -1693,7 +1839,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1693
1839
|
],
|
|
1694
1840
|
requireVerifiedEmail: true
|
|
1695
1841
|
},
|
|
1696
|
-
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1842
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "email_finding", "email_verification", "signals"],
|
|
1697
1843
|
preferredProviders: ["signaliz_native", "octave"],
|
|
1698
1844
|
memoryQueries: [{
|
|
1699
1845
|
query: "cloud hosting infrastructure VMware Broadcom qualification verified email persona trigger SKU mapping",
|
|
@@ -1726,25 +1872,21 @@ var CampaignBuilderAgent = class {
|
|
|
1726
1872
|
async createPlan(request, options = {}) {
|
|
1727
1873
|
const resolvedRequest = applyCampaignBuilderStrategyTemplate(request);
|
|
1728
1874
|
const warnings = [];
|
|
1729
|
-
const workspaceContext =
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1875
|
+
const [workspaceContext, scopeResult] = await Promise.all([
|
|
1876
|
+
resolvedRequest.workspaceContext ? Promise.resolve(resolvedRequest.workspaceContext) : this.getWorkspaceContext(warnings),
|
|
1877
|
+
options.scopeCampaign === false ? Promise.resolve(void 0) : this.scopeCampaign(resolvedRequest, warnings),
|
|
1878
|
+
options.discoverCapabilities === false ? Promise.resolve(void 0) : this.discoverPlannedRoutes(resolvedRequest, warnings)
|
|
1879
|
+
]);
|
|
1734
1880
|
const plan = createCampaignBuilderAgentPlan(resolvedRequest, {
|
|
1735
1881
|
workspaceContext,
|
|
1736
1882
|
scopeBuildArgs: asRecord(scopeResult?.build_campaign_args ?? scopeResult?.buildCampaignArgs),
|
|
1737
1883
|
warnings
|
|
1738
1884
|
});
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
}
|
|
1745
|
-
if (options.includeDeliveryRisk !== false) {
|
|
1746
|
-
await this.attachDeliveryRiskPreflight(plan, warnings);
|
|
1747
|
-
}
|
|
1885
|
+
await Promise.all([
|
|
1886
|
+
options.includeStrategyMemoryStatus === false ? Promise.resolve() : this.attachStrategyMemoryStatus(plan, warnings),
|
|
1887
|
+
options.includeKernelPlan === false ? Promise.resolve() : this.attachKernelCampaignBuildPlan(plan, warnings),
|
|
1888
|
+
options.includeDeliveryRisk === false ? Promise.resolve() : this.attachDeliveryRiskPreflight(plan, warnings)
|
|
1889
|
+
]);
|
|
1748
1890
|
return plan;
|
|
1749
1891
|
}
|
|
1750
1892
|
async readiness(request, options = {}) {
|
|
@@ -1792,6 +1934,8 @@ var CampaignBuilderAgent = class {
|
|
|
1792
1934
|
},
|
|
1793
1935
|
brain_defaults: plan.buildRequest.brainDefaults,
|
|
1794
1936
|
brain_preflight: plan.buildRequest.brainPreflight,
|
|
1937
|
+
learning_holdout: plan.buildRequest.learningHoldout,
|
|
1938
|
+
campaign_strategy_context: plan.buildRequest.campaignStrategyContext,
|
|
1795
1939
|
delivery_risk_preflight: plan.buildRequest.deliveryRisk,
|
|
1796
1940
|
delivery_risk: plan.buildRequest.deliveryRisk
|
|
1797
1941
|
}),
|
|
@@ -1804,7 +1948,8 @@ var CampaignBuilderAgent = class {
|
|
|
1804
1948
|
estimated_credits: plan.estimatedCredits
|
|
1805
1949
|
},
|
|
1806
1950
|
brain_delivery_risk_preflight: plan.buildRequest.deliveryRisk,
|
|
1807
|
-
delivery_risk: plan.buildRequest.deliveryRisk
|
|
1951
|
+
delivery_risk: plan.buildRequest.deliveryRisk,
|
|
1952
|
+
learning_holdout: plan.buildRequest.learningHoldout
|
|
1808
1953
|
},
|
|
1809
1954
|
approval_required: plan.approvals.some((approval) => approval.blocking),
|
|
1810
1955
|
actor_type: "agent",
|
|
@@ -1913,7 +2058,8 @@ var CampaignBuilderAgent = class {
|
|
|
1913
2058
|
const destinationType = options.deliveryDestinationType ?? plan.buildRequest.delivery?.destinationType ?? "json";
|
|
1914
2059
|
result.deliveryApproval = await this.approveCampaignDelivery(campaignBuildId, destinationType, {
|
|
1915
2060
|
destinationId: options.deliveryDestinationId,
|
|
1916
|
-
destinationConfig: options.deliveryDestinationConfig ?? plan.buildRequest.delivery?.destinationConfig
|
|
2061
|
+
destinationConfig: options.deliveryDestinationConfig ?? plan.buildRequest.delivery?.destinationConfig,
|
|
2062
|
+
allowPartialDelivery: options.allowPartialDelivery
|
|
1917
2063
|
});
|
|
1918
2064
|
finalStatus = await this.waitForCampaignBuildStatus(
|
|
1919
2065
|
campaignBuildId,
|
|
@@ -1936,8 +2082,12 @@ var CampaignBuilderAgent = class {
|
|
|
1936
2082
|
const args = compact({
|
|
1937
2083
|
campaign_build_id: campaignBuildId,
|
|
1938
2084
|
page_size: options.limit,
|
|
1939
|
-
cursor: options.cursor
|
|
2085
|
+
cursor: options.cursor,
|
|
2086
|
+
include_data: options.includeData,
|
|
2087
|
+
include_raw: options.includeRaw
|
|
1940
2088
|
});
|
|
2089
|
+
if (options.cached !== void 0) filters.cached = options.cached;
|
|
2090
|
+
if (options.exportReady !== void 0) filters.export_ready = options.exportReady;
|
|
1941
2091
|
if (Object.keys(filters).length > 0) args.filters = filters;
|
|
1942
2092
|
const data = await this.callMcp("get_campaign_build_rows", args);
|
|
1943
2093
|
return mapAgentCampaignRowsResult(data);
|
|
@@ -1952,12 +2102,14 @@ var CampaignBuilderAgent = class {
|
|
|
1952
2102
|
return this.approveCampaignDelivery(campaignBuildId, destinationType, options);
|
|
1953
2103
|
}
|
|
1954
2104
|
async reviewBuild(campaignBuildId, options = {}) {
|
|
1955
|
-
const status = await
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
2105
|
+
const [status, rows, artifacts] = await Promise.all([
|
|
2106
|
+
this.getBuildStatus(campaignBuildId),
|
|
2107
|
+
this.getBuildRows(campaignBuildId, {
|
|
2108
|
+
...options,
|
|
2109
|
+
limit: options.limit ?? 100
|
|
2110
|
+
}),
|
|
2111
|
+
this.listBuildArtifacts(campaignBuildId)
|
|
2112
|
+
]);
|
|
1961
2113
|
return createCampaignBuilderBuildReview(status, rows, artifacts);
|
|
1962
2114
|
}
|
|
1963
2115
|
async getCampaignBuildStatus(campaignBuildId) {
|
|
@@ -1985,7 +2137,8 @@ var CampaignBuilderAgent = class {
|
|
|
1985
2137
|
campaign_build_id: campaignBuildId,
|
|
1986
2138
|
destination_type: destinationType,
|
|
1987
2139
|
destination_id: options?.destinationId,
|
|
1988
|
-
destination_config: options?.destinationConfig
|
|
2140
|
+
destination_config: options?.destinationConfig,
|
|
2141
|
+
allow_partial_delivery: options?.allowPartialDelivery === true ? true : void 0
|
|
1989
2142
|
});
|
|
1990
2143
|
const data = await this.callMcp("approve_campaign_delivery", args);
|
|
1991
2144
|
return {
|
|
@@ -1995,7 +2148,10 @@ var CampaignBuilderAgent = class {
|
|
|
1995
2148
|
message: data.message ?? "",
|
|
1996
2149
|
deliveryId: data.delivery_id,
|
|
1997
2150
|
deliveryIds: data.delivery_ids,
|
|
1998
|
-
approvedCount: data.approved_count
|
|
2151
|
+
approvedCount: data.approved_count,
|
|
2152
|
+
partialDelivery: data.partial_delivery,
|
|
2153
|
+
effectiveTargetCount: data.effective_target_count,
|
|
2154
|
+
requestedTargetCount: data.requested_target_count
|
|
1999
2155
|
};
|
|
2000
2156
|
}
|
|
2001
2157
|
async getWorkspaceContext(warnings) {
|
|
@@ -2031,15 +2187,19 @@ var CampaignBuilderAgent = class {
|
|
|
2031
2187
|
const providers = new Set(
|
|
2032
2188
|
[...request.integrations ?? [], ...routesFromCustomerTools(request.customerTools ?? [])].filter((route) => route.provider !== "signaliz").map((route) => route.provider)
|
|
2033
2189
|
);
|
|
2034
|
-
|
|
2190
|
+
const warningsByProvider = await Promise.all(Array.from(providers, async (provider) => {
|
|
2035
2191
|
try {
|
|
2036
2192
|
await this.callMcp("discover_capabilities", {
|
|
2037
2193
|
query: `campaign builder ${provider} ${request.goal}`,
|
|
2038
2194
|
category: "campaign"
|
|
2039
2195
|
});
|
|
2196
|
+
return void 0;
|
|
2040
2197
|
} catch (error) {
|
|
2041
|
-
|
|
2198
|
+
return `Capability discovery for ${provider} failed: ${errorMessage(error)}`;
|
|
2042
2199
|
}
|
|
2200
|
+
}));
|
|
2201
|
+
for (const warning of warningsByProvider) {
|
|
2202
|
+
if (warning) warnings.push(warning);
|
|
2043
2203
|
}
|
|
2044
2204
|
}
|
|
2045
2205
|
async attachStrategyMemoryStatus(plan, warnings) {
|
|
@@ -2063,8 +2223,24 @@ var CampaignBuilderAgent = class {
|
|
|
2063
2223
|
const kernelPlan = await this.callMcp("gtm_campaign_build_plan", asRecord(plannerStep.arguments));
|
|
2064
2224
|
plan.kernelPlan = asRecord(kernelPlan);
|
|
2065
2225
|
const brainDefaults = asRecord(plan.kernelPlan.brain_defaults ?? plan.kernelPlan.brainDefaults);
|
|
2226
|
+
const corpusContext = asRecord(plan.kernelPlan.corpus_context ?? plan.kernelPlan.corpusContext);
|
|
2227
|
+
const campaignStrategyContext = asRecord(plan.kernelPlan.campaign_strategy_context ?? plan.kernelPlan.campaignStrategyContext);
|
|
2228
|
+
const memoryExamples = Array.isArray(plan.kernelPlan.memory_examples) ? plan.kernelPlan.memory_examples.map((item) => asRecord(item)).filter((item) => Object.keys(item).length > 0).slice(0, 15) : [];
|
|
2066
2229
|
if (Object.keys(brainDefaults).length > 0 && Object.keys(asRecord(plan.buildRequest.brainDefaults)).length === 0) {
|
|
2067
2230
|
plan.buildRequest.brainDefaults = brainDefaults;
|
|
2231
|
+
}
|
|
2232
|
+
if (Object.keys(campaignStrategyContext).length > 0) {
|
|
2233
|
+
plan.buildRequest.campaignStrategyContext = campaignStrategyContext;
|
|
2234
|
+
}
|
|
2235
|
+
if (Object.keys(corpusContext).length > 0 || memoryExamples.length > 0 || Object.keys(brainDefaults).length > 0 || Object.keys(campaignStrategyContext).length > 0) {
|
|
2236
|
+
plan.buildRequest.brainPreflight = compact({
|
|
2237
|
+
...asRecord(plan.buildRequest.brainPreflight),
|
|
2238
|
+
corpus_context: Object.keys(corpusContext).length > 0 ? corpusContext : void 0,
|
|
2239
|
+
memory_examples: memoryExamples.length > 0 ? memoryExamples : void 0,
|
|
2240
|
+
brain_defaults: Object.keys(brainDefaults).length > 0 ? brainDefaults : void 0,
|
|
2241
|
+
campaign_strategy_context: Object.keys(campaignStrategyContext).length > 0 ? campaignStrategyContext : void 0
|
|
2242
|
+
});
|
|
2243
|
+
plan.brainPreflight = asRecord(plan.buildRequest.brainPreflight);
|
|
2068
2244
|
refreshBuildStepArguments(plan);
|
|
2069
2245
|
}
|
|
2070
2246
|
} catch (error) {
|
|
@@ -2245,6 +2421,9 @@ function createCampaignBuilderProofReceipt(plan, result) {
|
|
|
2245
2421
|
campaign_build_id: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null
|
|
2246
2422
|
}
|
|
2247
2423
|
];
|
|
2424
|
+
const learnBackPlan = summarizeCampaignBuilderProofLearnBack(
|
|
2425
|
+
asRecord(asRecord(plan.buildRequest.brainPreflight).learn_back_plan ?? asRecord(plan.brainPreflight).learn_back_plan)
|
|
2426
|
+
);
|
|
2248
2427
|
return {
|
|
2249
2428
|
receipt_version: "campaign-agent-proof.v1",
|
|
2250
2429
|
source: "signaliz.campaignBuilderAgent.proof",
|
|
@@ -2267,6 +2446,7 @@ function createCampaignBuilderProofReceipt(plan, result) {
|
|
|
2267
2446
|
gates,
|
|
2268
2447
|
strategy_memory_status: summarizeCampaignBuilderProofStrategyMemory(strategyMemory),
|
|
2269
2448
|
dry_run_result: summarizeCampaignBuilderProofDryRun(dryRunResult),
|
|
2449
|
+
learn_back_plan: learnBackPlan,
|
|
2270
2450
|
recommended_next_actions: [
|
|
2271
2451
|
"Review the plan, approvals, and dry-run result.",
|
|
2272
2452
|
"Use campaign-agent commit-plan --confirm-write only after review.",
|
|
@@ -2823,6 +3003,13 @@ function campaignBuilderMemoryKitSdkExample(request, seedManifestFile) {
|
|
|
2823
3003
|
function campaignBuilderMemoryKitSource(source) {
|
|
2824
3004
|
const normalized = normalizeTemplateKey(source || "agency");
|
|
2825
3005
|
const catalog = {
|
|
3006
|
+
northStar: {
|
|
3007
|
+
id: "north_star_campaign_builder",
|
|
3008
|
+
label: "North Star campaign-builder acceptance patterns",
|
|
3009
|
+
seed_source: "north-star",
|
|
3010
|
+
scope: "redacted_acceptance_seed_packs",
|
|
3011
|
+
privacy: "redacted aggregate counts, QA gates, and fixture shape only"
|
|
3012
|
+
},
|
|
2826
3013
|
agency: {
|
|
2827
3014
|
id: "agency_campaign_builder",
|
|
2828
3015
|
label: "Agency campaign-builder strategy patterns",
|
|
@@ -2848,6 +3035,10 @@ function campaignBuilderMemoryKitSource(source) {
|
|
|
2848
3035
|
const sourceMap = {
|
|
2849
3036
|
agency: "agency",
|
|
2850
3037
|
"campaign-builder": "agency",
|
|
3038
|
+
"north-star": "northStar",
|
|
3039
|
+
northstar: "northStar",
|
|
3040
|
+
"campaign-builder-north-star": "northStar",
|
|
3041
|
+
acceptance: "northStar",
|
|
2851
3042
|
"strategy-memory": "agency",
|
|
2852
3043
|
"workflow-patterns": "workflow",
|
|
2853
3044
|
workflow: "workflow",
|
|
@@ -2863,13 +3054,13 @@ function campaignBuilderMemoryKitSource(source) {
|
|
|
2863
3054
|
return {
|
|
2864
3055
|
seedSource: "all",
|
|
2865
3056
|
verifyScript: null,
|
|
2866
|
-
memorySources: [catalog.agency, catalog.workflow, catalog.feedback]
|
|
3057
|
+
memorySources: [catalog.northStar, catalog.agency, catalog.workflow, catalog.feedback]
|
|
2867
3058
|
};
|
|
2868
3059
|
}
|
|
2869
3060
|
const item = catalog[selected];
|
|
2870
3061
|
return {
|
|
2871
3062
|
seedSource: item.seed_source,
|
|
2872
|
-
verifyScript: item.seed_source === "agency" ? "scripts/gtm-kernel/verify-agency-import-manifest.mjs" : item.seed_source === "building-clay" ? "scripts/gtm-kernel/verify-building-clay-import-manifest.mjs" : null,
|
|
3063
|
+
verifyScript: item.seed_source === "north-star" ? "scripts/gtm-kernel/verify-north-star-import-manifest.mjs" : item.seed_source === "agency" ? "scripts/gtm-kernel/verify-agency-import-manifest.mjs" : item.seed_source === "building-clay" ? "scripts/gtm-kernel/verify-building-clay-import-manifest.mjs" : null,
|
|
2873
3064
|
memorySources: [item]
|
|
2874
3065
|
};
|
|
2875
3066
|
}
|
|
@@ -3049,11 +3240,11 @@ function builtInRoutesFor(request) {
|
|
|
3049
3240
|
routes.push({
|
|
3050
3241
|
id: "signaliz-lead-generation",
|
|
3051
3242
|
layer: "source",
|
|
3052
|
-
|
|
3243
|
+
gtmLayer: "lead_generation",
|
|
3053
3244
|
provider: "signaliz",
|
|
3054
3245
|
mode: "required",
|
|
3055
3246
|
toolName: "generate_leads",
|
|
3056
|
-
rationale: "
|
|
3247
|
+
rationale: "Inventory verified cache first, then use Signaliz fresh workspace acquisition for the remaining approved gap."
|
|
3057
3248
|
});
|
|
3058
3249
|
}
|
|
3059
3250
|
if (builtIns.has("local_leads")) {
|
|
@@ -3067,6 +3258,28 @@ function builtInRoutesFor(request) {
|
|
|
3067
3258
|
rationale: "Use Signaliz local-leads sourcing for geography-bound local business campaigns."
|
|
3068
3259
|
});
|
|
3069
3260
|
}
|
|
3261
|
+
if (builtIns.has("company_discovery")) {
|
|
3262
|
+
routes.push({
|
|
3263
|
+
id: "signaliz-company-discovery",
|
|
3264
|
+
layer: "source",
|
|
3265
|
+
gtmLayer: "find_company",
|
|
3266
|
+
provider: "signaliz",
|
|
3267
|
+
mode: "if_available",
|
|
3268
|
+
toolName: "find_companies_signaliz",
|
|
3269
|
+
rationale: "Find and qualify company domains before people/email fill for account-led campaigns."
|
|
3270
|
+
});
|
|
3271
|
+
}
|
|
3272
|
+
if (builtIns.has("people_discovery")) {
|
|
3273
|
+
routes.push({
|
|
3274
|
+
id: "signaliz-people-discovery",
|
|
3275
|
+
layer: "source",
|
|
3276
|
+
gtmLayer: "find_people",
|
|
3277
|
+
provider: "signaliz",
|
|
3278
|
+
mode: "if_available",
|
|
3279
|
+
toolName: "find_people_signaliz",
|
|
3280
|
+
rationale: "Find people directly when the brief is contact research or LinkedIn-style prospecting."
|
|
3281
|
+
});
|
|
3282
|
+
}
|
|
3070
3283
|
if (builtIns.has("email_finding")) {
|
|
3071
3284
|
routes.push({
|
|
3072
3285
|
id: "signaliz-email-finding",
|
|
@@ -3111,7 +3324,7 @@ function normalizeBuiltIns(request) {
|
|
|
3111
3324
|
return [...builtIns].filter(isCampaignBuilderBuiltInTool);
|
|
3112
3325
|
}
|
|
3113
3326
|
function isCampaignBuilderBuiltInTool(value) {
|
|
3114
|
-
return ["lead_generation", "local_leads", "email_finding", "email_verification", "signals"].includes(String(value));
|
|
3327
|
+
return ["lead_generation", "local_leads", "company_discovery", "people_discovery", "email_finding", "email_verification", "signals"].includes(String(value));
|
|
3115
3328
|
}
|
|
3116
3329
|
function looksLikeLocalLeadCampaign(request) {
|
|
3117
3330
|
const text = [
|
|
@@ -3142,6 +3355,21 @@ function routesFromCustomerTools(tools) {
|
|
|
3142
3355
|
}))
|
|
3143
3356
|
);
|
|
3144
3357
|
}
|
|
3358
|
+
function normalizeCampaignBuilderLearningHoldout(input, gtmCampaignId, campaignName) {
|
|
3359
|
+
const source = asRecord(input);
|
|
3360
|
+
if (source.enabled === false) return { enabled: false };
|
|
3361
|
+
const controlPercentage = numberOrUndefined2(source.control_percentage ?? source.controlPercentage);
|
|
3362
|
+
const minControlSize = numberOrUndefined2(source.min_control_size ?? source.minControlSize);
|
|
3363
|
+
const experimentKey = stringValue(source.experiment_key ?? source.experimentKey) ?? (gtmCampaignId ? `gtm_campaign:${gtmCampaignId}:learning_holdout` : `campaign_builder_agent:${hashString(campaignName)}:learning_holdout`);
|
|
3364
|
+
return {
|
|
3365
|
+
enabled: true,
|
|
3366
|
+
controlPercentage: controlPercentage ?? 0.2,
|
|
3367
|
+
minControlSize: minControlSize ?? 50,
|
|
3368
|
+
experimentKey,
|
|
3369
|
+
sourceCampaignId: stringValue(source.source_campaign_id ?? source.sourceCampaignId) ?? gtmCampaignId,
|
|
3370
|
+
primaryMetric: stringValue(source.primary_metric ?? source.primaryMetric) ?? "positive_reply_rate"
|
|
3371
|
+
};
|
|
3372
|
+
}
|
|
3145
3373
|
function createBuildRequest(request, defaults, targetCount, campaignName, scopeBuildArgs, routes = [], memory, scopeBrainPreflight) {
|
|
3146
3374
|
const buildRequest = {
|
|
3147
3375
|
name: campaignName,
|
|
@@ -3166,10 +3394,19 @@ function createBuildRequest(request, defaults, targetCount, campaignName, scopeB
|
|
|
3166
3394
|
qualification: defaults.qualification,
|
|
3167
3395
|
copy: defaults.copy,
|
|
3168
3396
|
delivery: defaults.delivery,
|
|
3169
|
-
enhancers: enhancerConfig(request)
|
|
3397
|
+
enhancers: enhancerConfig(request),
|
|
3398
|
+
sourceRouting: request.sourceRouting ?? {
|
|
3399
|
+
mode: looksLikeLocalLeadCampaign(request) ? "local_leads" : "auto",
|
|
3400
|
+
fillPolicy: "aggressive"
|
|
3401
|
+
}
|
|
3170
3402
|
};
|
|
3171
3403
|
const scoped = asRecord(scopeBuildArgs);
|
|
3172
3404
|
buildRequest.gtmCampaignId = request.gtmCampaignId ?? stringValue(scoped.gtm_campaign_id ?? scoped.gtmCampaignId);
|
|
3405
|
+
buildRequest.learningHoldout = normalizeCampaignBuilderLearningHoldout(
|
|
3406
|
+
request.learningHoldout ?? scoped.learning_holdout ?? scoped.learningHoldout,
|
|
3407
|
+
buildRequest.gtmCampaignId,
|
|
3408
|
+
campaignName
|
|
3409
|
+
);
|
|
3173
3410
|
if (typeof scoped.name === "string") buildRequest.name = scoped.name;
|
|
3174
3411
|
if (typeof scoped.prompt === "string") buildRequest.prompt = scoped.prompt;
|
|
3175
3412
|
if (typeof scoped.target_count === "number") buildRequest.targetCount = scoped.target_count;
|
|
@@ -3244,13 +3481,137 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
3244
3481
|
target_icp: targetIcp,
|
|
3245
3482
|
provider_chain: providerChain,
|
|
3246
3483
|
lead_source: providerChain[0] ?? "signaliz",
|
|
3484
|
+
learning_holdout: buildRequest.learningHoldout,
|
|
3247
3485
|
tool_sequence: [
|
|
3248
3486
|
{ tool: "gtm_brain_learning_cycle_plan", purpose: "Plan the Brain learning loop for this campaign.", arguments: learningArgs },
|
|
3249
3487
|
{ tool: "gtm_brain_seed_defaults", purpose: "Seed campaign defaults from workspace memory and safe aggregate patterns.", arguments: defaultsArgs },
|
|
3250
3488
|
{ tool: "gtm_brain_delivery_risk", purpose: "Check deliverability risk before launch or external writes.", arguments: riskArgs }
|
|
3251
|
-
]
|
|
3489
|
+
],
|
|
3490
|
+
learn_back_plan: createCampaignBuilderLearnBackPlan(request, buildRequest)
|
|
3491
|
+
};
|
|
3492
|
+
}
|
|
3493
|
+
function createCampaignBuilderLearnBackPlan(request, buildRequest) {
|
|
3494
|
+
const instantlyFeedbackContext = campaignBuilderProviderFeedbackContext(request, buildRequest, "instantly");
|
|
3495
|
+
const postBuildSequence = [
|
|
3496
|
+
{
|
|
3497
|
+
tool: "get_campaign_build_status",
|
|
3498
|
+
approval_boundary: "read_only",
|
|
3499
|
+
arguments_template: { campaign_build_id: "<build_campaign.campaign_build_id>" },
|
|
3500
|
+
reason: "Wait for the Campaign Builder run to finish before deriving memory."
|
|
3501
|
+
},
|
|
3502
|
+
{
|
|
3503
|
+
tool: "gtm_campaign_build_backfill_preview",
|
|
3504
|
+
approval_boundary: "read_only",
|
|
3505
|
+
arguments_template: { campaign_build_id: "<build_campaign.campaign_build_id>", create_memory: true },
|
|
3506
|
+
reason: "Preview the provider-neutral Kernel import payload without writing rows."
|
|
3507
|
+
},
|
|
3508
|
+
{
|
|
3509
|
+
tool: "gtm_campaign_build_backfill_run",
|
|
3510
|
+
approval_boundary: "dry_run",
|
|
3511
|
+
arguments_template: { campaign_build_ids: ["<build_campaign.campaign_build_id>"], dry_run: true, create_memory: true, run_brain_cycle: false },
|
|
3512
|
+
reason: "Dry-run the Kernel history import before creating campaign memory."
|
|
3513
|
+
},
|
|
3514
|
+
{
|
|
3515
|
+
tool: "gtm_campaign_build_backfill_run",
|
|
3516
|
+
approval_boundary: "explicit_write_approval",
|
|
3517
|
+
arguments_template: { campaign_build_ids: ["<build_campaign.campaign_build_id>"], dry_run: false, create_memory: true, run_brain_cycle: true, brain_cycle_write_mode: "dry_run" },
|
|
3518
|
+
reason: "After review, queue the Kernel history import; Brain learning remains dry-run unless separately approved."
|
|
3519
|
+
}
|
|
3520
|
+
];
|
|
3521
|
+
if (instantlyFeedbackContext) {
|
|
3522
|
+
postBuildSequence.push({
|
|
3523
|
+
tool: "gtm_instantly_feedback_pull",
|
|
3524
|
+
approval_boundary: "dry_run_first_explicit_write_approval",
|
|
3525
|
+
arguments_template: {
|
|
3526
|
+
campaign_id: buildRequest.gtmCampaignId || "<gtm_campaign_id_after_commit>",
|
|
3527
|
+
campaign_build_id: "<build_campaign.campaign_build_id>",
|
|
3528
|
+
source: "emails",
|
|
3529
|
+
email_type: "received",
|
|
3530
|
+
...instantlyFeedbackContext,
|
|
3531
|
+
dry_run: true,
|
|
3532
|
+
create_memory: true,
|
|
3533
|
+
write_routine_outcomes: true,
|
|
3534
|
+
run_brain_cycle: true,
|
|
3535
|
+
brain_cycle_write_mode: "dry_run"
|
|
3536
|
+
},
|
|
3537
|
+
reason: "After Instantly delivery has live outcomes, pull reply and bounce history into private feedback memory before Brain learning."
|
|
3538
|
+
});
|
|
3539
|
+
}
|
|
3540
|
+
postBuildSequence.push(
|
|
3541
|
+
{
|
|
3542
|
+
tool: "gtm_campaign_learning_status",
|
|
3543
|
+
approval_boundary: "read_only",
|
|
3544
|
+
arguments_template: {
|
|
3545
|
+
campaign_id: buildRequest.gtmCampaignId || "<gtm_campaign_id_after_commit>",
|
|
3546
|
+
campaign_build_id: "<build_campaign.campaign_build_id>",
|
|
3547
|
+
write_mode: "dry_run"
|
|
3548
|
+
},
|
|
3549
|
+
reason: "Confirm feedback, memory, and Brain learning readiness after the import."
|
|
3550
|
+
},
|
|
3551
|
+
{
|
|
3552
|
+
tool: "gtm_memory_search",
|
|
3553
|
+
approval_boundary: "read_only",
|
|
3554
|
+
arguments_template: {
|
|
3555
|
+
query: request.goal,
|
|
3556
|
+
...buildRequest.gtmCampaignId ? { campaign_id: buildRequest.gtmCampaignId } : {},
|
|
3557
|
+
limit: 10
|
|
3558
|
+
},
|
|
3559
|
+
reason: "Verify the new private memory is retrievable for future campaign planning."
|
|
3560
|
+
},
|
|
3561
|
+
{
|
|
3562
|
+
tool: "gtm_brain_learning_cycle_plan",
|
|
3563
|
+
approval_boundary: "read_only",
|
|
3564
|
+
arguments_template: {
|
|
3565
|
+
...buildRequest.gtmCampaignId ? { campaign_id: buildRequest.gtmCampaignId } : {},
|
|
3566
|
+
include_memory: true,
|
|
3567
|
+
write_mode: "dry_run"
|
|
3568
|
+
},
|
|
3569
|
+
reason: "Plan the Brain phases from the imported outcomes before any pattern writes."
|
|
3570
|
+
}
|
|
3571
|
+
);
|
|
3572
|
+
return {
|
|
3573
|
+
source_tool: "campaign-builder-agent",
|
|
3574
|
+
gtm_campaign_id: buildRequest.gtmCampaignId ?? null,
|
|
3575
|
+
trigger: "After build_campaign returns a campaign_build_id and the build reaches a terminal reviewed state.",
|
|
3576
|
+
build_result_placeholders: {
|
|
3577
|
+
campaign_build_id: "<build_campaign.campaign_build_id>"
|
|
3578
|
+
},
|
|
3579
|
+
memory_write_policy: {
|
|
3580
|
+
target_tables: ["gtm_campaigns", "gtm_campaign_provider_links", "gtm_campaign_feedback_events", "gtm_memory_items", "gtm_brain_patterns"],
|
|
3581
|
+
gtm_memory_items: {
|
|
3582
|
+
shareable: false,
|
|
3583
|
+
allowed_redaction_states: ["redacted", "abstracted"],
|
|
3584
|
+
raw_private_fields_withheld: ["reply_text", "copy_body", "lead_email", "lead_domain", "company_domain", "provider_campaign_id", "provider_payload", "webhook_url", "secret"]
|
|
3585
|
+
},
|
|
3586
|
+
gtm_brain_patterns: "Workspace-scoped by default. Global promotion requires abstracted_only=true, shared opt-in, and privacy thresholds."
|
|
3587
|
+
},
|
|
3588
|
+
post_build_sequence: postBuildSequence.map((item, index) => ({ step: index + 1, ...item })),
|
|
3589
|
+
approval_policy: "This agent plan never writes learn-back rows. Backfill and provider-feedback writes require dry_run=false after review, and Brain writes require their own approved learning-cycle run.",
|
|
3590
|
+
privacy_policy: "Learn-back memory is workspace-private. Raw replies, copy bodies, leads, emails, domains, provider payloads, webhook URLs, secrets, private source paths, and raw client labels are withheld from memory rows and agent-visible outputs."
|
|
3252
3591
|
};
|
|
3253
3592
|
}
|
|
3593
|
+
function campaignBuilderProviderFeedbackContext(request, buildRequest, provider) {
|
|
3594
|
+
const normalizedProvider = String(provider).toLowerCase();
|
|
3595
|
+
const routes = [...request.integrations ?? [], ...routesFromCustomerTools(request.customerTools ?? [])];
|
|
3596
|
+
const providerRoute = routes.find((route) => String(route.provider).toLowerCase() === normalizedProvider);
|
|
3597
|
+
const routeConfig = asRecord(providerRoute?.config);
|
|
3598
|
+
const deliveryConfig = asRecord(buildRequest.delivery?.destinationConfig);
|
|
3599
|
+
const hasProviderContext = [
|
|
3600
|
+
...request.preferredProviders ?? [],
|
|
3601
|
+
...routes.map((route) => route.provider),
|
|
3602
|
+
stringValue(deliveryConfig.provider),
|
|
3603
|
+
stringValue(deliveryConfig.provider_id ?? deliveryConfig.providerId),
|
|
3604
|
+
stringValue(deliveryConfig.destination_provider ?? deliveryConfig.destinationProvider),
|
|
3605
|
+
stringValue(deliveryConfig.sink ?? deliveryConfig.sink_type ?? deliveryConfig.sinkType)
|
|
3606
|
+
].some((value) => String(value).toLowerCase() === normalizedProvider);
|
|
3607
|
+
if (!hasProviderContext) return void 0;
|
|
3608
|
+
return compact({
|
|
3609
|
+
provider_link_id: stringValue(routeConfig.provider_link_id ?? routeConfig.providerLinkId ?? deliveryConfig.provider_link_id ?? deliveryConfig.providerLinkId),
|
|
3610
|
+
provider_campaign_id: stringValue(routeConfig.provider_campaign_id ?? routeConfig.providerCampaignId ?? routeConfig.instantly_campaign_id ?? routeConfig.instantlyCampaignId ?? deliveryConfig.provider_campaign_id ?? deliveryConfig.providerCampaignId ?? deliveryConfig.instantly_campaign_id ?? deliveryConfig.instantlyCampaignId),
|
|
3611
|
+
integration_id: stringValue(routeConfig.integration_id ?? routeConfig.integrationId ?? deliveryConfig.integration_id ?? deliveryConfig.integrationId),
|
|
3612
|
+
instantly_profile: stringValue(routeConfig.instantly_profile ?? routeConfig.instantlyProfile ?? routeConfig.profile ?? deliveryConfig.instantly_profile ?? deliveryConfig.instantlyProfile ?? deliveryConfig.profile)
|
|
3613
|
+
});
|
|
3614
|
+
}
|
|
3254
3615
|
function gtmLayersForBuilderLayer(layer) {
|
|
3255
3616
|
const map = {
|
|
3256
3617
|
workspace_context: ["customer_data"],
|
|
@@ -3655,6 +4016,7 @@ function buildFallbackPlanSnapshot(plan) {
|
|
|
3655
4016
|
target_count: plan.targetCount,
|
|
3656
4017
|
approvals: plan.approvals,
|
|
3657
4018
|
brain_preflight: plan.brainPreflight,
|
|
4019
|
+
campaign_strategy_context: plan.buildRequest.campaignStrategyContext,
|
|
3658
4020
|
operating_playbooks: plan.operatingPlaybooks
|
|
3659
4021
|
});
|
|
3660
4022
|
}
|
|
@@ -3787,6 +4149,17 @@ function buildCampaignArgs(request) {
|
|
|
3787
4149
|
if (request.dedupKeys) args.dedup_keys = request.dedupKeys;
|
|
3788
4150
|
if (request.brainPreflight) args.brain_preflight = request.brainPreflight;
|
|
3789
4151
|
if (request.brainDefaults) args.brain_defaults = request.brainDefaults;
|
|
4152
|
+
if (request.learningHoldout) {
|
|
4153
|
+
args.learning_holdout = compact({
|
|
4154
|
+
enabled: request.learningHoldout.enabled,
|
|
4155
|
+
control_percentage: request.learningHoldout.controlPercentage,
|
|
4156
|
+
min_control_size: request.learningHoldout.minControlSize,
|
|
4157
|
+
experiment_key: request.learningHoldout.experimentKey,
|
|
4158
|
+
source_campaign_id: request.learningHoldout.sourceCampaignId,
|
|
4159
|
+
primary_metric: request.learningHoldout.primaryMetric
|
|
4160
|
+
});
|
|
4161
|
+
}
|
|
4162
|
+
if (request.campaignStrategyContext) args.campaign_strategy_context = request.campaignStrategyContext;
|
|
3790
4163
|
if (request.deliveryRisk) args.delivery_risk = request.deliveryRisk;
|
|
3791
4164
|
if (request.icp) {
|
|
3792
4165
|
args.icp = compact({
|
|
@@ -3806,6 +4179,15 @@ function buildCampaignArgs(request) {
|
|
|
3806
4179
|
model: request.policy.model
|
|
3807
4180
|
});
|
|
3808
4181
|
}
|
|
4182
|
+
if (request.sourceRouting) {
|
|
4183
|
+
args.source_routing = compact({
|
|
4184
|
+
mode: request.sourceRouting.mode,
|
|
4185
|
+
fill_policy: request.sourceRouting.fillPolicy,
|
|
4186
|
+
shard_size: request.sourceRouting.shardSize,
|
|
4187
|
+
max_source_shard_size: request.sourceRouting.maxSourceShardSize,
|
|
4188
|
+
max_local_source_shard_size: request.sourceRouting.maxLocalSourceShardSize
|
|
4189
|
+
});
|
|
4190
|
+
}
|
|
3809
4191
|
if (request.signals) {
|
|
3810
4192
|
args.signals = compact({
|
|
3811
4193
|
enabled: request.signals.enabled,
|
|
@@ -3873,11 +4255,13 @@ function buildExecutionPrepareArgs(request, dryRun, confirmSpend) {
|
|
|
3873
4255
|
delivery_risk: buildArgs2.delivery_risk,
|
|
3874
4256
|
dedup_keys: buildArgs2.dedup_keys,
|
|
3875
4257
|
policy: buildArgs2.policy,
|
|
4258
|
+
learning_holdout: buildArgs2.learning_holdout,
|
|
3876
4259
|
signals: buildArgs2.signals,
|
|
3877
4260
|
qualification: buildArgs2.qualification,
|
|
3878
4261
|
copy: buildArgs2.copy,
|
|
3879
4262
|
delivery: buildArgs2.delivery,
|
|
3880
|
-
enhancers: buildArgs2.enhancers
|
|
4263
|
+
enhancers: buildArgs2.enhancers,
|
|
4264
|
+
source_routing: buildArgs2.source_routing
|
|
3881
4265
|
});
|
|
3882
4266
|
}
|
|
3883
4267
|
function buildDeliveryApprovalArgs(request) {
|
|
@@ -3906,10 +4290,145 @@ function mapBuildResult(data, dryRun) {
|
|
|
3906
4290
|
targetLimitReason: data.target_limit_reason,
|
|
3907
4291
|
maxSupportedTargetCount: data.max_supported_target_count,
|
|
3908
4292
|
brainContext: data.brain_context ?? {},
|
|
4293
|
+
learningHoldout: data.learning_holdout ?? {},
|
|
3909
4294
|
providerRoute: mapProviderRoute2(data)
|
|
3910
4295
|
};
|
|
3911
4296
|
}
|
|
4297
|
+
var CAMPAIGN_BUILDER_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "canceled", "cancelled"]);
|
|
4298
|
+
var CAMPAIGN_BUILDER_BLOCKED_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["failed", "canceled", "cancelled"]);
|
|
4299
|
+
function mapAgentCampaignPhaseHealth(value) {
|
|
4300
|
+
if (!Array.isArray(value)) return [];
|
|
4301
|
+
return value.map((phase) => {
|
|
4302
|
+
const record = asRecord(phase);
|
|
4303
|
+
return {
|
|
4304
|
+
phase: stringValue(record.phase) ?? "unknown",
|
|
4305
|
+
status: stringValue(record.status) ?? "unknown",
|
|
4306
|
+
recordsProcessed: numberOrNull2(record.records_processed ?? record.recordsProcessed),
|
|
4307
|
+
recordsSucceeded: numberOrNull2(record.records_succeeded ?? record.recordsSucceeded),
|
|
4308
|
+
recordsFailed: numberOrNull2(record.records_failed ?? record.recordsFailed),
|
|
4309
|
+
heartbeatAgeSeconds: numberOrNull2(record.heartbeat_age_seconds ?? record.heartbeatAgeSeconds ?? record.phase_age_seconds)
|
|
4310
|
+
};
|
|
4311
|
+
});
|
|
4312
|
+
}
|
|
4313
|
+
function deriveCampaignBuildTerminalState(input) {
|
|
4314
|
+
const status = input.status.toLowerCase();
|
|
4315
|
+
const heartbeatAgeSeconds = input.phaseAgeSeconds;
|
|
4316
|
+
const stale = input.staleRunningPhase === true;
|
|
4317
|
+
const safeWatchAction = input.triggerRunId ? `signaliz ops run-status ${input.triggerRunId} --watch` : "signaliz campaign-agent status <campaign_build_id>";
|
|
4318
|
+
if (CAMPAIGN_BUILDER_BLOCKED_TERMINAL_STATUSES.has(status)) {
|
|
4319
|
+
return {
|
|
4320
|
+
kind: "blocked",
|
|
4321
|
+
label: "Blocked terminal state",
|
|
4322
|
+
reviewable: true,
|
|
4323
|
+
terminal: true,
|
|
4324
|
+
stale: false,
|
|
4325
|
+
phase: input.phase,
|
|
4326
|
+
phaseStatus: input.phaseStatus,
|
|
4327
|
+
heartbeatAgeSeconds,
|
|
4328
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4329
|
+
terminalReason: input.terminalReason,
|
|
4330
|
+
staleReason: null,
|
|
4331
|
+
safeNextAction: input.nextAction || "Review errors and rerun only after the blocker is resolved."
|
|
4332
|
+
};
|
|
4333
|
+
}
|
|
4334
|
+
if (status === "pending_approval") {
|
|
4335
|
+
return {
|
|
4336
|
+
kind: "pending_approval",
|
|
4337
|
+
label: "Pending delivery approval",
|
|
4338
|
+
reviewable: true,
|
|
4339
|
+
terminal: false,
|
|
4340
|
+
stale: false,
|
|
4341
|
+
phase: input.phase,
|
|
4342
|
+
phaseStatus: input.phaseStatus,
|
|
4343
|
+
heartbeatAgeSeconds,
|
|
4344
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4345
|
+
terminalReason: input.terminalReason,
|
|
4346
|
+
staleReason: null,
|
|
4347
|
+
safeNextAction: input.approvalAction || input.nextAction || "Review rows and approve delivery only after the approval packet passes."
|
|
4348
|
+
};
|
|
4349
|
+
}
|
|
4350
|
+
if (CAMPAIGN_BUILDER_TERMINAL_STATUSES.has(status)) {
|
|
4351
|
+
return {
|
|
4352
|
+
kind: "terminal",
|
|
4353
|
+
label: "Terminal and reviewable",
|
|
4354
|
+
reviewable: true,
|
|
4355
|
+
terminal: true,
|
|
4356
|
+
stale: false,
|
|
4357
|
+
phase: input.phase,
|
|
4358
|
+
phaseStatus: input.phaseStatus,
|
|
4359
|
+
heartbeatAgeSeconds,
|
|
4360
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4361
|
+
terminalReason: input.terminalReason,
|
|
4362
|
+
staleReason: null,
|
|
4363
|
+
safeNextAction: input.nextAction || "Review rows, artifacts, scorecard, and approval locks before delivery."
|
|
4364
|
+
};
|
|
4365
|
+
}
|
|
4366
|
+
if (status === "running" || status === "queued" || status === "processing") {
|
|
4367
|
+
if (stale) {
|
|
4368
|
+
return {
|
|
4369
|
+
kind: "running_stale",
|
|
4370
|
+
label: "Running but stale",
|
|
4371
|
+
reviewable: false,
|
|
4372
|
+
terminal: false,
|
|
4373
|
+
stale: true,
|
|
4374
|
+
phase: input.phase,
|
|
4375
|
+
phaseStatus: input.phaseStatus,
|
|
4376
|
+
heartbeatAgeSeconds,
|
|
4377
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4378
|
+
terminalReason: null,
|
|
4379
|
+
staleReason: input.staleReason || "The active phase heartbeat is stale.",
|
|
4380
|
+
safeNextAction: input.nextAction || safeWatchAction
|
|
4381
|
+
};
|
|
4382
|
+
}
|
|
4383
|
+
return {
|
|
4384
|
+
kind: "running_healthy",
|
|
4385
|
+
label: "Running and healthy",
|
|
4386
|
+
reviewable: false,
|
|
4387
|
+
terminal: false,
|
|
4388
|
+
stale: false,
|
|
4389
|
+
phase: input.phase,
|
|
4390
|
+
phaseStatus: input.phaseStatus,
|
|
4391
|
+
heartbeatAgeSeconds,
|
|
4392
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4393
|
+
terminalReason: null,
|
|
4394
|
+
staleReason: null,
|
|
4395
|
+
safeNextAction: input.nextAction || safeWatchAction
|
|
4396
|
+
};
|
|
4397
|
+
}
|
|
4398
|
+
return {
|
|
4399
|
+
kind: "unknown",
|
|
4400
|
+
label: "Unknown build state",
|
|
4401
|
+
reviewable: false,
|
|
4402
|
+
terminal: false,
|
|
4403
|
+
stale,
|
|
4404
|
+
phase: input.phase,
|
|
4405
|
+
phaseStatus: input.phaseStatus,
|
|
4406
|
+
heartbeatAgeSeconds,
|
|
4407
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4408
|
+
terminalReason: input.terminalReason,
|
|
4409
|
+
staleReason: input.staleReason,
|
|
4410
|
+
safeNextAction: input.nextAction || "Read campaign build status again before making a launch or delivery decision."
|
|
4411
|
+
};
|
|
4412
|
+
}
|
|
3912
4413
|
function mapAgentCampaignBuildStatus(data) {
|
|
4414
|
+
const customerRowCounts = mapAgentCustomerRowCounts(data.customer_row_counts);
|
|
4415
|
+
const phaseHealth = mapAgentCampaignPhaseHealth(data.phases);
|
|
4416
|
+
const terminalReason = stringValue(data.terminal_reason) ?? customerRowCounts?.terminalReason ?? null;
|
|
4417
|
+
const staleReason = stringValue(data.stale_reason) ?? stringValue(asRecord(data.diagnostics).stale_reason) ?? null;
|
|
4418
|
+
const nextPollAfterSeconds = numberOrNull2(data.next_poll_after_seconds ?? data.nextPollAfterSeconds);
|
|
4419
|
+
const terminalState = deriveCampaignBuildTerminalState({
|
|
4420
|
+
status: stringValue(data.status) ?? "unknown",
|
|
4421
|
+
phase: stringValue(data.current_phase) ?? null,
|
|
4422
|
+
phaseStatus: stringValue(data.current_phase_status) ?? null,
|
|
4423
|
+
staleRunningPhase: data.stale_running_phase === true,
|
|
4424
|
+
phaseAgeSeconds: numberOrNull2(data.phase_age_seconds),
|
|
4425
|
+
nextPollAfterSeconds,
|
|
4426
|
+
terminalReason,
|
|
4427
|
+
staleReason,
|
|
4428
|
+
nextAction: formatAgentNextAction(data.next_action),
|
|
4429
|
+
approvalAction: formatAgentNextAction(data.approval_action),
|
|
4430
|
+
triggerRunId: stringValue(data.trigger_run_id) ?? null
|
|
4431
|
+
});
|
|
3913
4432
|
return {
|
|
3914
4433
|
campaignBuildId: stringValue(data.campaign_build_id) ?? "",
|
|
3915
4434
|
campaignId: stringValue(data.campaign_id) ?? null,
|
|
@@ -3926,17 +4445,68 @@ function mapAgentCampaignBuildStatus(data) {
|
|
|
3926
4445
|
warnings: diagnosticMessages2(data.warnings),
|
|
3927
4446
|
errors: diagnosticMessages2(data.errors),
|
|
3928
4447
|
artifactCount: numberOrUndefined2(data.artifact_count) ?? 0,
|
|
4448
|
+
artifactDownloads: Array.isArray(data.artifact_downloads) ? data.artifact_downloads.map(mapAgentCampaignArtifactDownload) : [],
|
|
4449
|
+
customerRowCounts,
|
|
4450
|
+
phaseAttemptTotals: nullableRecord(data.phase_attempt_totals) ?? void 0,
|
|
3929
4451
|
providerRoute: mapProviderRoute2(data),
|
|
3930
4452
|
triggerRunId: stringValue(data.trigger_run_id) ?? null,
|
|
3931
4453
|
staleRunningPhase: data.stale_running_phase === true,
|
|
3932
4454
|
phaseAgeSeconds: numberOrNull2(data.phase_age_seconds),
|
|
4455
|
+
nextPollAfterSeconds,
|
|
4456
|
+
terminalReason,
|
|
4457
|
+
staleReason,
|
|
4458
|
+
safeNextAction: terminalState.safeNextAction,
|
|
4459
|
+
terminalState,
|
|
4460
|
+
phaseHealth,
|
|
3933
4461
|
diagnostics: nullableRecord(data.diagnostics) ?? {},
|
|
3934
4462
|
nextAction: formatAgentNextAction(data.next_action),
|
|
4463
|
+
approvalAction: formatAgentNextAction(data.approval_action),
|
|
3935
4464
|
createdAt: stringValue(data.created_at) ?? "",
|
|
3936
4465
|
updatedAt: stringValue(data.updated_at) ?? "",
|
|
3937
4466
|
completedAt: stringValue(data.completed_at) ?? null
|
|
3938
4467
|
};
|
|
3939
4468
|
}
|
|
4469
|
+
function mapAgentCampaignArtifactDownload(data) {
|
|
4470
|
+
return {
|
|
4471
|
+
id: stringValue(data.id) ?? "",
|
|
4472
|
+
artifactType: stringValue(data.artifact_type) ?? null,
|
|
4473
|
+
format: stringValue(data.format) ?? null,
|
|
4474
|
+
rowCount: numberOrUndefined2(data.row_count) ?? 0,
|
|
4475
|
+
signedUrl: stringValue(data.signed_url) ?? null,
|
|
4476
|
+
downloadUrl: stringValue(data.download_url) ?? null,
|
|
4477
|
+
manifestUrl: stringValue(data.manifest_url) ?? null,
|
|
4478
|
+
expiresAt: stringValue(data.expires_at) ?? null
|
|
4479
|
+
};
|
|
4480
|
+
}
|
|
4481
|
+
function mapAgentCustomerRowCounts(value) {
|
|
4482
|
+
const record = nullableRecord(value);
|
|
4483
|
+
if (!record) return void 0;
|
|
4484
|
+
return {
|
|
4485
|
+
requestedTarget: numberOrNull2(record.requested_target),
|
|
4486
|
+
acquiredRows: numberOrUndefined2(record.acquired_rows),
|
|
4487
|
+
acceptedRows: numberOrUndefined2(record.accepted_rows),
|
|
4488
|
+
usableRows: numberOrUndefined2(record.usable_rows),
|
|
4489
|
+
copiedRows: numberOrUndefined2(record.copied_rows),
|
|
4490
|
+
approvalReadyRows: numberOrUndefined2(record.approval_ready_rows),
|
|
4491
|
+
qaReadyRows: numberOrUndefined2(record.qa_ready_rows),
|
|
4492
|
+
deliveredRows: numberOrUndefined2(record.delivered_rows),
|
|
4493
|
+
disqualifiedRows: numberOrUndefined2(record.disqualified_rows),
|
|
4494
|
+
reviewableRows: numberOrUndefined2(record.reviewable_rows),
|
|
4495
|
+
rowFailures: numberOrUndefined2(record.row_failures),
|
|
4496
|
+
acceptedShortfall: numberOrNull2(record.accepted_shortfall),
|
|
4497
|
+
usableShortfall: numberOrNull2(record.usable_shortfall),
|
|
4498
|
+
qaReadyShortfall: numberOrNull2(record.qa_ready_shortfall),
|
|
4499
|
+
deliveryShortfall: numberOrNull2(record.delivery_shortfall),
|
|
4500
|
+
fillRatio: numberOrNull2(record.fill_ratio),
|
|
4501
|
+
qaReadyFillRatio: numberOrNull2(record.qa_ready_fill_ratio),
|
|
4502
|
+
deliveredFillRatio: numberOrNull2(record.delivered_fill_ratio),
|
|
4503
|
+
terminalReason: stringValue(record.terminal_reason) ?? null,
|
|
4504
|
+
acceptedShortfallReason: stringValue(record.accepted_shortfall_reason) ?? null,
|
|
4505
|
+
usableShortfallReason: stringValue(record.usable_shortfall_reason) ?? null,
|
|
4506
|
+
qaReadyShortfallReason: stringValue(record.qa_ready_shortfall_reason) ?? null,
|
|
4507
|
+
deliveryShortfallReason: stringValue(record.delivery_shortfall_reason) ?? null
|
|
4508
|
+
};
|
|
4509
|
+
}
|
|
3940
4510
|
function mapAgentCampaignRowsResult(data) {
|
|
3941
4511
|
const rows = Array.isArray(data.rows) ? data.rows : [];
|
|
3942
4512
|
return {
|
|
@@ -3964,74 +4534,296 @@ function mapAgentCampaignArtifact(data) {
|
|
|
3964
4534
|
artifactType: stringValue(data.artifact_type) ?? "",
|
|
3965
4535
|
destination: stringValue(data.destination) ?? "",
|
|
3966
4536
|
storagePath: stringValue(data.storage_path) ?? "",
|
|
4537
|
+
format: stringValue(data.format) ?? null,
|
|
3967
4538
|
signedUrl: stringValue(data.signed_url) ?? null,
|
|
4539
|
+
downloadUrl: stringValue(data.download_url) ?? null,
|
|
4540
|
+
manifestUrl: stringValue(data.manifest_url) ?? null,
|
|
4541
|
+
expiresAt: stringValue(data.expires_at) ?? null,
|
|
3968
4542
|
rowCount: numberOrUndefined2(data.row_count) ?? 0,
|
|
3969
4543
|
checksum: stringValue(data.checksum) ?? null,
|
|
3970
4544
|
metadata: nullableRecord(data.metadata) ?? {},
|
|
3971
4545
|
createdAt: stringValue(data.created_at) ?? ""
|
|
3972
4546
|
};
|
|
3973
4547
|
}
|
|
4548
|
+
var NORTH_STAR_BANNED_COPY_PHRASES = [
|
|
4549
|
+
"i have been following",
|
|
4550
|
+
"i saw that",
|
|
4551
|
+
"would you be opposed",
|
|
4552
|
+
"unlock new opportunities",
|
|
4553
|
+
"significant success",
|
|
4554
|
+
"we understand",
|
|
4555
|
+
"hope this finds you well"
|
|
4556
|
+
];
|
|
4557
|
+
function campaignReviewGate(id, label, status, detail) {
|
|
4558
|
+
return {
|
|
4559
|
+
id,
|
|
4560
|
+
label,
|
|
4561
|
+
status,
|
|
4562
|
+
passed: status !== "blocked",
|
|
4563
|
+
detail
|
|
4564
|
+
};
|
|
4565
|
+
}
|
|
4566
|
+
function northStarMetric(id, label, status, detail, value, target) {
|
|
4567
|
+
return {
|
|
4568
|
+
id,
|
|
4569
|
+
label,
|
|
4570
|
+
status,
|
|
4571
|
+
detail,
|
|
4572
|
+
...value !== void 0 ? { value } : {},
|
|
4573
|
+
...target !== void 0 ? { target } : {}
|
|
4574
|
+
};
|
|
4575
|
+
}
|
|
4576
|
+
function createCampaignBuilderNorthStarScorecard(status, rows, artifacts, terminalState) {
|
|
4577
|
+
if (!terminalState.reviewable) {
|
|
4578
|
+
const pendingMetric = northStarMetric(
|
|
4579
|
+
"terminal_state",
|
|
4580
|
+
"Terminal-state contract",
|
|
4581
|
+
terminalState.kind === "running_stale" ? "blocked" : "pending",
|
|
4582
|
+
terminalState.kind === "running_stale" ? `Build is stale in ${terminalState.phase || "unknown phase"}; do not grade output yet.` : `Build is ${terminalState.label.toLowerCase()}; wait for terminal or approval state before grading.`,
|
|
4583
|
+
terminalState.kind,
|
|
4584
|
+
"terminal or pending_approval"
|
|
4585
|
+
);
|
|
4586
|
+
return {
|
|
4587
|
+
version: "campaign-builder-north-star.v1",
|
|
4588
|
+
status: pendingMetric.status,
|
|
4589
|
+
score: null,
|
|
4590
|
+
moatState: "scaffolding_ready",
|
|
4591
|
+
metrics: [pendingMetric],
|
|
4592
|
+
blockers: pendingMetric.status === "blocked" ? [pendingMetric.detail] : [],
|
|
4593
|
+
warnings: pendingMetric.status === "pending" ? [pendingMetric.detail] : [],
|
|
4594
|
+
nextAction: terminalState.safeNextAction
|
|
4595
|
+
};
|
|
4596
|
+
}
|
|
4597
|
+
const sampledRows = rows.rows.length;
|
|
4598
|
+
const rowData = rows.rows.map((row) => asRecord(row.data));
|
|
4599
|
+
const requestedTarget = status.customerRowCounts?.requestedTarget ?? status.recordsTotal ?? rows.count;
|
|
4600
|
+
const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
|
|
4601
|
+
const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
|
|
4602
|
+
const verifiedEmailRows = rowData.filter(campaignReviewDataHasVerifiedEmail).length;
|
|
4603
|
+
const uniqueEmails = new Set(rowData.map(campaignReviewDataEmail).filter(Boolean)).size;
|
|
4604
|
+
const uniqueDomains = new Set(rowData.map(campaignReviewDataDomain).filter(Boolean)).size;
|
|
4605
|
+
const copyReadyRows = rows.rows.filter(campaignReviewRowHasCopy).length;
|
|
4606
|
+
const copyQaIssuesByRow = rowData.map(campaignReviewDataCopyQaIssues).filter((issues) => issues.length > 0);
|
|
4607
|
+
const copyQaIssueCounts = countCampaignReviewIssues(copyQaIssuesByRow);
|
|
4608
|
+
const signalBackedRows = rowData.filter(campaignReviewDataHasSignalBasis).length;
|
|
4609
|
+
const noSupportedSignalRows = rowData.filter(campaignReviewDataHasNoSupportedSignal).length;
|
|
4610
|
+
const unsupportedSignalClaims = rowData.filter(campaignReviewDataHasUnsupportedSignalClaim).length;
|
|
4611
|
+
const approvalLockedRows = rowData.filter(campaignReviewDataHasApprovalLock).length;
|
|
4612
|
+
const holdoutRows = rowData.filter(campaignReviewDataHasHoldoutAttribution).length;
|
|
4613
|
+
const artifactCount = artifacts.length || status.artifactCount || 0;
|
|
4614
|
+
const deliveredRows = status.customerRowCounts?.deliveredRows ?? 0;
|
|
4615
|
+
const feedbackReady = campaignReviewStatusHasFeedbackReadiness(status);
|
|
4616
|
+
const feedbackRequiredForApproval = terminalState.kind === "pending_approval";
|
|
4617
|
+
const moat = campaignReviewMoatState(status, holdoutRows);
|
|
4618
|
+
const metrics = [
|
|
4619
|
+
northStarMetric(
|
|
4620
|
+
"terminal_state",
|
|
4621
|
+
"Terminal-state contract",
|
|
4622
|
+
terminalState.kind === "blocked" ? "blocked" : "pass",
|
|
4623
|
+
terminalState.label,
|
|
4624
|
+
terminalState.kind,
|
|
4625
|
+
"terminal or pending_approval"
|
|
4626
|
+
),
|
|
4627
|
+
northStarMetric(
|
|
4628
|
+
"target_fill",
|
|
4629
|
+
"Target fill",
|
|
4630
|
+
requestedTarget && finalRows < requestedTarget ? "review" : "pass",
|
|
4631
|
+
requestedTarget ? `${finalRows || 0}/${requestedTarget} final or reviewable row(s) are accounted for.` : "No requested target was reported; using sampled rows for review.",
|
|
4632
|
+
finalRows || sampledRows,
|
|
4633
|
+
requestedTarget || sampledRows
|
|
4634
|
+
),
|
|
4635
|
+
northStarMetric(
|
|
4636
|
+
"unique_emails",
|
|
4637
|
+
"Unique emails",
|
|
4638
|
+
sampledRows === 0 ? "blocked" : uniqueEmails === rowsWithEmail ? "pass" : "blocked",
|
|
4639
|
+
sampledRows === 0 ? "No sampled rows were available for email uniqueness review." : `${uniqueEmails}/${rowsWithEmail} sampled email(s) are unique.`,
|
|
4640
|
+
uniqueEmails,
|
|
4641
|
+
rowsWithEmail
|
|
4642
|
+
),
|
|
4643
|
+
northStarMetric(
|
|
4644
|
+
"unique_domains",
|
|
4645
|
+
"Unique domains",
|
|
4646
|
+
sampledRows === 0 ? "blocked" : uniqueDomains === sampledRows ? "pass" : "review",
|
|
4647
|
+
sampledRows === 0 ? "No sampled rows were available for domain uniqueness review." : `${uniqueDomains}/${sampledRows} sampled company domain(s) are unique.`,
|
|
4648
|
+
uniqueDomains,
|
|
4649
|
+
sampledRows
|
|
4650
|
+
),
|
|
4651
|
+
northStarMetric(
|
|
4652
|
+
"verified_email_rows",
|
|
4653
|
+
"Verified email rows",
|
|
4654
|
+
sampledRows === 0 ? "blocked" : verifiedEmailRows === sampledRows ? "pass" : rowsWithEmail === sampledRows ? "review" : "blocked",
|
|
4655
|
+
sampledRows === 0 ? "No sampled rows were available for email verification review." : `${verifiedEmailRows}/${sampledRows} sampled row(s) carry verified-email evidence.`,
|
|
4656
|
+
verifiedEmailRows,
|
|
4657
|
+
sampledRows
|
|
4658
|
+
),
|
|
4659
|
+
northStarMetric(
|
|
4660
|
+
"copy_completeness",
|
|
4661
|
+
"Copy completeness",
|
|
4662
|
+
sampledRows === 0 ? "blocked" : copyReadyRows === sampledRows ? "pass" : "blocked",
|
|
4663
|
+
sampledRows === 0 ? "No sampled rows were available for copy review." : `${copyReadyRows}/${sampledRows} sampled row(s) include generated copy.`,
|
|
4664
|
+
copyReadyRows,
|
|
4665
|
+
sampledRows
|
|
4666
|
+
),
|
|
4667
|
+
northStarMetric(
|
|
4668
|
+
"copy_quality",
|
|
4669
|
+
"Copy QA",
|
|
4670
|
+
copyQaIssuesByRow.length === 0 ? "pass" : "blocked",
|
|
4671
|
+
copyQaIssuesByRow.length === 0 ? "No sampled copy QA blockers were detected." : `${copyQaIssuesByRow.length}/${sampledRows} sampled row(s) have copy QA issue(s): ${formatCampaignReviewIssueCounts(copyQaIssueCounts)}.`,
|
|
4672
|
+
copyQaIssuesByRow.length,
|
|
4673
|
+
0
|
|
4674
|
+
),
|
|
4675
|
+
northStarMetric(
|
|
4676
|
+
"signal_grounding",
|
|
4677
|
+
"Signal grounding",
|
|
4678
|
+
unsupportedSignalClaims > 0 ? "blocked" : signalBackedRows > 0 ? "pass" : "review",
|
|
4679
|
+
unsupportedSignalClaims > 0 ? `${unsupportedSignalClaims} sampled row(s) make unsupported signal claims.` : signalBackedRows > 0 ? `${signalBackedRows}/${sampledRows} sampled row(s) include supported signal or personalization basis.` : noSupportedSignalRows > 0 ? `${noSupportedSignalRows}/${sampledRows} sampled row(s) are explicitly marked no_supported_signal; copy should stay conservative.` : "No sampled rows include supported signal evidence; copy should stay conservative.",
|
|
4680
|
+
signalBackedRows,
|
|
4681
|
+
sampledRows
|
|
4682
|
+
),
|
|
4683
|
+
northStarMetric(
|
|
4684
|
+
"approval_locks",
|
|
4685
|
+
"Approval locks",
|
|
4686
|
+
approvalLockedRows > 0 || deliveredRows === 0 ? "pass" : "review",
|
|
4687
|
+
approvalLockedRows > 0 ? `${approvalLockedRows}/${sampledRows} sampled row(s) show approval/export lock metadata.` : "Approval-lock metadata was not visible in sampled rows; preserve delivery approval gates.",
|
|
4688
|
+
approvalLockedRows,
|
|
4689
|
+
sampledRows
|
|
4690
|
+
),
|
|
4691
|
+
northStarMetric(
|
|
4692
|
+
"export_send_safety",
|
|
4693
|
+
"Export/send safety",
|
|
4694
|
+
deliveredRows > 0 && status.status !== "completed" ? "blocked" : "pass",
|
|
4695
|
+
deliveredRows > 0 ? `${deliveredRows} row(s) are delivered; status is ${status.status}.` : "No delivered rows are reported before approval.",
|
|
4696
|
+
deliveredRows,
|
|
4697
|
+
0
|
|
4698
|
+
),
|
|
4699
|
+
northStarMetric(
|
|
4700
|
+
"holdout_attribution",
|
|
4701
|
+
"Holdout attribution",
|
|
4702
|
+
holdoutRows > 0 ? "pass" : "review",
|
|
4703
|
+
holdoutRows > 0 ? `${holdoutRows}/${sampledRows} sampled row(s) preserve holdout attribution.` : "No holdout attribution was visible in the sampled rows.",
|
|
4704
|
+
holdoutRows,
|
|
4705
|
+
sampledRows
|
|
4706
|
+
),
|
|
4707
|
+
northStarMetric(
|
|
4708
|
+
"feedback_readiness",
|
|
4709
|
+
"Feedback readiness",
|
|
4710
|
+
feedbackReady ? "pass" : feedbackRequiredForApproval ? "blocked" : "review",
|
|
4711
|
+
feedbackReady ? "Feedback readiness is visible in status diagnostics." : feedbackRequiredForApproval ? "Feedback webhook or approved pull readiness is required before delivery approval." : "Feedback webhook or approved pull readiness was not visible; require it before real send approval.",
|
|
4712
|
+
feedbackReady,
|
|
4713
|
+
true
|
|
4714
|
+
),
|
|
4715
|
+
northStarMetric(
|
|
4716
|
+
"causal_moat",
|
|
4717
|
+
"Causal moat",
|
|
4718
|
+
moat.state === "proved" ? "pass" : "review",
|
|
4719
|
+
moat.detail,
|
|
4720
|
+
moat.state,
|
|
4721
|
+
"proved"
|
|
4722
|
+
),
|
|
4723
|
+
northStarMetric(
|
|
4724
|
+
"artifact_readback",
|
|
4725
|
+
"Artifact readback",
|
|
4726
|
+
artifactCount > 0 ? "pass" : "review",
|
|
4727
|
+
artifactCount > 0 ? `${artifactCount} artifact(s) are available for review.` : "No review artifact is available yet.",
|
|
4728
|
+
artifactCount,
|
|
4729
|
+
1
|
|
4730
|
+
)
|
|
4731
|
+
];
|
|
4732
|
+
const gradedMetrics = metrics.filter((metric) => metric.status !== "pending");
|
|
4733
|
+
const score = gradedMetrics.length === 0 ? null : Math.round(gradedMetrics.filter((metric) => metric.status === "pass").length / gradedMetrics.length * 100);
|
|
4734
|
+
const blockers = metrics.filter((metric) => metric.status === "blocked").map((metric) => metric.detail);
|
|
4735
|
+
const warnings = metrics.filter((metric) => metric.status === "review").map((metric) => metric.detail);
|
|
4736
|
+
const scorecardStatus = blockers.length > 0 ? "blocked" : warnings.length > 0 ? "review" : "pass";
|
|
4737
|
+
return {
|
|
4738
|
+
version: "campaign-builder-north-star.v1",
|
|
4739
|
+
status: scorecardStatus,
|
|
4740
|
+
score,
|
|
4741
|
+
moatState: moat.state,
|
|
4742
|
+
metrics,
|
|
4743
|
+
blockers,
|
|
4744
|
+
warnings,
|
|
4745
|
+
nextAction: scorecardStatus === "blocked" ? "Fix blocked North Star gates before approval or delivery." : terminalState.safeNextAction
|
|
4746
|
+
};
|
|
4747
|
+
}
|
|
3974
4748
|
function createCampaignBuilderBuildReview(status, rows, artifacts) {
|
|
4749
|
+
const terminalState = status.terminalState ?? deriveCampaignBuildTerminalState({
|
|
4750
|
+
status: status.status,
|
|
4751
|
+
phase: status.currentPhase,
|
|
4752
|
+
phaseStatus: status.currentPhaseStatus,
|
|
4753
|
+
staleRunningPhase: status.staleRunningPhase === true,
|
|
4754
|
+
phaseAgeSeconds: status.phaseAgeSeconds ?? null,
|
|
4755
|
+
nextPollAfterSeconds: status.nextPollAfterSeconds ?? null,
|
|
4756
|
+
terminalReason: status.terminalReason ?? status.customerRowCounts?.terminalReason ?? null,
|
|
4757
|
+
staleReason: status.staleReason ?? null,
|
|
4758
|
+
nextAction: status.nextAction,
|
|
4759
|
+
approvalAction: status.approvalAction,
|
|
4760
|
+
triggerRunId: status.triggerRunId ?? null
|
|
4761
|
+
});
|
|
3975
4762
|
const sampledRows = rows.rows.length;
|
|
3976
4763
|
const availableRows = rows.count || sampledRows;
|
|
3977
4764
|
const qualifiedRows = rows.rows.filter((row) => row.qualified !== false).length;
|
|
3978
4765
|
const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
|
|
3979
4766
|
const copyReadyRows = rows.rows.filter(campaignReviewRowHasCopy).length;
|
|
3980
4767
|
const artifactCount = artifacts.length || status.artifactCount || 0;
|
|
4768
|
+
const northStarScorecard = createCampaignBuilderNorthStarScorecard(status, rows, artifacts, terminalState);
|
|
3981
4769
|
const gates = [
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4770
|
+
campaignReviewGate(
|
|
4771
|
+
"build_reviewable",
|
|
4772
|
+
"Build reviewable",
|
|
4773
|
+
terminalState.kind === "running_healthy" ? "pending" : terminalState.kind === "running_stale" || terminalState.kind === "blocked" ? "blocked" : "pass",
|
|
4774
|
+
terminalState.label
|
|
4775
|
+
),
|
|
4776
|
+
campaignReviewGate(
|
|
4777
|
+
"rows_available",
|
|
4778
|
+
"Rows available",
|
|
4779
|
+
sampledRows > 0 ? "pass" : terminalState.reviewable ? "blocked" : "pending",
|
|
4780
|
+
sampledRows > 0 ? `${sampledRows} sampled row(s) are available for review.` : terminalState.reviewable ? "No rows were returned for review." : "Rows are not graded until the build is reviewable."
|
|
4781
|
+
),
|
|
4782
|
+
campaignReviewGate(
|
|
4783
|
+
"qualified_sample",
|
|
4784
|
+
"Sample rows qualified",
|
|
4785
|
+
sampledRows === 0 ? terminalState.reviewable ? "blocked" : "pending" : qualifiedRows === sampledRows ? "pass" : "blocked",
|
|
4786
|
+
sampledRows > 0 ? `${qualifiedRows}/${sampledRows} sampled row(s) are marked qualified.` : "Qualification could not be checked without sampled rows."
|
|
4787
|
+
),
|
|
4788
|
+
campaignReviewGate(
|
|
4789
|
+
"email_coverage",
|
|
4790
|
+
"Email coverage",
|
|
4791
|
+
sampledRows === 0 ? terminalState.reviewable ? "blocked" : "pending" : rowsWithEmail === sampledRows ? "pass" : "blocked",
|
|
4792
|
+
sampledRows > 0 ? `${rowsWithEmail}/${sampledRows} sampled row(s) include an email.` : "Email coverage could not be checked without sampled rows."
|
|
4793
|
+
),
|
|
4794
|
+
campaignReviewGate(
|
|
4795
|
+
"artifact_available",
|
|
4796
|
+
"Artifact available",
|
|
4797
|
+
artifactCount > 0 ? "pass" : terminalState.reviewable ? "review" : "pending",
|
|
4798
|
+
artifactCount > 0 ? `${artifactCount} artifact(s) are available.` : "No delivery artifact is available yet."
|
|
4799
|
+
),
|
|
4800
|
+
campaignReviewGate(
|
|
4801
|
+
"no_failed_rows",
|
|
4802
|
+
"No failed rows",
|
|
4803
|
+
status.recordsFailed === 0 ? "pass" : "blocked",
|
|
4804
|
+
status.recordsFailed === 0 ? "The build reports zero failed rows." : `${status.recordsFailed} row(s) failed during the build.`
|
|
4805
|
+
)
|
|
4018
4806
|
];
|
|
4019
|
-
const blockedReasons = gates.filter((gate) => !gate.passed).map((gate) => gate.detail);
|
|
4807
|
+
const blockedReasons = gates.filter((gate) => gate.status === "blocked" || !gate.passed).map((gate) => gate.detail);
|
|
4020
4808
|
const warnings = [
|
|
4021
4809
|
rows.hasMore ? "This review is based on a row sample; page through remaining rows before final approval." : void 0,
|
|
4022
4810
|
sampledRows > 0 && copyReadyRows < sampledRows ? `${copyReadyRows}/${sampledRows} sampled row(s) include generated copy.` : void 0,
|
|
4023
4811
|
...status.warnings
|
|
4024
4812
|
].filter((item) => Boolean(item));
|
|
4025
|
-
const readyForDeliveryApproval = blockedReasons.length === 0;
|
|
4813
|
+
const readyForDeliveryApproval = terminalState.reviewable && blockedReasons.length === 0 && northStarScorecard.status !== "blocked";
|
|
4026
4814
|
return {
|
|
4027
4815
|
campaignBuildId: status.campaignBuildId || rows.campaignBuildId,
|
|
4028
4816
|
status,
|
|
4029
4817
|
rows,
|
|
4030
4818
|
artifacts,
|
|
4031
4819
|
gates,
|
|
4820
|
+
northStarScorecard,
|
|
4032
4821
|
summary: {
|
|
4033
4822
|
status: status.status,
|
|
4034
4823
|
phase: status.currentPhase,
|
|
4824
|
+
terminalState: terminalState.kind,
|
|
4825
|
+
scorecardStatus: northStarScorecard.status,
|
|
4826
|
+
scorecardScore: northStarScorecard.score,
|
|
4035
4827
|
sampledRows,
|
|
4036
4828
|
availableRows,
|
|
4037
4829
|
qualifiedRows,
|
|
@@ -4085,6 +4877,184 @@ function campaignReviewRowHasCopy(row) {
|
|
|
4085
4877
|
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)
|
|
4086
4878
|
);
|
|
4087
4879
|
}
|
|
4880
|
+
function campaignReviewDataEmail(data) {
|
|
4881
|
+
return stringValue(data.email) || stringValue(data.work_email) || stringValue(data.workEmail) || stringValue(asRecord(data.contact).email);
|
|
4882
|
+
}
|
|
4883
|
+
function campaignReviewDataDomain(data) {
|
|
4884
|
+
const domain = stringValue(data.company_domain) || stringValue(data.companyDomain) || stringValue(asRecord(data.company).domain);
|
|
4885
|
+
return domain?.toLowerCase();
|
|
4886
|
+
}
|
|
4887
|
+
function campaignReviewDataHasVerifiedEmail(data) {
|
|
4888
|
+
const status = String(data.email_status ?? data.emailStatus ?? asRecord(data.contact).email_status ?? "").toLowerCase();
|
|
4889
|
+
return data.email_verified === true || data.emailVerified === true || asRecord(data.contact).email_verified === true || ["valid", "validated", "verified"].includes(status);
|
|
4890
|
+
}
|
|
4891
|
+
function campaignReviewDataCopyParts(data) {
|
|
4892
|
+
const copy = asRecord(data.copy);
|
|
4893
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4894
|
+
return [
|
|
4895
|
+
stringValue(data.subject),
|
|
4896
|
+
stringValue(data.subject_line),
|
|
4897
|
+
stringValue(data.opener),
|
|
4898
|
+
stringValue(data.body),
|
|
4899
|
+
stringValue(data.cta),
|
|
4900
|
+
stringValue(copy.subject),
|
|
4901
|
+
stringValue(copy.opener),
|
|
4902
|
+
stringValue(copy.body),
|
|
4903
|
+
stringValue(copy.cta),
|
|
4904
|
+
stringValue(rawCopy.subject),
|
|
4905
|
+
stringValue(rawCopy.opener),
|
|
4906
|
+
stringValue(rawCopy.body),
|
|
4907
|
+
stringValue(rawCopy.cta)
|
|
4908
|
+
].filter((part) => Boolean(part));
|
|
4909
|
+
}
|
|
4910
|
+
function campaignReviewDataHasBadGreeting(data) {
|
|
4911
|
+
return campaignReviewDataCopyParts(data).some(
|
|
4912
|
+
(part) => /\bhi\s*(?:,|\{\{|\[)|\bhello\s*(?:,|\{\{|\[)/i.test(part) || /\b(first_name|firstname|name)\b/i.test(part)
|
|
4913
|
+
);
|
|
4914
|
+
}
|
|
4915
|
+
function campaignReviewDataHasBannedPhrase(data) {
|
|
4916
|
+
const text = campaignReviewDataCopyParts(data).join(" ").toLowerCase();
|
|
4917
|
+
return NORTH_STAR_BANNED_COPY_PHRASES.some((phrase) => text.includes(phrase));
|
|
4918
|
+
}
|
|
4919
|
+
function campaignReviewDataSubject(data) {
|
|
4920
|
+
const copy = asRecord(data.copy);
|
|
4921
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4922
|
+
return stringValue(data.subject) || stringValue(data.subject_line) || stringValue(data.subjectLine) || stringValue(copy.subject) || stringValue(rawCopy.subject);
|
|
4923
|
+
}
|
|
4924
|
+
function campaignReviewDataCta(data) {
|
|
4925
|
+
const copy = asRecord(data.copy);
|
|
4926
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4927
|
+
return stringValue(data.cta) || stringValue(copy.cta) || stringValue(rawCopy.cta);
|
|
4928
|
+
}
|
|
4929
|
+
function countCampaignReviewIssues(issueRows) {
|
|
4930
|
+
return issueRows.flat().reduce((acc, issue) => {
|
|
4931
|
+
acc[issue] = (acc[issue] || 0) + 1;
|
|
4932
|
+
return acc;
|
|
4933
|
+
}, {});
|
|
4934
|
+
}
|
|
4935
|
+
function formatCampaignReviewIssueCounts(counts) {
|
|
4936
|
+
const entries = Object.entries(counts);
|
|
4937
|
+
return entries.length > 0 ? entries.map(([issue, count]) => `${issue}=${count}`).join(", ") : "none";
|
|
4938
|
+
}
|
|
4939
|
+
function campaignReviewDataCopyQaIssues(data) {
|
|
4940
|
+
const issues = /* @__PURE__ */ new Set();
|
|
4941
|
+
const copyParts = campaignReviewDataCopyParts(data);
|
|
4942
|
+
if (copyParts.length === 0) return [];
|
|
4943
|
+
if (campaignReviewDataHasBadGreeting(data)) issues.add("bad_greeting");
|
|
4944
|
+
if (campaignReviewDataHasBannedPhrase(data)) issues.add("banned_or_vague_phrase");
|
|
4945
|
+
if (campaignReviewDataHasUnsupportedSignalClaim(data)) issues.add("unsupported_signal_claim");
|
|
4946
|
+
if (campaignReviewDataPersonalizationBasis(data).length === 0) issues.add("missing_personalization_basis");
|
|
4947
|
+
if (!campaignReviewDataCta(data)) issues.add("missing_cta");
|
|
4948
|
+
const subject = campaignReviewDataSubject(data);
|
|
4949
|
+
if (subject && subject.length > 70) issues.add("overlong_subject");
|
|
4950
|
+
return [...issues];
|
|
4951
|
+
}
|
|
4952
|
+
function campaignReviewDataPersonalizationBasis(data) {
|
|
4953
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4954
|
+
const copy = asRecord(data.copy);
|
|
4955
|
+
const metadata = asRecord(data.metadata);
|
|
4956
|
+
const signalEvidence = asRecord(data.signal_evidence ?? metadata.signal_evidence ?? metadata.signalEvidence);
|
|
4957
|
+
return [
|
|
4958
|
+
...arrayOfStrings(data.personalization_basis) ?? [],
|
|
4959
|
+
...arrayOfStrings(data.personalizationBasis) ?? [],
|
|
4960
|
+
...arrayOfStrings(copy.personalization_basis) ?? [],
|
|
4961
|
+
...arrayOfStrings(rawCopy.personalization_basis) ?? [],
|
|
4962
|
+
...arrayOfStrings(metadata.personalization_basis) ?? [],
|
|
4963
|
+
...arrayOfStrings(metadata.personalizationBasis) ?? [],
|
|
4964
|
+
...arrayOfStrings(signalEvidence.personalization_basis) ?? []
|
|
4965
|
+
];
|
|
4966
|
+
}
|
|
4967
|
+
function campaignReviewDataHasNoSupportedSignal(data) {
|
|
4968
|
+
const metadata = asRecord(data.metadata);
|
|
4969
|
+
const copy = asRecord(data.copy);
|
|
4970
|
+
const state = [
|
|
4971
|
+
data.copy_signal_state,
|
|
4972
|
+
data.signal_basis,
|
|
4973
|
+
data.signal_type,
|
|
4974
|
+
metadata.copy_signal_state,
|
|
4975
|
+
metadata.signal_basis,
|
|
4976
|
+
metadata.signal_type,
|
|
4977
|
+
copy.copy_signal_state
|
|
4978
|
+
].map((value) => stringValue(value)?.toLowerCase()).filter(Boolean);
|
|
4979
|
+
return data.no_supported_signal === true || metadata.no_supported_signal === true || state.includes("no_supported_signal");
|
|
4980
|
+
}
|
|
4981
|
+
function campaignReviewDataHasSignalBasis(data) {
|
|
4982
|
+
if (campaignReviewDataHasNoSupportedSignal(data)) return false;
|
|
4983
|
+
const metadata = asRecord(data.metadata);
|
|
4984
|
+
const signal = asRecord(data.signal);
|
|
4985
|
+
const signalEvidence = asRecord(data.signal_evidence ?? metadata.signal_evidence ?? metadata.signalEvidence);
|
|
4986
|
+
const basis = campaignReviewDataPersonalizationBasis(data);
|
|
4987
|
+
return Boolean(
|
|
4988
|
+
stringValue(data.signal_type) || stringValue(data.signalType) || stringValue(data.signal_summary) || stringValue(data.signalSummary) || stringValue(data.signal_source_url) || stringValue(data.signalSourceUrl) || stringValue(metadata.signal_type) || stringValue(metadata.signal_summary) || stringValue(metadata.signal_source_url) || stringValue(signal.type) || stringValue(signal.summary) || stringValue(signal.source_url) || stringValue(signalEvidence.signal_type) || stringValue(signalEvidence.summary) || stringValue(signalEvidence.source_url) || basis.some((item) => /\bsignal|hiring|funding|leadership|growth|launch|news|technology\b/i.test(item))
|
|
4989
|
+
);
|
|
4990
|
+
}
|
|
4991
|
+
function campaignReviewDataHasUnsupportedSignalClaim(data) {
|
|
4992
|
+
const copyText = campaignReviewDataCopyParts(data).join(" ").toLowerCase();
|
|
4993
|
+
const claimsSignal = /\b(hiring|funding|raised|launched|expanding|appointed|announced|recent news|new role|job posting)\b/.test(copyText);
|
|
4994
|
+
return claimsSignal && !campaignReviewDataHasSignalBasis(data);
|
|
4995
|
+
}
|
|
4996
|
+
function campaignReviewDataHasApprovalLock(data) {
|
|
4997
|
+
const metadata = asRecord(data.fit_metadata ?? data.metadata);
|
|
4998
|
+
const approval = String(data.approval_status ?? data.delivery_approval_status ?? metadata.approval_status ?? "").toLowerCase();
|
|
4999
|
+
const exportStatus = String(data.export_status ?? data.exportStatus ?? "").toLowerCase();
|
|
5000
|
+
return data.export_ready === false || data.exportReady === false || data.delivery_approved === false || data.deliveryApproved === false || ["pending", "pending_approval", "blocked", "approval_required", "held"].includes(approval) || ["pending", "blocked", "approval_required", "held"].includes(exportStatus);
|
|
5001
|
+
}
|
|
5002
|
+
function campaignReviewDataHasHoldoutAttribution(data) {
|
|
5003
|
+
const fitMetadata = asRecord(data.fit_metadata ?? data.fitMetadata);
|
|
5004
|
+
const metadata = asRecord(data.metadata);
|
|
5005
|
+
const holdout = asRecord(
|
|
5006
|
+
fitMetadata.learning_holdout ?? fitMetadata.learningHoldout ?? metadata.learning_holdout ?? metadata.learningHoldout ?? data.learning_holdout ?? data.learningHoldout
|
|
5007
|
+
);
|
|
5008
|
+
const experimentKey = stringValue(holdout.experiment_key ?? holdout.experimentKey ?? data.experiment_key ?? data.experimentKey);
|
|
5009
|
+
const cohort = stringValue(holdout.cohort_role ?? holdout.cohortRole ?? data.cohort_role ?? data.learning_cohort ?? data.learningCohort);
|
|
5010
|
+
const brainApplied = holdout.brain_applied ?? holdout.brainApplied ?? data.brain_applied ?? data.signaliz_brain_applied;
|
|
5011
|
+
return Boolean(experimentKey && cohort && brainApplied !== void 0);
|
|
5012
|
+
}
|
|
5013
|
+
function campaignReviewStatusHasFeedbackReadiness(status) {
|
|
5014
|
+
const diagnostics = asRecord(status.diagnostics);
|
|
5015
|
+
const feedbackReadiness = asRecord(diagnostics.feedback_readiness ?? diagnostics.feedbackReadiness);
|
|
5016
|
+
const feedbackSubstrate = asRecord(diagnostics.feedback_substrate ?? diagnostics.feedbackSubstrate);
|
|
5017
|
+
const evidenceCounts = asRecord(diagnostics.evidence_counts ?? diagnostics.evidenceCounts);
|
|
5018
|
+
return feedbackReadiness.ready === true || feedbackReadiness.webhook_configured === true || feedbackSubstrate.stage === "ready" || Number(evidenceCounts.feedback_events ?? 0) > 0;
|
|
5019
|
+
}
|
|
5020
|
+
function campaignReviewMoatState(status, holdoutRows) {
|
|
5021
|
+
const diagnostics = asRecord(status.diagnostics);
|
|
5022
|
+
const evidenceCounts = asRecord(diagnostics.evidence_counts ?? diagnostics.evidenceCounts);
|
|
5023
|
+
const embeddedHoldout = asRecord(diagnostics.embedded_holdout ?? diagnostics.embeddedHoldout);
|
|
5024
|
+
const holdoutLift = asRecord(diagnostics.holdout_lift ?? diagnostics.holdoutLift ?? diagnostics.holdout_measurement ?? diagnostics.holdoutMeasurement);
|
|
5025
|
+
const controlSample = Math.max(
|
|
5026
|
+
Number(evidenceCounts.holdout_control_sample_size ?? 0),
|
|
5027
|
+
Number(evidenceCounts.embedded_holdout_control_sample ?? 0),
|
|
5028
|
+
Number(embeddedHoldout.control_sample_size ?? 0)
|
|
5029
|
+
);
|
|
5030
|
+
const learnedSample = Math.max(
|
|
5031
|
+
Number(evidenceCounts.holdout_learned_sample_size ?? 0),
|
|
5032
|
+
Number(evidenceCounts.embedded_holdout_learned_sample ?? 0),
|
|
5033
|
+
Number(embeddedHoldout.learned_sample_size ?? 0)
|
|
5034
|
+
);
|
|
5035
|
+
const feedbackEvents = Math.max(
|
|
5036
|
+
Number(evidenceCounts.feedback_events ?? 0),
|
|
5037
|
+
Number(evidenceCounts.campaign_build_feedback_events ?? 0),
|
|
5038
|
+
Number(evidenceCounts.delivery_holdout_sent_outcomes ?? 0)
|
|
5039
|
+
);
|
|
5040
|
+
const proved = diagnostics.closed_loop_proof_ready === true || holdoutLift.honest_measurement === true && holdoutLift.positive_lift === true;
|
|
5041
|
+
if (proved) {
|
|
5042
|
+
return {
|
|
5043
|
+
state: "proved",
|
|
5044
|
+
detail: "Real attributed feedback shows positive lift for explicit control and learned cohorts."
|
|
5045
|
+
};
|
|
5046
|
+
}
|
|
5047
|
+
if (controlSample > 0 && learnedSample > 0 && feedbackEvents > 0) {
|
|
5048
|
+
return {
|
|
5049
|
+
state: "moved_needs_lift_volume",
|
|
5050
|
+
detail: `Control and learned cohorts have attributed feedback (${controlSample} control, ${learnedSample} learned, ${feedbackEvents} feedback event(s)); keep collecting lift volume before claiming proof.`
|
|
5051
|
+
};
|
|
5052
|
+
}
|
|
5053
|
+
return {
|
|
5054
|
+
state: "scaffolding_ready",
|
|
5055
|
+
detail: holdoutRows > 0 ? `${holdoutRows} sampled row(s) carry holdout attribution, but real control/learned feedback lift is not proved yet.` : "Holdout and feedback scaffolding may be ready, but no real control/learned feedback lift is proved yet."
|
|
5056
|
+
};
|
|
5057
|
+
}
|
|
4088
5058
|
function createCampaignBuilderReadinessLane(route, plan) {
|
|
4089
5059
|
const builtIn = campaignBuilderBuiltInForRoute(route);
|
|
4090
5060
|
const customRoute = route.provider !== "signaliz" && route.provider !== "csv" && builtIn === void 0;
|
|
@@ -4126,6 +5096,8 @@ function readinessLaneLabel(route, builtIn) {
|
|
|
4126
5096
|
const labels = {
|
|
4127
5097
|
lead_generation: "Signaliz lead generation",
|
|
4128
5098
|
local_leads: "Signaliz local leads",
|
|
5099
|
+
company_discovery: "Signaliz company discovery",
|
|
5100
|
+
people_discovery: "Signaliz people discovery",
|
|
4129
5101
|
email_finding: "Signaliz email finding",
|
|
4130
5102
|
email_verification: "Signaliz email verification",
|
|
4131
5103
|
signals: "Signaliz signals"
|
|
@@ -4210,6 +5182,35 @@ function summarizeCampaignBuilderProofDryRun(dryRunResult) {
|
|
|
4210
5182
|
plannedTargetCount: dryRunResult.plannedTargetCount ?? dryRunResult.planned_target_count ?? null
|
|
4211
5183
|
};
|
|
4212
5184
|
}
|
|
5185
|
+
function summarizeCampaignBuilderProofLearnBack(plan) {
|
|
5186
|
+
if (Object.keys(plan).length === 0) return { ready: false };
|
|
5187
|
+
const memoryPolicy = asRecord(plan.memory_write_policy);
|
|
5188
|
+
const memoryItemsPolicy = asRecord(memoryPolicy.gtm_memory_items);
|
|
5189
|
+
const sequence = Array.isArray(plan.post_build_sequence) ? plan.post_build_sequence.map((step) => {
|
|
5190
|
+
const record = asRecord(step);
|
|
5191
|
+
return compact({
|
|
5192
|
+
step: record.step,
|
|
5193
|
+
tool: stringValue(record.tool),
|
|
5194
|
+
approval_boundary: stringValue(record.approval_boundary),
|
|
5195
|
+
reason: stringValue(record.reason)
|
|
5196
|
+
});
|
|
5197
|
+
}).filter((step) => typeof step.tool === "string") : [];
|
|
5198
|
+
return {
|
|
5199
|
+
ready: sequence.length > 0,
|
|
5200
|
+
source_tool: firstNonEmptyString(plan.source_tool, plan.sourceTool),
|
|
5201
|
+
post_build_sequence: sequence,
|
|
5202
|
+
memory_write_policy: {
|
|
5203
|
+
target_tables: Array.isArray(memoryPolicy.target_tables) ? memoryPolicy.target_tables : [],
|
|
5204
|
+
gtm_memory_items: {
|
|
5205
|
+
shareable: memoryItemsPolicy.shareable === false ? false : memoryItemsPolicy.shareable ?? null,
|
|
5206
|
+
allowed_redaction_states: Array.isArray(memoryItemsPolicy.allowed_redaction_states) ? memoryItemsPolicy.allowed_redaction_states : [],
|
|
5207
|
+
raw_private_fields_withheld: Array.isArray(memoryItemsPolicy.raw_private_fields_withheld) ? memoryItemsPolicy.raw_private_fields_withheld : []
|
|
5208
|
+
}
|
|
5209
|
+
},
|
|
5210
|
+
approval_policy: firstNonEmptyString(plan.approval_policy, plan.approvalPolicy),
|
|
5211
|
+
privacy_policy: firstNonEmptyString(plan.privacy_policy, plan.privacyPolicy)
|
|
5212
|
+
};
|
|
5213
|
+
}
|
|
4213
5214
|
function firstNonEmptyString(...values) {
|
|
4214
5215
|
for (const value of values) {
|
|
4215
5216
|
if (typeof value === "string" && value.trim()) return value;
|
|
@@ -4692,14 +5693,87 @@ var Ops = class {
|
|
|
4692
5693
|
const body = typeof params === "string" ? { prompt: params } : buildOpsCreateBody(params);
|
|
4693
5694
|
return normalizeOpsCreateResult(withExecutionRefs(await this.call("ops_create", body)));
|
|
4694
5695
|
}
|
|
5696
|
+
async schedule(params) {
|
|
5697
|
+
const createBody = typeof params === "string" ? { prompt: params, cadence: "daily" } : { ...buildOpsCreateBody(params), cadence: params.cadence ?? "daily" };
|
|
5698
|
+
const { activate: _activate, ...body } = createBody;
|
|
5699
|
+
return normalizeOpsCreateResult(withExecutionRefs(await this.call("ops_schedule", body)));
|
|
5700
|
+
}
|
|
5701
|
+
async scheduleAndWait(params) {
|
|
5702
|
+
const options = typeof params === "string" ? { schedule: { prompt: params, cadence: "daily" }, run: {}, wait: {} } : buildOpsScheduleAndWaitOptions(params);
|
|
5703
|
+
const raw = await this.call("ops_schedule_and_wait", buildOpsScheduleAndWaitBody(options));
|
|
5704
|
+
return normalizeOpsScheduleAndWaitCallResult(raw, options.wait, {
|
|
5705
|
+
approvalMessage: "ops.scheduleAndWait requires an approved schedulable Op. Retry with confirmSpend=true after reviewing approval details.",
|
|
5706
|
+
notCreatedMessage: "ops.scheduleAndWait requires ops_schedule_and_wait to create an op_id. Use ops.schedule for approval review flows."
|
|
5707
|
+
});
|
|
5708
|
+
}
|
|
5709
|
+
/** Schedule a recurring Op that delivers through a customer-owned Nango API connection. */
|
|
5710
|
+
async scheduleNangoAction(input) {
|
|
5711
|
+
return normalizeOpsCreateResult(withExecutionRefs(await this.call("ops_nango_schedule", buildOpsNangoScheduleBody(input))));
|
|
5712
|
+
}
|
|
5713
|
+
/** Schedule a recurring Nango-backed Op, run the first tick, and return result readback. */
|
|
5714
|
+
async scheduleNangoActionAndWait(input) {
|
|
5715
|
+
const options = buildOpsNangoScheduleAndWaitOptions(input);
|
|
5716
|
+
const raw = await this.call("ops_nango_schedule_and_wait", buildOpsNangoScheduleAndWaitBody(options));
|
|
5717
|
+
return normalizeOpsScheduleAndWaitCallResult(raw, options.wait, {
|
|
5718
|
+
approvalMessage: "ops.scheduleNangoActionAndWait requires an approved Nango-backed Op. Retry with confirmSpend=true after reviewing approval details.",
|
|
5719
|
+
notCreatedMessage: "ops.scheduleNangoActionAndWait requires ops_nango_schedule_and_wait to create an op_id. Use ops.scheduleNangoAction for approval review flows."
|
|
5720
|
+
});
|
|
5721
|
+
}
|
|
4695
5722
|
async execute(params) {
|
|
4696
5723
|
const body = typeof params === "string" ? { prompt: params } : buildOpsExecuteBody(params);
|
|
4697
5724
|
return normalizeOpsExecuteResult(withExecutionRefs(await this.call("ops_execute", body)));
|
|
4698
5725
|
}
|
|
5726
|
+
async executeAndWait(params) {
|
|
5727
|
+
const options = typeof params === "string" ? { execute: { prompt: params, auto_run: true }, wait: {} } : buildOpsExecuteAndWaitOptions(params);
|
|
5728
|
+
const execute = await this.execute(options.execute);
|
|
5729
|
+
if (execute.approval_required || execute.error_code === "APPROVAL_REQUIRED") {
|
|
5730
|
+
throw new SignalizError({
|
|
5731
|
+
code: "APPROVAL_REQUIRED",
|
|
5732
|
+
errorType: "validation",
|
|
5733
|
+
message: "ops.executeAndWait requires an approved executable Op. Retry with confirmSpend=true after reviewing approval details.",
|
|
5734
|
+
details: { execute }
|
|
5735
|
+
});
|
|
5736
|
+
}
|
|
5737
|
+
if (!execute.op_id) {
|
|
5738
|
+
throw new SignalizError({
|
|
5739
|
+
code: "OP_NOT_CREATED",
|
|
5740
|
+
errorType: "validation",
|
|
5741
|
+
message: "ops.executeAndWait requires ops_execute to create an op_id. Use ops.execute for dry runs or approval review flows.",
|
|
5742
|
+
details: { execute }
|
|
5743
|
+
});
|
|
5744
|
+
}
|
|
5745
|
+
const waited = await this.waitForResults({
|
|
5746
|
+
...options.wait,
|
|
5747
|
+
op_id: execute.op_id
|
|
5748
|
+
});
|
|
5749
|
+
const runId = execute.run_id ?? execute.runId ?? waited.status.run_id ?? waited.status.runId ?? null;
|
|
5750
|
+
return {
|
|
5751
|
+
...waited,
|
|
5752
|
+
execute,
|
|
5753
|
+
run_id: runId,
|
|
5754
|
+
runId,
|
|
5755
|
+
execution_refs: mergeExecutionRefsFrom([execute, waited])
|
|
5756
|
+
};
|
|
5757
|
+
}
|
|
4699
5758
|
async run(params) {
|
|
4700
5759
|
const body = typeof params === "string" ? { op_id: params } : buildOpsRunBody(params);
|
|
4701
5760
|
return normalizeOpsRunResult(withExecutionRefs(await this.call("ops_run", body)));
|
|
4702
5761
|
}
|
|
5762
|
+
async runAndWait(params) {
|
|
5763
|
+
const options = typeof params === "string" ? { op_id: params } : buildOpsRunAndWaitOptions(params);
|
|
5764
|
+
if (!options.op_id) throw new Error("ops.runAndWait requires op_id or opId");
|
|
5765
|
+
const run = await this.run({
|
|
5766
|
+
op_id: options.op_id,
|
|
5767
|
+
instruction: options.instruction,
|
|
5768
|
+
force: options.force
|
|
5769
|
+
});
|
|
5770
|
+
const waited = await this.waitForResults(options);
|
|
5771
|
+
return {
|
|
5772
|
+
...waited,
|
|
5773
|
+
run,
|
|
5774
|
+
execution_refs: mergeExecutionRefsFrom([run, waited])
|
|
5775
|
+
};
|
|
5776
|
+
}
|
|
4703
5777
|
async status(params) {
|
|
4704
5778
|
const body = typeof params === "string" ? { op_id: params } : buildOpsStatusBody(params);
|
|
4705
5779
|
return normalizeOpsStatusResult(withExecutionRefs(await this.call("ops_status", body)));
|
|
@@ -4708,21 +5782,188 @@ var Ops = class {
|
|
|
4708
5782
|
const body = typeof params === "string" ? { op_id: params } : buildOpsResultsBody(params);
|
|
4709
5783
|
return normalizeOpsResultsResult(withExecutionRefs(await this.call("ops_results", body)));
|
|
4710
5784
|
}
|
|
4711
|
-
async
|
|
4712
|
-
const
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
return normalizeOpsProofResult(data);
|
|
5785
|
+
async waitForResults(params) {
|
|
5786
|
+
const options = typeof params === "string" ? { op_id: params } : buildOpsWaitForResultsOptions(params);
|
|
5787
|
+
if (!options.op_id) throw new Error("ops.waitForResults requires op_id or opId");
|
|
5788
|
+
const waitResult = await this.call("ops_wait", buildOpsWaitBody(options));
|
|
5789
|
+
return normalizeOpsWaitForResultsResult(waitResult, options);
|
|
4717
5790
|
}
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
5791
|
+
/** Create a short-lived Nango Connect session from the Ops namespace. */
|
|
5792
|
+
async createNangoConnectSession(input) {
|
|
5793
|
+
return this.call("nango_connect_session_create", {
|
|
5794
|
+
provider_id: input.providerId,
|
|
5795
|
+
integration_id: input.integrationId,
|
|
5796
|
+
provider_display_name: input.providerDisplayName,
|
|
5797
|
+
integration_display_name: input.integrationDisplayName,
|
|
5798
|
+
allowed_integrations: input.allowedIntegrations,
|
|
5799
|
+
surface: input.surface,
|
|
5800
|
+
source: input.source,
|
|
5801
|
+
user_email: input.userEmail,
|
|
5802
|
+
user_display_name: input.userDisplayName
|
|
5803
|
+
});
|
|
5804
|
+
}
|
|
5805
|
+
/** Prepare the full Nango provider search, connect, pull/export, Ops, and route flow. */
|
|
5806
|
+
async prepareNangoIntegrationFlow(input = {}) {
|
|
5807
|
+
return this.call("nango_integration_flow_prepare", {
|
|
5808
|
+
query: input.query,
|
|
5809
|
+
search: input.search,
|
|
5810
|
+
provider_id: input.providerId,
|
|
5811
|
+
provider: input.provider,
|
|
5812
|
+
integration_id: input.integrationId,
|
|
5813
|
+
provider_config_key: input.providerConfigKey,
|
|
5814
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
5815
|
+
connection_id: input.connectionId,
|
|
5816
|
+
nango_connection_id: input.nangoConnectionId,
|
|
5817
|
+
intent: input.intent,
|
|
5818
|
+
action_name: input.actionName,
|
|
5819
|
+
tool_name: input.toolName,
|
|
5820
|
+
proxy_path: input.proxyPath,
|
|
5821
|
+
method: input.method,
|
|
5822
|
+
input: input.input,
|
|
5823
|
+
cadence: input.cadence,
|
|
5824
|
+
field_map: input.fieldMap,
|
|
5825
|
+
required_fields: input.requiredFields,
|
|
5826
|
+
confirm_spend: input.confirmSpend,
|
|
5827
|
+
write_confirmed: input.writeConfirmed,
|
|
5828
|
+
layer: input.layer,
|
|
5829
|
+
campaign_id: input.campaignId,
|
|
5830
|
+
limit: input.limit,
|
|
5831
|
+
include_provider_catalog: input.includeProviderCatalog
|
|
5832
|
+
});
|
|
5833
|
+
}
|
|
5834
|
+
/** List Nango-backed action tools for a workspace connection without executing them. */
|
|
5835
|
+
async listNangoTools(options = {}) {
|
|
5836
|
+
return this.call("nango_mcp_tools_list", {
|
|
5837
|
+
workspace_connection_id: options.workspaceConnectionId,
|
|
5838
|
+
connection_id: options.connectionId,
|
|
5839
|
+
provider_config_key: options.providerConfigKey,
|
|
5840
|
+
integration_id: options.integrationId,
|
|
5841
|
+
nango_connection_id: options.nangoConnectionId,
|
|
5842
|
+
format: options.format,
|
|
5843
|
+
include_raw: options.includeRaw
|
|
5844
|
+
});
|
|
5845
|
+
}
|
|
5846
|
+
/** Audit connected Nango rows, action/proxy readiness, and read/write proof gaps. */
|
|
5847
|
+
async proveNangoReadWrite(options = {}) {
|
|
5848
|
+
return this.call("nango_mcp_read_write_audit", {
|
|
5849
|
+
workspace_connection_id: options.workspaceConnectionId,
|
|
5850
|
+
connection_id: options.connectionId,
|
|
5851
|
+
provider_config_key: options.providerConfigKey,
|
|
5852
|
+
integration_id: options.integrationId,
|
|
5853
|
+
nango_connection_id: options.nangoConnectionId,
|
|
5854
|
+
limit: options.limit,
|
|
5855
|
+
include_raw: options.includeRaw,
|
|
5856
|
+
read_proxy_path: options.readProxyPath,
|
|
5857
|
+
write_proxy_path: options.writeProxyPath,
|
|
5858
|
+
method: options.method,
|
|
5859
|
+
execute_read_probe: options.executeReadProbe,
|
|
5860
|
+
execute_write_probe: options.executeWriteProbe,
|
|
5861
|
+
confirm: options.confirm,
|
|
5862
|
+
confirm_write: options.confirmWrite,
|
|
5863
|
+
input: options.input,
|
|
5864
|
+
write_input: options.writeInput
|
|
5865
|
+
});
|
|
5866
|
+
}
|
|
5867
|
+
/** Dry-run or execute a Nango-backed action tool through the approval-aware MCP bridge. */
|
|
5868
|
+
async callNangoTool(input) {
|
|
5869
|
+
return this.call("nango_mcp_tool_call", {
|
|
5870
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
5871
|
+
connection_id: input.connectionId,
|
|
5872
|
+
provider_config_key: input.providerConfigKey,
|
|
5873
|
+
integration_id: input.integrationId,
|
|
5874
|
+
nango_connection_id: input.nangoConnectionId,
|
|
5875
|
+
action_name: input.actionName,
|
|
5876
|
+
tool_name: input.toolName,
|
|
5877
|
+
delivery_mode: input.deliveryMode,
|
|
5878
|
+
proxy_path: input.proxyPath,
|
|
5879
|
+
nango_proxy_path: input.nangoProxyPath,
|
|
5880
|
+
method: input.method,
|
|
5881
|
+
http_method: input.httpMethod,
|
|
5882
|
+
proxy_headers: input.proxyHeaders,
|
|
5883
|
+
input: input.input,
|
|
5884
|
+
async: input.async,
|
|
5885
|
+
max_retries: input.maxRetries,
|
|
5886
|
+
dry_run: input.dryRun,
|
|
5887
|
+
confirm: input.confirm,
|
|
5888
|
+
confirm_write: input.confirmWrite
|
|
5889
|
+
});
|
|
5890
|
+
}
|
|
5891
|
+
/** Execute a Nango action and poll its async result when a status URL/action id is returned. */
|
|
5892
|
+
async callNangoToolAndWait(input) {
|
|
5893
|
+
const result = await this.call("nango_mcp_tool_call_and_wait", {
|
|
5894
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
5895
|
+
connection_id: input.connectionId,
|
|
5896
|
+
provider_config_key: input.providerConfigKey,
|
|
5897
|
+
integration_id: input.integrationId,
|
|
5898
|
+
nango_connection_id: input.nangoConnectionId,
|
|
5899
|
+
action_name: input.actionName,
|
|
5900
|
+
tool_name: input.toolName,
|
|
5901
|
+
delivery_mode: input.deliveryMode,
|
|
5902
|
+
proxy_path: input.proxyPath,
|
|
5903
|
+
nango_proxy_path: input.nangoProxyPath,
|
|
5904
|
+
method: input.method,
|
|
5905
|
+
http_method: input.httpMethod,
|
|
5906
|
+
proxy_headers: input.proxyHeaders,
|
|
5907
|
+
input: input.input,
|
|
5908
|
+
async: input.async ?? true,
|
|
5909
|
+
max_retries: input.maxRetries,
|
|
5910
|
+
dry_run: input.dryRun,
|
|
5911
|
+
confirm: input.confirm,
|
|
5912
|
+
confirm_write: input.confirmWrite,
|
|
5913
|
+
interval_ms: input.intervalMs,
|
|
5914
|
+
max_polls: input.maxPolls,
|
|
5915
|
+
timeout_ms: input.timeoutMs
|
|
5916
|
+
});
|
|
5917
|
+
const packet = asRecord2(result);
|
|
5918
|
+
const actionId = optionalString(packet.actionId) ?? optionalString(packet.action_id);
|
|
5919
|
+
const statusUrl = optionalString(packet.statusUrl) ?? optionalString(packet.status_url);
|
|
5920
|
+
const maxPolls = Number(packet.maxPolls ?? packet.max_polls ?? 0);
|
|
5921
|
+
const intervalMs = Number(packet.intervalMs ?? packet.interval_ms ?? 0);
|
|
5922
|
+
const timeoutMs = Number(packet.timeoutMs ?? packet.timeout_ms ?? 0);
|
|
5923
|
+
const timedOut = Boolean(packet.timedOut ?? packet.timed_out);
|
|
5924
|
+
return {
|
|
5925
|
+
...packet,
|
|
5926
|
+
success: typeof packet.success === "boolean" ? packet.success : void 0,
|
|
5927
|
+
call: packet.call,
|
|
5928
|
+
result: packet.result,
|
|
5929
|
+
status: optionalString(packet.status),
|
|
5930
|
+
action_id: actionId,
|
|
5931
|
+
actionId,
|
|
5932
|
+
status_url: statusUrl,
|
|
5933
|
+
statusUrl,
|
|
5934
|
+
polls: Number(packet.polls ?? 0),
|
|
5935
|
+
max_polls: maxPolls,
|
|
5936
|
+
maxPolls,
|
|
5937
|
+
interval_ms: intervalMs,
|
|
5938
|
+
intervalMs,
|
|
5939
|
+
timeout_ms: timeoutMs,
|
|
5940
|
+
timeoutMs,
|
|
5941
|
+
timed_out: timedOut,
|
|
5942
|
+
timedOut
|
|
5943
|
+
};
|
|
5944
|
+
}
|
|
5945
|
+
/** Poll an async Nango action result by action id or status URL. */
|
|
5946
|
+
async getNangoActionResult(input) {
|
|
5947
|
+
return this.call("nango_mcp_action_result_get", {
|
|
5948
|
+
action_id: input.actionId,
|
|
5949
|
+
status_url: input.statusUrl
|
|
5950
|
+
});
|
|
5951
|
+
}
|
|
5952
|
+
async proof(params = {}) {
|
|
5953
|
+
const data = await this.call("ops_proof", {
|
|
5954
|
+
window_hours: params.windowHours,
|
|
5955
|
+
output_format: "json"
|
|
5956
|
+
});
|
|
5957
|
+
return normalizeOpsProofResult(data);
|
|
5958
|
+
}
|
|
5959
|
+
async debug(params) {
|
|
5960
|
+
const options = typeof params === "string" ? { op_id: params } : buildOpsDebugOptions(params);
|
|
5961
|
+
const diagnosticErrors = [];
|
|
5962
|
+
const status = await this.status(options.op_id);
|
|
5963
|
+
const refs = /* @__PURE__ */ new Map();
|
|
5964
|
+
const addRefs = (items) => {
|
|
5965
|
+
for (const ref of items ?? []) refs.set(`${ref.kind}:${ref.id}`, ref);
|
|
5966
|
+
};
|
|
4726
5967
|
const recordError = (step, err) => {
|
|
4727
5968
|
diagnosticErrors.push({
|
|
4728
5969
|
step,
|
|
@@ -4734,51 +5975,57 @@ var Ops = class {
|
|
|
4734
5975
|
addRefs(collectExecutionReferences(status.latest_run));
|
|
4735
5976
|
}
|
|
4736
5977
|
const runRefs = Array.from(refs.values()).filter((ref) => ref.kind === "trigger_run" || ref.kind === "dataplane_run" || ref.kind === "replay_run");
|
|
4737
|
-
|
|
4738
|
-
for (const ref of runRefs) {
|
|
4739
|
-
try {
|
|
4740
|
-
const result = await this.getTriggerRunStatus(ref.id);
|
|
4741
|
-
const runs = "runs" in result ? result.runs : [result];
|
|
4742
|
-
runStatuses.push(...runs);
|
|
4743
|
-
for (const run of runs) addRefs(run.execution_refs);
|
|
4744
|
-
} catch (err) {
|
|
4745
|
-
recordError(`run-status:${ref.id}`, err);
|
|
4746
|
-
}
|
|
4747
|
-
}
|
|
5978
|
+
let runStatuses = [];
|
|
4748
5979
|
let queue;
|
|
4749
|
-
if (options.include_queue !== false) {
|
|
4750
|
-
try {
|
|
4751
|
-
queue = await this.getQueueStatus({ summary: true });
|
|
4752
|
-
addRefs(queue.execution_refs);
|
|
4753
|
-
} catch (err) {
|
|
4754
|
-
recordError("queue", err);
|
|
4755
|
-
}
|
|
4756
|
-
}
|
|
4757
5980
|
let dashboardRecent;
|
|
4758
|
-
if (options.include_dashboard !== false) {
|
|
4759
|
-
try {
|
|
4760
|
-
dashboardRecent = await this.getDashboard({
|
|
4761
|
-
section: "recent",
|
|
4762
|
-
limit: options.dashboard_limit ?? 10,
|
|
4763
|
-
timeRangeDays: options.time_range_days
|
|
4764
|
-
});
|
|
4765
|
-
} catch (err) {
|
|
4766
|
-
recordError("dashboard:recent", err);
|
|
4767
|
-
}
|
|
4768
|
-
}
|
|
4769
5981
|
let results;
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
|
|
4777
|
-
|
|
4778
|
-
|
|
4779
|
-
|
|
4780
|
-
|
|
4781
|
-
|
|
5982
|
+
await Promise.all([
|
|
5983
|
+
(async () => {
|
|
5984
|
+
if (runRefs.length === 0) return;
|
|
5985
|
+
try {
|
|
5986
|
+
const result = await this.getTriggerRunStatus({ run_ids: runRefs.map((ref) => ref.id) });
|
|
5987
|
+
const runs = "runs" in result ? result.runs : [result];
|
|
5988
|
+
runStatuses = runs;
|
|
5989
|
+
for (const run of runs) addRefs(run.execution_refs);
|
|
5990
|
+
} catch (err) {
|
|
5991
|
+
recordError(runRefs.length === 1 ? `run-status:${runRefs[0].id}` : "run-status:batch", err);
|
|
5992
|
+
}
|
|
5993
|
+
})(),
|
|
5994
|
+
(async () => {
|
|
5995
|
+
if (options.include_queue === false) return;
|
|
5996
|
+
try {
|
|
5997
|
+
queue = await this.getQueueStatus({ summary: true });
|
|
5998
|
+
addRefs(queue.execution_refs);
|
|
5999
|
+
} catch (err) {
|
|
6000
|
+
recordError("queue", err);
|
|
6001
|
+
}
|
|
6002
|
+
})(),
|
|
6003
|
+
(async () => {
|
|
6004
|
+
if (options.include_dashboard === false) return;
|
|
6005
|
+
try {
|
|
6006
|
+
dashboardRecent = await this.getDashboard({
|
|
6007
|
+
section: "recent",
|
|
6008
|
+
limit: options.dashboard_limit ?? 10,
|
|
6009
|
+
timeRangeDays: options.time_range_days
|
|
6010
|
+
});
|
|
6011
|
+
} catch (err) {
|
|
6012
|
+
recordError("dashboard:recent", err);
|
|
6013
|
+
}
|
|
6014
|
+
})(),
|
|
6015
|
+
(async () => {
|
|
6016
|
+
if (!options.include_results) return;
|
|
6017
|
+
try {
|
|
6018
|
+
results = await this.results({
|
|
6019
|
+
op_id: options.op_id,
|
|
6020
|
+
limit: options.results_limit ?? 25,
|
|
6021
|
+
include_failed_runs: true
|
|
6022
|
+
});
|
|
6023
|
+
addRefs(results.execution_refs);
|
|
6024
|
+
} catch (err) {
|
|
6025
|
+
recordError("results", err);
|
|
6026
|
+
}
|
|
6027
|
+
})()
|
|
6028
|
+
]);
|
|
4782
6029
|
const executionRefs = Array.from(refs.values());
|
|
4783
6030
|
const replayCandidates = executionRefs.filter((ref) => ref.kind === "execution_event");
|
|
4784
6031
|
const nextActions = buildDebugNextActions(status, executionRefs, diagnosticErrors);
|
|
@@ -4980,6 +6227,69 @@ function mergeExecutionRefs(result) {
|
|
|
4980
6227
|
for (const ref of collectExecutionReferences(result)) add(ref);
|
|
4981
6228
|
return Array.from(refs.values());
|
|
4982
6229
|
}
|
|
6230
|
+
function mergeExecutionRefsFrom(results) {
|
|
6231
|
+
const refs = /* @__PURE__ */ new Map();
|
|
6232
|
+
for (const result of results) {
|
|
6233
|
+
if (!result) continue;
|
|
6234
|
+
for (const ref of mergeExecutionRefs(result)) refs.set(`${ref.kind}:${ref.id}`, ref);
|
|
6235
|
+
}
|
|
6236
|
+
return Array.from(refs.values());
|
|
6237
|
+
}
|
|
6238
|
+
function normalizeOpsScheduleAndWaitCallResult(raw, waitOptions, messages) {
|
|
6239
|
+
if (raw.approval_required || raw.approvalRequired || raw.error_code === "APPROVAL_REQUIRED" || raw.errorCode === "APPROVAL_REQUIRED") {
|
|
6240
|
+
throw new SignalizError({
|
|
6241
|
+
code: "APPROVAL_REQUIRED",
|
|
6242
|
+
errorType: "validation",
|
|
6243
|
+
message: messages.approvalMessage,
|
|
6244
|
+
details: { schedule: raw }
|
|
6245
|
+
});
|
|
6246
|
+
}
|
|
6247
|
+
const opId = stringValue2(raw.op_id ?? raw.opId);
|
|
6248
|
+
if (!opId) {
|
|
6249
|
+
throw new SignalizError({
|
|
6250
|
+
code: "OP_NOT_CREATED",
|
|
6251
|
+
errorType: "validation",
|
|
6252
|
+
message: messages.notCreatedMessage,
|
|
6253
|
+
details: { schedule: raw }
|
|
6254
|
+
});
|
|
6255
|
+
}
|
|
6256
|
+
const scheduleRaw = asRecord2(raw.schedule ?? raw.schedule_result ?? raw.scheduleResult);
|
|
6257
|
+
const runRaw = asRecord2(raw.run ?? raw.run_result ?? raw.runResult);
|
|
6258
|
+
const schedule = normalizeOpsCreateResult(withExecutionRefs(
|
|
6259
|
+
Object.keys(scheduleRaw).length > 0 ? scheduleRaw : {
|
|
6260
|
+
...raw,
|
|
6261
|
+
op_id: opId,
|
|
6262
|
+
routine_id: raw.routine_id ?? raw.routineId ?? opId,
|
|
6263
|
+
status: "ready",
|
|
6264
|
+
phase: "scheduled",
|
|
6265
|
+
next_action: raw.next_action ?? raw.nextAction
|
|
6266
|
+
}
|
|
6267
|
+
));
|
|
6268
|
+
const run = normalizeOpsRunResult(withExecutionRefs(
|
|
6269
|
+
Object.keys(runRaw).length > 0 ? runRaw : {
|
|
6270
|
+
success: raw.success !== false,
|
|
6271
|
+
op_id: opId,
|
|
6272
|
+
routine_id: raw.routine_id ?? raw.routineId ?? opId,
|
|
6273
|
+
run_id: raw.run_id ?? raw.runId ?? null,
|
|
6274
|
+
status: "running",
|
|
6275
|
+
phase: "queued",
|
|
6276
|
+
next_action: raw.next_action ?? raw.nextAction,
|
|
6277
|
+
results_count: 0,
|
|
6278
|
+
results_url: raw.results_url ?? raw.resultsUrl,
|
|
6279
|
+
delivery_status: raw.delivery_status ?? raw.deliveryStatus
|
|
6280
|
+
}
|
|
6281
|
+
));
|
|
6282
|
+
const waited = normalizeOpsWaitForResultsResult(raw, { ...waitOptions, op_id: opId });
|
|
6283
|
+
const runId = run.run_id ?? run.runId ?? waited.run_id ?? waited.runId ?? waited.status.run_id ?? waited.status.runId ?? null;
|
|
6284
|
+
return {
|
|
6285
|
+
...waited,
|
|
6286
|
+
schedule,
|
|
6287
|
+
run,
|
|
6288
|
+
run_id: runId,
|
|
6289
|
+
runId,
|
|
6290
|
+
execution_refs: mergeExecutionRefsFrom([schedule, run, waited])
|
|
6291
|
+
};
|
|
6292
|
+
}
|
|
4983
6293
|
function normalizeOpsPrimitiveRetryPolicy(policy = {}) {
|
|
4984
6294
|
return {
|
|
4985
6295
|
...policy,
|
|
@@ -5055,8 +6365,122 @@ function normalizeOpsPrimitive(primitive) {
|
|
|
5055
6365
|
observability: normalizeOpsPrimitiveObservabilityPolicy(primitive.observability)
|
|
5056
6366
|
};
|
|
5057
6367
|
}
|
|
6368
|
+
function normalizeOpsExecutionToolCall(rawCall) {
|
|
6369
|
+
const call = asRecord2(rawCall);
|
|
6370
|
+
return {
|
|
6371
|
+
...call,
|
|
6372
|
+
tool: stringValue2(call.tool),
|
|
6373
|
+
arguments: asRecord2(call.arguments),
|
|
6374
|
+
purpose: stringValue2(call.purpose)
|
|
6375
|
+
};
|
|
6376
|
+
}
|
|
6377
|
+
function normalizeOpsExecutionScheduleContract(rawSchedule) {
|
|
6378
|
+
const schedule = asRecord2(rawSchedule);
|
|
6379
|
+
const wakeOnEvents = Array.isArray(schedule.wake_on_events) ? schedule.wake_on_events.map(String) : Array.isArray(schedule.wakeOnEvents) ? schedule.wakeOnEvents.map(String) : [];
|
|
6380
|
+
return {
|
|
6381
|
+
...schedule,
|
|
6382
|
+
create_tool: stringValue2(schedule.create_tool ?? schedule.createTool),
|
|
6383
|
+
createTool: stringValue2(schedule.createTool ?? schedule.create_tool),
|
|
6384
|
+
activate_tool: stringValue2(schedule.activate_tool ?? schedule.activateTool),
|
|
6385
|
+
activateTool: stringValue2(schedule.activateTool ?? schedule.activate_tool),
|
|
6386
|
+
cadence: stringValue2(schedule.cadence, "manual"),
|
|
6387
|
+
recurrence: stringValue2(schedule.recurrence),
|
|
6388
|
+
wake_on_events: wakeOnEvents,
|
|
6389
|
+
wakeOnEvents
|
|
6390
|
+
};
|
|
6391
|
+
}
|
|
6392
|
+
function normalizeOpsExecutionApprovalContract(rawApproval) {
|
|
6393
|
+
const approval = asRecord2(rawApproval);
|
|
6394
|
+
return {
|
|
6395
|
+
...approval,
|
|
6396
|
+
required: Boolean(approval.required),
|
|
6397
|
+
tool: stringValue2(approval.tool),
|
|
6398
|
+
reason: stringValue2(approval.reason)
|
|
6399
|
+
};
|
|
6400
|
+
}
|
|
6401
|
+
function normalizeOpsExecutionMonitorContract(rawMonitor) {
|
|
6402
|
+
const monitor = asRecord2(rawMonitor);
|
|
6403
|
+
const pollAfterMs = numberValue(monitor.poll_after_ms ?? monitor.pollAfterMs);
|
|
6404
|
+
return {
|
|
6405
|
+
...monitor,
|
|
6406
|
+
status_tool: stringValue2(monitor.status_tool ?? monitor.statusTool),
|
|
6407
|
+
statusTool: stringValue2(monitor.statusTool ?? monitor.status_tool),
|
|
6408
|
+
wait_tool: stringValue2(monitor.wait_tool ?? monitor.waitTool),
|
|
6409
|
+
waitTool: stringValue2(monitor.waitTool ?? monitor.wait_tool),
|
|
6410
|
+
results_tool: stringValue2(monitor.results_tool ?? monitor.resultsTool),
|
|
6411
|
+
resultsTool: stringValue2(monitor.resultsTool ?? monitor.results_tool),
|
|
6412
|
+
poll_after_ms: pollAfterMs,
|
|
6413
|
+
pollAfterMs
|
|
6414
|
+
};
|
|
6415
|
+
}
|
|
6416
|
+
function normalizeOpsExecutionResultContract(rawResult) {
|
|
6417
|
+
const result = asRecord2(rawResult);
|
|
6418
|
+
const shape = Array.isArray(result.shape) ? result.shape.map(String) : [];
|
|
6419
|
+
return {
|
|
6420
|
+
...result,
|
|
6421
|
+
tool: stringValue2(result.tool),
|
|
6422
|
+
wait_tool: stringValue2(result.wait_tool ?? result.waitTool),
|
|
6423
|
+
waitTool: stringValue2(result.waitTool ?? result.wait_tool),
|
|
6424
|
+
shape,
|
|
6425
|
+
empty_result_recovery: stringValue2(result.empty_result_recovery ?? result.emptyResultRecovery),
|
|
6426
|
+
emptyResultRecovery: stringValue2(result.emptyResultRecovery ?? result.empty_result_recovery)
|
|
6427
|
+
};
|
|
6428
|
+
}
|
|
6429
|
+
function normalizeOpsExecutionNangoRouteContract(rawRoute) {
|
|
6430
|
+
if (!rawRoute || typeof rawRoute !== "object" || Array.isArray(rawRoute)) return void 0;
|
|
6431
|
+
const route = asRecord2(rawRoute);
|
|
6432
|
+
const requiredFields = Array.isArray(route.required_fields) ? route.required_fields.map(String) : Array.isArray(route.requiredFields) ? route.requiredFields.map(String) : [];
|
|
6433
|
+
return {
|
|
6434
|
+
...route,
|
|
6435
|
+
enabled: route.enabled !== false,
|
|
6436
|
+
connect_tool: stringValue2(route.connect_tool ?? route.connectTool),
|
|
6437
|
+
connectTool: stringValue2(route.connectTool ?? route.connect_tool),
|
|
6438
|
+
discover_tool: stringValue2(route.discover_tool ?? route.discoverTool),
|
|
6439
|
+
discoverTool: stringValue2(route.discoverTool ?? route.discover_tool),
|
|
6440
|
+
dry_run_tool: stringValue2(route.dry_run_tool ?? route.dryRunTool),
|
|
6441
|
+
dryRunTool: stringValue2(route.dryRunTool ?? route.dry_run_tool),
|
|
6442
|
+
execute_tool: stringValue2(route.execute_tool ?? route.executeTool),
|
|
6443
|
+
executeTool: stringValue2(route.executeTool ?? route.execute_tool),
|
|
6444
|
+
execute_and_wait_tool: stringValue2(route.execute_and_wait_tool ?? route.executeAndWaitTool),
|
|
6445
|
+
executeAndWaitTool: stringValue2(route.executeAndWaitTool ?? route.execute_and_wait_tool),
|
|
6446
|
+
schedule_tool: stringValue2(route.schedule_tool ?? route.scheduleTool),
|
|
6447
|
+
scheduleTool: stringValue2(route.scheduleTool ?? route.schedule_tool),
|
|
6448
|
+
schedule_and_wait_tool: stringValue2(route.schedule_and_wait_tool ?? route.scheduleAndWaitTool),
|
|
6449
|
+
scheduleAndWaitTool: stringValue2(route.scheduleAndWaitTool ?? route.schedule_and_wait_tool),
|
|
6450
|
+
result_tool: stringValue2(route.result_tool ?? route.resultTool),
|
|
6451
|
+
resultTool: stringValue2(route.resultTool ?? route.result_tool),
|
|
6452
|
+
write_gate: stringValue2(route.write_gate ?? route.writeGate),
|
|
6453
|
+
writeGate: stringValue2(route.writeGate ?? route.write_gate),
|
|
6454
|
+
required_fields: requiredFields,
|
|
6455
|
+
requiredFields,
|
|
6456
|
+
schedule_arguments: asRecord2(route.schedule_arguments ?? route.scheduleArguments),
|
|
6457
|
+
scheduleArguments: asRecord2(route.scheduleArguments ?? route.schedule_arguments),
|
|
6458
|
+
schedule_and_wait_arguments: asRecord2(route.schedule_and_wait_arguments ?? route.scheduleAndWaitArguments),
|
|
6459
|
+
scheduleAndWaitArguments: asRecord2(route.scheduleAndWaitArguments ?? route.schedule_and_wait_arguments)
|
|
6460
|
+
};
|
|
6461
|
+
}
|
|
6462
|
+
function normalizeOpsExecutionContract(rawContract) {
|
|
6463
|
+
if (!rawContract || typeof rawContract !== "object" || Array.isArray(rawContract)) return void 0;
|
|
6464
|
+
const contract = asRecord2(rawContract);
|
|
6465
|
+
const nangoRoute = normalizeOpsExecutionNangoRouteContract(contract.nango_route ?? contract.nangoRoute);
|
|
6466
|
+
const sequence = Array.isArray(contract.sequence) ? contract.sequence.map(normalizeOpsExecutionToolCall) : [];
|
|
6467
|
+
return {
|
|
6468
|
+
...contract,
|
|
6469
|
+
mode: stringValue2(contract.mode, "run_once"),
|
|
6470
|
+
run_now: normalizeOpsExecutionToolCall(contract.run_now ?? contract.runNow),
|
|
6471
|
+
runNow: normalizeOpsExecutionToolCall(contract.runNow ?? contract.run_now),
|
|
6472
|
+
schedule: normalizeOpsExecutionScheduleContract(contract.schedule),
|
|
6473
|
+
approval: normalizeOpsExecutionApprovalContract(contract.approval),
|
|
6474
|
+
monitor: normalizeOpsExecutionMonitorContract(contract.monitor),
|
|
6475
|
+
result_contract: normalizeOpsExecutionResultContract(contract.result_contract ?? contract.resultContract),
|
|
6476
|
+
resultContract: normalizeOpsExecutionResultContract(contract.resultContract ?? contract.result_contract),
|
|
6477
|
+
...nangoRoute ? { nango_route: nangoRoute, nangoRoute } : {},
|
|
6478
|
+
sequence
|
|
6479
|
+
};
|
|
6480
|
+
}
|
|
5058
6481
|
function normalizeOpsPlanResult(result) {
|
|
5059
6482
|
const primitiveGraph = result.primitive_graph ?? result.primitiveGraph;
|
|
6483
|
+
const executionContract = normalizeOpsExecutionContract(result.execution_contract ?? result.executionContract);
|
|
5060
6484
|
return {
|
|
5061
6485
|
...result,
|
|
5062
6486
|
plan_id: result.plan_id ?? result.planId,
|
|
@@ -5080,7 +6504,8 @@ function normalizeOpsPlanResult(result) {
|
|
|
5080
6504
|
destination_status: result.destination_status ?? result.destinationStatus,
|
|
5081
6505
|
destinationStatus: result.destinationStatus ?? result.destination_status,
|
|
5082
6506
|
primitive_graph: primitiveGraph?.map(normalizeOpsPrimitive),
|
|
5083
|
-
primitiveGraph: primitiveGraph?.map(normalizeOpsPrimitive)
|
|
6507
|
+
primitiveGraph: primitiveGraph?.map(normalizeOpsPrimitive),
|
|
6508
|
+
...executionContract ? { execution_contract: executionContract, executionContract } : {}
|
|
5084
6509
|
};
|
|
5085
6510
|
}
|
|
5086
6511
|
function normalizeOpsCreateResult(result) {
|
|
@@ -5102,7 +6527,18 @@ function normalizeOpsCreateResult(result) {
|
|
|
5102
6527
|
deliveryStatus: result.deliveryStatus ?? result.delivery_status,
|
|
5103
6528
|
estimated_credits: result.estimated_credits ?? result.estimatedCredits,
|
|
5104
6529
|
estimatedCredits: result.estimatedCredits ?? result.estimated_credits,
|
|
5105
|
-
|
|
6530
|
+
error_code: result.error_code ?? result.errorCode,
|
|
6531
|
+
errorCode: result.errorCode ?? result.error_code,
|
|
6532
|
+
approval_required: result.approval_required ?? result.approvalRequired,
|
|
6533
|
+
approvalRequired: result.approvalRequired ?? result.approval_required,
|
|
6534
|
+
retry_arguments: result.retry_arguments ?? result.retryArguments,
|
|
6535
|
+
retryArguments: result.retryArguments ?? result.retry_arguments,
|
|
6536
|
+
blockers: result.blockers,
|
|
6537
|
+
plan: result.plan ? normalizeOpsPlanResult(result.plan) : result.plan,
|
|
6538
|
+
next_step: result.next_step ?? result.nextStep,
|
|
6539
|
+
nextStep: result.nextStep ?? result.next_step,
|
|
6540
|
+
next_steps: result.next_steps ?? result.nextSteps,
|
|
6541
|
+
nextSteps: result.nextSteps ?? result.next_steps
|
|
5106
6542
|
};
|
|
5107
6543
|
}
|
|
5108
6544
|
function normalizeOpsExecuteResult(result) {
|
|
@@ -5230,6 +6666,40 @@ function normalizeOpsStatusResult(result) {
|
|
|
5230
6666
|
diagnosis: result.diagnosis ? normalizeOpsDebugDiagnosis(result.diagnosis) : void 0
|
|
5231
6667
|
};
|
|
5232
6668
|
}
|
|
6669
|
+
function normalizeOpsResultsSummary(value) {
|
|
6670
|
+
const summary = asRecord2(value);
|
|
6671
|
+
if (Object.keys(summary).length === 0) return void 0;
|
|
6672
|
+
const resultsTotal = summary.results_total ?? summary.resultsTotal;
|
|
6673
|
+
const nextCursor = summary.next_cursor ?? summary.nextCursor ?? null;
|
|
6674
|
+
const resultsUrl = summary.results_url ?? summary.resultsUrl;
|
|
6675
|
+
const nextAction = summary.next_action ?? summary.nextAction;
|
|
6676
|
+
const runId = summary.run_id ?? summary.runId ?? null;
|
|
6677
|
+
const creditsUsed = summary.credits_used ?? summary.creditsUsed;
|
|
6678
|
+
return {
|
|
6679
|
+
...summary,
|
|
6680
|
+
label: optionalString(summary.label),
|
|
6681
|
+
status: optionalString(summary.status),
|
|
6682
|
+
phase: optionalString(summary.phase),
|
|
6683
|
+
results_count: numberValue(summary.results_count ?? summary.resultsCount),
|
|
6684
|
+
resultsCount: numberValue(summary.results_count ?? summary.resultsCount),
|
|
6685
|
+
results_total: resultsTotal === null || resultsTotal === void 0 ? resultsTotal : numberValue(resultsTotal),
|
|
6686
|
+
resultsTotal: resultsTotal === null || resultsTotal === void 0 ? resultsTotal : numberValue(resultsTotal),
|
|
6687
|
+
delivery_status: optionalString(summary.delivery_status ?? summary.deliveryStatus),
|
|
6688
|
+
deliveryStatus: optionalString(summary.delivery_status ?? summary.deliveryStatus),
|
|
6689
|
+
has_more: Boolean(summary.has_more ?? summary.hasMore),
|
|
6690
|
+
hasMore: Boolean(summary.has_more ?? summary.hasMore),
|
|
6691
|
+
next_cursor: nextCursor === null ? null : optionalString(nextCursor),
|
|
6692
|
+
nextCursor: nextCursor === null ? null : optionalString(nextCursor),
|
|
6693
|
+
results_url: optionalString(resultsUrl),
|
|
6694
|
+
resultsUrl: optionalString(resultsUrl),
|
|
6695
|
+
next_action: optionalString(nextAction),
|
|
6696
|
+
nextAction: optionalString(nextAction),
|
|
6697
|
+
run_id: runId === null ? null : optionalString(runId),
|
|
6698
|
+
runId: runId === null ? null : optionalString(runId),
|
|
6699
|
+
credits_used: creditsUsed === void 0 ? void 0 : numberValue(creditsUsed),
|
|
6700
|
+
creditsUsed: creditsUsed === void 0 ? void 0 : numberValue(creditsUsed)
|
|
6701
|
+
};
|
|
6702
|
+
}
|
|
5233
6703
|
function normalizeOpsResultsResult(result) {
|
|
5234
6704
|
const nextCursor = result.next_cursor ?? result.nextCursor ?? null;
|
|
5235
6705
|
const hasMore = result.has_more ?? result.hasMore ?? false;
|
|
@@ -5254,7 +6724,104 @@ function normalizeOpsResultsResult(result) {
|
|
|
5254
6724
|
results_url: result.results_url ?? result.resultsUrl,
|
|
5255
6725
|
resultsUrl: result.resultsUrl ?? result.results_url,
|
|
5256
6726
|
delivery_status: result.delivery_status ?? result.deliveryStatus,
|
|
5257
|
-
deliveryStatus: result.deliveryStatus ?? result.delivery_status
|
|
6727
|
+
deliveryStatus: result.deliveryStatus ?? result.delivery_status,
|
|
6728
|
+
summary: normalizeOpsResultsSummary(result.summary)
|
|
6729
|
+
};
|
|
6730
|
+
}
|
|
6731
|
+
function normalizeOpsWaitForResultsPoll(value, fallbackPoll) {
|
|
6732
|
+
const raw = asRecord2(value);
|
|
6733
|
+
const checkedAt = stringValue2(raw.checked_at ?? raw.checkedAt);
|
|
6734
|
+
const resultsCount = raw.results_count ?? raw.resultsCount;
|
|
6735
|
+
const runId = raw.run_id ?? raw.runId ?? null;
|
|
6736
|
+
const nextAction = raw.next_action ?? raw.nextAction;
|
|
6737
|
+
return {
|
|
6738
|
+
...raw,
|
|
6739
|
+
poll: numberValue(raw.poll) || fallbackPoll,
|
|
6740
|
+
checked_at: checkedAt,
|
|
6741
|
+
checkedAt,
|
|
6742
|
+
status: stringValue2(raw.status, "unknown"),
|
|
6743
|
+
phase: optionalString(raw.phase),
|
|
6744
|
+
results_count: resultsCount === void 0 ? void 0 : numberValue(resultsCount),
|
|
6745
|
+
resultsCount: resultsCount === void 0 ? void 0 : numberValue(resultsCount),
|
|
6746
|
+
run_id: runId === null ? null : optionalString(runId),
|
|
6747
|
+
runId: runId === null ? null : optionalString(runId),
|
|
6748
|
+
next_action: optionalString(nextAction),
|
|
6749
|
+
nextAction: optionalString(nextAction)
|
|
6750
|
+
};
|
|
6751
|
+
}
|
|
6752
|
+
function normalizeOpsWaitForResultsResult(result, options) {
|
|
6753
|
+
const opId = stringValue2(result.op_id ?? result.opId ?? options.op_id);
|
|
6754
|
+
const routineId = stringValue2(result.routine_id ?? result.routineId ?? opId);
|
|
6755
|
+
const runId = result.run_id ?? result.runId ?? null;
|
|
6756
|
+
const timedOut = Boolean(result.timed_out ?? result.timedOut);
|
|
6757
|
+
const statusRaw = asRecord2(result.status_result ?? result.statusResult);
|
|
6758
|
+
const resultsRaw = asRecord2(result.results_result ?? result.resultsResult);
|
|
6759
|
+
const historySource = Array.isArray(result.poll_history) ? result.poll_history : Array.isArray(result.history) ? result.history : [];
|
|
6760
|
+
const history = historySource.map((item, index) => normalizeOpsWaitForResultsPoll(item, index + 1));
|
|
6761
|
+
const status = normalizeOpsStatusResult(withExecutionRefs({
|
|
6762
|
+
success: result.success !== false,
|
|
6763
|
+
op_id: opId,
|
|
6764
|
+
routine_id: routineId,
|
|
6765
|
+
run_id: runId,
|
|
6766
|
+
status: stringValue2(result.status, "unknown"),
|
|
6767
|
+
phase: stringValue2(result.phase, "unknown"),
|
|
6768
|
+
next_action: stringValue2(result.next_action ?? result.nextAction),
|
|
6769
|
+
results_count: numberValue(result.results_count ?? result.resultsCount),
|
|
6770
|
+
results_url: optionalString(result.results_url ?? result.resultsUrl),
|
|
6771
|
+
delivery_status: optionalString(result.delivery_status ?? result.deliveryStatus),
|
|
6772
|
+
...statusRaw
|
|
6773
|
+
}));
|
|
6774
|
+
const includeResults = options.include_results !== false && options.includeResults !== false;
|
|
6775
|
+
const hasResultsPacket = Object.keys(resultsRaw).length > 0 || Array.isArray(result.results);
|
|
6776
|
+
const results = includeResults && hasResultsPacket ? normalizeOpsResultsResult(withExecutionRefs({
|
|
6777
|
+
success: result.success !== false,
|
|
6778
|
+
op_id: opId,
|
|
6779
|
+
routine_id: routineId,
|
|
6780
|
+
run_id: runId,
|
|
6781
|
+
status: stringValue2(result.status, status.status),
|
|
6782
|
+
phase: stringValue2(result.phase, status.phase),
|
|
6783
|
+
results_count: numberValue(result.results_count ?? result.resultsCount),
|
|
6784
|
+
results_total: result.results_total ?? result.resultsTotal ?? null,
|
|
6785
|
+
results: Array.isArray(result.results) ? result.results : [],
|
|
6786
|
+
next_cursor: result.next_cursor ?? result.nextCursor ?? null,
|
|
6787
|
+
has_more: Boolean(result.has_more ?? result.hasMore),
|
|
6788
|
+
next_action: stringValue2(result.next_action ?? result.nextAction),
|
|
6789
|
+
results_url: optionalString(result.results_url ?? result.resultsUrl),
|
|
6790
|
+
delivery_status: optionalString(result.delivery_status ?? result.deliveryStatus),
|
|
6791
|
+
...resultsRaw
|
|
6792
|
+
})) : void 0;
|
|
6793
|
+
const polls = numberValue(result.polls) || history.length;
|
|
6794
|
+
const maxPolls = result.max_polls ?? result.maxPolls;
|
|
6795
|
+
const intervalMs = result.interval_ms ?? result.intervalMs;
|
|
6796
|
+
const timeoutMs = result.timeout_ms ?? result.timeoutMs;
|
|
6797
|
+
const stopReason = result.stop_reason ?? result.stopReason;
|
|
6798
|
+
const nextAction = result.next_action ?? result.nextAction ?? results?.next_action ?? status.next_action;
|
|
6799
|
+
return {
|
|
6800
|
+
...result,
|
|
6801
|
+
success: result.success !== false && !timedOut,
|
|
6802
|
+
op_id: opId,
|
|
6803
|
+
opId,
|
|
6804
|
+
routine_id: routineId,
|
|
6805
|
+
routineId,
|
|
6806
|
+
run_id: runId === null ? null : optionalString(runId),
|
|
6807
|
+
runId: runId === null ? null : optionalString(runId),
|
|
6808
|
+
status,
|
|
6809
|
+
results,
|
|
6810
|
+
timed_out: timedOut,
|
|
6811
|
+
timedOut,
|
|
6812
|
+
polls,
|
|
6813
|
+
max_polls: maxPolls === void 0 ? void 0 : numberValue(maxPolls),
|
|
6814
|
+
maxPolls: maxPolls === void 0 ? void 0 : numberValue(maxPolls),
|
|
6815
|
+
interval_ms: intervalMs === void 0 ? void 0 : numberValue(intervalMs),
|
|
6816
|
+
intervalMs: intervalMs === void 0 ? void 0 : numberValue(intervalMs),
|
|
6817
|
+
timeout_ms: timeoutMs === void 0 ? void 0 : numberValue(timeoutMs),
|
|
6818
|
+
timeoutMs: timeoutMs === void 0 ? void 0 : numberValue(timeoutMs),
|
|
6819
|
+
stop_reason: optionalString(stopReason),
|
|
6820
|
+
stopReason: optionalString(stopReason),
|
|
6821
|
+
history,
|
|
6822
|
+
next_action: optionalString(nextAction),
|
|
6823
|
+
nextAction: optionalString(nextAction),
|
|
6824
|
+
execution_refs: mergeExecutionRefsFrom([result, status, results, { history }])
|
|
5258
6825
|
};
|
|
5259
6826
|
}
|
|
5260
6827
|
function normalizeOpsProofResult(data) {
|
|
@@ -5334,11 +6901,107 @@ function normalizeOpsProofResult(data) {
|
|
|
5334
6901
|
raw: data
|
|
5335
6902
|
};
|
|
5336
6903
|
}
|
|
6904
|
+
function normalizeOpsAutopilotSchedulePacket(rawPacket) {
|
|
6905
|
+
const packet = asRecord2(rawPacket);
|
|
6906
|
+
return {
|
|
6907
|
+
...packet,
|
|
6908
|
+
cadence: stringValue2(packet.cadence, "manual"),
|
|
6909
|
+
recurrence: stringValue2(packet.recurrence),
|
|
6910
|
+
activate_with: stringValue2(packet.activate_with ?? packet.activateWith),
|
|
6911
|
+
activateWith: stringValue2(packet.activate_with ?? packet.activateWith),
|
|
6912
|
+
run_now_with: stringValue2(packet.run_now_with ?? packet.runNowWith),
|
|
6913
|
+
runNowWith: stringValue2(packet.run_now_with ?? packet.runNowWith),
|
|
6914
|
+
monitor_with: stringValue2(packet.monitor_with ?? packet.monitorWith),
|
|
6915
|
+
monitorWith: stringValue2(packet.monitor_with ?? packet.monitorWith),
|
|
6916
|
+
retrieve_with: stringValue2(packet.retrieve_with ?? packet.retrieveWith),
|
|
6917
|
+
retrieveWith: stringValue2(packet.retrieve_with ?? packet.retrieveWith)
|
|
6918
|
+
};
|
|
6919
|
+
}
|
|
6920
|
+
function normalizeOpsAutopilotNangoRoutePacket(rawPacket) {
|
|
6921
|
+
if (!rawPacket || typeof rawPacket !== "object" || Array.isArray(rawPacket)) return void 0;
|
|
6922
|
+
const packet = asRecord2(rawPacket);
|
|
6923
|
+
const requiredFields = Array.isArray(packet.required_fields) ? packet.required_fields.map(String) : Array.isArray(packet.requiredFields) ? packet.requiredFields.map(String) : [];
|
|
6924
|
+
return {
|
|
6925
|
+
...packet,
|
|
6926
|
+
enabled: packet.enabled !== false,
|
|
6927
|
+
route_label: stringValue2(packet.route_label ?? packet.routeLabel),
|
|
6928
|
+
routeLabel: stringValue2(packet.route_label ?? packet.routeLabel),
|
|
6929
|
+
connect_tool: stringValue2(packet.connect_tool ?? packet.connectTool),
|
|
6930
|
+
connectTool: stringValue2(packet.connect_tool ?? packet.connectTool),
|
|
6931
|
+
discover_tool: stringValue2(packet.discover_tool ?? packet.discoverTool),
|
|
6932
|
+
discoverTool: stringValue2(packet.discover_tool ?? packet.discoverTool),
|
|
6933
|
+
dry_run_tool: stringValue2(packet.dry_run_tool ?? packet.dryRunTool),
|
|
6934
|
+
dryRunTool: stringValue2(packet.dry_run_tool ?? packet.dryRunTool),
|
|
6935
|
+
execute_tool: stringValue2(packet.execute_tool ?? packet.executeTool),
|
|
6936
|
+
executeTool: stringValue2(packet.execute_tool ?? packet.executeTool),
|
|
6937
|
+
execute_and_wait_tool: stringValue2(packet.execute_and_wait_tool ?? packet.executeAndWaitTool),
|
|
6938
|
+
executeAndWaitTool: stringValue2(packet.execute_and_wait_tool ?? packet.executeAndWaitTool),
|
|
6939
|
+
schedule_tool: stringValue2(packet.schedule_tool ?? packet.scheduleTool),
|
|
6940
|
+
scheduleTool: stringValue2(packet.schedule_tool ?? packet.scheduleTool),
|
|
6941
|
+
schedule_and_wait_tool: stringValue2(packet.schedule_and_wait_tool ?? packet.scheduleAndWaitTool),
|
|
6942
|
+
scheduleAndWaitTool: stringValue2(packet.schedule_and_wait_tool ?? packet.scheduleAndWaitTool),
|
|
6943
|
+
result_tool: stringValue2(packet.result_tool ?? packet.resultTool),
|
|
6944
|
+
resultTool: stringValue2(packet.result_tool ?? packet.resultTool),
|
|
6945
|
+
write_gate: stringValue2(packet.write_gate ?? packet.writeGate),
|
|
6946
|
+
writeGate: stringValue2(packet.write_gate ?? packet.writeGate),
|
|
6947
|
+
required_fields: requiredFields,
|
|
6948
|
+
requiredFields,
|
|
6949
|
+
placeholders: asRecord2(packet.placeholders),
|
|
6950
|
+
dry_run_arguments: asRecord2(packet.dry_run_arguments ?? packet.dryRunArguments),
|
|
6951
|
+
dryRunArguments: asRecord2(packet.dry_run_arguments ?? packet.dryRunArguments),
|
|
6952
|
+
execute_arguments: asRecord2(packet.execute_arguments ?? packet.executeArguments),
|
|
6953
|
+
executeArguments: asRecord2(packet.execute_arguments ?? packet.executeArguments),
|
|
6954
|
+
execute_and_wait_arguments: asRecord2(packet.execute_and_wait_arguments ?? packet.executeAndWaitArguments),
|
|
6955
|
+
executeAndWaitArguments: asRecord2(packet.execute_and_wait_arguments ?? packet.executeAndWaitArguments),
|
|
6956
|
+
schedule_arguments: asRecord2(packet.schedule_arguments ?? packet.scheduleArguments),
|
|
6957
|
+
scheduleArguments: asRecord2(packet.schedule_arguments ?? packet.scheduleArguments),
|
|
6958
|
+
schedule_and_wait_arguments: asRecord2(packet.schedule_and_wait_arguments ?? packet.scheduleAndWaitArguments),
|
|
6959
|
+
scheduleAndWaitArguments: asRecord2(packet.schedule_and_wait_arguments ?? packet.scheduleAndWaitArguments),
|
|
6960
|
+
result_arguments: asRecord2(packet.result_arguments ?? packet.resultArguments),
|
|
6961
|
+
resultArguments: asRecord2(packet.result_arguments ?? packet.resultArguments)
|
|
6962
|
+
};
|
|
6963
|
+
}
|
|
6964
|
+
function normalizeOpsAutopilotResultPacket(rawPacket) {
|
|
6965
|
+
const packet = asRecord2(rawPacket);
|
|
6966
|
+
const resultShape = Array.isArray(packet.result_shape) ? packet.result_shape.map(String) : Array.isArray(packet.resultShape) ? packet.resultShape.map(String) : [];
|
|
6967
|
+
const deliveryReceipts = Array.isArray(packet.delivery_receipts) ? packet.delivery_receipts.map(String) : Array.isArray(packet.deliveryReceipts) ? packet.deliveryReceipts.map(String) : [];
|
|
6968
|
+
return {
|
|
6969
|
+
...packet,
|
|
6970
|
+
retrieve_tool: stringValue2(packet.retrieve_tool ?? packet.retrieveTool),
|
|
6971
|
+
retrieveTool: stringValue2(packet.retrieve_tool ?? packet.retrieveTool),
|
|
6972
|
+
result_shape: resultShape,
|
|
6973
|
+
resultShape,
|
|
6974
|
+
delivery_receipts: deliveryReceipts,
|
|
6975
|
+
deliveryReceipts,
|
|
6976
|
+
empty_result_recovery: stringValue2(packet.empty_result_recovery ?? packet.emptyResultRecovery),
|
|
6977
|
+
emptyResultRecovery: stringValue2(packet.empty_result_recovery ?? packet.emptyResultRecovery)
|
|
6978
|
+
};
|
|
6979
|
+
}
|
|
6980
|
+
function normalizeOpsAutopilotOperatingPacket(rawPacket) {
|
|
6981
|
+
if (!rawPacket || typeof rawPacket !== "object" || Array.isArray(rawPacket)) return void 0;
|
|
6982
|
+
const packet = asRecord2(rawPacket);
|
|
6983
|
+
const nangoRoute = normalizeOpsAutopilotNangoRoutePacket(packet.nango_route ?? packet.nangoRoute);
|
|
6984
|
+
const approvalBoundaries = Array.isArray(packet.approval_boundaries) ? packet.approval_boundaries.map(String) : Array.isArray(packet.approvalBoundaries) ? packet.approvalBoundaries.map(String) : [];
|
|
6985
|
+
return {
|
|
6986
|
+
...packet,
|
|
6987
|
+
north_star: stringValue2(packet.north_star ?? packet.northStar),
|
|
6988
|
+
northStar: stringValue2(packet.north_star ?? packet.northStar),
|
|
6989
|
+
schedule: normalizeOpsAutopilotSchedulePacket(packet.schedule),
|
|
6990
|
+
...nangoRoute ? { nango_route: nangoRoute, nangoRoute } : {},
|
|
6991
|
+
result_contract: normalizeOpsAutopilotResultPacket(packet.result_contract ?? packet.resultContract),
|
|
6992
|
+
resultContract: normalizeOpsAutopilotResultPacket(packet.result_contract ?? packet.resultContract),
|
|
6993
|
+
approval_boundaries: approvalBoundaries,
|
|
6994
|
+
approvalBoundaries,
|
|
6995
|
+
saved_command_hint: stringValue2(packet.saved_command_hint ?? packet.savedCommandHint),
|
|
6996
|
+
savedCommandHint: stringValue2(packet.saved_command_hint ?? packet.savedCommandHint)
|
|
6997
|
+
};
|
|
6998
|
+
}
|
|
5337
6999
|
function normalizeOpsAutopilotMotion(rawMotion) {
|
|
5338
7000
|
const motion = asRecord2(rawMotion);
|
|
5339
7001
|
const targetCount = numberValue(motion.target_count ?? motion.targetCount);
|
|
5340
7002
|
const estimatedCredits = numberValue(motion.estimated_credits ?? motion.estimatedCredits);
|
|
5341
7003
|
const mcpSequence = Array.isArray(motion.mcp_sequence) ? motion.mcp_sequence : Array.isArray(motion.mcpSequence) ? motion.mcpSequence : [];
|
|
7004
|
+
const operatingPacket = normalizeOpsAutopilotOperatingPacket(motion.operating_packet ?? motion.operatingPacket);
|
|
5342
7005
|
return {
|
|
5343
7006
|
...motion,
|
|
5344
7007
|
id: stringValue2(motion.id),
|
|
@@ -5361,12 +7024,16 @@ function normalizeOpsAutopilotMotion(rawMotion) {
|
|
|
5361
7024
|
cli_command: optionalString(motion.cli_command ?? motion.cliCommand),
|
|
5362
7025
|
cliCommand: optionalString(motion.cli_command ?? motion.cliCommand),
|
|
5363
7026
|
mcp_sequence: mcpSequence,
|
|
5364
|
-
mcpSequence
|
|
7027
|
+
mcpSequence,
|
|
7028
|
+
...operatingPacket ? { operating_packet: operatingPacket, operatingPacket } : {}
|
|
5365
7029
|
};
|
|
5366
7030
|
}
|
|
5367
7031
|
function normalizeOpsAutopilotResult(result) {
|
|
5368
7032
|
const primary = normalizeOpsAutopilotMotion(result.primary_motion ?? result.primaryMotion);
|
|
5369
7033
|
const motions = Array.isArray(result.motions) ? result.motions.map(normalizeOpsAutopilotMotion) : [];
|
|
7034
|
+
const operatingPacket = normalizeOpsAutopilotOperatingPacket(
|
|
7035
|
+
result.operating_packet ?? result.operatingPacket ?? primary.operating_packet ?? primary.operatingPacket
|
|
7036
|
+
);
|
|
5370
7037
|
const queryErrors = Array.isArray(result.query_errors) ? result.query_errors.map(String) : Array.isArray(result.queryErrors) ? result.queryErrors.map(String) : [];
|
|
5371
7038
|
return {
|
|
5372
7039
|
...result,
|
|
@@ -5382,6 +7049,7 @@ function normalizeOpsAutopilotResult(result) {
|
|
|
5382
7049
|
scaleRule: optionalString(result.scale_rule ?? result.scaleRule),
|
|
5383
7050
|
agent_handoff: optionalString(result.agent_handoff ?? result.agentHandoff),
|
|
5384
7051
|
agentHandoff: optionalString(result.agent_handoff ?? result.agentHandoff),
|
|
7052
|
+
...operatingPacket ? { operating_packet: operatingPacket, operatingPacket } : {},
|
|
5385
7053
|
proof_state: optionalString(result.proof_state ?? result.proofState),
|
|
5386
7054
|
proofState: optionalString(result.proof_state ?? result.proofState),
|
|
5387
7055
|
proof_summary: result.proof_summary ?? result.proofSummary,
|
|
@@ -5646,11 +7314,125 @@ function normalizeOpsRoutineTickItemsResult(result) {
|
|
|
5646
7314
|
hasMore
|
|
5647
7315
|
};
|
|
5648
7316
|
}
|
|
7317
|
+
function buildOpsNangoScheduleBody(input) {
|
|
7318
|
+
const {
|
|
7319
|
+
workspaceConnectionId,
|
|
7320
|
+
workspace_connection_id,
|
|
7321
|
+
connectionId,
|
|
7322
|
+
connection_id,
|
|
7323
|
+
providerConfigKey,
|
|
7324
|
+
provider_config_key,
|
|
7325
|
+
integrationId,
|
|
7326
|
+
integration_id,
|
|
7327
|
+
nangoConnectionId,
|
|
7328
|
+
nango_connection_id,
|
|
7329
|
+
actionName,
|
|
7330
|
+
action_name,
|
|
7331
|
+
toolName,
|
|
7332
|
+
tool_name,
|
|
7333
|
+
proxyPath,
|
|
7334
|
+
proxy_path,
|
|
7335
|
+
nangoProxyPath,
|
|
7336
|
+
nango_proxy_path,
|
|
7337
|
+
method,
|
|
7338
|
+
httpMethod,
|
|
7339
|
+
http_method,
|
|
7340
|
+
input: nangoInput,
|
|
7341
|
+
arguments: nangoArguments,
|
|
7342
|
+
fieldMap,
|
|
7343
|
+
field_map,
|
|
7344
|
+
requiredFields,
|
|
7345
|
+
required_fields,
|
|
7346
|
+
writeConfirmed,
|
|
7347
|
+
write_confirmed,
|
|
7348
|
+
agentWriteConfirmed,
|
|
7349
|
+
agent_write_confirmed,
|
|
7350
|
+
config,
|
|
7351
|
+
destinations: _destinations,
|
|
7352
|
+
...schedule
|
|
7353
|
+
} = input;
|
|
7354
|
+
return {
|
|
7355
|
+
...buildOpsCreateBody({
|
|
7356
|
+
...schedule,
|
|
7357
|
+
cadence: schedule.cadence ?? "daily"
|
|
7358
|
+
}),
|
|
7359
|
+
workspace_connection_id: workspace_connection_id ?? workspaceConnectionId,
|
|
7360
|
+
connection_id: connection_id ?? connectionId,
|
|
7361
|
+
provider_config_key: provider_config_key ?? providerConfigKey,
|
|
7362
|
+
integration_id: integration_id ?? integrationId,
|
|
7363
|
+
nango_connection_id: nango_connection_id ?? nangoConnectionId,
|
|
7364
|
+
action_name: action_name ?? actionName,
|
|
7365
|
+
tool_name: tool_name ?? toolName,
|
|
7366
|
+
proxy_path: proxy_path ?? proxyPath ?? nango_proxy_path ?? nangoProxyPath,
|
|
7367
|
+
nango_proxy_path: nango_proxy_path ?? nangoProxyPath,
|
|
7368
|
+
method: method ?? http_method ?? httpMethod,
|
|
7369
|
+
input: nangoInput ?? nangoArguments,
|
|
7370
|
+
field_map: field_map ?? fieldMap,
|
|
7371
|
+
required_fields: required_fields ?? requiredFields,
|
|
7372
|
+
write_confirmed: write_confirmed ?? writeConfirmed,
|
|
7373
|
+
agent_write_confirmed: agent_write_confirmed ?? agentWriteConfirmed,
|
|
7374
|
+
config
|
|
7375
|
+
};
|
|
7376
|
+
}
|
|
7377
|
+
function buildOpsNangoScheduleAndWaitOptions(params) {
|
|
7378
|
+
const {
|
|
7379
|
+
force,
|
|
7380
|
+
instruction,
|
|
7381
|
+
nextCursor,
|
|
7382
|
+
includeFailedRuns,
|
|
7383
|
+
intervalMs,
|
|
7384
|
+
maxPolls,
|
|
7385
|
+
timeoutMs,
|
|
7386
|
+
includeResults,
|
|
7387
|
+
cursor,
|
|
7388
|
+
state,
|
|
7389
|
+
limit,
|
|
7390
|
+
include_failed_runs,
|
|
7391
|
+
interval_ms,
|
|
7392
|
+
max_polls,
|
|
7393
|
+
timeout_ms,
|
|
7394
|
+
include_results,
|
|
7395
|
+
...schedule
|
|
7396
|
+
} = params;
|
|
7397
|
+
return {
|
|
7398
|
+
schedule: {
|
|
7399
|
+
...schedule,
|
|
7400
|
+
cadence: schedule.cadence ?? "daily"
|
|
7401
|
+
},
|
|
7402
|
+
run: {
|
|
7403
|
+
force,
|
|
7404
|
+
instruction
|
|
7405
|
+
},
|
|
7406
|
+
wait: {
|
|
7407
|
+
cursor: cursor ?? nextCursor,
|
|
7408
|
+
state,
|
|
7409
|
+
limit,
|
|
7410
|
+
include_failed_runs: include_failed_runs ?? includeFailedRuns,
|
|
7411
|
+
interval_ms: interval_ms ?? intervalMs,
|
|
7412
|
+
max_polls: max_polls ?? maxPolls,
|
|
7413
|
+
timeout_ms: timeout_ms ?? timeoutMs,
|
|
7414
|
+
include_results: include_results ?? includeResults
|
|
7415
|
+
}
|
|
7416
|
+
};
|
|
7417
|
+
}
|
|
7418
|
+
function buildOpsNangoScheduleAndWaitBody(options) {
|
|
7419
|
+
const waitBody = buildOpsWaitBody(options.wait);
|
|
7420
|
+
const { op_id: _opId, ...waitWithoutOp } = waitBody;
|
|
7421
|
+
return {
|
|
7422
|
+
...buildOpsNangoScheduleBody(options.schedule),
|
|
7423
|
+
...waitWithoutOp,
|
|
7424
|
+
instruction: options.run.instruction,
|
|
7425
|
+
force: options.run.force
|
|
7426
|
+
};
|
|
7427
|
+
}
|
|
5649
7428
|
function buildOpsPlanBody(params) {
|
|
5650
|
-
const { targetCount, companyDomains, customAiPrompt, signalPrompt, outputPrompt, ...rest } = params;
|
|
7429
|
+
const { targetCount, wakeOnEvents, companyDomains, customAiPrompt, signalPrompt, outputPrompt, ...rest } = params;
|
|
7430
|
+
const destinations = Array.isArray(rest.destinations) ? rest.destinations.map(normalizeOpsDestinationRequest) : rest.destinations;
|
|
5651
7431
|
return {
|
|
5652
7432
|
...rest,
|
|
7433
|
+
destinations,
|
|
5653
7434
|
target_count: rest.target_count ?? targetCount,
|
|
7435
|
+
wake_on_events: rest.wake_on_events ?? wakeOnEvents,
|
|
5654
7436
|
company_domains: rest.company_domains ?? companyDomains,
|
|
5655
7437
|
custom_ai_prompt: rest.custom_ai_prompt ?? customAiPrompt,
|
|
5656
7438
|
signal_prompt: rest.signal_prompt ?? signalPrompt,
|
|
@@ -5673,6 +7455,95 @@ function buildOpsExecuteBody(params) {
|
|
|
5673
7455
|
output_format: rest.output_format ?? outputFormat
|
|
5674
7456
|
};
|
|
5675
7457
|
}
|
|
7458
|
+
function buildOpsExecuteAndWaitOptions(params) {
|
|
7459
|
+
const {
|
|
7460
|
+
nextCursor,
|
|
7461
|
+
includeFailedRuns,
|
|
7462
|
+
intervalMs,
|
|
7463
|
+
maxPolls,
|
|
7464
|
+
timeoutMs,
|
|
7465
|
+
includeResults,
|
|
7466
|
+
cursor,
|
|
7467
|
+
state,
|
|
7468
|
+
limit,
|
|
7469
|
+
include_failed_runs,
|
|
7470
|
+
interval_ms,
|
|
7471
|
+
max_polls,
|
|
7472
|
+
timeout_ms,
|
|
7473
|
+
include_results,
|
|
7474
|
+
...execute
|
|
7475
|
+
} = params;
|
|
7476
|
+
return {
|
|
7477
|
+
execute: {
|
|
7478
|
+
...execute,
|
|
7479
|
+
auto_run: execute.auto_run ?? execute.autoRun ?? true
|
|
7480
|
+
},
|
|
7481
|
+
wait: {
|
|
7482
|
+
cursor: cursor ?? nextCursor,
|
|
7483
|
+
state,
|
|
7484
|
+
limit,
|
|
7485
|
+
include_failed_runs: include_failed_runs ?? includeFailedRuns,
|
|
7486
|
+
interval_ms: interval_ms ?? intervalMs,
|
|
7487
|
+
max_polls: max_polls ?? maxPolls,
|
|
7488
|
+
timeout_ms: timeout_ms ?? timeoutMs,
|
|
7489
|
+
include_results: include_results ?? includeResults
|
|
7490
|
+
}
|
|
7491
|
+
};
|
|
7492
|
+
}
|
|
7493
|
+
function buildOpsScheduleAndWaitOptions(params) {
|
|
7494
|
+
const {
|
|
7495
|
+
force,
|
|
7496
|
+
instruction,
|
|
7497
|
+
nextCursor,
|
|
7498
|
+
includeFailedRuns,
|
|
7499
|
+
intervalMs,
|
|
7500
|
+
maxPolls,
|
|
7501
|
+
timeoutMs,
|
|
7502
|
+
includeResults,
|
|
7503
|
+
cursor,
|
|
7504
|
+
state,
|
|
7505
|
+
limit,
|
|
7506
|
+
include_failed_runs,
|
|
7507
|
+
interval_ms,
|
|
7508
|
+
max_polls,
|
|
7509
|
+
timeout_ms,
|
|
7510
|
+
include_results,
|
|
7511
|
+
...schedule
|
|
7512
|
+
} = params;
|
|
7513
|
+
return {
|
|
7514
|
+
schedule: {
|
|
7515
|
+
...schedule,
|
|
7516
|
+
cadence: schedule.cadence ?? "daily"
|
|
7517
|
+
},
|
|
7518
|
+
run: {
|
|
7519
|
+
force,
|
|
7520
|
+
instruction
|
|
7521
|
+
},
|
|
7522
|
+
wait: {
|
|
7523
|
+
cursor: cursor ?? nextCursor,
|
|
7524
|
+
state,
|
|
7525
|
+
limit,
|
|
7526
|
+
include_failed_runs: include_failed_runs ?? includeFailedRuns,
|
|
7527
|
+
interval_ms: interval_ms ?? intervalMs,
|
|
7528
|
+
max_polls: max_polls ?? maxPolls,
|
|
7529
|
+
timeout_ms: timeout_ms ?? timeoutMs,
|
|
7530
|
+
include_results: include_results ?? includeResults
|
|
7531
|
+
}
|
|
7532
|
+
};
|
|
7533
|
+
}
|
|
7534
|
+
function buildOpsScheduleAndWaitBody(options) {
|
|
7535
|
+
const waitBody = buildOpsWaitBody(options.wait);
|
|
7536
|
+
const { op_id: _opId, ...waitWithoutOp } = waitBody;
|
|
7537
|
+
return {
|
|
7538
|
+
...buildOpsCreateBody({
|
|
7539
|
+
...options.schedule,
|
|
7540
|
+
cadence: options.schedule.cadence ?? "daily"
|
|
7541
|
+
}),
|
|
7542
|
+
...waitWithoutOp,
|
|
7543
|
+
instruction: options.run.instruction,
|
|
7544
|
+
force: options.run.force
|
|
7545
|
+
};
|
|
7546
|
+
}
|
|
5676
7547
|
function buildOpsRunBody(params) {
|
|
5677
7548
|
const { opId, ...rest } = params;
|
|
5678
7549
|
return {
|
|
@@ -5680,6 +7551,28 @@ function buildOpsRunBody(params) {
|
|
|
5680
7551
|
op_id: rest.op_id ?? opId
|
|
5681
7552
|
};
|
|
5682
7553
|
}
|
|
7554
|
+
function buildOpsRunAndWaitOptions(params) {
|
|
7555
|
+
const {
|
|
7556
|
+
opId,
|
|
7557
|
+
nextCursor,
|
|
7558
|
+
includeFailedRuns,
|
|
7559
|
+
intervalMs,
|
|
7560
|
+
maxPolls,
|
|
7561
|
+
timeoutMs,
|
|
7562
|
+
includeResults,
|
|
7563
|
+
...rest
|
|
7564
|
+
} = params;
|
|
7565
|
+
return {
|
|
7566
|
+
...rest,
|
|
7567
|
+
op_id: rest.op_id ?? opId,
|
|
7568
|
+
cursor: rest.cursor ?? nextCursor,
|
|
7569
|
+
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns,
|
|
7570
|
+
interval_ms: rest.interval_ms ?? intervalMs,
|
|
7571
|
+
max_polls: rest.max_polls ?? maxPolls,
|
|
7572
|
+
timeout_ms: rest.timeout_ms ?? timeoutMs,
|
|
7573
|
+
include_results: rest.include_results ?? includeResults
|
|
7574
|
+
};
|
|
7575
|
+
}
|
|
5683
7576
|
function buildOpsStatusBody(params) {
|
|
5684
7577
|
const { opId, ...rest } = params;
|
|
5685
7578
|
return {
|
|
@@ -5696,6 +7589,50 @@ function buildOpsResultsBody(params) {
|
|
|
5696
7589
|
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns
|
|
5697
7590
|
};
|
|
5698
7591
|
}
|
|
7592
|
+
function buildOpsWaitForResultsOptions(params) {
|
|
7593
|
+
const {
|
|
7594
|
+
opId,
|
|
7595
|
+
nextCursor,
|
|
7596
|
+
includeFailedRuns,
|
|
7597
|
+
intervalMs,
|
|
7598
|
+
maxPolls,
|
|
7599
|
+
timeoutMs,
|
|
7600
|
+
includeResults,
|
|
7601
|
+
...rest
|
|
7602
|
+
} = params;
|
|
7603
|
+
return {
|
|
7604
|
+
...rest,
|
|
7605
|
+
op_id: rest.op_id ?? opId,
|
|
7606
|
+
cursor: rest.cursor ?? nextCursor,
|
|
7607
|
+
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns,
|
|
7608
|
+
interval_ms: rest.interval_ms ?? intervalMs,
|
|
7609
|
+
max_polls: rest.max_polls ?? maxPolls,
|
|
7610
|
+
timeout_ms: rest.timeout_ms ?? timeoutMs,
|
|
7611
|
+
include_results: rest.include_results ?? includeResults
|
|
7612
|
+
};
|
|
7613
|
+
}
|
|
7614
|
+
function buildOpsWaitBody(params) {
|
|
7615
|
+
const {
|
|
7616
|
+
opId,
|
|
7617
|
+
nextCursor,
|
|
7618
|
+
includeFailedRuns,
|
|
7619
|
+
intervalMs,
|
|
7620
|
+
maxPolls,
|
|
7621
|
+
timeoutMs,
|
|
7622
|
+
includeResults,
|
|
7623
|
+
...rest
|
|
7624
|
+
} = params;
|
|
7625
|
+
return {
|
|
7626
|
+
...rest,
|
|
7627
|
+
op_id: rest.op_id ?? opId,
|
|
7628
|
+
cursor: rest.cursor ?? nextCursor,
|
|
7629
|
+
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns,
|
|
7630
|
+
interval_ms: rest.interval_ms ?? intervalMs,
|
|
7631
|
+
max_polls: rest.max_polls ?? maxPolls,
|
|
7632
|
+
timeout_ms: rest.timeout_ms ?? timeoutMs,
|
|
7633
|
+
include_results: rest.include_results ?? includeResults
|
|
7634
|
+
};
|
|
7635
|
+
}
|
|
5699
7636
|
function buildOpsDebugOptions(params) {
|
|
5700
7637
|
const {
|
|
5701
7638
|
opId,
|
|
@@ -5773,6 +7710,8 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5773
7710
|
nangoAction,
|
|
5774
7711
|
proxyPath,
|
|
5775
7712
|
nangoProxyPath,
|
|
7713
|
+
method,
|
|
7714
|
+
httpMethod,
|
|
5776
7715
|
fieldMap,
|
|
5777
7716
|
requiredFields,
|
|
5778
7717
|
writeConfirmed,
|
|
@@ -5791,6 +7730,7 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5791
7730
|
const nango_action = rest.nango_action ?? nangoAction;
|
|
5792
7731
|
const proxy_path = rest.proxy_path ?? proxyPath;
|
|
5793
7732
|
const nango_proxy_path = rest.nango_proxy_path ?? nangoProxyPath;
|
|
7733
|
+
const http_method = rest.http_method ?? httpMethod;
|
|
5794
7734
|
const field_map = rest.field_map ?? fieldMap;
|
|
5795
7735
|
const required_fields = rest.required_fields ?? requiredFields;
|
|
5796
7736
|
const write_confirmed = rest.write_confirmed ?? writeConfirmed;
|
|
@@ -5805,6 +7745,9 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5805
7745
|
if (nango_action !== void 0 && normalizedConfig.nango_action === void 0) normalizedConfig.nango_action = nango_action;
|
|
5806
7746
|
if (proxy_path !== void 0 && normalizedConfig.proxy_path === void 0) normalizedConfig.proxy_path = proxy_path;
|
|
5807
7747
|
if (nango_proxy_path !== void 0 && normalizedConfig.nango_proxy_path === void 0) normalizedConfig.nango_proxy_path = nango_proxy_path;
|
|
7748
|
+
if (method !== void 0 && normalizedConfig.method === void 0) normalizedConfig.method = method;
|
|
7749
|
+
if (http_method !== void 0 && normalizedConfig.http_method === void 0) normalizedConfig.http_method = http_method;
|
|
7750
|
+
if (normalizedConfig.method === void 0 && http_method !== void 0) normalizedConfig.method = http_method;
|
|
5808
7751
|
if (field_map !== void 0 && normalizedConfig.field_map === void 0) normalizedConfig.field_map = field_map;
|
|
5809
7752
|
if (required_fields !== void 0 && normalizedConfig.required_fields === void 0) normalizedConfig.required_fields = required_fields;
|
|
5810
7753
|
if (write_confirmed !== void 0 && normalizedConfig.write_confirmed === void 0) normalizedConfig.write_confirmed = write_confirmed;
|
|
@@ -5824,6 +7767,8 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5824
7767
|
nango_action,
|
|
5825
7768
|
proxy_path,
|
|
5826
7769
|
nango_proxy_path,
|
|
7770
|
+
method,
|
|
7771
|
+
http_method,
|
|
5827
7772
|
field_map,
|
|
5828
7773
|
required_fields,
|
|
5829
7774
|
write_confirmed,
|
|
@@ -5831,6 +7776,10 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5831
7776
|
config: normalizedConfig
|
|
5832
7777
|
};
|
|
5833
7778
|
}
|
|
7779
|
+
function normalizeOpsDestinationRequest(destination) {
|
|
7780
|
+
if (!destination || typeof destination !== "object" || Array.isArray(destination)) return destination;
|
|
7781
|
+
return normalizeOpsSinkRequest(destination);
|
|
7782
|
+
}
|
|
5834
7783
|
function normalizeOpsSinkConfigRequest(config) {
|
|
5835
7784
|
const out = { ...config ?? {} };
|
|
5836
7785
|
if (out.connection_id === void 0 && out.connectionId !== void 0) out.connection_id = out.connectionId;
|
|
@@ -5844,6 +7793,8 @@ function normalizeOpsSinkConfigRequest(config) {
|
|
|
5844
7793
|
if (out.nango_action === void 0 && out.nangoAction !== void 0) out.nango_action = out.nangoAction;
|
|
5845
7794
|
if (out.proxy_path === void 0 && out.proxyPath !== void 0) out.proxy_path = out.proxyPath;
|
|
5846
7795
|
if (out.nango_proxy_path === void 0 && out.nangoProxyPath !== void 0) out.nango_proxy_path = out.nangoProxyPath;
|
|
7796
|
+
if (out.http_method === void 0 && out.httpMethod !== void 0) out.http_method = out.httpMethod;
|
|
7797
|
+
if (out.method === void 0 && out.http_method !== void 0) out.method = out.http_method;
|
|
5847
7798
|
if (out.field_map === void 0 && out.fieldMap !== void 0) out.field_map = out.fieldMap;
|
|
5848
7799
|
if (out.required_fields === void 0 && out.requiredFields !== void 0) out.required_fields = out.requiredFields;
|
|
5849
7800
|
if (out.write_confirmed === void 0 && out.writeConfirmed !== void 0) out.write_confirmed = out.writeConfirmed;
|
|
@@ -5917,7 +7868,6 @@ function toSnakeConfig(params) {
|
|
|
5917
7868
|
return {
|
|
5918
7869
|
system_prompt: params.systemPrompt || params.system_prompt || "You are a senior business research analyst. Use multi-model evidence carefully and return concise structured enrichment.",
|
|
5919
7870
|
user_template: params.userTemplate || params.user_template || params.prompt,
|
|
5920
|
-
model: params.model,
|
|
5921
7871
|
temperature: params.temperature,
|
|
5922
7872
|
max_concurrency: params.maxConcurrency || params.max_concurrency,
|
|
5923
7873
|
max_tokens: params.maxTokens || params.max_tokens,
|
|
@@ -5941,13 +7891,10 @@ var Ai = class {
|
|
|
5941
7891
|
/**
|
|
5942
7892
|
* Run Custom AI Enrichment - Multi Model.
|
|
5943
7893
|
*
|
|
5944
|
-
* Uses
|
|
5945
|
-
*
|
|
7894
|
+
* Uses the hosted default model with bounded synthesis, then returns the
|
|
7895
|
+
* requested structured output fields.
|
|
5946
7896
|
*/
|
|
5947
7897
|
async multiModel(params) {
|
|
5948
|
-
if (!params.model) {
|
|
5949
|
-
throw new Error('model is required. Use an OpenRouter id such as "anthropic/claude-sonnet-4" or "google/gemini-2.5-flash".');
|
|
5950
|
-
}
|
|
5951
7898
|
if (!params.prompt && !params.userTemplate && !params.user_template) {
|
|
5952
7899
|
throw new Error("prompt or userTemplate is required.");
|
|
5953
7900
|
}
|
|
@@ -6164,6 +8111,10 @@ var GtmKernel = class {
|
|
|
6164
8111
|
days: options.days,
|
|
6165
8112
|
network_days: options.networkDays,
|
|
6166
8113
|
min_sample_size: options.minSampleSize,
|
|
8114
|
+
holdout_min_sample_size: options.holdoutMinSampleSize,
|
|
8115
|
+
predictive_min_labeled_outcomes: options.predictiveMinLabeledOutcomes,
|
|
8116
|
+
predictive_min_positive_outcomes: options.predictiveMinPositiveOutcomes,
|
|
8117
|
+
predictive_min_memory_sample_size: options.predictiveMinMemorySampleSize,
|
|
6167
8118
|
min_workspace_count: options.minWorkspaceCount,
|
|
6168
8119
|
min_privacy_k: options.minPrivacyK,
|
|
6169
8120
|
include_memory: options.includeMemory,
|
|
@@ -6230,9 +8181,11 @@ var GtmKernel = class {
|
|
|
6230
8181
|
write_routine_outcomes: input.writeRoutineOutcomes
|
|
6231
8182
|
});
|
|
6232
8183
|
}
|
|
6233
|
-
/** Start a background Instantly webhook-events pull and route results into the GTM feedback loop. */
|
|
8184
|
+
/** Start a background Instantly webhook-events or email-history pull and route results into the GTM feedback loop. */
|
|
6234
8185
|
async pullInstantlyFeedback(input) {
|
|
6235
8186
|
return this.callMcp("gtm_instantly_feedback_pull", {
|
|
8187
|
+
source: input.source,
|
|
8188
|
+
instantly_profile: input.instantlyProfile,
|
|
6236
8189
|
campaign_id: input.campaignId,
|
|
6237
8190
|
campaign_build_id: input.campaignBuildId,
|
|
6238
8191
|
provider_link_id: input.providerLinkId,
|
|
@@ -6244,6 +8197,9 @@ var GtmKernel = class {
|
|
|
6244
8197
|
to: input.to,
|
|
6245
8198
|
limit: input.limit,
|
|
6246
8199
|
max_pages: input.maxPages,
|
|
8200
|
+
email_type: input.emailType,
|
|
8201
|
+
mode: input.mode,
|
|
8202
|
+
sort_order: input.sortOrder,
|
|
6247
8203
|
create_memory: input.createMemory,
|
|
6248
8204
|
write_routine_outcomes: input.writeRoutineOutcomes,
|
|
6249
8205
|
dry_run: input.dryRun,
|
|
@@ -6314,6 +8270,16 @@ var GtmKernel = class {
|
|
|
6314
8270
|
min_privacy_k: input.minPrivacyK
|
|
6315
8271
|
});
|
|
6316
8272
|
}
|
|
8273
|
+
/** Queue a dry-run-first bridge from imported historical feedback to attribution-only Campaign Build surrogates. */
|
|
8274
|
+
async runHistoricalCampaignBuildBridge(input = {}) {
|
|
8275
|
+
return this.callMcp("gtm_historical_campaign_build_bridge_run", {
|
|
8276
|
+
dry_run: input.dryRun,
|
|
8277
|
+
write_approved: input.writeApproved,
|
|
8278
|
+
max_events: input.maxEvents,
|
|
8279
|
+
max_campaigns: input.maxCampaigns,
|
|
8280
|
+
min_feedback_events: input.minFeedbackEvents
|
|
8281
|
+
});
|
|
8282
|
+
}
|
|
6317
8283
|
/** Prepare a provider-agnostic feedback webhook URL for Smartlead, HeyReach, Airbyte, or custom sender events. */
|
|
6318
8284
|
async prepareFeedbackWebhook(input) {
|
|
6319
8285
|
return this.callMcp("gtm_feedback_webhook_prepare", {
|
|
@@ -6373,6 +8339,7 @@ var GtmKernel = class {
|
|
|
6373
8339
|
days: input.days,
|
|
6374
8340
|
network_days: input.networkDays,
|
|
6375
8341
|
min_sample_size: input.minSampleSize,
|
|
8342
|
+
holdout_min_sample_size: input.holdoutMinSampleSize,
|
|
6376
8343
|
min_workspace_count: input.minWorkspaceCount,
|
|
6377
8344
|
min_privacy_k: input.minPrivacyK,
|
|
6378
8345
|
include_memory: input.includeMemory,
|
|
@@ -6393,6 +8360,7 @@ var GtmKernel = class {
|
|
|
6393
8360
|
days: input.days,
|
|
6394
8361
|
network_days: input.networkDays,
|
|
6395
8362
|
min_sample_size: input.minSampleSize,
|
|
8363
|
+
holdout_min_sample_size: input.holdoutMinSampleSize,
|
|
6396
8364
|
min_workspace_count: input.minWorkspaceCount,
|
|
6397
8365
|
min_privacy_k: input.minPrivacyK,
|
|
6398
8366
|
include_memory: input.includeMemory,
|
|
@@ -6517,6 +8485,29 @@ var GtmKernel = class {
|
|
|
6517
8485
|
include_details: options.includeDetails
|
|
6518
8486
|
});
|
|
6519
8487
|
}
|
|
8488
|
+
/** Search the Agency Autopilot safe-action catalog for agency-style lead lists, Clay tables, and GTM motions. */
|
|
8489
|
+
async agencyAutopilotCapabilityCatalog(options = {}) {
|
|
8490
|
+
return this.callMcp("gtm_agency_autopilot_capability_catalog", {
|
|
8491
|
+
query: options.query,
|
|
8492
|
+
family: options.family,
|
|
8493
|
+
phase: options.phase,
|
|
8494
|
+
account_label: options.accountLabel,
|
|
8495
|
+
workspace_label: options.workspaceLabel,
|
|
8496
|
+
target_count: options.targetCount,
|
|
8497
|
+
limit: options.limit,
|
|
8498
|
+
include_agent_prompts: options.includeAgentPrompts
|
|
8499
|
+
});
|
|
8500
|
+
}
|
|
8501
|
+
/** Search agency operating playbooks Agency Autopilot can use for lead lists, Clay tables, GTM motions, and proof gates. */
|
|
8502
|
+
async agencyAutopilotPlaybookCatalog(options = {}) {
|
|
8503
|
+
return this.callMcp("gtm_agency_autopilot_playbook_catalog", {
|
|
8504
|
+
query: options.query,
|
|
8505
|
+
playbook_slug: options.playbookSlug,
|
|
8506
|
+
outcome_type: options.outcomeType,
|
|
8507
|
+
limit: options.limit,
|
|
8508
|
+
include_required_fields: options.includeRequiredFields
|
|
8509
|
+
});
|
|
8510
|
+
}
|
|
6520
8511
|
/** Build the read-only Memory, Brain, risk, and provider-route runbook needed before planning a campaign. */
|
|
6521
8512
|
async campaignStartContext(input = {}) {
|
|
6522
8513
|
return this.callMcp("gtm_campaign_start_context", {
|
|
@@ -6875,6 +8866,35 @@ var GtmKernel = class {
|
|
|
6875
8866
|
user_display_name: input.userDisplayName
|
|
6876
8867
|
});
|
|
6877
8868
|
}
|
|
8869
|
+
/** Prepare the full Nango provider search, connect, pull/export, Ops, and campaign-route flow. */
|
|
8870
|
+
async prepareNangoIntegrationFlow(input = {}) {
|
|
8871
|
+
return this.callMcp("nango_integration_flow_prepare", {
|
|
8872
|
+
query: input.query,
|
|
8873
|
+
search: input.search,
|
|
8874
|
+
provider_id: input.providerId,
|
|
8875
|
+
provider: input.provider,
|
|
8876
|
+
integration_id: input.integrationId,
|
|
8877
|
+
provider_config_key: input.providerConfigKey,
|
|
8878
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
8879
|
+
connection_id: input.connectionId,
|
|
8880
|
+
nango_connection_id: input.nangoConnectionId,
|
|
8881
|
+
intent: input.intent,
|
|
8882
|
+
action_name: input.actionName,
|
|
8883
|
+
tool_name: input.toolName,
|
|
8884
|
+
proxy_path: input.proxyPath,
|
|
8885
|
+
method: input.method,
|
|
8886
|
+
input: input.input,
|
|
8887
|
+
cadence: input.cadence,
|
|
8888
|
+
field_map: input.fieldMap,
|
|
8889
|
+
required_fields: input.requiredFields,
|
|
8890
|
+
confirm_spend: input.confirmSpend,
|
|
8891
|
+
write_confirmed: input.writeConfirmed,
|
|
8892
|
+
layer: input.layer,
|
|
8893
|
+
campaign_id: input.campaignId,
|
|
8894
|
+
limit: input.limit,
|
|
8895
|
+
include_provider_catalog: input.includeProviderCatalog
|
|
8896
|
+
});
|
|
8897
|
+
}
|
|
6878
8898
|
/** List Nango-backed action tools for a workspace connection without executing them. */
|
|
6879
8899
|
async listNangoTools(options = {}) {
|
|
6880
8900
|
return this.callMcp("nango_mcp_tools_list", {
|
|
@@ -6897,6 +8917,12 @@ var GtmKernel = class {
|
|
|
6897
8917
|
nango_connection_id: input.nangoConnectionId,
|
|
6898
8918
|
action_name: input.actionName,
|
|
6899
8919
|
tool_name: input.toolName,
|
|
8920
|
+
delivery_mode: input.deliveryMode,
|
|
8921
|
+
proxy_path: input.proxyPath,
|
|
8922
|
+
nango_proxy_path: input.nangoProxyPath,
|
|
8923
|
+
method: input.method,
|
|
8924
|
+
http_method: input.httpMethod,
|
|
8925
|
+
proxy_headers: input.proxyHeaders,
|
|
6900
8926
|
input: input.input,
|
|
6901
8927
|
async: input.async,
|
|
6902
8928
|
max_retries: input.maxRetries,
|
|
@@ -7046,6 +9072,7 @@ function compact2(value) {
|
|
|
7046
9072
|
}
|
|
7047
9073
|
|
|
7048
9074
|
// src/index.ts
|
|
9075
|
+
var MCP_TOOL_CACHE_TTL_MS = 3e4;
|
|
7049
9076
|
function inferMcpToolCategory(toolName) {
|
|
7050
9077
|
if (typeof toolName !== "string" || !toolName) return void 0;
|
|
7051
9078
|
if (toolName.startsWith("ops_") || toolName === "get_ops_readiness" || toolName === "get_gtm_ops_readiness" || toolName.startsWith("gtm_") || [
|
|
@@ -7177,6 +9204,21 @@ var Signaliz = class {
|
|
|
7177
9204
|
}
|
|
7178
9205
|
/** List all available MCP tools */
|
|
7179
9206
|
async listTools() {
|
|
9207
|
+
const now = Date.now();
|
|
9208
|
+
if (this.toolListCache && this.toolListCache.expiresAt > now) {
|
|
9209
|
+
return this.toolListCache.promise;
|
|
9210
|
+
}
|
|
9211
|
+
const promise = this.fetchTools().catch((error) => {
|
|
9212
|
+
if (this.toolListCache?.promise === promise) this.toolListCache = void 0;
|
|
9213
|
+
throw error;
|
|
9214
|
+
});
|
|
9215
|
+
this.toolListCache = {
|
|
9216
|
+
expiresAt: now + MCP_TOOL_CACHE_TTL_MS,
|
|
9217
|
+
promise
|
|
9218
|
+
};
|
|
9219
|
+
return promise;
|
|
9220
|
+
}
|
|
9221
|
+
async fetchTools() {
|
|
7180
9222
|
try {
|
|
7181
9223
|
const manifest = await this.client.mcp("tools/call", {
|
|
7182
9224
|
name: "get_tool_manifest",
|