@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/mcp-config.js
CHANGED
|
@@ -243,25 +243,31 @@ var HttpClient = class {
|
|
|
243
243
|
async getToken() {
|
|
244
244
|
if (this.apiKey) return this.apiKey;
|
|
245
245
|
if (this.accessToken) return this.accessToken;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
throw new SignalizError({
|
|
257
|
-
code: "AUTH_FAILED",
|
|
258
|
-
message: "Failed to obtain access token",
|
|
259
|
-
errorType: "auth_expired"
|
|
246
|
+
if (this.accessTokenPromise) return this.accessTokenPromise;
|
|
247
|
+
this.accessTokenPromise = (async () => {
|
|
248
|
+
const res = await fetch("https://api.signaliz.com/token", {
|
|
249
|
+
method: "POST",
|
|
250
|
+
headers: { "Content-Type": "application/json" },
|
|
251
|
+
body: JSON.stringify({
|
|
252
|
+
grant_type: "client_credentials",
|
|
253
|
+
client_id: this.clientId,
|
|
254
|
+
client_secret: this.clientSecret
|
|
255
|
+
})
|
|
260
256
|
});
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
257
|
+
if (!res.ok) {
|
|
258
|
+
throw new SignalizError({
|
|
259
|
+
code: "AUTH_FAILED",
|
|
260
|
+
message: "Failed to obtain access token",
|
|
261
|
+
errorType: "auth_expired"
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
const data = await res.json();
|
|
265
|
+
this.accessToken = data.access_token;
|
|
266
|
+
return this.accessToken;
|
|
267
|
+
})().finally(() => {
|
|
268
|
+
this.accessTokenPromise = void 0;
|
|
269
|
+
});
|
|
270
|
+
return this.accessTokenPromise;
|
|
265
271
|
}
|
|
266
272
|
};
|
|
267
273
|
function sleep(ms) {
|
|
@@ -510,7 +516,6 @@ var Signals = class {
|
|
|
510
516
|
if (params.online !== void 0) args.online = params.online;
|
|
511
517
|
if (params.targetSignalCount) args.target_signal_count = params.targetSignalCount;
|
|
512
518
|
if (params.lookbackDays) args.lookback_days = params.lookbackDays;
|
|
513
|
-
if (params.model) args.model = params.model;
|
|
514
519
|
if (params.enableDeepSearch) args.enable_deep_search = params.enableDeepSearch;
|
|
515
520
|
if (params.enableOutreachIntelligence) args.enable_outreach_intelligence = params.enableOutreachIntelligence;
|
|
516
521
|
if (params.enablePredictiveIntelligence) args.enable_predictive_intelligence = params.enablePredictiveIntelligence;
|
|
@@ -805,6 +810,10 @@ var Campaigns = class {
|
|
|
805
810
|
async artifacts(campaignBuildId) {
|
|
806
811
|
return this.listCampaignBuildArtifacts(campaignBuildId);
|
|
807
812
|
}
|
|
813
|
+
/** Generate fresh signed URLs for a downloadable campaign artifact. */
|
|
814
|
+
async downloadArtifact(campaignBuildId, options) {
|
|
815
|
+
return this.downloadCampaignArtifact(campaignBuildId, options);
|
|
816
|
+
}
|
|
808
817
|
/** Cancel a queued or running build. */
|
|
809
818
|
async cancel(campaignBuildId, reason) {
|
|
810
819
|
return this.cancelCampaignBuild(campaignBuildId, reason);
|
|
@@ -849,13 +858,21 @@ var Campaigns = class {
|
|
|
849
858
|
dryRun: isDryRun,
|
|
850
859
|
requestedTargetCount: data.requested_target_count,
|
|
851
860
|
plannedTargetCount: data.planned_target_count,
|
|
861
|
+
acquisitionMode: data.acquisition_mode,
|
|
862
|
+
acquisitionSource: data.acquisition_source,
|
|
863
|
+
cacheReusePolicy: data.cache_reuse_policy,
|
|
852
864
|
estimatedCredits: data.estimated_credits,
|
|
853
865
|
estimatedDurationSeconds: data.estimated_duration_seconds,
|
|
854
866
|
targetLimitApplied: data.target_limit_applied,
|
|
855
867
|
targetLimitReason: data.target_limit_reason,
|
|
856
868
|
maxSupportedTargetCount: data.max_supported_target_count,
|
|
857
869
|
brainContext: data.brain_context ?? {},
|
|
858
|
-
|
|
870
|
+
learningHoldout: data.learning_holdout ?? {},
|
|
871
|
+
providerRoute: mapProviderRoute(data),
|
|
872
|
+
effectiveSourceRouting: recordOrNull(data.effective_source_routing ?? data.source_routing),
|
|
873
|
+
sourcePlan: recordOrNull(data.source_plan ?? data.plan?.source_plan),
|
|
874
|
+
sourceRoutes: recordArray(data.source_routes ?? data.source_plan?.routes ?? data.plan?.source_plan?.routes),
|
|
875
|
+
sourceShards: recordArray(data.source_shards ?? data.source_plan?.shards ?? data.plan?.source_plan?.shards)
|
|
859
876
|
};
|
|
860
877
|
}
|
|
861
878
|
async getCampaignBuildStatus(campaignBuildId) {
|
|
@@ -870,14 +887,24 @@ var Campaigns = class {
|
|
|
870
887
|
});
|
|
871
888
|
return (data.artifacts ?? []).map(mapArtifact);
|
|
872
889
|
}
|
|
890
|
+
async downloadCampaignArtifact(campaignBuildId, options) {
|
|
891
|
+
const args = { campaign_build_id: campaignBuildId };
|
|
892
|
+
if (options?.format) args.format = options.format;
|
|
893
|
+
const data = await this.callMcp("download_campaign_artifact", args);
|
|
894
|
+
return mapArtifactDownloadResult(data);
|
|
895
|
+
}
|
|
873
896
|
async getCampaignBuildRows(campaignBuildId, options) {
|
|
874
897
|
const args = { campaign_build_id: campaignBuildId };
|
|
875
898
|
if (options?.limit) args.page_size = options.limit;
|
|
876
899
|
if (options?.cursor) args.cursor = options.cursor;
|
|
900
|
+
if (options?.includeData !== void 0) args.include_data = options.includeData;
|
|
901
|
+
if (options?.includeRaw !== void 0) args.include_raw = options.includeRaw;
|
|
877
902
|
const filters = {};
|
|
878
903
|
if (options?.segment) filters.segment = options.segment;
|
|
879
904
|
if (options?.rowStatus) filters.row_status = options.rowStatus;
|
|
880
905
|
if (options?.qualified !== void 0) filters.qualified = options.qualified;
|
|
906
|
+
if (options?.cached !== void 0) filters.cached = options.cached;
|
|
907
|
+
if (options?.exportReady !== void 0) filters.export_ready = options.exportReady;
|
|
881
908
|
if (Object.keys(filters).length > 0) args.filters = filters;
|
|
882
909
|
const data = await this.callMcp("get_campaign_build_rows", args);
|
|
883
910
|
return {
|
|
@@ -902,6 +929,7 @@ var Campaigns = class {
|
|
|
902
929
|
};
|
|
903
930
|
if (options?.destinationId) args.destination_id = options.destinationId;
|
|
904
931
|
if (options?.destinationConfig) args.destination_config = options.destinationConfig;
|
|
932
|
+
if (options?.allowPartialDelivery === true) args.allow_partial_delivery = true;
|
|
905
933
|
const data = await this.callMcp("approve_campaign_delivery", args);
|
|
906
934
|
return {
|
|
907
935
|
campaignBuildId: data.campaign_build_id,
|
|
@@ -910,7 +938,10 @@ var Campaigns = class {
|
|
|
910
938
|
message: data.message ?? "",
|
|
911
939
|
deliveryId: data.delivery_id,
|
|
912
940
|
deliveryIds: data.delivery_ids,
|
|
913
|
-
approvedCount: data.approved_count
|
|
941
|
+
approvedCount: data.approved_count,
|
|
942
|
+
partialDelivery: data.partial_delivery,
|
|
943
|
+
effectiveTargetCount: data.effective_target_count,
|
|
944
|
+
requestedTargetCount: data.requested_target_count
|
|
914
945
|
};
|
|
915
946
|
}
|
|
916
947
|
async cancelCampaignBuild(campaignBuildId, reason) {
|
|
@@ -963,17 +994,50 @@ function mapStatus(data) {
|
|
|
963
994
|
warnings: diagnosticMessages(data.warnings),
|
|
964
995
|
errors: diagnosticMessages(data.errors),
|
|
965
996
|
artifactCount: data.artifact_count ?? 0,
|
|
997
|
+
artifactDownloads: Array.isArray(data.artifact_downloads) ? data.artifact_downloads.map(mapArtifactDownload) : [],
|
|
998
|
+
customerRowCounts: mapCustomerRowCounts(data.customer_row_counts),
|
|
999
|
+
phaseAttemptTotals: recordOrNull(data.phase_attempt_totals) ?? void 0,
|
|
966
1000
|
providerRoute: mapProviderRoute(data),
|
|
967
1001
|
triggerRunId: typeof data.trigger_run_id === "string" ? data.trigger_run_id : null,
|
|
968
1002
|
staleRunningPhase: data.stale_running_phase === true,
|
|
969
1003
|
phaseAgeSeconds: numberOrNull(data.phase_age_seconds),
|
|
970
1004
|
diagnostics: recordOrNull(data.diagnostics) ?? {},
|
|
971
1005
|
nextAction: formatNextAction(data.next_action),
|
|
1006
|
+
approvalAction: formatNextAction(data.approval_action),
|
|
972
1007
|
createdAt: data.created_at,
|
|
973
1008
|
updatedAt: data.updated_at,
|
|
974
1009
|
completedAt: data.completed_at
|
|
975
1010
|
};
|
|
976
1011
|
}
|
|
1012
|
+
function mapCustomerRowCounts(value) {
|
|
1013
|
+
const record = recordOrNull(value);
|
|
1014
|
+
if (!record) return void 0;
|
|
1015
|
+
return {
|
|
1016
|
+
requestedTarget: numberOrNull(record.requested_target),
|
|
1017
|
+
acquiredRows: numberOrNull(record.acquired_rows) ?? void 0,
|
|
1018
|
+
acceptedRows: numberOrNull(record.accepted_rows) ?? void 0,
|
|
1019
|
+
usableRows: numberOrNull(record.usable_rows) ?? void 0,
|
|
1020
|
+
copiedRows: numberOrNull(record.copied_rows) ?? void 0,
|
|
1021
|
+
approvalReadyRows: numberOrNull(record.approval_ready_rows) ?? void 0,
|
|
1022
|
+
qaReadyRows: numberOrNull(record.qa_ready_rows) ?? void 0,
|
|
1023
|
+
deliveredRows: numberOrNull(record.delivered_rows) ?? void 0,
|
|
1024
|
+
disqualifiedRows: numberOrNull(record.disqualified_rows) ?? void 0,
|
|
1025
|
+
reviewableRows: numberOrNull(record.reviewable_rows) ?? void 0,
|
|
1026
|
+
rowFailures: numberOrNull(record.row_failures) ?? void 0,
|
|
1027
|
+
acceptedShortfall: numberOrNull(record.accepted_shortfall),
|
|
1028
|
+
usableShortfall: numberOrNull(record.usable_shortfall),
|
|
1029
|
+
qaReadyShortfall: numberOrNull(record.qa_ready_shortfall),
|
|
1030
|
+
deliveryShortfall: numberOrNull(record.delivery_shortfall),
|
|
1031
|
+
fillRatio: numberOrNull(record.fill_ratio),
|
|
1032
|
+
qaReadyFillRatio: numberOrNull(record.qa_ready_fill_ratio),
|
|
1033
|
+
deliveredFillRatio: numberOrNull(record.delivered_fill_ratio),
|
|
1034
|
+
terminalReason: typeof record.terminal_reason === "string" ? record.terminal_reason : null,
|
|
1035
|
+
acceptedShortfallReason: typeof record.accepted_shortfall_reason === "string" ? record.accepted_shortfall_reason : null,
|
|
1036
|
+
usableShortfallReason: typeof record.usable_shortfall_reason === "string" ? record.usable_shortfall_reason : null,
|
|
1037
|
+
qaReadyShortfallReason: typeof record.qa_ready_shortfall_reason === "string" ? record.qa_ready_shortfall_reason : null,
|
|
1038
|
+
deliveryShortfallReason: typeof record.delivery_shortfall_reason === "string" ? record.delivery_shortfall_reason : null
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
977
1041
|
function mapProviderRoute(data) {
|
|
978
1042
|
const brainContext = recordOrNull(data?.brain_context);
|
|
979
1043
|
const plan = recordOrNull(data?.provider_route_plan) ?? recordOrNull(brainContext?.provider_route_plan);
|
|
@@ -1000,6 +1064,9 @@ function recordOrNull(value) {
|
|
|
1000
1064
|
function stringArray(value) {
|
|
1001
1065
|
return Array.isArray(value) ? value.map((item) => String(item || "").trim()).filter(Boolean) : [];
|
|
1002
1066
|
}
|
|
1067
|
+
function recordArray(value) {
|
|
1068
|
+
return Array.isArray(value) ? value.map(recordOrNull).filter((item) => Boolean(item)) : [];
|
|
1069
|
+
}
|
|
1003
1070
|
function diagnosticMessages(value) {
|
|
1004
1071
|
if (!Array.isArray(value)) return [];
|
|
1005
1072
|
return value.map((item) => {
|
|
@@ -1051,13 +1118,56 @@ function mapArtifact(a) {
|
|
|
1051
1118
|
artifactType: a.artifact_type,
|
|
1052
1119
|
destination: a.destination,
|
|
1053
1120
|
storagePath: a.storage_path,
|
|
1121
|
+
format: a.format ?? null,
|
|
1054
1122
|
signedUrl: a.signed_url,
|
|
1123
|
+
downloadUrl: a.download_url ?? null,
|
|
1124
|
+
manifestUrl: a.manifest_url ?? null,
|
|
1125
|
+
expiresAt: a.expires_at ?? null,
|
|
1055
1126
|
rowCount: a.row_count ?? 0,
|
|
1056
1127
|
checksum: a.checksum,
|
|
1057
1128
|
metadata: a.metadata ?? {},
|
|
1058
1129
|
createdAt: a.created_at
|
|
1059
1130
|
};
|
|
1060
1131
|
}
|
|
1132
|
+
function mapArtifactDownload(data) {
|
|
1133
|
+
return {
|
|
1134
|
+
id: data.id,
|
|
1135
|
+
artifactType: data.artifact_type ?? null,
|
|
1136
|
+
format: data.format ?? null,
|
|
1137
|
+
rowCount: data.row_count ?? 0,
|
|
1138
|
+
signedUrl: data.signed_url ?? null,
|
|
1139
|
+
downloadUrl: data.download_url ?? null,
|
|
1140
|
+
manifestUrl: data.manifest_url ?? null,
|
|
1141
|
+
expiresAt: data.expires_at ?? null
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
function mapArtifactDownloadResult(data) {
|
|
1145
|
+
return {
|
|
1146
|
+
campaignBuildId: data.campaign_build_id,
|
|
1147
|
+
artifactId: data.artifact_id,
|
|
1148
|
+
format: data.format,
|
|
1149
|
+
rowCount: data.row_count ?? 0,
|
|
1150
|
+
byteSize: numberOrNull(data.byte_size),
|
|
1151
|
+
partCount: data.part_count ?? 0,
|
|
1152
|
+
checksum: data.checksum ?? null,
|
|
1153
|
+
signedUrl: data.signed_url ?? null,
|
|
1154
|
+
downloadUrl: data.download_url ?? null,
|
|
1155
|
+
manifestUrl: data.manifest_url ?? null,
|
|
1156
|
+
expiresAt: data.expires_at ?? null,
|
|
1157
|
+
parts: Array.isArray(data.parts) ? data.parts.map(mapArtifactDownloadPart) : [],
|
|
1158
|
+
downloadCommands: recordOrNull(data.download_commands) ?? {},
|
|
1159
|
+
expiresInSeconds: numberOrNull(data.expires_in_seconds)
|
|
1160
|
+
};
|
|
1161
|
+
}
|
|
1162
|
+
function mapArtifactDownloadPart(data) {
|
|
1163
|
+
return {
|
|
1164
|
+
partIndex: data.part_index ?? 0,
|
|
1165
|
+
rowCount: data.row_count ?? 0,
|
|
1166
|
+
byteSize: numberOrNull(data.byte_size),
|
|
1167
|
+
checksum: data.checksum ?? null,
|
|
1168
|
+
signedUrl: data.signed_url ?? null
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1061
1171
|
function mapScope(data) {
|
|
1062
1172
|
return {
|
|
1063
1173
|
campaignScopeId: data.campaign_scope_id,
|
|
@@ -1111,8 +1221,30 @@ function buildArgs(request) {
|
|
|
1111
1221
|
if (request.allowDownscale !== void 0) args.allow_downscale = request.allowDownscale;
|
|
1112
1222
|
if (request.confirmSpend !== void 0) args.confirm_spend = request.confirmSpend;
|
|
1113
1223
|
if (request.dedupKeys) args.dedup_keys = request.dedupKeys;
|
|
1224
|
+
if (request.acquisitionMode) args.acquisition_mode = request.acquisitionMode;
|
|
1225
|
+
if (request.cacheReusePolicy) {
|
|
1226
|
+
args.cache_reuse_policy = {
|
|
1227
|
+
allow_verified_cache: request.cacheReusePolicy.allowVerifiedCache,
|
|
1228
|
+
suppress_prior_campaign_ids: request.cacheReusePolicy.suppressPriorCampaignIds,
|
|
1229
|
+
suppress_prior_list_ids: request.cacheReusePolicy.suppressPriorListIds,
|
|
1230
|
+
uniqueness: request.cacheReusePolicy.uniqueness,
|
|
1231
|
+
require_usage_metadata: request.cacheReusePolicy.requireUsageMetadata,
|
|
1232
|
+
verified_cache_ttl_days: request.cacheReusePolicy.verifiedCacheTtlDays
|
|
1233
|
+
};
|
|
1234
|
+
}
|
|
1114
1235
|
if (request.brainPreflight) args.brain_preflight = request.brainPreflight;
|
|
1115
1236
|
if (request.brainDefaults) args.brain_defaults = request.brainDefaults;
|
|
1237
|
+
if (request.learningHoldout) {
|
|
1238
|
+
args.learning_holdout = {
|
|
1239
|
+
enabled: request.learningHoldout.enabled,
|
|
1240
|
+
control_percentage: request.learningHoldout.controlPercentage,
|
|
1241
|
+
min_control_size: request.learningHoldout.minControlSize,
|
|
1242
|
+
experiment_key: request.learningHoldout.experimentKey,
|
|
1243
|
+
source_campaign_id: request.learningHoldout.sourceCampaignId,
|
|
1244
|
+
primary_metric: request.learningHoldout.primaryMetric
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
if (request.campaignStrategyContext) args.campaign_strategy_context = request.campaignStrategyContext;
|
|
1116
1248
|
if (request.deliveryRisk) args.delivery_risk = request.deliveryRisk;
|
|
1117
1249
|
if (request.icp) {
|
|
1118
1250
|
args.icp = {
|
|
@@ -1154,7 +1286,17 @@ function buildArgs(request) {
|
|
|
1154
1286
|
max_body_words: request.copy.maxBodyWords,
|
|
1155
1287
|
sender_context: request.copy.senderContext,
|
|
1156
1288
|
offer_context: request.copy.offerContext,
|
|
1157
|
-
model: request.copy.model
|
|
1289
|
+
model: request.copy.model,
|
|
1290
|
+
style_source: request.copy.styleSource ? {
|
|
1291
|
+
sample_text: request.copy.styleSource.sampleText,
|
|
1292
|
+
campaign_ids: request.copy.styleSource.campaignIds,
|
|
1293
|
+
artifact_ids: request.copy.styleSource.artifactIds
|
|
1294
|
+
} : void 0,
|
|
1295
|
+
sequence_steps: request.copy.sequenceSteps,
|
|
1296
|
+
copy_schema: request.copy.copySchema,
|
|
1297
|
+
banned_phrases: request.copy.bannedPhrases,
|
|
1298
|
+
approval_required: request.copy.approvalRequired,
|
|
1299
|
+
quality_tier: request.copy.qualityTier
|
|
1158
1300
|
};
|
|
1159
1301
|
}
|
|
1160
1302
|
if (request.delivery) {
|
|
@@ -1217,6 +1359,8 @@ var DEFAULT_SIGNALIZ_CAMPAIGN_BUILDER_DEFAULTS = {
|
|
|
1217
1359
|
}
|
|
1218
1360
|
};
|
|
1219
1361
|
var DEFAULT_CAMPAIGN_BUILDER_BUILT_INS = [
|
|
1362
|
+
"company_discovery",
|
|
1363
|
+
"people_discovery",
|
|
1220
1364
|
"lead_generation",
|
|
1221
1365
|
"email_finding",
|
|
1222
1366
|
"email_verification",
|
|
@@ -1225,6 +1369,8 @@ var DEFAULT_CAMPAIGN_BUILDER_BUILT_INS = [
|
|
|
1225
1369
|
var CAMPAIGN_BUILDER_BUILT_IN_ROUTE_IDS = {
|
|
1226
1370
|
lead_generation: "signaliz-lead-generation",
|
|
1227
1371
|
local_leads: "signaliz-local-leads",
|
|
1372
|
+
company_discovery: "signaliz-company-discovery",
|
|
1373
|
+
people_discovery: "signaliz-people-discovery",
|
|
1228
1374
|
email_finding: "signaliz-email-finding",
|
|
1229
1375
|
email_verification: "signaliz-email-verification",
|
|
1230
1376
|
signals: "signaliz-signals"
|
|
@@ -1242,8 +1388,8 @@ var CAMPAIGN_BUILDER_OPERATING_PLAYBOOKS = [
|
|
|
1242
1388
|
slug: "cache-first-large-list",
|
|
1243
1389
|
label: "Cache-First Large List",
|
|
1244
1390
|
whenToUse: [
|
|
1245
|
-
"The
|
|
1246
|
-
"The deliverable is a
|
|
1391
|
+
"The operator explicitly references a previous campaign, prior list, seed list, or suppression baseline.",
|
|
1392
|
+
"The deliverable is a top-up, continuation, or backfill where prior campaign context should guide reuse."
|
|
1247
1393
|
],
|
|
1248
1394
|
sequence: [
|
|
1249
1395
|
"Inventory reusable cache before paid sourcing.",
|
|
@@ -1449,7 +1595,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1449
1595
|
],
|
|
1450
1596
|
requireVerifiedEmail: true
|
|
1451
1597
|
},
|
|
1452
|
-
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1598
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "email_finding", "email_verification", "signals"],
|
|
1453
1599
|
preferredProviders: ["signaliz_native"],
|
|
1454
1600
|
memoryQueries: [{
|
|
1455
1601
|
query: "industrial OT net-new prior email suppression verified manufacturing embedded systems field service cyber resilience business continuity",
|
|
@@ -1523,7 +1669,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1523
1669
|
],
|
|
1524
1670
|
requireVerifiedEmail: true
|
|
1525
1671
|
},
|
|
1526
|
-
builtIns: ["lead_generation", "local_leads", "email_finding", "email_verification", "signals"],
|
|
1672
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "local_leads", "email_finding", "email_verification", "signals"],
|
|
1527
1673
|
preferredProviders: ["signaliz_native", "octave", "clay_webhook", "apify"],
|
|
1528
1674
|
memoryQueries: [{
|
|
1529
1675
|
query: "mature non-medical home care agencies billable hours franchise caregiver recruiting proof gate qualification export approval",
|
|
@@ -1589,7 +1735,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1589
1735
|
exclusions: ["enterprise holding company", "staffing", "recruiting", "software-only vendor", "freelancer-only profile"],
|
|
1590
1736
|
requireVerifiedEmail: true
|
|
1591
1737
|
},
|
|
1592
|
-
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1738
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "email_finding", "email_verification", "signals"],
|
|
1593
1739
|
preferredProviders: ["signaliz_native", "octave"],
|
|
1594
1740
|
memoryQueries: [{
|
|
1595
1741
|
query: "agency founder owner CEO marketing services suppression domain pool email verification final approval gate",
|
|
@@ -1671,7 +1817,7 @@ var CAMPAIGN_BUILDER_STRATEGY_TEMPLATES = [
|
|
|
1671
1817
|
],
|
|
1672
1818
|
requireVerifiedEmail: true
|
|
1673
1819
|
},
|
|
1674
|
-
builtIns: ["lead_generation", "email_finding", "email_verification", "signals"],
|
|
1820
|
+
builtIns: ["company_discovery", "people_discovery", "lead_generation", "email_finding", "email_verification", "signals"],
|
|
1675
1821
|
preferredProviders: ["signaliz_native", "octave"],
|
|
1676
1822
|
memoryQueries: [{
|
|
1677
1823
|
query: "cloud hosting infrastructure VMware Broadcom qualification verified email persona trigger SKU mapping",
|
|
@@ -1704,25 +1850,21 @@ var CampaignBuilderAgent = class {
|
|
|
1704
1850
|
async createPlan(request, options = {}) {
|
|
1705
1851
|
const resolvedRequest = applyCampaignBuilderStrategyTemplate(request);
|
|
1706
1852
|
const warnings = [];
|
|
1707
|
-
const workspaceContext =
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1853
|
+
const [workspaceContext, scopeResult] = await Promise.all([
|
|
1854
|
+
resolvedRequest.workspaceContext ? Promise.resolve(resolvedRequest.workspaceContext) : this.getWorkspaceContext(warnings),
|
|
1855
|
+
options.scopeCampaign === false ? Promise.resolve(void 0) : this.scopeCampaign(resolvedRequest, warnings),
|
|
1856
|
+
options.discoverCapabilities === false ? Promise.resolve(void 0) : this.discoverPlannedRoutes(resolvedRequest, warnings)
|
|
1857
|
+
]);
|
|
1712
1858
|
const plan = createCampaignBuilderAgentPlan(resolvedRequest, {
|
|
1713
1859
|
workspaceContext,
|
|
1714
1860
|
scopeBuildArgs: asRecord(scopeResult?.build_campaign_args ?? scopeResult?.buildCampaignArgs),
|
|
1715
1861
|
warnings
|
|
1716
1862
|
});
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
}
|
|
1723
|
-
if (options.includeDeliveryRisk !== false) {
|
|
1724
|
-
await this.attachDeliveryRiskPreflight(plan, warnings);
|
|
1725
|
-
}
|
|
1863
|
+
await Promise.all([
|
|
1864
|
+
options.includeStrategyMemoryStatus === false ? Promise.resolve() : this.attachStrategyMemoryStatus(plan, warnings),
|
|
1865
|
+
options.includeKernelPlan === false ? Promise.resolve() : this.attachKernelCampaignBuildPlan(plan, warnings),
|
|
1866
|
+
options.includeDeliveryRisk === false ? Promise.resolve() : this.attachDeliveryRiskPreflight(plan, warnings)
|
|
1867
|
+
]);
|
|
1726
1868
|
return plan;
|
|
1727
1869
|
}
|
|
1728
1870
|
async readiness(request, options = {}) {
|
|
@@ -1770,6 +1912,8 @@ var CampaignBuilderAgent = class {
|
|
|
1770
1912
|
},
|
|
1771
1913
|
brain_defaults: plan.buildRequest.brainDefaults,
|
|
1772
1914
|
brain_preflight: plan.buildRequest.brainPreflight,
|
|
1915
|
+
learning_holdout: plan.buildRequest.learningHoldout,
|
|
1916
|
+
campaign_strategy_context: plan.buildRequest.campaignStrategyContext,
|
|
1773
1917
|
delivery_risk_preflight: plan.buildRequest.deliveryRisk,
|
|
1774
1918
|
delivery_risk: plan.buildRequest.deliveryRisk
|
|
1775
1919
|
}),
|
|
@@ -1782,7 +1926,8 @@ var CampaignBuilderAgent = class {
|
|
|
1782
1926
|
estimated_credits: plan.estimatedCredits
|
|
1783
1927
|
},
|
|
1784
1928
|
brain_delivery_risk_preflight: plan.buildRequest.deliveryRisk,
|
|
1785
|
-
delivery_risk: plan.buildRequest.deliveryRisk
|
|
1929
|
+
delivery_risk: plan.buildRequest.deliveryRisk,
|
|
1930
|
+
learning_holdout: plan.buildRequest.learningHoldout
|
|
1786
1931
|
},
|
|
1787
1932
|
approval_required: plan.approvals.some((approval) => approval.blocking),
|
|
1788
1933
|
actor_type: "agent",
|
|
@@ -1891,7 +2036,8 @@ var CampaignBuilderAgent = class {
|
|
|
1891
2036
|
const destinationType = options.deliveryDestinationType ?? plan.buildRequest.delivery?.destinationType ?? "json";
|
|
1892
2037
|
result.deliveryApproval = await this.approveCampaignDelivery(campaignBuildId, destinationType, {
|
|
1893
2038
|
destinationId: options.deliveryDestinationId,
|
|
1894
|
-
destinationConfig: options.deliveryDestinationConfig ?? plan.buildRequest.delivery?.destinationConfig
|
|
2039
|
+
destinationConfig: options.deliveryDestinationConfig ?? plan.buildRequest.delivery?.destinationConfig,
|
|
2040
|
+
allowPartialDelivery: options.allowPartialDelivery
|
|
1895
2041
|
});
|
|
1896
2042
|
finalStatus = await this.waitForCampaignBuildStatus(
|
|
1897
2043
|
campaignBuildId,
|
|
@@ -1914,8 +2060,12 @@ var CampaignBuilderAgent = class {
|
|
|
1914
2060
|
const args = compact({
|
|
1915
2061
|
campaign_build_id: campaignBuildId,
|
|
1916
2062
|
page_size: options.limit,
|
|
1917
|
-
cursor: options.cursor
|
|
2063
|
+
cursor: options.cursor,
|
|
2064
|
+
include_data: options.includeData,
|
|
2065
|
+
include_raw: options.includeRaw
|
|
1918
2066
|
});
|
|
2067
|
+
if (options.cached !== void 0) filters.cached = options.cached;
|
|
2068
|
+
if (options.exportReady !== void 0) filters.export_ready = options.exportReady;
|
|
1919
2069
|
if (Object.keys(filters).length > 0) args.filters = filters;
|
|
1920
2070
|
const data = await this.callMcp("get_campaign_build_rows", args);
|
|
1921
2071
|
return mapAgentCampaignRowsResult(data);
|
|
@@ -1930,12 +2080,14 @@ var CampaignBuilderAgent = class {
|
|
|
1930
2080
|
return this.approveCampaignDelivery(campaignBuildId, destinationType, options);
|
|
1931
2081
|
}
|
|
1932
2082
|
async reviewBuild(campaignBuildId, options = {}) {
|
|
1933
|
-
const status = await
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
2083
|
+
const [status, rows, artifacts] = await Promise.all([
|
|
2084
|
+
this.getBuildStatus(campaignBuildId),
|
|
2085
|
+
this.getBuildRows(campaignBuildId, {
|
|
2086
|
+
...options,
|
|
2087
|
+
limit: options.limit ?? 100
|
|
2088
|
+
}),
|
|
2089
|
+
this.listBuildArtifacts(campaignBuildId)
|
|
2090
|
+
]);
|
|
1939
2091
|
return createCampaignBuilderBuildReview(status, rows, artifacts);
|
|
1940
2092
|
}
|
|
1941
2093
|
async getCampaignBuildStatus(campaignBuildId) {
|
|
@@ -1963,7 +2115,8 @@ var CampaignBuilderAgent = class {
|
|
|
1963
2115
|
campaign_build_id: campaignBuildId,
|
|
1964
2116
|
destination_type: destinationType,
|
|
1965
2117
|
destination_id: options?.destinationId,
|
|
1966
|
-
destination_config: options?.destinationConfig
|
|
2118
|
+
destination_config: options?.destinationConfig,
|
|
2119
|
+
allow_partial_delivery: options?.allowPartialDelivery === true ? true : void 0
|
|
1967
2120
|
});
|
|
1968
2121
|
const data = await this.callMcp("approve_campaign_delivery", args);
|
|
1969
2122
|
return {
|
|
@@ -1973,7 +2126,10 @@ var CampaignBuilderAgent = class {
|
|
|
1973
2126
|
message: data.message ?? "",
|
|
1974
2127
|
deliveryId: data.delivery_id,
|
|
1975
2128
|
deliveryIds: data.delivery_ids,
|
|
1976
|
-
approvedCount: data.approved_count
|
|
2129
|
+
approvedCount: data.approved_count,
|
|
2130
|
+
partialDelivery: data.partial_delivery,
|
|
2131
|
+
effectiveTargetCount: data.effective_target_count,
|
|
2132
|
+
requestedTargetCount: data.requested_target_count
|
|
1977
2133
|
};
|
|
1978
2134
|
}
|
|
1979
2135
|
async getWorkspaceContext(warnings) {
|
|
@@ -2009,15 +2165,19 @@ var CampaignBuilderAgent = class {
|
|
|
2009
2165
|
const providers = new Set(
|
|
2010
2166
|
[...request.integrations ?? [], ...routesFromCustomerTools(request.customerTools ?? [])].filter((route) => route.provider !== "signaliz").map((route) => route.provider)
|
|
2011
2167
|
);
|
|
2012
|
-
|
|
2168
|
+
const warningsByProvider = await Promise.all(Array.from(providers, async (provider) => {
|
|
2013
2169
|
try {
|
|
2014
2170
|
await this.callMcp("discover_capabilities", {
|
|
2015
2171
|
query: `campaign builder ${provider} ${request.goal}`,
|
|
2016
2172
|
category: "campaign"
|
|
2017
2173
|
});
|
|
2174
|
+
return void 0;
|
|
2018
2175
|
} catch (error) {
|
|
2019
|
-
|
|
2176
|
+
return `Capability discovery for ${provider} failed: ${errorMessage(error)}`;
|
|
2020
2177
|
}
|
|
2178
|
+
}));
|
|
2179
|
+
for (const warning of warningsByProvider) {
|
|
2180
|
+
if (warning) warnings.push(warning);
|
|
2021
2181
|
}
|
|
2022
2182
|
}
|
|
2023
2183
|
async attachStrategyMemoryStatus(plan, warnings) {
|
|
@@ -2041,8 +2201,24 @@ var CampaignBuilderAgent = class {
|
|
|
2041
2201
|
const kernelPlan = await this.callMcp("gtm_campaign_build_plan", asRecord(plannerStep.arguments));
|
|
2042
2202
|
plan.kernelPlan = asRecord(kernelPlan);
|
|
2043
2203
|
const brainDefaults = asRecord(plan.kernelPlan.brain_defaults ?? plan.kernelPlan.brainDefaults);
|
|
2204
|
+
const corpusContext = asRecord(plan.kernelPlan.corpus_context ?? plan.kernelPlan.corpusContext);
|
|
2205
|
+
const campaignStrategyContext = asRecord(plan.kernelPlan.campaign_strategy_context ?? plan.kernelPlan.campaignStrategyContext);
|
|
2206
|
+
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) : [];
|
|
2044
2207
|
if (Object.keys(brainDefaults).length > 0 && Object.keys(asRecord(plan.buildRequest.brainDefaults)).length === 0) {
|
|
2045
2208
|
plan.buildRequest.brainDefaults = brainDefaults;
|
|
2209
|
+
}
|
|
2210
|
+
if (Object.keys(campaignStrategyContext).length > 0) {
|
|
2211
|
+
plan.buildRequest.campaignStrategyContext = campaignStrategyContext;
|
|
2212
|
+
}
|
|
2213
|
+
if (Object.keys(corpusContext).length > 0 || memoryExamples.length > 0 || Object.keys(brainDefaults).length > 0 || Object.keys(campaignStrategyContext).length > 0) {
|
|
2214
|
+
plan.buildRequest.brainPreflight = compact({
|
|
2215
|
+
...asRecord(plan.buildRequest.brainPreflight),
|
|
2216
|
+
corpus_context: Object.keys(corpusContext).length > 0 ? corpusContext : void 0,
|
|
2217
|
+
memory_examples: memoryExamples.length > 0 ? memoryExamples : void 0,
|
|
2218
|
+
brain_defaults: Object.keys(brainDefaults).length > 0 ? brainDefaults : void 0,
|
|
2219
|
+
campaign_strategy_context: Object.keys(campaignStrategyContext).length > 0 ? campaignStrategyContext : void 0
|
|
2220
|
+
});
|
|
2221
|
+
plan.brainPreflight = asRecord(plan.buildRequest.brainPreflight);
|
|
2046
2222
|
refreshBuildStepArguments(plan);
|
|
2047
2223
|
}
|
|
2048
2224
|
} catch (error) {
|
|
@@ -2223,6 +2399,9 @@ function createCampaignBuilderProofReceipt(plan, result) {
|
|
|
2223
2399
|
campaign_build_id: dryRunResult.campaignBuildId ?? dryRunResult.campaign_build_id ?? null
|
|
2224
2400
|
}
|
|
2225
2401
|
];
|
|
2402
|
+
const learnBackPlan = summarizeCampaignBuilderProofLearnBack(
|
|
2403
|
+
asRecord(asRecord(plan.buildRequest.brainPreflight).learn_back_plan ?? asRecord(plan.brainPreflight).learn_back_plan)
|
|
2404
|
+
);
|
|
2226
2405
|
return {
|
|
2227
2406
|
receipt_version: "campaign-agent-proof.v1",
|
|
2228
2407
|
source: "signaliz.campaignBuilderAgent.proof",
|
|
@@ -2245,6 +2424,7 @@ function createCampaignBuilderProofReceipt(plan, result) {
|
|
|
2245
2424
|
gates,
|
|
2246
2425
|
strategy_memory_status: summarizeCampaignBuilderProofStrategyMemory(strategyMemory),
|
|
2247
2426
|
dry_run_result: summarizeCampaignBuilderProofDryRun(dryRunResult),
|
|
2427
|
+
learn_back_plan: learnBackPlan,
|
|
2248
2428
|
recommended_next_actions: [
|
|
2249
2429
|
"Review the plan, approvals, and dry-run result.",
|
|
2250
2430
|
"Use campaign-agent commit-plan --confirm-write only after review.",
|
|
@@ -2794,6 +2974,13 @@ function campaignBuilderMemoryKitSdkExample(request, seedManifestFile) {
|
|
|
2794
2974
|
function campaignBuilderMemoryKitSource(source) {
|
|
2795
2975
|
const normalized = normalizeTemplateKey(source || "agency");
|
|
2796
2976
|
const catalog = {
|
|
2977
|
+
northStar: {
|
|
2978
|
+
id: "north_star_campaign_builder",
|
|
2979
|
+
label: "North Star campaign-builder acceptance patterns",
|
|
2980
|
+
seed_source: "north-star",
|
|
2981
|
+
scope: "redacted_acceptance_seed_packs",
|
|
2982
|
+
privacy: "redacted aggregate counts, QA gates, and fixture shape only"
|
|
2983
|
+
},
|
|
2797
2984
|
agency: {
|
|
2798
2985
|
id: "agency_campaign_builder",
|
|
2799
2986
|
label: "Agency campaign-builder strategy patterns",
|
|
@@ -2819,6 +3006,10 @@ function campaignBuilderMemoryKitSource(source) {
|
|
|
2819
3006
|
const sourceMap = {
|
|
2820
3007
|
agency: "agency",
|
|
2821
3008
|
"campaign-builder": "agency",
|
|
3009
|
+
"north-star": "northStar",
|
|
3010
|
+
northstar: "northStar",
|
|
3011
|
+
"campaign-builder-north-star": "northStar",
|
|
3012
|
+
acceptance: "northStar",
|
|
2822
3013
|
"strategy-memory": "agency",
|
|
2823
3014
|
"workflow-patterns": "workflow",
|
|
2824
3015
|
workflow: "workflow",
|
|
@@ -2834,13 +3025,13 @@ function campaignBuilderMemoryKitSource(source) {
|
|
|
2834
3025
|
return {
|
|
2835
3026
|
seedSource: "all",
|
|
2836
3027
|
verifyScript: null,
|
|
2837
|
-
memorySources: [catalog.agency, catalog.workflow, catalog.feedback]
|
|
3028
|
+
memorySources: [catalog.northStar, catalog.agency, catalog.workflow, catalog.feedback]
|
|
2838
3029
|
};
|
|
2839
3030
|
}
|
|
2840
3031
|
const item = catalog[selected];
|
|
2841
3032
|
return {
|
|
2842
3033
|
seedSource: item.seed_source,
|
|
2843
|
-
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,
|
|
3034
|
+
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,
|
|
2844
3035
|
memorySources: [item]
|
|
2845
3036
|
};
|
|
2846
3037
|
}
|
|
@@ -3020,11 +3211,11 @@ function builtInRoutesFor(request) {
|
|
|
3020
3211
|
routes.push({
|
|
3021
3212
|
id: "signaliz-lead-generation",
|
|
3022
3213
|
layer: "source",
|
|
3023
|
-
|
|
3214
|
+
gtmLayer: "lead_generation",
|
|
3024
3215
|
provider: "signaliz",
|
|
3025
3216
|
mode: "required",
|
|
3026
3217
|
toolName: "generate_leads",
|
|
3027
|
-
rationale: "
|
|
3218
|
+
rationale: "Inventory verified cache first, then use Signaliz fresh workspace acquisition for the remaining approved gap."
|
|
3028
3219
|
});
|
|
3029
3220
|
}
|
|
3030
3221
|
if (builtIns.has("local_leads")) {
|
|
@@ -3038,6 +3229,28 @@ function builtInRoutesFor(request) {
|
|
|
3038
3229
|
rationale: "Use Signaliz local-leads sourcing for geography-bound local business campaigns."
|
|
3039
3230
|
});
|
|
3040
3231
|
}
|
|
3232
|
+
if (builtIns.has("company_discovery")) {
|
|
3233
|
+
routes.push({
|
|
3234
|
+
id: "signaliz-company-discovery",
|
|
3235
|
+
layer: "source",
|
|
3236
|
+
gtmLayer: "find_company",
|
|
3237
|
+
provider: "signaliz",
|
|
3238
|
+
mode: "if_available",
|
|
3239
|
+
toolName: "find_companies_signaliz",
|
|
3240
|
+
rationale: "Find and qualify company domains before people/email fill for account-led campaigns."
|
|
3241
|
+
});
|
|
3242
|
+
}
|
|
3243
|
+
if (builtIns.has("people_discovery")) {
|
|
3244
|
+
routes.push({
|
|
3245
|
+
id: "signaliz-people-discovery",
|
|
3246
|
+
layer: "source",
|
|
3247
|
+
gtmLayer: "find_people",
|
|
3248
|
+
provider: "signaliz",
|
|
3249
|
+
mode: "if_available",
|
|
3250
|
+
toolName: "find_people_signaliz",
|
|
3251
|
+
rationale: "Find people directly when the brief is contact research or LinkedIn-style prospecting."
|
|
3252
|
+
});
|
|
3253
|
+
}
|
|
3041
3254
|
if (builtIns.has("email_finding")) {
|
|
3042
3255
|
routes.push({
|
|
3043
3256
|
id: "signaliz-email-finding",
|
|
@@ -3082,7 +3295,7 @@ function normalizeBuiltIns(request) {
|
|
|
3082
3295
|
return [...builtIns].filter(isCampaignBuilderBuiltInTool);
|
|
3083
3296
|
}
|
|
3084
3297
|
function isCampaignBuilderBuiltInTool(value) {
|
|
3085
|
-
return ["lead_generation", "local_leads", "email_finding", "email_verification", "signals"].includes(String(value));
|
|
3298
|
+
return ["lead_generation", "local_leads", "company_discovery", "people_discovery", "email_finding", "email_verification", "signals"].includes(String(value));
|
|
3086
3299
|
}
|
|
3087
3300
|
function looksLikeLocalLeadCampaign(request) {
|
|
3088
3301
|
const text = [
|
|
@@ -3113,6 +3326,21 @@ function routesFromCustomerTools(tools) {
|
|
|
3113
3326
|
}))
|
|
3114
3327
|
);
|
|
3115
3328
|
}
|
|
3329
|
+
function normalizeCampaignBuilderLearningHoldout(input, gtmCampaignId, campaignName) {
|
|
3330
|
+
const source = asRecord(input);
|
|
3331
|
+
if (source.enabled === false) return { enabled: false };
|
|
3332
|
+
const controlPercentage = numberOrUndefined2(source.control_percentage ?? source.controlPercentage);
|
|
3333
|
+
const minControlSize = numberOrUndefined2(source.min_control_size ?? source.minControlSize);
|
|
3334
|
+
const experimentKey = stringValue(source.experiment_key ?? source.experimentKey) ?? (gtmCampaignId ? `gtm_campaign:${gtmCampaignId}:learning_holdout` : `campaign_builder_agent:${hashString(campaignName)}:learning_holdout`);
|
|
3335
|
+
return {
|
|
3336
|
+
enabled: true,
|
|
3337
|
+
controlPercentage: controlPercentage ?? 0.2,
|
|
3338
|
+
minControlSize: minControlSize ?? 50,
|
|
3339
|
+
experimentKey,
|
|
3340
|
+
sourceCampaignId: stringValue(source.source_campaign_id ?? source.sourceCampaignId) ?? gtmCampaignId,
|
|
3341
|
+
primaryMetric: stringValue(source.primary_metric ?? source.primaryMetric) ?? "positive_reply_rate"
|
|
3342
|
+
};
|
|
3343
|
+
}
|
|
3116
3344
|
function createBuildRequest(request, defaults, targetCount, campaignName, scopeBuildArgs, routes = [], memory, scopeBrainPreflight) {
|
|
3117
3345
|
const buildRequest = {
|
|
3118
3346
|
name: campaignName,
|
|
@@ -3137,10 +3365,19 @@ function createBuildRequest(request, defaults, targetCount, campaignName, scopeB
|
|
|
3137
3365
|
qualification: defaults.qualification,
|
|
3138
3366
|
copy: defaults.copy,
|
|
3139
3367
|
delivery: defaults.delivery,
|
|
3140
|
-
enhancers: enhancerConfig(request)
|
|
3368
|
+
enhancers: enhancerConfig(request),
|
|
3369
|
+
sourceRouting: request.sourceRouting ?? {
|
|
3370
|
+
mode: looksLikeLocalLeadCampaign(request) ? "local_leads" : "auto",
|
|
3371
|
+
fillPolicy: "aggressive"
|
|
3372
|
+
}
|
|
3141
3373
|
};
|
|
3142
3374
|
const scoped = asRecord(scopeBuildArgs);
|
|
3143
3375
|
buildRequest.gtmCampaignId = request.gtmCampaignId ?? stringValue(scoped.gtm_campaign_id ?? scoped.gtmCampaignId);
|
|
3376
|
+
buildRequest.learningHoldout = normalizeCampaignBuilderLearningHoldout(
|
|
3377
|
+
request.learningHoldout ?? scoped.learning_holdout ?? scoped.learningHoldout,
|
|
3378
|
+
buildRequest.gtmCampaignId,
|
|
3379
|
+
campaignName
|
|
3380
|
+
);
|
|
3144
3381
|
if (typeof scoped.name === "string") buildRequest.name = scoped.name;
|
|
3145
3382
|
if (typeof scoped.prompt === "string") buildRequest.prompt = scoped.prompt;
|
|
3146
3383
|
if (typeof scoped.target_count === "number") buildRequest.targetCount = scoped.target_count;
|
|
@@ -3215,13 +3452,137 @@ function createBrainPreflight(request, buildRequest, routes, memory) {
|
|
|
3215
3452
|
target_icp: targetIcp,
|
|
3216
3453
|
provider_chain: providerChain,
|
|
3217
3454
|
lead_source: providerChain[0] ?? "signaliz",
|
|
3455
|
+
learning_holdout: buildRequest.learningHoldout,
|
|
3218
3456
|
tool_sequence: [
|
|
3219
3457
|
{ tool: "gtm_brain_learning_cycle_plan", purpose: "Plan the Brain learning loop for this campaign.", arguments: learningArgs },
|
|
3220
3458
|
{ tool: "gtm_brain_seed_defaults", purpose: "Seed campaign defaults from workspace memory and safe aggregate patterns.", arguments: defaultsArgs },
|
|
3221
3459
|
{ tool: "gtm_brain_delivery_risk", purpose: "Check deliverability risk before launch or external writes.", arguments: riskArgs }
|
|
3222
|
-
]
|
|
3460
|
+
],
|
|
3461
|
+
learn_back_plan: createCampaignBuilderLearnBackPlan(request, buildRequest)
|
|
3462
|
+
};
|
|
3463
|
+
}
|
|
3464
|
+
function createCampaignBuilderLearnBackPlan(request, buildRequest) {
|
|
3465
|
+
const instantlyFeedbackContext = campaignBuilderProviderFeedbackContext(request, buildRequest, "instantly");
|
|
3466
|
+
const postBuildSequence = [
|
|
3467
|
+
{
|
|
3468
|
+
tool: "get_campaign_build_status",
|
|
3469
|
+
approval_boundary: "read_only",
|
|
3470
|
+
arguments_template: { campaign_build_id: "<build_campaign.campaign_build_id>" },
|
|
3471
|
+
reason: "Wait for the Campaign Builder run to finish before deriving memory."
|
|
3472
|
+
},
|
|
3473
|
+
{
|
|
3474
|
+
tool: "gtm_campaign_build_backfill_preview",
|
|
3475
|
+
approval_boundary: "read_only",
|
|
3476
|
+
arguments_template: { campaign_build_id: "<build_campaign.campaign_build_id>", create_memory: true },
|
|
3477
|
+
reason: "Preview the provider-neutral Kernel import payload without writing rows."
|
|
3478
|
+
},
|
|
3479
|
+
{
|
|
3480
|
+
tool: "gtm_campaign_build_backfill_run",
|
|
3481
|
+
approval_boundary: "dry_run",
|
|
3482
|
+
arguments_template: { campaign_build_ids: ["<build_campaign.campaign_build_id>"], dry_run: true, create_memory: true, run_brain_cycle: false },
|
|
3483
|
+
reason: "Dry-run the Kernel history import before creating campaign memory."
|
|
3484
|
+
},
|
|
3485
|
+
{
|
|
3486
|
+
tool: "gtm_campaign_build_backfill_run",
|
|
3487
|
+
approval_boundary: "explicit_write_approval",
|
|
3488
|
+
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" },
|
|
3489
|
+
reason: "After review, queue the Kernel history import; Brain learning remains dry-run unless separately approved."
|
|
3490
|
+
}
|
|
3491
|
+
];
|
|
3492
|
+
if (instantlyFeedbackContext) {
|
|
3493
|
+
postBuildSequence.push({
|
|
3494
|
+
tool: "gtm_instantly_feedback_pull",
|
|
3495
|
+
approval_boundary: "dry_run_first_explicit_write_approval",
|
|
3496
|
+
arguments_template: {
|
|
3497
|
+
campaign_id: buildRequest.gtmCampaignId || "<gtm_campaign_id_after_commit>",
|
|
3498
|
+
campaign_build_id: "<build_campaign.campaign_build_id>",
|
|
3499
|
+
source: "emails",
|
|
3500
|
+
email_type: "received",
|
|
3501
|
+
...instantlyFeedbackContext,
|
|
3502
|
+
dry_run: true,
|
|
3503
|
+
create_memory: true,
|
|
3504
|
+
write_routine_outcomes: true,
|
|
3505
|
+
run_brain_cycle: true,
|
|
3506
|
+
brain_cycle_write_mode: "dry_run"
|
|
3507
|
+
},
|
|
3508
|
+
reason: "After Instantly delivery has live outcomes, pull reply and bounce history into private feedback memory before Brain learning."
|
|
3509
|
+
});
|
|
3510
|
+
}
|
|
3511
|
+
postBuildSequence.push(
|
|
3512
|
+
{
|
|
3513
|
+
tool: "gtm_campaign_learning_status",
|
|
3514
|
+
approval_boundary: "read_only",
|
|
3515
|
+
arguments_template: {
|
|
3516
|
+
campaign_id: buildRequest.gtmCampaignId || "<gtm_campaign_id_after_commit>",
|
|
3517
|
+
campaign_build_id: "<build_campaign.campaign_build_id>",
|
|
3518
|
+
write_mode: "dry_run"
|
|
3519
|
+
},
|
|
3520
|
+
reason: "Confirm feedback, memory, and Brain learning readiness after the import."
|
|
3521
|
+
},
|
|
3522
|
+
{
|
|
3523
|
+
tool: "gtm_memory_search",
|
|
3524
|
+
approval_boundary: "read_only",
|
|
3525
|
+
arguments_template: {
|
|
3526
|
+
query: request.goal,
|
|
3527
|
+
...buildRequest.gtmCampaignId ? { campaign_id: buildRequest.gtmCampaignId } : {},
|
|
3528
|
+
limit: 10
|
|
3529
|
+
},
|
|
3530
|
+
reason: "Verify the new private memory is retrievable for future campaign planning."
|
|
3531
|
+
},
|
|
3532
|
+
{
|
|
3533
|
+
tool: "gtm_brain_learning_cycle_plan",
|
|
3534
|
+
approval_boundary: "read_only",
|
|
3535
|
+
arguments_template: {
|
|
3536
|
+
...buildRequest.gtmCampaignId ? { campaign_id: buildRequest.gtmCampaignId } : {},
|
|
3537
|
+
include_memory: true,
|
|
3538
|
+
write_mode: "dry_run"
|
|
3539
|
+
},
|
|
3540
|
+
reason: "Plan the Brain phases from the imported outcomes before any pattern writes."
|
|
3541
|
+
}
|
|
3542
|
+
);
|
|
3543
|
+
return {
|
|
3544
|
+
source_tool: "campaign-builder-agent",
|
|
3545
|
+
gtm_campaign_id: buildRequest.gtmCampaignId ?? null,
|
|
3546
|
+
trigger: "After build_campaign returns a campaign_build_id and the build reaches a terminal reviewed state.",
|
|
3547
|
+
build_result_placeholders: {
|
|
3548
|
+
campaign_build_id: "<build_campaign.campaign_build_id>"
|
|
3549
|
+
},
|
|
3550
|
+
memory_write_policy: {
|
|
3551
|
+
target_tables: ["gtm_campaigns", "gtm_campaign_provider_links", "gtm_campaign_feedback_events", "gtm_memory_items", "gtm_brain_patterns"],
|
|
3552
|
+
gtm_memory_items: {
|
|
3553
|
+
shareable: false,
|
|
3554
|
+
allowed_redaction_states: ["redacted", "abstracted"],
|
|
3555
|
+
raw_private_fields_withheld: ["reply_text", "copy_body", "lead_email", "lead_domain", "company_domain", "provider_campaign_id", "provider_payload", "webhook_url", "secret"]
|
|
3556
|
+
},
|
|
3557
|
+
gtm_brain_patterns: "Workspace-scoped by default. Global promotion requires abstracted_only=true, shared opt-in, and privacy thresholds."
|
|
3558
|
+
},
|
|
3559
|
+
post_build_sequence: postBuildSequence.map((item, index) => ({ step: index + 1, ...item })),
|
|
3560
|
+
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.",
|
|
3561
|
+
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."
|
|
3223
3562
|
};
|
|
3224
3563
|
}
|
|
3564
|
+
function campaignBuilderProviderFeedbackContext(request, buildRequest, provider) {
|
|
3565
|
+
const normalizedProvider = String(provider).toLowerCase();
|
|
3566
|
+
const routes = [...request.integrations ?? [], ...routesFromCustomerTools(request.customerTools ?? [])];
|
|
3567
|
+
const providerRoute = routes.find((route) => String(route.provider).toLowerCase() === normalizedProvider);
|
|
3568
|
+
const routeConfig = asRecord(providerRoute?.config);
|
|
3569
|
+
const deliveryConfig = asRecord(buildRequest.delivery?.destinationConfig);
|
|
3570
|
+
const hasProviderContext = [
|
|
3571
|
+
...request.preferredProviders ?? [],
|
|
3572
|
+
...routes.map((route) => route.provider),
|
|
3573
|
+
stringValue(deliveryConfig.provider),
|
|
3574
|
+
stringValue(deliveryConfig.provider_id ?? deliveryConfig.providerId),
|
|
3575
|
+
stringValue(deliveryConfig.destination_provider ?? deliveryConfig.destinationProvider),
|
|
3576
|
+
stringValue(deliveryConfig.sink ?? deliveryConfig.sink_type ?? deliveryConfig.sinkType)
|
|
3577
|
+
].some((value) => String(value).toLowerCase() === normalizedProvider);
|
|
3578
|
+
if (!hasProviderContext) return void 0;
|
|
3579
|
+
return compact({
|
|
3580
|
+
provider_link_id: stringValue(routeConfig.provider_link_id ?? routeConfig.providerLinkId ?? deliveryConfig.provider_link_id ?? deliveryConfig.providerLinkId),
|
|
3581
|
+
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),
|
|
3582
|
+
integration_id: stringValue(routeConfig.integration_id ?? routeConfig.integrationId ?? deliveryConfig.integration_id ?? deliveryConfig.integrationId),
|
|
3583
|
+
instantly_profile: stringValue(routeConfig.instantly_profile ?? routeConfig.instantlyProfile ?? routeConfig.profile ?? deliveryConfig.instantly_profile ?? deliveryConfig.instantlyProfile ?? deliveryConfig.profile)
|
|
3584
|
+
});
|
|
3585
|
+
}
|
|
3225
3586
|
function gtmLayersForBuilderLayer(layer) {
|
|
3226
3587
|
const map = {
|
|
3227
3588
|
workspace_context: ["customer_data"],
|
|
@@ -3626,6 +3987,7 @@ function buildFallbackPlanSnapshot(plan) {
|
|
|
3626
3987
|
target_count: plan.targetCount,
|
|
3627
3988
|
approvals: plan.approvals,
|
|
3628
3989
|
brain_preflight: plan.brainPreflight,
|
|
3990
|
+
campaign_strategy_context: plan.buildRequest.campaignStrategyContext,
|
|
3629
3991
|
operating_playbooks: plan.operatingPlaybooks
|
|
3630
3992
|
});
|
|
3631
3993
|
}
|
|
@@ -3758,6 +4120,17 @@ function buildCampaignArgs(request) {
|
|
|
3758
4120
|
if (request.dedupKeys) args.dedup_keys = request.dedupKeys;
|
|
3759
4121
|
if (request.brainPreflight) args.brain_preflight = request.brainPreflight;
|
|
3760
4122
|
if (request.brainDefaults) args.brain_defaults = request.brainDefaults;
|
|
4123
|
+
if (request.learningHoldout) {
|
|
4124
|
+
args.learning_holdout = compact({
|
|
4125
|
+
enabled: request.learningHoldout.enabled,
|
|
4126
|
+
control_percentage: request.learningHoldout.controlPercentage,
|
|
4127
|
+
min_control_size: request.learningHoldout.minControlSize,
|
|
4128
|
+
experiment_key: request.learningHoldout.experimentKey,
|
|
4129
|
+
source_campaign_id: request.learningHoldout.sourceCampaignId,
|
|
4130
|
+
primary_metric: request.learningHoldout.primaryMetric
|
|
4131
|
+
});
|
|
4132
|
+
}
|
|
4133
|
+
if (request.campaignStrategyContext) args.campaign_strategy_context = request.campaignStrategyContext;
|
|
3761
4134
|
if (request.deliveryRisk) args.delivery_risk = request.deliveryRisk;
|
|
3762
4135
|
if (request.icp) {
|
|
3763
4136
|
args.icp = compact({
|
|
@@ -3777,6 +4150,15 @@ function buildCampaignArgs(request) {
|
|
|
3777
4150
|
model: request.policy.model
|
|
3778
4151
|
});
|
|
3779
4152
|
}
|
|
4153
|
+
if (request.sourceRouting) {
|
|
4154
|
+
args.source_routing = compact({
|
|
4155
|
+
mode: request.sourceRouting.mode,
|
|
4156
|
+
fill_policy: request.sourceRouting.fillPolicy,
|
|
4157
|
+
shard_size: request.sourceRouting.shardSize,
|
|
4158
|
+
max_source_shard_size: request.sourceRouting.maxSourceShardSize,
|
|
4159
|
+
max_local_source_shard_size: request.sourceRouting.maxLocalSourceShardSize
|
|
4160
|
+
});
|
|
4161
|
+
}
|
|
3780
4162
|
if (request.signals) {
|
|
3781
4163
|
args.signals = compact({
|
|
3782
4164
|
enabled: request.signals.enabled,
|
|
@@ -3844,11 +4226,13 @@ function buildExecutionPrepareArgs(request, dryRun, confirmSpend) {
|
|
|
3844
4226
|
delivery_risk: buildArgs2.delivery_risk,
|
|
3845
4227
|
dedup_keys: buildArgs2.dedup_keys,
|
|
3846
4228
|
policy: buildArgs2.policy,
|
|
4229
|
+
learning_holdout: buildArgs2.learning_holdout,
|
|
3847
4230
|
signals: buildArgs2.signals,
|
|
3848
4231
|
qualification: buildArgs2.qualification,
|
|
3849
4232
|
copy: buildArgs2.copy,
|
|
3850
4233
|
delivery: buildArgs2.delivery,
|
|
3851
|
-
enhancers: buildArgs2.enhancers
|
|
4234
|
+
enhancers: buildArgs2.enhancers,
|
|
4235
|
+
source_routing: buildArgs2.source_routing
|
|
3852
4236
|
});
|
|
3853
4237
|
}
|
|
3854
4238
|
function buildDeliveryApprovalArgs(request) {
|
|
@@ -3877,10 +4261,145 @@ function mapBuildResult(data, dryRun) {
|
|
|
3877
4261
|
targetLimitReason: data.target_limit_reason,
|
|
3878
4262
|
maxSupportedTargetCount: data.max_supported_target_count,
|
|
3879
4263
|
brainContext: data.brain_context ?? {},
|
|
4264
|
+
learningHoldout: data.learning_holdout ?? {},
|
|
3880
4265
|
providerRoute: mapProviderRoute2(data)
|
|
3881
4266
|
};
|
|
3882
4267
|
}
|
|
4268
|
+
var CAMPAIGN_BUILDER_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "canceled", "cancelled"]);
|
|
4269
|
+
var CAMPAIGN_BUILDER_BLOCKED_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["failed", "canceled", "cancelled"]);
|
|
4270
|
+
function mapAgentCampaignPhaseHealth(value) {
|
|
4271
|
+
if (!Array.isArray(value)) return [];
|
|
4272
|
+
return value.map((phase) => {
|
|
4273
|
+
const record = asRecord(phase);
|
|
4274
|
+
return {
|
|
4275
|
+
phase: stringValue(record.phase) ?? "unknown",
|
|
4276
|
+
status: stringValue(record.status) ?? "unknown",
|
|
4277
|
+
recordsProcessed: numberOrNull2(record.records_processed ?? record.recordsProcessed),
|
|
4278
|
+
recordsSucceeded: numberOrNull2(record.records_succeeded ?? record.recordsSucceeded),
|
|
4279
|
+
recordsFailed: numberOrNull2(record.records_failed ?? record.recordsFailed),
|
|
4280
|
+
heartbeatAgeSeconds: numberOrNull2(record.heartbeat_age_seconds ?? record.heartbeatAgeSeconds ?? record.phase_age_seconds)
|
|
4281
|
+
};
|
|
4282
|
+
});
|
|
4283
|
+
}
|
|
4284
|
+
function deriveCampaignBuildTerminalState(input) {
|
|
4285
|
+
const status = input.status.toLowerCase();
|
|
4286
|
+
const heartbeatAgeSeconds = input.phaseAgeSeconds;
|
|
4287
|
+
const stale = input.staleRunningPhase === true;
|
|
4288
|
+
const safeWatchAction = input.triggerRunId ? `signaliz ops run-status ${input.triggerRunId} --watch` : "signaliz campaign-agent status <campaign_build_id>";
|
|
4289
|
+
if (CAMPAIGN_BUILDER_BLOCKED_TERMINAL_STATUSES.has(status)) {
|
|
4290
|
+
return {
|
|
4291
|
+
kind: "blocked",
|
|
4292
|
+
label: "Blocked terminal state",
|
|
4293
|
+
reviewable: true,
|
|
4294
|
+
terminal: true,
|
|
4295
|
+
stale: false,
|
|
4296
|
+
phase: input.phase,
|
|
4297
|
+
phaseStatus: input.phaseStatus,
|
|
4298
|
+
heartbeatAgeSeconds,
|
|
4299
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4300
|
+
terminalReason: input.terminalReason,
|
|
4301
|
+
staleReason: null,
|
|
4302
|
+
safeNextAction: input.nextAction || "Review errors and rerun only after the blocker is resolved."
|
|
4303
|
+
};
|
|
4304
|
+
}
|
|
4305
|
+
if (status === "pending_approval") {
|
|
4306
|
+
return {
|
|
4307
|
+
kind: "pending_approval",
|
|
4308
|
+
label: "Pending delivery approval",
|
|
4309
|
+
reviewable: true,
|
|
4310
|
+
terminal: false,
|
|
4311
|
+
stale: false,
|
|
4312
|
+
phase: input.phase,
|
|
4313
|
+
phaseStatus: input.phaseStatus,
|
|
4314
|
+
heartbeatAgeSeconds,
|
|
4315
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4316
|
+
terminalReason: input.terminalReason,
|
|
4317
|
+
staleReason: null,
|
|
4318
|
+
safeNextAction: input.approvalAction || input.nextAction || "Review rows and approve delivery only after the approval packet passes."
|
|
4319
|
+
};
|
|
4320
|
+
}
|
|
4321
|
+
if (CAMPAIGN_BUILDER_TERMINAL_STATUSES.has(status)) {
|
|
4322
|
+
return {
|
|
4323
|
+
kind: "terminal",
|
|
4324
|
+
label: "Terminal and reviewable",
|
|
4325
|
+
reviewable: true,
|
|
4326
|
+
terminal: true,
|
|
4327
|
+
stale: false,
|
|
4328
|
+
phase: input.phase,
|
|
4329
|
+
phaseStatus: input.phaseStatus,
|
|
4330
|
+
heartbeatAgeSeconds,
|
|
4331
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4332
|
+
terminalReason: input.terminalReason,
|
|
4333
|
+
staleReason: null,
|
|
4334
|
+
safeNextAction: input.nextAction || "Review rows, artifacts, scorecard, and approval locks before delivery."
|
|
4335
|
+
};
|
|
4336
|
+
}
|
|
4337
|
+
if (status === "running" || status === "queued" || status === "processing") {
|
|
4338
|
+
if (stale) {
|
|
4339
|
+
return {
|
|
4340
|
+
kind: "running_stale",
|
|
4341
|
+
label: "Running but stale",
|
|
4342
|
+
reviewable: false,
|
|
4343
|
+
terminal: false,
|
|
4344
|
+
stale: true,
|
|
4345
|
+
phase: input.phase,
|
|
4346
|
+
phaseStatus: input.phaseStatus,
|
|
4347
|
+
heartbeatAgeSeconds,
|
|
4348
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4349
|
+
terminalReason: null,
|
|
4350
|
+
staleReason: input.staleReason || "The active phase heartbeat is stale.",
|
|
4351
|
+
safeNextAction: input.nextAction || safeWatchAction
|
|
4352
|
+
};
|
|
4353
|
+
}
|
|
4354
|
+
return {
|
|
4355
|
+
kind: "running_healthy",
|
|
4356
|
+
label: "Running and healthy",
|
|
4357
|
+
reviewable: false,
|
|
4358
|
+
terminal: false,
|
|
4359
|
+
stale: false,
|
|
4360
|
+
phase: input.phase,
|
|
4361
|
+
phaseStatus: input.phaseStatus,
|
|
4362
|
+
heartbeatAgeSeconds,
|
|
4363
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4364
|
+
terminalReason: null,
|
|
4365
|
+
staleReason: null,
|
|
4366
|
+
safeNextAction: input.nextAction || safeWatchAction
|
|
4367
|
+
};
|
|
4368
|
+
}
|
|
4369
|
+
return {
|
|
4370
|
+
kind: "unknown",
|
|
4371
|
+
label: "Unknown build state",
|
|
4372
|
+
reviewable: false,
|
|
4373
|
+
terminal: false,
|
|
4374
|
+
stale,
|
|
4375
|
+
phase: input.phase,
|
|
4376
|
+
phaseStatus: input.phaseStatus,
|
|
4377
|
+
heartbeatAgeSeconds,
|
|
4378
|
+
nextPollAfterSeconds: input.nextPollAfterSeconds,
|
|
4379
|
+
terminalReason: input.terminalReason,
|
|
4380
|
+
staleReason: input.staleReason,
|
|
4381
|
+
safeNextAction: input.nextAction || "Read campaign build status again before making a launch or delivery decision."
|
|
4382
|
+
};
|
|
4383
|
+
}
|
|
3883
4384
|
function mapAgentCampaignBuildStatus(data) {
|
|
4385
|
+
const customerRowCounts = mapAgentCustomerRowCounts(data.customer_row_counts);
|
|
4386
|
+
const phaseHealth = mapAgentCampaignPhaseHealth(data.phases);
|
|
4387
|
+
const terminalReason = stringValue(data.terminal_reason) ?? customerRowCounts?.terminalReason ?? null;
|
|
4388
|
+
const staleReason = stringValue(data.stale_reason) ?? stringValue(asRecord(data.diagnostics).stale_reason) ?? null;
|
|
4389
|
+
const nextPollAfterSeconds = numberOrNull2(data.next_poll_after_seconds ?? data.nextPollAfterSeconds);
|
|
4390
|
+
const terminalState = deriveCampaignBuildTerminalState({
|
|
4391
|
+
status: stringValue(data.status) ?? "unknown",
|
|
4392
|
+
phase: stringValue(data.current_phase) ?? null,
|
|
4393
|
+
phaseStatus: stringValue(data.current_phase_status) ?? null,
|
|
4394
|
+
staleRunningPhase: data.stale_running_phase === true,
|
|
4395
|
+
phaseAgeSeconds: numberOrNull2(data.phase_age_seconds),
|
|
4396
|
+
nextPollAfterSeconds,
|
|
4397
|
+
terminalReason,
|
|
4398
|
+
staleReason,
|
|
4399
|
+
nextAction: formatAgentNextAction(data.next_action),
|
|
4400
|
+
approvalAction: formatAgentNextAction(data.approval_action),
|
|
4401
|
+
triggerRunId: stringValue(data.trigger_run_id) ?? null
|
|
4402
|
+
});
|
|
3884
4403
|
return {
|
|
3885
4404
|
campaignBuildId: stringValue(data.campaign_build_id) ?? "",
|
|
3886
4405
|
campaignId: stringValue(data.campaign_id) ?? null,
|
|
@@ -3897,17 +4416,68 @@ function mapAgentCampaignBuildStatus(data) {
|
|
|
3897
4416
|
warnings: diagnosticMessages2(data.warnings),
|
|
3898
4417
|
errors: diagnosticMessages2(data.errors),
|
|
3899
4418
|
artifactCount: numberOrUndefined2(data.artifact_count) ?? 0,
|
|
4419
|
+
artifactDownloads: Array.isArray(data.artifact_downloads) ? data.artifact_downloads.map(mapAgentCampaignArtifactDownload) : [],
|
|
4420
|
+
customerRowCounts,
|
|
4421
|
+
phaseAttemptTotals: nullableRecord(data.phase_attempt_totals) ?? void 0,
|
|
3900
4422
|
providerRoute: mapProviderRoute2(data),
|
|
3901
4423
|
triggerRunId: stringValue(data.trigger_run_id) ?? null,
|
|
3902
4424
|
staleRunningPhase: data.stale_running_phase === true,
|
|
3903
4425
|
phaseAgeSeconds: numberOrNull2(data.phase_age_seconds),
|
|
4426
|
+
nextPollAfterSeconds,
|
|
4427
|
+
terminalReason,
|
|
4428
|
+
staleReason,
|
|
4429
|
+
safeNextAction: terminalState.safeNextAction,
|
|
4430
|
+
terminalState,
|
|
4431
|
+
phaseHealth,
|
|
3904
4432
|
diagnostics: nullableRecord(data.diagnostics) ?? {},
|
|
3905
4433
|
nextAction: formatAgentNextAction(data.next_action),
|
|
4434
|
+
approvalAction: formatAgentNextAction(data.approval_action),
|
|
3906
4435
|
createdAt: stringValue(data.created_at) ?? "",
|
|
3907
4436
|
updatedAt: stringValue(data.updated_at) ?? "",
|
|
3908
4437
|
completedAt: stringValue(data.completed_at) ?? null
|
|
3909
4438
|
};
|
|
3910
4439
|
}
|
|
4440
|
+
function mapAgentCampaignArtifactDownload(data) {
|
|
4441
|
+
return {
|
|
4442
|
+
id: stringValue(data.id) ?? "",
|
|
4443
|
+
artifactType: stringValue(data.artifact_type) ?? null,
|
|
4444
|
+
format: stringValue(data.format) ?? null,
|
|
4445
|
+
rowCount: numberOrUndefined2(data.row_count) ?? 0,
|
|
4446
|
+
signedUrl: stringValue(data.signed_url) ?? null,
|
|
4447
|
+
downloadUrl: stringValue(data.download_url) ?? null,
|
|
4448
|
+
manifestUrl: stringValue(data.manifest_url) ?? null,
|
|
4449
|
+
expiresAt: stringValue(data.expires_at) ?? null
|
|
4450
|
+
};
|
|
4451
|
+
}
|
|
4452
|
+
function mapAgentCustomerRowCounts(value) {
|
|
4453
|
+
const record = nullableRecord(value);
|
|
4454
|
+
if (!record) return void 0;
|
|
4455
|
+
return {
|
|
4456
|
+
requestedTarget: numberOrNull2(record.requested_target),
|
|
4457
|
+
acquiredRows: numberOrUndefined2(record.acquired_rows),
|
|
4458
|
+
acceptedRows: numberOrUndefined2(record.accepted_rows),
|
|
4459
|
+
usableRows: numberOrUndefined2(record.usable_rows),
|
|
4460
|
+
copiedRows: numberOrUndefined2(record.copied_rows),
|
|
4461
|
+
approvalReadyRows: numberOrUndefined2(record.approval_ready_rows),
|
|
4462
|
+
qaReadyRows: numberOrUndefined2(record.qa_ready_rows),
|
|
4463
|
+
deliveredRows: numberOrUndefined2(record.delivered_rows),
|
|
4464
|
+
disqualifiedRows: numberOrUndefined2(record.disqualified_rows),
|
|
4465
|
+
reviewableRows: numberOrUndefined2(record.reviewable_rows),
|
|
4466
|
+
rowFailures: numberOrUndefined2(record.row_failures),
|
|
4467
|
+
acceptedShortfall: numberOrNull2(record.accepted_shortfall),
|
|
4468
|
+
usableShortfall: numberOrNull2(record.usable_shortfall),
|
|
4469
|
+
qaReadyShortfall: numberOrNull2(record.qa_ready_shortfall),
|
|
4470
|
+
deliveryShortfall: numberOrNull2(record.delivery_shortfall),
|
|
4471
|
+
fillRatio: numberOrNull2(record.fill_ratio),
|
|
4472
|
+
qaReadyFillRatio: numberOrNull2(record.qa_ready_fill_ratio),
|
|
4473
|
+
deliveredFillRatio: numberOrNull2(record.delivered_fill_ratio),
|
|
4474
|
+
terminalReason: stringValue(record.terminal_reason) ?? null,
|
|
4475
|
+
acceptedShortfallReason: stringValue(record.accepted_shortfall_reason) ?? null,
|
|
4476
|
+
usableShortfallReason: stringValue(record.usable_shortfall_reason) ?? null,
|
|
4477
|
+
qaReadyShortfallReason: stringValue(record.qa_ready_shortfall_reason) ?? null,
|
|
4478
|
+
deliveryShortfallReason: stringValue(record.delivery_shortfall_reason) ?? null
|
|
4479
|
+
};
|
|
4480
|
+
}
|
|
3911
4481
|
function mapAgentCampaignRowsResult(data) {
|
|
3912
4482
|
const rows = Array.isArray(data.rows) ? data.rows : [];
|
|
3913
4483
|
return {
|
|
@@ -3935,74 +4505,296 @@ function mapAgentCampaignArtifact(data) {
|
|
|
3935
4505
|
artifactType: stringValue(data.artifact_type) ?? "",
|
|
3936
4506
|
destination: stringValue(data.destination) ?? "",
|
|
3937
4507
|
storagePath: stringValue(data.storage_path) ?? "",
|
|
4508
|
+
format: stringValue(data.format) ?? null,
|
|
3938
4509
|
signedUrl: stringValue(data.signed_url) ?? null,
|
|
4510
|
+
downloadUrl: stringValue(data.download_url) ?? null,
|
|
4511
|
+
manifestUrl: stringValue(data.manifest_url) ?? null,
|
|
4512
|
+
expiresAt: stringValue(data.expires_at) ?? null,
|
|
3939
4513
|
rowCount: numberOrUndefined2(data.row_count) ?? 0,
|
|
3940
4514
|
checksum: stringValue(data.checksum) ?? null,
|
|
3941
4515
|
metadata: nullableRecord(data.metadata) ?? {},
|
|
3942
4516
|
createdAt: stringValue(data.created_at) ?? ""
|
|
3943
4517
|
};
|
|
3944
4518
|
}
|
|
4519
|
+
var NORTH_STAR_BANNED_COPY_PHRASES = [
|
|
4520
|
+
"i have been following",
|
|
4521
|
+
"i saw that",
|
|
4522
|
+
"would you be opposed",
|
|
4523
|
+
"unlock new opportunities",
|
|
4524
|
+
"significant success",
|
|
4525
|
+
"we understand",
|
|
4526
|
+
"hope this finds you well"
|
|
4527
|
+
];
|
|
4528
|
+
function campaignReviewGate(id, label, status, detail) {
|
|
4529
|
+
return {
|
|
4530
|
+
id,
|
|
4531
|
+
label,
|
|
4532
|
+
status,
|
|
4533
|
+
passed: status !== "blocked",
|
|
4534
|
+
detail
|
|
4535
|
+
};
|
|
4536
|
+
}
|
|
4537
|
+
function northStarMetric(id, label, status, detail, value, target) {
|
|
4538
|
+
return {
|
|
4539
|
+
id,
|
|
4540
|
+
label,
|
|
4541
|
+
status,
|
|
4542
|
+
detail,
|
|
4543
|
+
...value !== void 0 ? { value } : {},
|
|
4544
|
+
...target !== void 0 ? { target } : {}
|
|
4545
|
+
};
|
|
4546
|
+
}
|
|
4547
|
+
function createCampaignBuilderNorthStarScorecard(status, rows, artifacts, terminalState) {
|
|
4548
|
+
if (!terminalState.reviewable) {
|
|
4549
|
+
const pendingMetric = northStarMetric(
|
|
4550
|
+
"terminal_state",
|
|
4551
|
+
"Terminal-state contract",
|
|
4552
|
+
terminalState.kind === "running_stale" ? "blocked" : "pending",
|
|
4553
|
+
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.`,
|
|
4554
|
+
terminalState.kind,
|
|
4555
|
+
"terminal or pending_approval"
|
|
4556
|
+
);
|
|
4557
|
+
return {
|
|
4558
|
+
version: "campaign-builder-north-star.v1",
|
|
4559
|
+
status: pendingMetric.status,
|
|
4560
|
+
score: null,
|
|
4561
|
+
moatState: "scaffolding_ready",
|
|
4562
|
+
metrics: [pendingMetric],
|
|
4563
|
+
blockers: pendingMetric.status === "blocked" ? [pendingMetric.detail] : [],
|
|
4564
|
+
warnings: pendingMetric.status === "pending" ? [pendingMetric.detail] : [],
|
|
4565
|
+
nextAction: terminalState.safeNextAction
|
|
4566
|
+
};
|
|
4567
|
+
}
|
|
4568
|
+
const sampledRows = rows.rows.length;
|
|
4569
|
+
const rowData = rows.rows.map((row) => asRecord(row.data));
|
|
4570
|
+
const requestedTarget = status.customerRowCounts?.requestedTarget ?? status.recordsTotal ?? rows.count;
|
|
4571
|
+
const finalRows = status.customerRowCounts?.deliveredRows ?? status.customerRowCounts?.qaReadyRows ?? status.customerRowCounts?.copiedRows ?? status.customerRowCounts?.acceptedRows ?? rows.count;
|
|
4572
|
+
const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
|
|
4573
|
+
const verifiedEmailRows = rowData.filter(campaignReviewDataHasVerifiedEmail).length;
|
|
4574
|
+
const uniqueEmails = new Set(rowData.map(campaignReviewDataEmail).filter(Boolean)).size;
|
|
4575
|
+
const uniqueDomains = new Set(rowData.map(campaignReviewDataDomain).filter(Boolean)).size;
|
|
4576
|
+
const copyReadyRows = rows.rows.filter(campaignReviewRowHasCopy).length;
|
|
4577
|
+
const copyQaIssuesByRow = rowData.map(campaignReviewDataCopyQaIssues).filter((issues) => issues.length > 0);
|
|
4578
|
+
const copyQaIssueCounts = countCampaignReviewIssues(copyQaIssuesByRow);
|
|
4579
|
+
const signalBackedRows = rowData.filter(campaignReviewDataHasSignalBasis).length;
|
|
4580
|
+
const noSupportedSignalRows = rowData.filter(campaignReviewDataHasNoSupportedSignal).length;
|
|
4581
|
+
const unsupportedSignalClaims = rowData.filter(campaignReviewDataHasUnsupportedSignalClaim).length;
|
|
4582
|
+
const approvalLockedRows = rowData.filter(campaignReviewDataHasApprovalLock).length;
|
|
4583
|
+
const holdoutRows = rowData.filter(campaignReviewDataHasHoldoutAttribution).length;
|
|
4584
|
+
const artifactCount = artifacts.length || status.artifactCount || 0;
|
|
4585
|
+
const deliveredRows = status.customerRowCounts?.deliveredRows ?? 0;
|
|
4586
|
+
const feedbackReady = campaignReviewStatusHasFeedbackReadiness(status);
|
|
4587
|
+
const feedbackRequiredForApproval = terminalState.kind === "pending_approval";
|
|
4588
|
+
const moat = campaignReviewMoatState(status, holdoutRows);
|
|
4589
|
+
const metrics = [
|
|
4590
|
+
northStarMetric(
|
|
4591
|
+
"terminal_state",
|
|
4592
|
+
"Terminal-state contract",
|
|
4593
|
+
terminalState.kind === "blocked" ? "blocked" : "pass",
|
|
4594
|
+
terminalState.label,
|
|
4595
|
+
terminalState.kind,
|
|
4596
|
+
"terminal or pending_approval"
|
|
4597
|
+
),
|
|
4598
|
+
northStarMetric(
|
|
4599
|
+
"target_fill",
|
|
4600
|
+
"Target fill",
|
|
4601
|
+
requestedTarget && finalRows < requestedTarget ? "review" : "pass",
|
|
4602
|
+
requestedTarget ? `${finalRows || 0}/${requestedTarget} final or reviewable row(s) are accounted for.` : "No requested target was reported; using sampled rows for review.",
|
|
4603
|
+
finalRows || sampledRows,
|
|
4604
|
+
requestedTarget || sampledRows
|
|
4605
|
+
),
|
|
4606
|
+
northStarMetric(
|
|
4607
|
+
"unique_emails",
|
|
4608
|
+
"Unique emails",
|
|
4609
|
+
sampledRows === 0 ? "blocked" : uniqueEmails === rowsWithEmail ? "pass" : "blocked",
|
|
4610
|
+
sampledRows === 0 ? "No sampled rows were available for email uniqueness review." : `${uniqueEmails}/${rowsWithEmail} sampled email(s) are unique.`,
|
|
4611
|
+
uniqueEmails,
|
|
4612
|
+
rowsWithEmail
|
|
4613
|
+
),
|
|
4614
|
+
northStarMetric(
|
|
4615
|
+
"unique_domains",
|
|
4616
|
+
"Unique domains",
|
|
4617
|
+
sampledRows === 0 ? "blocked" : uniqueDomains === sampledRows ? "pass" : "review",
|
|
4618
|
+
sampledRows === 0 ? "No sampled rows were available for domain uniqueness review." : `${uniqueDomains}/${sampledRows} sampled company domain(s) are unique.`,
|
|
4619
|
+
uniqueDomains,
|
|
4620
|
+
sampledRows
|
|
4621
|
+
),
|
|
4622
|
+
northStarMetric(
|
|
4623
|
+
"verified_email_rows",
|
|
4624
|
+
"Verified email rows",
|
|
4625
|
+
sampledRows === 0 ? "blocked" : verifiedEmailRows === sampledRows ? "pass" : rowsWithEmail === sampledRows ? "review" : "blocked",
|
|
4626
|
+
sampledRows === 0 ? "No sampled rows were available for email verification review." : `${verifiedEmailRows}/${sampledRows} sampled row(s) carry verified-email evidence.`,
|
|
4627
|
+
verifiedEmailRows,
|
|
4628
|
+
sampledRows
|
|
4629
|
+
),
|
|
4630
|
+
northStarMetric(
|
|
4631
|
+
"copy_completeness",
|
|
4632
|
+
"Copy completeness",
|
|
4633
|
+
sampledRows === 0 ? "blocked" : copyReadyRows === sampledRows ? "pass" : "blocked",
|
|
4634
|
+
sampledRows === 0 ? "No sampled rows were available for copy review." : `${copyReadyRows}/${sampledRows} sampled row(s) include generated copy.`,
|
|
4635
|
+
copyReadyRows,
|
|
4636
|
+
sampledRows
|
|
4637
|
+
),
|
|
4638
|
+
northStarMetric(
|
|
4639
|
+
"copy_quality",
|
|
4640
|
+
"Copy QA",
|
|
4641
|
+
copyQaIssuesByRow.length === 0 ? "pass" : "blocked",
|
|
4642
|
+
copyQaIssuesByRow.length === 0 ? "No sampled copy QA blockers were detected." : `${copyQaIssuesByRow.length}/${sampledRows} sampled row(s) have copy QA issue(s): ${formatCampaignReviewIssueCounts(copyQaIssueCounts)}.`,
|
|
4643
|
+
copyQaIssuesByRow.length,
|
|
4644
|
+
0
|
|
4645
|
+
),
|
|
4646
|
+
northStarMetric(
|
|
4647
|
+
"signal_grounding",
|
|
4648
|
+
"Signal grounding",
|
|
4649
|
+
unsupportedSignalClaims > 0 ? "blocked" : signalBackedRows > 0 ? "pass" : "review",
|
|
4650
|
+
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.",
|
|
4651
|
+
signalBackedRows,
|
|
4652
|
+
sampledRows
|
|
4653
|
+
),
|
|
4654
|
+
northStarMetric(
|
|
4655
|
+
"approval_locks",
|
|
4656
|
+
"Approval locks",
|
|
4657
|
+
approvalLockedRows > 0 || deliveredRows === 0 ? "pass" : "review",
|
|
4658
|
+
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.",
|
|
4659
|
+
approvalLockedRows,
|
|
4660
|
+
sampledRows
|
|
4661
|
+
),
|
|
4662
|
+
northStarMetric(
|
|
4663
|
+
"export_send_safety",
|
|
4664
|
+
"Export/send safety",
|
|
4665
|
+
deliveredRows > 0 && status.status !== "completed" ? "blocked" : "pass",
|
|
4666
|
+
deliveredRows > 0 ? `${deliveredRows} row(s) are delivered; status is ${status.status}.` : "No delivered rows are reported before approval.",
|
|
4667
|
+
deliveredRows,
|
|
4668
|
+
0
|
|
4669
|
+
),
|
|
4670
|
+
northStarMetric(
|
|
4671
|
+
"holdout_attribution",
|
|
4672
|
+
"Holdout attribution",
|
|
4673
|
+
holdoutRows > 0 ? "pass" : "review",
|
|
4674
|
+
holdoutRows > 0 ? `${holdoutRows}/${sampledRows} sampled row(s) preserve holdout attribution.` : "No holdout attribution was visible in the sampled rows.",
|
|
4675
|
+
holdoutRows,
|
|
4676
|
+
sampledRows
|
|
4677
|
+
),
|
|
4678
|
+
northStarMetric(
|
|
4679
|
+
"feedback_readiness",
|
|
4680
|
+
"Feedback readiness",
|
|
4681
|
+
feedbackReady ? "pass" : feedbackRequiredForApproval ? "blocked" : "review",
|
|
4682
|
+
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.",
|
|
4683
|
+
feedbackReady,
|
|
4684
|
+
true
|
|
4685
|
+
),
|
|
4686
|
+
northStarMetric(
|
|
4687
|
+
"causal_moat",
|
|
4688
|
+
"Causal moat",
|
|
4689
|
+
moat.state === "proved" ? "pass" : "review",
|
|
4690
|
+
moat.detail,
|
|
4691
|
+
moat.state,
|
|
4692
|
+
"proved"
|
|
4693
|
+
),
|
|
4694
|
+
northStarMetric(
|
|
4695
|
+
"artifact_readback",
|
|
4696
|
+
"Artifact readback",
|
|
4697
|
+
artifactCount > 0 ? "pass" : "review",
|
|
4698
|
+
artifactCount > 0 ? `${artifactCount} artifact(s) are available for review.` : "No review artifact is available yet.",
|
|
4699
|
+
artifactCount,
|
|
4700
|
+
1
|
|
4701
|
+
)
|
|
4702
|
+
];
|
|
4703
|
+
const gradedMetrics = metrics.filter((metric) => metric.status !== "pending");
|
|
4704
|
+
const score = gradedMetrics.length === 0 ? null : Math.round(gradedMetrics.filter((metric) => metric.status === "pass").length / gradedMetrics.length * 100);
|
|
4705
|
+
const blockers = metrics.filter((metric) => metric.status === "blocked").map((metric) => metric.detail);
|
|
4706
|
+
const warnings = metrics.filter((metric) => metric.status === "review").map((metric) => metric.detail);
|
|
4707
|
+
const scorecardStatus = blockers.length > 0 ? "blocked" : warnings.length > 0 ? "review" : "pass";
|
|
4708
|
+
return {
|
|
4709
|
+
version: "campaign-builder-north-star.v1",
|
|
4710
|
+
status: scorecardStatus,
|
|
4711
|
+
score,
|
|
4712
|
+
moatState: moat.state,
|
|
4713
|
+
metrics,
|
|
4714
|
+
blockers,
|
|
4715
|
+
warnings,
|
|
4716
|
+
nextAction: scorecardStatus === "blocked" ? "Fix blocked North Star gates before approval or delivery." : terminalState.safeNextAction
|
|
4717
|
+
};
|
|
4718
|
+
}
|
|
3945
4719
|
function createCampaignBuilderBuildReview(status, rows, artifacts) {
|
|
4720
|
+
const terminalState = status.terminalState ?? deriveCampaignBuildTerminalState({
|
|
4721
|
+
status: status.status,
|
|
4722
|
+
phase: status.currentPhase,
|
|
4723
|
+
phaseStatus: status.currentPhaseStatus,
|
|
4724
|
+
staleRunningPhase: status.staleRunningPhase === true,
|
|
4725
|
+
phaseAgeSeconds: status.phaseAgeSeconds ?? null,
|
|
4726
|
+
nextPollAfterSeconds: status.nextPollAfterSeconds ?? null,
|
|
4727
|
+
terminalReason: status.terminalReason ?? status.customerRowCounts?.terminalReason ?? null,
|
|
4728
|
+
staleReason: status.staleReason ?? null,
|
|
4729
|
+
nextAction: status.nextAction,
|
|
4730
|
+
approvalAction: status.approvalAction,
|
|
4731
|
+
triggerRunId: status.triggerRunId ?? null
|
|
4732
|
+
});
|
|
3946
4733
|
const sampledRows = rows.rows.length;
|
|
3947
4734
|
const availableRows = rows.count || sampledRows;
|
|
3948
4735
|
const qualifiedRows = rows.rows.filter((row) => row.qualified !== false).length;
|
|
3949
4736
|
const rowsWithEmail = rows.rows.filter(campaignReviewRowHasEmail).length;
|
|
3950
4737
|
const copyReadyRows = rows.rows.filter(campaignReviewRowHasCopy).length;
|
|
3951
4738
|
const artifactCount = artifacts.length || status.artifactCount || 0;
|
|
4739
|
+
const northStarScorecard = createCampaignBuilderNorthStarScorecard(status, rows, artifacts, terminalState);
|
|
3952
4740
|
const gates = [
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
4741
|
+
campaignReviewGate(
|
|
4742
|
+
"build_reviewable",
|
|
4743
|
+
"Build reviewable",
|
|
4744
|
+
terminalState.kind === "running_healthy" ? "pending" : terminalState.kind === "running_stale" || terminalState.kind === "blocked" ? "blocked" : "pass",
|
|
4745
|
+
terminalState.label
|
|
4746
|
+
),
|
|
4747
|
+
campaignReviewGate(
|
|
4748
|
+
"rows_available",
|
|
4749
|
+
"Rows available",
|
|
4750
|
+
sampledRows > 0 ? "pass" : terminalState.reviewable ? "blocked" : "pending",
|
|
4751
|
+
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."
|
|
4752
|
+
),
|
|
4753
|
+
campaignReviewGate(
|
|
4754
|
+
"qualified_sample",
|
|
4755
|
+
"Sample rows qualified",
|
|
4756
|
+
sampledRows === 0 ? terminalState.reviewable ? "blocked" : "pending" : qualifiedRows === sampledRows ? "pass" : "blocked",
|
|
4757
|
+
sampledRows > 0 ? `${qualifiedRows}/${sampledRows} sampled row(s) are marked qualified.` : "Qualification could not be checked without sampled rows."
|
|
4758
|
+
),
|
|
4759
|
+
campaignReviewGate(
|
|
4760
|
+
"email_coverage",
|
|
4761
|
+
"Email coverage",
|
|
4762
|
+
sampledRows === 0 ? terminalState.reviewable ? "blocked" : "pending" : rowsWithEmail === sampledRows ? "pass" : "blocked",
|
|
4763
|
+
sampledRows > 0 ? `${rowsWithEmail}/${sampledRows} sampled row(s) include an email.` : "Email coverage could not be checked without sampled rows."
|
|
4764
|
+
),
|
|
4765
|
+
campaignReviewGate(
|
|
4766
|
+
"artifact_available",
|
|
4767
|
+
"Artifact available",
|
|
4768
|
+
artifactCount > 0 ? "pass" : terminalState.reviewable ? "review" : "pending",
|
|
4769
|
+
artifactCount > 0 ? `${artifactCount} artifact(s) are available.` : "No delivery artifact is available yet."
|
|
4770
|
+
),
|
|
4771
|
+
campaignReviewGate(
|
|
4772
|
+
"no_failed_rows",
|
|
4773
|
+
"No failed rows",
|
|
4774
|
+
status.recordsFailed === 0 ? "pass" : "blocked",
|
|
4775
|
+
status.recordsFailed === 0 ? "The build reports zero failed rows." : `${status.recordsFailed} row(s) failed during the build.`
|
|
4776
|
+
)
|
|
3989
4777
|
];
|
|
3990
|
-
const blockedReasons = gates.filter((gate) => !gate.passed).map((gate) => gate.detail);
|
|
4778
|
+
const blockedReasons = gates.filter((gate) => gate.status === "blocked" || !gate.passed).map((gate) => gate.detail);
|
|
3991
4779
|
const warnings = [
|
|
3992
4780
|
rows.hasMore ? "This review is based on a row sample; page through remaining rows before final approval." : void 0,
|
|
3993
4781
|
sampledRows > 0 && copyReadyRows < sampledRows ? `${copyReadyRows}/${sampledRows} sampled row(s) include generated copy.` : void 0,
|
|
3994
4782
|
...status.warnings
|
|
3995
4783
|
].filter((item) => Boolean(item));
|
|
3996
|
-
const readyForDeliveryApproval = blockedReasons.length === 0;
|
|
4784
|
+
const readyForDeliveryApproval = terminalState.reviewable && blockedReasons.length === 0 && northStarScorecard.status !== "blocked";
|
|
3997
4785
|
return {
|
|
3998
4786
|
campaignBuildId: status.campaignBuildId || rows.campaignBuildId,
|
|
3999
4787
|
status,
|
|
4000
4788
|
rows,
|
|
4001
4789
|
artifacts,
|
|
4002
4790
|
gates,
|
|
4791
|
+
northStarScorecard,
|
|
4003
4792
|
summary: {
|
|
4004
4793
|
status: status.status,
|
|
4005
4794
|
phase: status.currentPhase,
|
|
4795
|
+
terminalState: terminalState.kind,
|
|
4796
|
+
scorecardStatus: northStarScorecard.status,
|
|
4797
|
+
scorecardScore: northStarScorecard.score,
|
|
4006
4798
|
sampledRows,
|
|
4007
4799
|
availableRows,
|
|
4008
4800
|
qualifiedRows,
|
|
@@ -4056,6 +4848,184 @@ function campaignReviewRowHasCopy(row) {
|
|
|
4056
4848
|
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)
|
|
4057
4849
|
);
|
|
4058
4850
|
}
|
|
4851
|
+
function campaignReviewDataEmail(data) {
|
|
4852
|
+
return stringValue(data.email) || stringValue(data.work_email) || stringValue(data.workEmail) || stringValue(asRecord(data.contact).email);
|
|
4853
|
+
}
|
|
4854
|
+
function campaignReviewDataDomain(data) {
|
|
4855
|
+
const domain = stringValue(data.company_domain) || stringValue(data.companyDomain) || stringValue(asRecord(data.company).domain);
|
|
4856
|
+
return domain?.toLowerCase();
|
|
4857
|
+
}
|
|
4858
|
+
function campaignReviewDataHasVerifiedEmail(data) {
|
|
4859
|
+
const status = String(data.email_status ?? data.emailStatus ?? asRecord(data.contact).email_status ?? "").toLowerCase();
|
|
4860
|
+
return data.email_verified === true || data.emailVerified === true || asRecord(data.contact).email_verified === true || ["valid", "validated", "verified"].includes(status);
|
|
4861
|
+
}
|
|
4862
|
+
function campaignReviewDataCopyParts(data) {
|
|
4863
|
+
const copy = asRecord(data.copy);
|
|
4864
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4865
|
+
return [
|
|
4866
|
+
stringValue(data.subject),
|
|
4867
|
+
stringValue(data.subject_line),
|
|
4868
|
+
stringValue(data.opener),
|
|
4869
|
+
stringValue(data.body),
|
|
4870
|
+
stringValue(data.cta),
|
|
4871
|
+
stringValue(copy.subject),
|
|
4872
|
+
stringValue(copy.opener),
|
|
4873
|
+
stringValue(copy.body),
|
|
4874
|
+
stringValue(copy.cta),
|
|
4875
|
+
stringValue(rawCopy.subject),
|
|
4876
|
+
stringValue(rawCopy.opener),
|
|
4877
|
+
stringValue(rawCopy.body),
|
|
4878
|
+
stringValue(rawCopy.cta)
|
|
4879
|
+
].filter((part) => Boolean(part));
|
|
4880
|
+
}
|
|
4881
|
+
function campaignReviewDataHasBadGreeting(data) {
|
|
4882
|
+
return campaignReviewDataCopyParts(data).some(
|
|
4883
|
+
(part) => /\bhi\s*(?:,|\{\{|\[)|\bhello\s*(?:,|\{\{|\[)/i.test(part) || /\b(first_name|firstname|name)\b/i.test(part)
|
|
4884
|
+
);
|
|
4885
|
+
}
|
|
4886
|
+
function campaignReviewDataHasBannedPhrase(data) {
|
|
4887
|
+
const text = campaignReviewDataCopyParts(data).join(" ").toLowerCase();
|
|
4888
|
+
return NORTH_STAR_BANNED_COPY_PHRASES.some((phrase) => text.includes(phrase));
|
|
4889
|
+
}
|
|
4890
|
+
function campaignReviewDataSubject(data) {
|
|
4891
|
+
const copy = asRecord(data.copy);
|
|
4892
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4893
|
+
return stringValue(data.subject) || stringValue(data.subject_line) || stringValue(data.subjectLine) || stringValue(copy.subject) || stringValue(rawCopy.subject);
|
|
4894
|
+
}
|
|
4895
|
+
function campaignReviewDataCta(data) {
|
|
4896
|
+
const copy = asRecord(data.copy);
|
|
4897
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4898
|
+
return stringValue(data.cta) || stringValue(copy.cta) || stringValue(rawCopy.cta);
|
|
4899
|
+
}
|
|
4900
|
+
function countCampaignReviewIssues(issueRows) {
|
|
4901
|
+
return issueRows.flat().reduce((acc, issue) => {
|
|
4902
|
+
acc[issue] = (acc[issue] || 0) + 1;
|
|
4903
|
+
return acc;
|
|
4904
|
+
}, {});
|
|
4905
|
+
}
|
|
4906
|
+
function formatCampaignReviewIssueCounts(counts) {
|
|
4907
|
+
const entries = Object.entries(counts);
|
|
4908
|
+
return entries.length > 0 ? entries.map(([issue, count]) => `${issue}=${count}`).join(", ") : "none";
|
|
4909
|
+
}
|
|
4910
|
+
function campaignReviewDataCopyQaIssues(data) {
|
|
4911
|
+
const issues = /* @__PURE__ */ new Set();
|
|
4912
|
+
const copyParts = campaignReviewDataCopyParts(data);
|
|
4913
|
+
if (copyParts.length === 0) return [];
|
|
4914
|
+
if (campaignReviewDataHasBadGreeting(data)) issues.add("bad_greeting");
|
|
4915
|
+
if (campaignReviewDataHasBannedPhrase(data)) issues.add("banned_or_vague_phrase");
|
|
4916
|
+
if (campaignReviewDataHasUnsupportedSignalClaim(data)) issues.add("unsupported_signal_claim");
|
|
4917
|
+
if (campaignReviewDataPersonalizationBasis(data).length === 0) issues.add("missing_personalization_basis");
|
|
4918
|
+
if (!campaignReviewDataCta(data)) issues.add("missing_cta");
|
|
4919
|
+
const subject = campaignReviewDataSubject(data);
|
|
4920
|
+
if (subject && subject.length > 70) issues.add("overlong_subject");
|
|
4921
|
+
return [...issues];
|
|
4922
|
+
}
|
|
4923
|
+
function campaignReviewDataPersonalizationBasis(data) {
|
|
4924
|
+
const rawCopy = asRecord(data.raw_copy ?? data.rawCopy);
|
|
4925
|
+
const copy = asRecord(data.copy);
|
|
4926
|
+
const metadata = asRecord(data.metadata);
|
|
4927
|
+
const signalEvidence = asRecord(data.signal_evidence ?? metadata.signal_evidence ?? metadata.signalEvidence);
|
|
4928
|
+
return [
|
|
4929
|
+
...arrayOfStrings(data.personalization_basis) ?? [],
|
|
4930
|
+
...arrayOfStrings(data.personalizationBasis) ?? [],
|
|
4931
|
+
...arrayOfStrings(copy.personalization_basis) ?? [],
|
|
4932
|
+
...arrayOfStrings(rawCopy.personalization_basis) ?? [],
|
|
4933
|
+
...arrayOfStrings(metadata.personalization_basis) ?? [],
|
|
4934
|
+
...arrayOfStrings(metadata.personalizationBasis) ?? [],
|
|
4935
|
+
...arrayOfStrings(signalEvidence.personalization_basis) ?? []
|
|
4936
|
+
];
|
|
4937
|
+
}
|
|
4938
|
+
function campaignReviewDataHasNoSupportedSignal(data) {
|
|
4939
|
+
const metadata = asRecord(data.metadata);
|
|
4940
|
+
const copy = asRecord(data.copy);
|
|
4941
|
+
const state = [
|
|
4942
|
+
data.copy_signal_state,
|
|
4943
|
+
data.signal_basis,
|
|
4944
|
+
data.signal_type,
|
|
4945
|
+
metadata.copy_signal_state,
|
|
4946
|
+
metadata.signal_basis,
|
|
4947
|
+
metadata.signal_type,
|
|
4948
|
+
copy.copy_signal_state
|
|
4949
|
+
].map((value) => stringValue(value)?.toLowerCase()).filter(Boolean);
|
|
4950
|
+
return data.no_supported_signal === true || metadata.no_supported_signal === true || state.includes("no_supported_signal");
|
|
4951
|
+
}
|
|
4952
|
+
function campaignReviewDataHasSignalBasis(data) {
|
|
4953
|
+
if (campaignReviewDataHasNoSupportedSignal(data)) return false;
|
|
4954
|
+
const metadata = asRecord(data.metadata);
|
|
4955
|
+
const signal = asRecord(data.signal);
|
|
4956
|
+
const signalEvidence = asRecord(data.signal_evidence ?? metadata.signal_evidence ?? metadata.signalEvidence);
|
|
4957
|
+
const basis = campaignReviewDataPersonalizationBasis(data);
|
|
4958
|
+
return Boolean(
|
|
4959
|
+
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))
|
|
4960
|
+
);
|
|
4961
|
+
}
|
|
4962
|
+
function campaignReviewDataHasUnsupportedSignalClaim(data) {
|
|
4963
|
+
const copyText = campaignReviewDataCopyParts(data).join(" ").toLowerCase();
|
|
4964
|
+
const claimsSignal = /\b(hiring|funding|raised|launched|expanding|appointed|announced|recent news|new role|job posting)\b/.test(copyText);
|
|
4965
|
+
return claimsSignal && !campaignReviewDataHasSignalBasis(data);
|
|
4966
|
+
}
|
|
4967
|
+
function campaignReviewDataHasApprovalLock(data) {
|
|
4968
|
+
const metadata = asRecord(data.fit_metadata ?? data.metadata);
|
|
4969
|
+
const approval = String(data.approval_status ?? data.delivery_approval_status ?? metadata.approval_status ?? "").toLowerCase();
|
|
4970
|
+
const exportStatus = String(data.export_status ?? data.exportStatus ?? "").toLowerCase();
|
|
4971
|
+
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);
|
|
4972
|
+
}
|
|
4973
|
+
function campaignReviewDataHasHoldoutAttribution(data) {
|
|
4974
|
+
const fitMetadata = asRecord(data.fit_metadata ?? data.fitMetadata);
|
|
4975
|
+
const metadata = asRecord(data.metadata);
|
|
4976
|
+
const holdout = asRecord(
|
|
4977
|
+
fitMetadata.learning_holdout ?? fitMetadata.learningHoldout ?? metadata.learning_holdout ?? metadata.learningHoldout ?? data.learning_holdout ?? data.learningHoldout
|
|
4978
|
+
);
|
|
4979
|
+
const experimentKey = stringValue(holdout.experiment_key ?? holdout.experimentKey ?? data.experiment_key ?? data.experimentKey);
|
|
4980
|
+
const cohort = stringValue(holdout.cohort_role ?? holdout.cohortRole ?? data.cohort_role ?? data.learning_cohort ?? data.learningCohort);
|
|
4981
|
+
const brainApplied = holdout.brain_applied ?? holdout.brainApplied ?? data.brain_applied ?? data.signaliz_brain_applied;
|
|
4982
|
+
return Boolean(experimentKey && cohort && brainApplied !== void 0);
|
|
4983
|
+
}
|
|
4984
|
+
function campaignReviewStatusHasFeedbackReadiness(status) {
|
|
4985
|
+
const diagnostics = asRecord(status.diagnostics);
|
|
4986
|
+
const feedbackReadiness = asRecord(diagnostics.feedback_readiness ?? diagnostics.feedbackReadiness);
|
|
4987
|
+
const feedbackSubstrate = asRecord(diagnostics.feedback_substrate ?? diagnostics.feedbackSubstrate);
|
|
4988
|
+
const evidenceCounts = asRecord(diagnostics.evidence_counts ?? diagnostics.evidenceCounts);
|
|
4989
|
+
return feedbackReadiness.ready === true || feedbackReadiness.webhook_configured === true || feedbackSubstrate.stage === "ready" || Number(evidenceCounts.feedback_events ?? 0) > 0;
|
|
4990
|
+
}
|
|
4991
|
+
function campaignReviewMoatState(status, holdoutRows) {
|
|
4992
|
+
const diagnostics = asRecord(status.diagnostics);
|
|
4993
|
+
const evidenceCounts = asRecord(diagnostics.evidence_counts ?? diagnostics.evidenceCounts);
|
|
4994
|
+
const embeddedHoldout = asRecord(diagnostics.embedded_holdout ?? diagnostics.embeddedHoldout);
|
|
4995
|
+
const holdoutLift = asRecord(diagnostics.holdout_lift ?? diagnostics.holdoutLift ?? diagnostics.holdout_measurement ?? diagnostics.holdoutMeasurement);
|
|
4996
|
+
const controlSample = Math.max(
|
|
4997
|
+
Number(evidenceCounts.holdout_control_sample_size ?? 0),
|
|
4998
|
+
Number(evidenceCounts.embedded_holdout_control_sample ?? 0),
|
|
4999
|
+
Number(embeddedHoldout.control_sample_size ?? 0)
|
|
5000
|
+
);
|
|
5001
|
+
const learnedSample = Math.max(
|
|
5002
|
+
Number(evidenceCounts.holdout_learned_sample_size ?? 0),
|
|
5003
|
+
Number(evidenceCounts.embedded_holdout_learned_sample ?? 0),
|
|
5004
|
+
Number(embeddedHoldout.learned_sample_size ?? 0)
|
|
5005
|
+
);
|
|
5006
|
+
const feedbackEvents = Math.max(
|
|
5007
|
+
Number(evidenceCounts.feedback_events ?? 0),
|
|
5008
|
+
Number(evidenceCounts.campaign_build_feedback_events ?? 0),
|
|
5009
|
+
Number(evidenceCounts.delivery_holdout_sent_outcomes ?? 0)
|
|
5010
|
+
);
|
|
5011
|
+
const proved = diagnostics.closed_loop_proof_ready === true || holdoutLift.honest_measurement === true && holdoutLift.positive_lift === true;
|
|
5012
|
+
if (proved) {
|
|
5013
|
+
return {
|
|
5014
|
+
state: "proved",
|
|
5015
|
+
detail: "Real attributed feedback shows positive lift for explicit control and learned cohorts."
|
|
5016
|
+
};
|
|
5017
|
+
}
|
|
5018
|
+
if (controlSample > 0 && learnedSample > 0 && feedbackEvents > 0) {
|
|
5019
|
+
return {
|
|
5020
|
+
state: "moved_needs_lift_volume",
|
|
5021
|
+
detail: `Control and learned cohorts have attributed feedback (${controlSample} control, ${learnedSample} learned, ${feedbackEvents} feedback event(s)); keep collecting lift volume before claiming proof.`
|
|
5022
|
+
};
|
|
5023
|
+
}
|
|
5024
|
+
return {
|
|
5025
|
+
state: "scaffolding_ready",
|
|
5026
|
+
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."
|
|
5027
|
+
};
|
|
5028
|
+
}
|
|
4059
5029
|
function createCampaignBuilderReadinessLane(route, plan) {
|
|
4060
5030
|
const builtIn = campaignBuilderBuiltInForRoute(route);
|
|
4061
5031
|
const customRoute = route.provider !== "signaliz" && route.provider !== "csv" && builtIn === void 0;
|
|
@@ -4097,6 +5067,8 @@ function readinessLaneLabel(route, builtIn) {
|
|
|
4097
5067
|
const labels = {
|
|
4098
5068
|
lead_generation: "Signaliz lead generation",
|
|
4099
5069
|
local_leads: "Signaliz local leads",
|
|
5070
|
+
company_discovery: "Signaliz company discovery",
|
|
5071
|
+
people_discovery: "Signaliz people discovery",
|
|
4100
5072
|
email_finding: "Signaliz email finding",
|
|
4101
5073
|
email_verification: "Signaliz email verification",
|
|
4102
5074
|
signals: "Signaliz signals"
|
|
@@ -4181,6 +5153,35 @@ function summarizeCampaignBuilderProofDryRun(dryRunResult) {
|
|
|
4181
5153
|
plannedTargetCount: dryRunResult.plannedTargetCount ?? dryRunResult.planned_target_count ?? null
|
|
4182
5154
|
};
|
|
4183
5155
|
}
|
|
5156
|
+
function summarizeCampaignBuilderProofLearnBack(plan) {
|
|
5157
|
+
if (Object.keys(plan).length === 0) return { ready: false };
|
|
5158
|
+
const memoryPolicy = asRecord(plan.memory_write_policy);
|
|
5159
|
+
const memoryItemsPolicy = asRecord(memoryPolicy.gtm_memory_items);
|
|
5160
|
+
const sequence = Array.isArray(plan.post_build_sequence) ? plan.post_build_sequence.map((step) => {
|
|
5161
|
+
const record = asRecord(step);
|
|
5162
|
+
return compact({
|
|
5163
|
+
step: record.step,
|
|
5164
|
+
tool: stringValue(record.tool),
|
|
5165
|
+
approval_boundary: stringValue(record.approval_boundary),
|
|
5166
|
+
reason: stringValue(record.reason)
|
|
5167
|
+
});
|
|
5168
|
+
}).filter((step) => typeof step.tool === "string") : [];
|
|
5169
|
+
return {
|
|
5170
|
+
ready: sequence.length > 0,
|
|
5171
|
+
source_tool: firstNonEmptyString(plan.source_tool, plan.sourceTool),
|
|
5172
|
+
post_build_sequence: sequence,
|
|
5173
|
+
memory_write_policy: {
|
|
5174
|
+
target_tables: Array.isArray(memoryPolicy.target_tables) ? memoryPolicy.target_tables : [],
|
|
5175
|
+
gtm_memory_items: {
|
|
5176
|
+
shareable: memoryItemsPolicy.shareable === false ? false : memoryItemsPolicy.shareable ?? null,
|
|
5177
|
+
allowed_redaction_states: Array.isArray(memoryItemsPolicy.allowed_redaction_states) ? memoryItemsPolicy.allowed_redaction_states : [],
|
|
5178
|
+
raw_private_fields_withheld: Array.isArray(memoryItemsPolicy.raw_private_fields_withheld) ? memoryItemsPolicy.raw_private_fields_withheld : []
|
|
5179
|
+
}
|
|
5180
|
+
},
|
|
5181
|
+
approval_policy: firstNonEmptyString(plan.approval_policy, plan.approvalPolicy),
|
|
5182
|
+
privacy_policy: firstNonEmptyString(plan.privacy_policy, plan.privacyPolicy)
|
|
5183
|
+
};
|
|
5184
|
+
}
|
|
4184
5185
|
function firstNonEmptyString(...values) {
|
|
4185
5186
|
for (const value of values) {
|
|
4186
5187
|
if (typeof value === "string" && value.trim()) return value;
|
|
@@ -4663,14 +5664,87 @@ var Ops = class {
|
|
|
4663
5664
|
const body = typeof params === "string" ? { prompt: params } : buildOpsCreateBody(params);
|
|
4664
5665
|
return normalizeOpsCreateResult(withExecutionRefs(await this.call("ops_create", body)));
|
|
4665
5666
|
}
|
|
5667
|
+
async schedule(params) {
|
|
5668
|
+
const createBody = typeof params === "string" ? { prompt: params, cadence: "daily" } : { ...buildOpsCreateBody(params), cadence: params.cadence ?? "daily" };
|
|
5669
|
+
const { activate: _activate, ...body } = createBody;
|
|
5670
|
+
return normalizeOpsCreateResult(withExecutionRefs(await this.call("ops_schedule", body)));
|
|
5671
|
+
}
|
|
5672
|
+
async scheduleAndWait(params) {
|
|
5673
|
+
const options = typeof params === "string" ? { schedule: { prompt: params, cadence: "daily" }, run: {}, wait: {} } : buildOpsScheduleAndWaitOptions(params);
|
|
5674
|
+
const raw = await this.call("ops_schedule_and_wait", buildOpsScheduleAndWaitBody(options));
|
|
5675
|
+
return normalizeOpsScheduleAndWaitCallResult(raw, options.wait, {
|
|
5676
|
+
approvalMessage: "ops.scheduleAndWait requires an approved schedulable Op. Retry with confirmSpend=true after reviewing approval details.",
|
|
5677
|
+
notCreatedMessage: "ops.scheduleAndWait requires ops_schedule_and_wait to create an op_id. Use ops.schedule for approval review flows."
|
|
5678
|
+
});
|
|
5679
|
+
}
|
|
5680
|
+
/** Schedule a recurring Op that delivers through a customer-owned Nango API connection. */
|
|
5681
|
+
async scheduleNangoAction(input) {
|
|
5682
|
+
return normalizeOpsCreateResult(withExecutionRefs(await this.call("ops_nango_schedule", buildOpsNangoScheduleBody(input))));
|
|
5683
|
+
}
|
|
5684
|
+
/** Schedule a recurring Nango-backed Op, run the first tick, and return result readback. */
|
|
5685
|
+
async scheduleNangoActionAndWait(input) {
|
|
5686
|
+
const options = buildOpsNangoScheduleAndWaitOptions(input);
|
|
5687
|
+
const raw = await this.call("ops_nango_schedule_and_wait", buildOpsNangoScheduleAndWaitBody(options));
|
|
5688
|
+
return normalizeOpsScheduleAndWaitCallResult(raw, options.wait, {
|
|
5689
|
+
approvalMessage: "ops.scheduleNangoActionAndWait requires an approved Nango-backed Op. Retry with confirmSpend=true after reviewing approval details.",
|
|
5690
|
+
notCreatedMessage: "ops.scheduleNangoActionAndWait requires ops_nango_schedule_and_wait to create an op_id. Use ops.scheduleNangoAction for approval review flows."
|
|
5691
|
+
});
|
|
5692
|
+
}
|
|
4666
5693
|
async execute(params) {
|
|
4667
5694
|
const body = typeof params === "string" ? { prompt: params } : buildOpsExecuteBody(params);
|
|
4668
5695
|
return normalizeOpsExecuteResult(withExecutionRefs(await this.call("ops_execute", body)));
|
|
4669
5696
|
}
|
|
5697
|
+
async executeAndWait(params) {
|
|
5698
|
+
const options = typeof params === "string" ? { execute: { prompt: params, auto_run: true }, wait: {} } : buildOpsExecuteAndWaitOptions(params);
|
|
5699
|
+
const execute = await this.execute(options.execute);
|
|
5700
|
+
if (execute.approval_required || execute.error_code === "APPROVAL_REQUIRED") {
|
|
5701
|
+
throw new SignalizError({
|
|
5702
|
+
code: "APPROVAL_REQUIRED",
|
|
5703
|
+
errorType: "validation",
|
|
5704
|
+
message: "ops.executeAndWait requires an approved executable Op. Retry with confirmSpend=true after reviewing approval details.",
|
|
5705
|
+
details: { execute }
|
|
5706
|
+
});
|
|
5707
|
+
}
|
|
5708
|
+
if (!execute.op_id) {
|
|
5709
|
+
throw new SignalizError({
|
|
5710
|
+
code: "OP_NOT_CREATED",
|
|
5711
|
+
errorType: "validation",
|
|
5712
|
+
message: "ops.executeAndWait requires ops_execute to create an op_id. Use ops.execute for dry runs or approval review flows.",
|
|
5713
|
+
details: { execute }
|
|
5714
|
+
});
|
|
5715
|
+
}
|
|
5716
|
+
const waited = await this.waitForResults({
|
|
5717
|
+
...options.wait,
|
|
5718
|
+
op_id: execute.op_id
|
|
5719
|
+
});
|
|
5720
|
+
const runId = execute.run_id ?? execute.runId ?? waited.status.run_id ?? waited.status.runId ?? null;
|
|
5721
|
+
return {
|
|
5722
|
+
...waited,
|
|
5723
|
+
execute,
|
|
5724
|
+
run_id: runId,
|
|
5725
|
+
runId,
|
|
5726
|
+
execution_refs: mergeExecutionRefsFrom([execute, waited])
|
|
5727
|
+
};
|
|
5728
|
+
}
|
|
4670
5729
|
async run(params) {
|
|
4671
5730
|
const body = typeof params === "string" ? { op_id: params } : buildOpsRunBody(params);
|
|
4672
5731
|
return normalizeOpsRunResult(withExecutionRefs(await this.call("ops_run", body)));
|
|
4673
5732
|
}
|
|
5733
|
+
async runAndWait(params) {
|
|
5734
|
+
const options = typeof params === "string" ? { op_id: params } : buildOpsRunAndWaitOptions(params);
|
|
5735
|
+
if (!options.op_id) throw new Error("ops.runAndWait requires op_id or opId");
|
|
5736
|
+
const run = await this.run({
|
|
5737
|
+
op_id: options.op_id,
|
|
5738
|
+
instruction: options.instruction,
|
|
5739
|
+
force: options.force
|
|
5740
|
+
});
|
|
5741
|
+
const waited = await this.waitForResults(options);
|
|
5742
|
+
return {
|
|
5743
|
+
...waited,
|
|
5744
|
+
run,
|
|
5745
|
+
execution_refs: mergeExecutionRefsFrom([run, waited])
|
|
5746
|
+
};
|
|
5747
|
+
}
|
|
4674
5748
|
async status(params) {
|
|
4675
5749
|
const body = typeof params === "string" ? { op_id: params } : buildOpsStatusBody(params);
|
|
4676
5750
|
return normalizeOpsStatusResult(withExecutionRefs(await this.call("ops_status", body)));
|
|
@@ -4679,21 +5753,188 @@ var Ops = class {
|
|
|
4679
5753
|
const body = typeof params === "string" ? { op_id: params } : buildOpsResultsBody(params);
|
|
4680
5754
|
return normalizeOpsResultsResult(withExecutionRefs(await this.call("ops_results", body)));
|
|
4681
5755
|
}
|
|
4682
|
-
async
|
|
4683
|
-
const
|
|
4684
|
-
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
return normalizeOpsProofResult(data);
|
|
5756
|
+
async waitForResults(params) {
|
|
5757
|
+
const options = typeof params === "string" ? { op_id: params } : buildOpsWaitForResultsOptions(params);
|
|
5758
|
+
if (!options.op_id) throw new Error("ops.waitForResults requires op_id or opId");
|
|
5759
|
+
const waitResult = await this.call("ops_wait", buildOpsWaitBody(options));
|
|
5760
|
+
return normalizeOpsWaitForResultsResult(waitResult, options);
|
|
4688
5761
|
}
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
5762
|
+
/** Create a short-lived Nango Connect session from the Ops namespace. */
|
|
5763
|
+
async createNangoConnectSession(input) {
|
|
5764
|
+
return this.call("nango_connect_session_create", {
|
|
5765
|
+
provider_id: input.providerId,
|
|
5766
|
+
integration_id: input.integrationId,
|
|
5767
|
+
provider_display_name: input.providerDisplayName,
|
|
5768
|
+
integration_display_name: input.integrationDisplayName,
|
|
5769
|
+
allowed_integrations: input.allowedIntegrations,
|
|
5770
|
+
surface: input.surface,
|
|
5771
|
+
source: input.source,
|
|
5772
|
+
user_email: input.userEmail,
|
|
5773
|
+
user_display_name: input.userDisplayName
|
|
5774
|
+
});
|
|
5775
|
+
}
|
|
5776
|
+
/** Prepare the full Nango provider search, connect, pull/export, Ops, and route flow. */
|
|
5777
|
+
async prepareNangoIntegrationFlow(input = {}) {
|
|
5778
|
+
return this.call("nango_integration_flow_prepare", {
|
|
5779
|
+
query: input.query,
|
|
5780
|
+
search: input.search,
|
|
5781
|
+
provider_id: input.providerId,
|
|
5782
|
+
provider: input.provider,
|
|
5783
|
+
integration_id: input.integrationId,
|
|
5784
|
+
provider_config_key: input.providerConfigKey,
|
|
5785
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
5786
|
+
connection_id: input.connectionId,
|
|
5787
|
+
nango_connection_id: input.nangoConnectionId,
|
|
5788
|
+
intent: input.intent,
|
|
5789
|
+
action_name: input.actionName,
|
|
5790
|
+
tool_name: input.toolName,
|
|
5791
|
+
proxy_path: input.proxyPath,
|
|
5792
|
+
method: input.method,
|
|
5793
|
+
input: input.input,
|
|
5794
|
+
cadence: input.cadence,
|
|
5795
|
+
field_map: input.fieldMap,
|
|
5796
|
+
required_fields: input.requiredFields,
|
|
5797
|
+
confirm_spend: input.confirmSpend,
|
|
5798
|
+
write_confirmed: input.writeConfirmed,
|
|
5799
|
+
layer: input.layer,
|
|
5800
|
+
campaign_id: input.campaignId,
|
|
5801
|
+
limit: input.limit,
|
|
5802
|
+
include_provider_catalog: input.includeProviderCatalog
|
|
5803
|
+
});
|
|
5804
|
+
}
|
|
5805
|
+
/** List Nango-backed action tools for a workspace connection without executing them. */
|
|
5806
|
+
async listNangoTools(options = {}) {
|
|
5807
|
+
return this.call("nango_mcp_tools_list", {
|
|
5808
|
+
workspace_connection_id: options.workspaceConnectionId,
|
|
5809
|
+
connection_id: options.connectionId,
|
|
5810
|
+
provider_config_key: options.providerConfigKey,
|
|
5811
|
+
integration_id: options.integrationId,
|
|
5812
|
+
nango_connection_id: options.nangoConnectionId,
|
|
5813
|
+
format: options.format,
|
|
5814
|
+
include_raw: options.includeRaw
|
|
5815
|
+
});
|
|
5816
|
+
}
|
|
5817
|
+
/** Audit connected Nango rows, action/proxy readiness, and read/write proof gaps. */
|
|
5818
|
+
async proveNangoReadWrite(options = {}) {
|
|
5819
|
+
return this.call("nango_mcp_read_write_audit", {
|
|
5820
|
+
workspace_connection_id: options.workspaceConnectionId,
|
|
5821
|
+
connection_id: options.connectionId,
|
|
5822
|
+
provider_config_key: options.providerConfigKey,
|
|
5823
|
+
integration_id: options.integrationId,
|
|
5824
|
+
nango_connection_id: options.nangoConnectionId,
|
|
5825
|
+
limit: options.limit,
|
|
5826
|
+
include_raw: options.includeRaw,
|
|
5827
|
+
read_proxy_path: options.readProxyPath,
|
|
5828
|
+
write_proxy_path: options.writeProxyPath,
|
|
5829
|
+
method: options.method,
|
|
5830
|
+
execute_read_probe: options.executeReadProbe,
|
|
5831
|
+
execute_write_probe: options.executeWriteProbe,
|
|
5832
|
+
confirm: options.confirm,
|
|
5833
|
+
confirm_write: options.confirmWrite,
|
|
5834
|
+
input: options.input,
|
|
5835
|
+
write_input: options.writeInput
|
|
5836
|
+
});
|
|
5837
|
+
}
|
|
5838
|
+
/** Dry-run or execute a Nango-backed action tool through the approval-aware MCP bridge. */
|
|
5839
|
+
async callNangoTool(input) {
|
|
5840
|
+
return this.call("nango_mcp_tool_call", {
|
|
5841
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
5842
|
+
connection_id: input.connectionId,
|
|
5843
|
+
provider_config_key: input.providerConfigKey,
|
|
5844
|
+
integration_id: input.integrationId,
|
|
5845
|
+
nango_connection_id: input.nangoConnectionId,
|
|
5846
|
+
action_name: input.actionName,
|
|
5847
|
+
tool_name: input.toolName,
|
|
5848
|
+
delivery_mode: input.deliveryMode,
|
|
5849
|
+
proxy_path: input.proxyPath,
|
|
5850
|
+
nango_proxy_path: input.nangoProxyPath,
|
|
5851
|
+
method: input.method,
|
|
5852
|
+
http_method: input.httpMethod,
|
|
5853
|
+
proxy_headers: input.proxyHeaders,
|
|
5854
|
+
input: input.input,
|
|
5855
|
+
async: input.async,
|
|
5856
|
+
max_retries: input.maxRetries,
|
|
5857
|
+
dry_run: input.dryRun,
|
|
5858
|
+
confirm: input.confirm,
|
|
5859
|
+
confirm_write: input.confirmWrite
|
|
5860
|
+
});
|
|
5861
|
+
}
|
|
5862
|
+
/** Execute a Nango action and poll its async result when a status URL/action id is returned. */
|
|
5863
|
+
async callNangoToolAndWait(input) {
|
|
5864
|
+
const result = await this.call("nango_mcp_tool_call_and_wait", {
|
|
5865
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
5866
|
+
connection_id: input.connectionId,
|
|
5867
|
+
provider_config_key: input.providerConfigKey,
|
|
5868
|
+
integration_id: input.integrationId,
|
|
5869
|
+
nango_connection_id: input.nangoConnectionId,
|
|
5870
|
+
action_name: input.actionName,
|
|
5871
|
+
tool_name: input.toolName,
|
|
5872
|
+
delivery_mode: input.deliveryMode,
|
|
5873
|
+
proxy_path: input.proxyPath,
|
|
5874
|
+
nango_proxy_path: input.nangoProxyPath,
|
|
5875
|
+
method: input.method,
|
|
5876
|
+
http_method: input.httpMethod,
|
|
5877
|
+
proxy_headers: input.proxyHeaders,
|
|
5878
|
+
input: input.input,
|
|
5879
|
+
async: input.async ?? true,
|
|
5880
|
+
max_retries: input.maxRetries,
|
|
5881
|
+
dry_run: input.dryRun,
|
|
5882
|
+
confirm: input.confirm,
|
|
5883
|
+
confirm_write: input.confirmWrite,
|
|
5884
|
+
interval_ms: input.intervalMs,
|
|
5885
|
+
max_polls: input.maxPolls,
|
|
5886
|
+
timeout_ms: input.timeoutMs
|
|
5887
|
+
});
|
|
5888
|
+
const packet = asRecord2(result);
|
|
5889
|
+
const actionId = optionalString(packet.actionId) ?? optionalString(packet.action_id);
|
|
5890
|
+
const statusUrl = optionalString(packet.statusUrl) ?? optionalString(packet.status_url);
|
|
5891
|
+
const maxPolls = Number(packet.maxPolls ?? packet.max_polls ?? 0);
|
|
5892
|
+
const intervalMs = Number(packet.intervalMs ?? packet.interval_ms ?? 0);
|
|
5893
|
+
const timeoutMs = Number(packet.timeoutMs ?? packet.timeout_ms ?? 0);
|
|
5894
|
+
const timedOut = Boolean(packet.timedOut ?? packet.timed_out);
|
|
5895
|
+
return {
|
|
5896
|
+
...packet,
|
|
5897
|
+
success: typeof packet.success === "boolean" ? packet.success : void 0,
|
|
5898
|
+
call: packet.call,
|
|
5899
|
+
result: packet.result,
|
|
5900
|
+
status: optionalString(packet.status),
|
|
5901
|
+
action_id: actionId,
|
|
5902
|
+
actionId,
|
|
5903
|
+
status_url: statusUrl,
|
|
5904
|
+
statusUrl,
|
|
5905
|
+
polls: Number(packet.polls ?? 0),
|
|
5906
|
+
max_polls: maxPolls,
|
|
5907
|
+
maxPolls,
|
|
5908
|
+
interval_ms: intervalMs,
|
|
5909
|
+
intervalMs,
|
|
5910
|
+
timeout_ms: timeoutMs,
|
|
5911
|
+
timeoutMs,
|
|
5912
|
+
timed_out: timedOut,
|
|
5913
|
+
timedOut
|
|
5914
|
+
};
|
|
5915
|
+
}
|
|
5916
|
+
/** Poll an async Nango action result by action id or status URL. */
|
|
5917
|
+
async getNangoActionResult(input) {
|
|
5918
|
+
return this.call("nango_mcp_action_result_get", {
|
|
5919
|
+
action_id: input.actionId,
|
|
5920
|
+
status_url: input.statusUrl
|
|
5921
|
+
});
|
|
5922
|
+
}
|
|
5923
|
+
async proof(params = {}) {
|
|
5924
|
+
const data = await this.call("ops_proof", {
|
|
5925
|
+
window_hours: params.windowHours,
|
|
5926
|
+
output_format: "json"
|
|
5927
|
+
});
|
|
5928
|
+
return normalizeOpsProofResult(data);
|
|
5929
|
+
}
|
|
5930
|
+
async debug(params) {
|
|
5931
|
+
const options = typeof params === "string" ? { op_id: params } : buildOpsDebugOptions(params);
|
|
5932
|
+
const diagnosticErrors = [];
|
|
5933
|
+
const status = await this.status(options.op_id);
|
|
5934
|
+
const refs = /* @__PURE__ */ new Map();
|
|
5935
|
+
const addRefs = (items) => {
|
|
5936
|
+
for (const ref of items ?? []) refs.set(`${ref.kind}:${ref.id}`, ref);
|
|
5937
|
+
};
|
|
4697
5938
|
const recordError = (step, err) => {
|
|
4698
5939
|
diagnosticErrors.push({
|
|
4699
5940
|
step,
|
|
@@ -4705,51 +5946,57 @@ var Ops = class {
|
|
|
4705
5946
|
addRefs(collectExecutionReferences(status.latest_run));
|
|
4706
5947
|
}
|
|
4707
5948
|
const runRefs = Array.from(refs.values()).filter((ref) => ref.kind === "trigger_run" || ref.kind === "dataplane_run" || ref.kind === "replay_run");
|
|
4708
|
-
|
|
4709
|
-
for (const ref of runRefs) {
|
|
4710
|
-
try {
|
|
4711
|
-
const result = await this.getTriggerRunStatus(ref.id);
|
|
4712
|
-
const runs = "runs" in result ? result.runs : [result];
|
|
4713
|
-
runStatuses.push(...runs);
|
|
4714
|
-
for (const run of runs) addRefs(run.execution_refs);
|
|
4715
|
-
} catch (err) {
|
|
4716
|
-
recordError(`run-status:${ref.id}`, err);
|
|
4717
|
-
}
|
|
4718
|
-
}
|
|
5949
|
+
let runStatuses = [];
|
|
4719
5950
|
let queue;
|
|
4720
|
-
if (options.include_queue !== false) {
|
|
4721
|
-
try {
|
|
4722
|
-
queue = await this.getQueueStatus({ summary: true });
|
|
4723
|
-
addRefs(queue.execution_refs);
|
|
4724
|
-
} catch (err) {
|
|
4725
|
-
recordError("queue", err);
|
|
4726
|
-
}
|
|
4727
|
-
}
|
|
4728
5951
|
let dashboardRecent;
|
|
4729
|
-
if (options.include_dashboard !== false) {
|
|
4730
|
-
try {
|
|
4731
|
-
dashboardRecent = await this.getDashboard({
|
|
4732
|
-
section: "recent",
|
|
4733
|
-
limit: options.dashboard_limit ?? 10,
|
|
4734
|
-
timeRangeDays: options.time_range_days
|
|
4735
|
-
});
|
|
4736
|
-
} catch (err) {
|
|
4737
|
-
recordError("dashboard:recent", err);
|
|
4738
|
-
}
|
|
4739
|
-
}
|
|
4740
5952
|
let results;
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
5953
|
+
await Promise.all([
|
|
5954
|
+
(async () => {
|
|
5955
|
+
if (runRefs.length === 0) return;
|
|
5956
|
+
try {
|
|
5957
|
+
const result = await this.getTriggerRunStatus({ run_ids: runRefs.map((ref) => ref.id) });
|
|
5958
|
+
const runs = "runs" in result ? result.runs : [result];
|
|
5959
|
+
runStatuses = runs;
|
|
5960
|
+
for (const run of runs) addRefs(run.execution_refs);
|
|
5961
|
+
} catch (err) {
|
|
5962
|
+
recordError(runRefs.length === 1 ? `run-status:${runRefs[0].id}` : "run-status:batch", err);
|
|
5963
|
+
}
|
|
5964
|
+
})(),
|
|
5965
|
+
(async () => {
|
|
5966
|
+
if (options.include_queue === false) return;
|
|
5967
|
+
try {
|
|
5968
|
+
queue = await this.getQueueStatus({ summary: true });
|
|
5969
|
+
addRefs(queue.execution_refs);
|
|
5970
|
+
} catch (err) {
|
|
5971
|
+
recordError("queue", err);
|
|
5972
|
+
}
|
|
5973
|
+
})(),
|
|
5974
|
+
(async () => {
|
|
5975
|
+
if (options.include_dashboard === false) return;
|
|
5976
|
+
try {
|
|
5977
|
+
dashboardRecent = await this.getDashboard({
|
|
5978
|
+
section: "recent",
|
|
5979
|
+
limit: options.dashboard_limit ?? 10,
|
|
5980
|
+
timeRangeDays: options.time_range_days
|
|
5981
|
+
});
|
|
5982
|
+
} catch (err) {
|
|
5983
|
+
recordError("dashboard:recent", err);
|
|
5984
|
+
}
|
|
5985
|
+
})(),
|
|
5986
|
+
(async () => {
|
|
5987
|
+
if (!options.include_results) return;
|
|
5988
|
+
try {
|
|
5989
|
+
results = await this.results({
|
|
5990
|
+
op_id: options.op_id,
|
|
5991
|
+
limit: options.results_limit ?? 25,
|
|
5992
|
+
include_failed_runs: true
|
|
5993
|
+
});
|
|
5994
|
+
addRefs(results.execution_refs);
|
|
5995
|
+
} catch (err) {
|
|
5996
|
+
recordError("results", err);
|
|
5997
|
+
}
|
|
5998
|
+
})()
|
|
5999
|
+
]);
|
|
4753
6000
|
const executionRefs = Array.from(refs.values());
|
|
4754
6001
|
const replayCandidates = executionRefs.filter((ref) => ref.kind === "execution_event");
|
|
4755
6002
|
const nextActions = buildDebugNextActions(status, executionRefs, diagnosticErrors);
|
|
@@ -4951,6 +6198,69 @@ function mergeExecutionRefs(result) {
|
|
|
4951
6198
|
for (const ref of collectExecutionReferences(result)) add(ref);
|
|
4952
6199
|
return Array.from(refs.values());
|
|
4953
6200
|
}
|
|
6201
|
+
function mergeExecutionRefsFrom(results) {
|
|
6202
|
+
const refs = /* @__PURE__ */ new Map();
|
|
6203
|
+
for (const result of results) {
|
|
6204
|
+
if (!result) continue;
|
|
6205
|
+
for (const ref of mergeExecutionRefs(result)) refs.set(`${ref.kind}:${ref.id}`, ref);
|
|
6206
|
+
}
|
|
6207
|
+
return Array.from(refs.values());
|
|
6208
|
+
}
|
|
6209
|
+
function normalizeOpsScheduleAndWaitCallResult(raw, waitOptions, messages) {
|
|
6210
|
+
if (raw.approval_required || raw.approvalRequired || raw.error_code === "APPROVAL_REQUIRED" || raw.errorCode === "APPROVAL_REQUIRED") {
|
|
6211
|
+
throw new SignalizError({
|
|
6212
|
+
code: "APPROVAL_REQUIRED",
|
|
6213
|
+
errorType: "validation",
|
|
6214
|
+
message: messages.approvalMessage,
|
|
6215
|
+
details: { schedule: raw }
|
|
6216
|
+
});
|
|
6217
|
+
}
|
|
6218
|
+
const opId = stringValue2(raw.op_id ?? raw.opId);
|
|
6219
|
+
if (!opId) {
|
|
6220
|
+
throw new SignalizError({
|
|
6221
|
+
code: "OP_NOT_CREATED",
|
|
6222
|
+
errorType: "validation",
|
|
6223
|
+
message: messages.notCreatedMessage,
|
|
6224
|
+
details: { schedule: raw }
|
|
6225
|
+
});
|
|
6226
|
+
}
|
|
6227
|
+
const scheduleRaw = asRecord2(raw.schedule ?? raw.schedule_result ?? raw.scheduleResult);
|
|
6228
|
+
const runRaw = asRecord2(raw.run ?? raw.run_result ?? raw.runResult);
|
|
6229
|
+
const schedule = normalizeOpsCreateResult(withExecutionRefs(
|
|
6230
|
+
Object.keys(scheduleRaw).length > 0 ? scheduleRaw : {
|
|
6231
|
+
...raw,
|
|
6232
|
+
op_id: opId,
|
|
6233
|
+
routine_id: raw.routine_id ?? raw.routineId ?? opId,
|
|
6234
|
+
status: "ready",
|
|
6235
|
+
phase: "scheduled",
|
|
6236
|
+
next_action: raw.next_action ?? raw.nextAction
|
|
6237
|
+
}
|
|
6238
|
+
));
|
|
6239
|
+
const run = normalizeOpsRunResult(withExecutionRefs(
|
|
6240
|
+
Object.keys(runRaw).length > 0 ? runRaw : {
|
|
6241
|
+
success: raw.success !== false,
|
|
6242
|
+
op_id: opId,
|
|
6243
|
+
routine_id: raw.routine_id ?? raw.routineId ?? opId,
|
|
6244
|
+
run_id: raw.run_id ?? raw.runId ?? null,
|
|
6245
|
+
status: "running",
|
|
6246
|
+
phase: "queued",
|
|
6247
|
+
next_action: raw.next_action ?? raw.nextAction,
|
|
6248
|
+
results_count: 0,
|
|
6249
|
+
results_url: raw.results_url ?? raw.resultsUrl,
|
|
6250
|
+
delivery_status: raw.delivery_status ?? raw.deliveryStatus
|
|
6251
|
+
}
|
|
6252
|
+
));
|
|
6253
|
+
const waited = normalizeOpsWaitForResultsResult(raw, { ...waitOptions, op_id: opId });
|
|
6254
|
+
const runId = run.run_id ?? run.runId ?? waited.run_id ?? waited.runId ?? waited.status.run_id ?? waited.status.runId ?? null;
|
|
6255
|
+
return {
|
|
6256
|
+
...waited,
|
|
6257
|
+
schedule,
|
|
6258
|
+
run,
|
|
6259
|
+
run_id: runId,
|
|
6260
|
+
runId,
|
|
6261
|
+
execution_refs: mergeExecutionRefsFrom([schedule, run, waited])
|
|
6262
|
+
};
|
|
6263
|
+
}
|
|
4954
6264
|
function normalizeOpsPrimitiveRetryPolicy(policy = {}) {
|
|
4955
6265
|
return {
|
|
4956
6266
|
...policy,
|
|
@@ -5026,8 +6336,122 @@ function normalizeOpsPrimitive(primitive) {
|
|
|
5026
6336
|
observability: normalizeOpsPrimitiveObservabilityPolicy(primitive.observability)
|
|
5027
6337
|
};
|
|
5028
6338
|
}
|
|
6339
|
+
function normalizeOpsExecutionToolCall(rawCall) {
|
|
6340
|
+
const call = asRecord2(rawCall);
|
|
6341
|
+
return {
|
|
6342
|
+
...call,
|
|
6343
|
+
tool: stringValue2(call.tool),
|
|
6344
|
+
arguments: asRecord2(call.arguments),
|
|
6345
|
+
purpose: stringValue2(call.purpose)
|
|
6346
|
+
};
|
|
6347
|
+
}
|
|
6348
|
+
function normalizeOpsExecutionScheduleContract(rawSchedule) {
|
|
6349
|
+
const schedule = asRecord2(rawSchedule);
|
|
6350
|
+
const wakeOnEvents = Array.isArray(schedule.wake_on_events) ? schedule.wake_on_events.map(String) : Array.isArray(schedule.wakeOnEvents) ? schedule.wakeOnEvents.map(String) : [];
|
|
6351
|
+
return {
|
|
6352
|
+
...schedule,
|
|
6353
|
+
create_tool: stringValue2(schedule.create_tool ?? schedule.createTool),
|
|
6354
|
+
createTool: stringValue2(schedule.createTool ?? schedule.create_tool),
|
|
6355
|
+
activate_tool: stringValue2(schedule.activate_tool ?? schedule.activateTool),
|
|
6356
|
+
activateTool: stringValue2(schedule.activateTool ?? schedule.activate_tool),
|
|
6357
|
+
cadence: stringValue2(schedule.cadence, "manual"),
|
|
6358
|
+
recurrence: stringValue2(schedule.recurrence),
|
|
6359
|
+
wake_on_events: wakeOnEvents,
|
|
6360
|
+
wakeOnEvents
|
|
6361
|
+
};
|
|
6362
|
+
}
|
|
6363
|
+
function normalizeOpsExecutionApprovalContract(rawApproval) {
|
|
6364
|
+
const approval = asRecord2(rawApproval);
|
|
6365
|
+
return {
|
|
6366
|
+
...approval,
|
|
6367
|
+
required: Boolean(approval.required),
|
|
6368
|
+
tool: stringValue2(approval.tool),
|
|
6369
|
+
reason: stringValue2(approval.reason)
|
|
6370
|
+
};
|
|
6371
|
+
}
|
|
6372
|
+
function normalizeOpsExecutionMonitorContract(rawMonitor) {
|
|
6373
|
+
const monitor = asRecord2(rawMonitor);
|
|
6374
|
+
const pollAfterMs = numberValue(monitor.poll_after_ms ?? monitor.pollAfterMs);
|
|
6375
|
+
return {
|
|
6376
|
+
...monitor,
|
|
6377
|
+
status_tool: stringValue2(monitor.status_tool ?? monitor.statusTool),
|
|
6378
|
+
statusTool: stringValue2(monitor.statusTool ?? monitor.status_tool),
|
|
6379
|
+
wait_tool: stringValue2(monitor.wait_tool ?? monitor.waitTool),
|
|
6380
|
+
waitTool: stringValue2(monitor.waitTool ?? monitor.wait_tool),
|
|
6381
|
+
results_tool: stringValue2(monitor.results_tool ?? monitor.resultsTool),
|
|
6382
|
+
resultsTool: stringValue2(monitor.resultsTool ?? monitor.results_tool),
|
|
6383
|
+
poll_after_ms: pollAfterMs,
|
|
6384
|
+
pollAfterMs
|
|
6385
|
+
};
|
|
6386
|
+
}
|
|
6387
|
+
function normalizeOpsExecutionResultContract(rawResult) {
|
|
6388
|
+
const result = asRecord2(rawResult);
|
|
6389
|
+
const shape = Array.isArray(result.shape) ? result.shape.map(String) : [];
|
|
6390
|
+
return {
|
|
6391
|
+
...result,
|
|
6392
|
+
tool: stringValue2(result.tool),
|
|
6393
|
+
wait_tool: stringValue2(result.wait_tool ?? result.waitTool),
|
|
6394
|
+
waitTool: stringValue2(result.waitTool ?? result.wait_tool),
|
|
6395
|
+
shape,
|
|
6396
|
+
empty_result_recovery: stringValue2(result.empty_result_recovery ?? result.emptyResultRecovery),
|
|
6397
|
+
emptyResultRecovery: stringValue2(result.emptyResultRecovery ?? result.empty_result_recovery)
|
|
6398
|
+
};
|
|
6399
|
+
}
|
|
6400
|
+
function normalizeOpsExecutionNangoRouteContract(rawRoute) {
|
|
6401
|
+
if (!rawRoute || typeof rawRoute !== "object" || Array.isArray(rawRoute)) return void 0;
|
|
6402
|
+
const route = asRecord2(rawRoute);
|
|
6403
|
+
const requiredFields = Array.isArray(route.required_fields) ? route.required_fields.map(String) : Array.isArray(route.requiredFields) ? route.requiredFields.map(String) : [];
|
|
6404
|
+
return {
|
|
6405
|
+
...route,
|
|
6406
|
+
enabled: route.enabled !== false,
|
|
6407
|
+
connect_tool: stringValue2(route.connect_tool ?? route.connectTool),
|
|
6408
|
+
connectTool: stringValue2(route.connectTool ?? route.connect_tool),
|
|
6409
|
+
discover_tool: stringValue2(route.discover_tool ?? route.discoverTool),
|
|
6410
|
+
discoverTool: stringValue2(route.discoverTool ?? route.discover_tool),
|
|
6411
|
+
dry_run_tool: stringValue2(route.dry_run_tool ?? route.dryRunTool),
|
|
6412
|
+
dryRunTool: stringValue2(route.dryRunTool ?? route.dry_run_tool),
|
|
6413
|
+
execute_tool: stringValue2(route.execute_tool ?? route.executeTool),
|
|
6414
|
+
executeTool: stringValue2(route.executeTool ?? route.execute_tool),
|
|
6415
|
+
execute_and_wait_tool: stringValue2(route.execute_and_wait_tool ?? route.executeAndWaitTool),
|
|
6416
|
+
executeAndWaitTool: stringValue2(route.executeAndWaitTool ?? route.execute_and_wait_tool),
|
|
6417
|
+
schedule_tool: stringValue2(route.schedule_tool ?? route.scheduleTool),
|
|
6418
|
+
scheduleTool: stringValue2(route.scheduleTool ?? route.schedule_tool),
|
|
6419
|
+
schedule_and_wait_tool: stringValue2(route.schedule_and_wait_tool ?? route.scheduleAndWaitTool),
|
|
6420
|
+
scheduleAndWaitTool: stringValue2(route.scheduleAndWaitTool ?? route.schedule_and_wait_tool),
|
|
6421
|
+
result_tool: stringValue2(route.result_tool ?? route.resultTool),
|
|
6422
|
+
resultTool: stringValue2(route.resultTool ?? route.result_tool),
|
|
6423
|
+
write_gate: stringValue2(route.write_gate ?? route.writeGate),
|
|
6424
|
+
writeGate: stringValue2(route.writeGate ?? route.write_gate),
|
|
6425
|
+
required_fields: requiredFields,
|
|
6426
|
+
requiredFields,
|
|
6427
|
+
schedule_arguments: asRecord2(route.schedule_arguments ?? route.scheduleArguments),
|
|
6428
|
+
scheduleArguments: asRecord2(route.scheduleArguments ?? route.schedule_arguments),
|
|
6429
|
+
schedule_and_wait_arguments: asRecord2(route.schedule_and_wait_arguments ?? route.scheduleAndWaitArguments),
|
|
6430
|
+
scheduleAndWaitArguments: asRecord2(route.scheduleAndWaitArguments ?? route.schedule_and_wait_arguments)
|
|
6431
|
+
};
|
|
6432
|
+
}
|
|
6433
|
+
function normalizeOpsExecutionContract(rawContract) {
|
|
6434
|
+
if (!rawContract || typeof rawContract !== "object" || Array.isArray(rawContract)) return void 0;
|
|
6435
|
+
const contract = asRecord2(rawContract);
|
|
6436
|
+
const nangoRoute = normalizeOpsExecutionNangoRouteContract(contract.nango_route ?? contract.nangoRoute);
|
|
6437
|
+
const sequence = Array.isArray(contract.sequence) ? contract.sequence.map(normalizeOpsExecutionToolCall) : [];
|
|
6438
|
+
return {
|
|
6439
|
+
...contract,
|
|
6440
|
+
mode: stringValue2(contract.mode, "run_once"),
|
|
6441
|
+
run_now: normalizeOpsExecutionToolCall(contract.run_now ?? contract.runNow),
|
|
6442
|
+
runNow: normalizeOpsExecutionToolCall(contract.runNow ?? contract.run_now),
|
|
6443
|
+
schedule: normalizeOpsExecutionScheduleContract(contract.schedule),
|
|
6444
|
+
approval: normalizeOpsExecutionApprovalContract(contract.approval),
|
|
6445
|
+
monitor: normalizeOpsExecutionMonitorContract(contract.monitor),
|
|
6446
|
+
result_contract: normalizeOpsExecutionResultContract(contract.result_contract ?? contract.resultContract),
|
|
6447
|
+
resultContract: normalizeOpsExecutionResultContract(contract.resultContract ?? contract.result_contract),
|
|
6448
|
+
...nangoRoute ? { nango_route: nangoRoute, nangoRoute } : {},
|
|
6449
|
+
sequence
|
|
6450
|
+
};
|
|
6451
|
+
}
|
|
5029
6452
|
function normalizeOpsPlanResult(result) {
|
|
5030
6453
|
const primitiveGraph = result.primitive_graph ?? result.primitiveGraph;
|
|
6454
|
+
const executionContract = normalizeOpsExecutionContract(result.execution_contract ?? result.executionContract);
|
|
5031
6455
|
return {
|
|
5032
6456
|
...result,
|
|
5033
6457
|
plan_id: result.plan_id ?? result.planId,
|
|
@@ -5051,7 +6475,8 @@ function normalizeOpsPlanResult(result) {
|
|
|
5051
6475
|
destination_status: result.destination_status ?? result.destinationStatus,
|
|
5052
6476
|
destinationStatus: result.destinationStatus ?? result.destination_status,
|
|
5053
6477
|
primitive_graph: primitiveGraph?.map(normalizeOpsPrimitive),
|
|
5054
|
-
primitiveGraph: primitiveGraph?.map(normalizeOpsPrimitive)
|
|
6478
|
+
primitiveGraph: primitiveGraph?.map(normalizeOpsPrimitive),
|
|
6479
|
+
...executionContract ? { execution_contract: executionContract, executionContract } : {}
|
|
5055
6480
|
};
|
|
5056
6481
|
}
|
|
5057
6482
|
function normalizeOpsCreateResult(result) {
|
|
@@ -5073,7 +6498,18 @@ function normalizeOpsCreateResult(result) {
|
|
|
5073
6498
|
deliveryStatus: result.deliveryStatus ?? result.delivery_status,
|
|
5074
6499
|
estimated_credits: result.estimated_credits ?? result.estimatedCredits,
|
|
5075
6500
|
estimatedCredits: result.estimatedCredits ?? result.estimated_credits,
|
|
5076
|
-
|
|
6501
|
+
error_code: result.error_code ?? result.errorCode,
|
|
6502
|
+
errorCode: result.errorCode ?? result.error_code,
|
|
6503
|
+
approval_required: result.approval_required ?? result.approvalRequired,
|
|
6504
|
+
approvalRequired: result.approvalRequired ?? result.approval_required,
|
|
6505
|
+
retry_arguments: result.retry_arguments ?? result.retryArguments,
|
|
6506
|
+
retryArguments: result.retryArguments ?? result.retry_arguments,
|
|
6507
|
+
blockers: result.blockers,
|
|
6508
|
+
plan: result.plan ? normalizeOpsPlanResult(result.plan) : result.plan,
|
|
6509
|
+
next_step: result.next_step ?? result.nextStep,
|
|
6510
|
+
nextStep: result.nextStep ?? result.next_step,
|
|
6511
|
+
next_steps: result.next_steps ?? result.nextSteps,
|
|
6512
|
+
nextSteps: result.nextSteps ?? result.next_steps
|
|
5077
6513
|
};
|
|
5078
6514
|
}
|
|
5079
6515
|
function normalizeOpsExecuteResult(result) {
|
|
@@ -5201,6 +6637,40 @@ function normalizeOpsStatusResult(result) {
|
|
|
5201
6637
|
diagnosis: result.diagnosis ? normalizeOpsDebugDiagnosis(result.diagnosis) : void 0
|
|
5202
6638
|
};
|
|
5203
6639
|
}
|
|
6640
|
+
function normalizeOpsResultsSummary(value) {
|
|
6641
|
+
const summary = asRecord2(value);
|
|
6642
|
+
if (Object.keys(summary).length === 0) return void 0;
|
|
6643
|
+
const resultsTotal = summary.results_total ?? summary.resultsTotal;
|
|
6644
|
+
const nextCursor = summary.next_cursor ?? summary.nextCursor ?? null;
|
|
6645
|
+
const resultsUrl = summary.results_url ?? summary.resultsUrl;
|
|
6646
|
+
const nextAction = summary.next_action ?? summary.nextAction;
|
|
6647
|
+
const runId = summary.run_id ?? summary.runId ?? null;
|
|
6648
|
+
const creditsUsed = summary.credits_used ?? summary.creditsUsed;
|
|
6649
|
+
return {
|
|
6650
|
+
...summary,
|
|
6651
|
+
label: optionalString(summary.label),
|
|
6652
|
+
status: optionalString(summary.status),
|
|
6653
|
+
phase: optionalString(summary.phase),
|
|
6654
|
+
results_count: numberValue(summary.results_count ?? summary.resultsCount),
|
|
6655
|
+
resultsCount: numberValue(summary.results_count ?? summary.resultsCount),
|
|
6656
|
+
results_total: resultsTotal === null || resultsTotal === void 0 ? resultsTotal : numberValue(resultsTotal),
|
|
6657
|
+
resultsTotal: resultsTotal === null || resultsTotal === void 0 ? resultsTotal : numberValue(resultsTotal),
|
|
6658
|
+
delivery_status: optionalString(summary.delivery_status ?? summary.deliveryStatus),
|
|
6659
|
+
deliveryStatus: optionalString(summary.delivery_status ?? summary.deliveryStatus),
|
|
6660
|
+
has_more: Boolean(summary.has_more ?? summary.hasMore),
|
|
6661
|
+
hasMore: Boolean(summary.has_more ?? summary.hasMore),
|
|
6662
|
+
next_cursor: nextCursor === null ? null : optionalString(nextCursor),
|
|
6663
|
+
nextCursor: nextCursor === null ? null : optionalString(nextCursor),
|
|
6664
|
+
results_url: optionalString(resultsUrl),
|
|
6665
|
+
resultsUrl: optionalString(resultsUrl),
|
|
6666
|
+
next_action: optionalString(nextAction),
|
|
6667
|
+
nextAction: optionalString(nextAction),
|
|
6668
|
+
run_id: runId === null ? null : optionalString(runId),
|
|
6669
|
+
runId: runId === null ? null : optionalString(runId),
|
|
6670
|
+
credits_used: creditsUsed === void 0 ? void 0 : numberValue(creditsUsed),
|
|
6671
|
+
creditsUsed: creditsUsed === void 0 ? void 0 : numberValue(creditsUsed)
|
|
6672
|
+
};
|
|
6673
|
+
}
|
|
5204
6674
|
function normalizeOpsResultsResult(result) {
|
|
5205
6675
|
const nextCursor = result.next_cursor ?? result.nextCursor ?? null;
|
|
5206
6676
|
const hasMore = result.has_more ?? result.hasMore ?? false;
|
|
@@ -5225,7 +6695,104 @@ function normalizeOpsResultsResult(result) {
|
|
|
5225
6695
|
results_url: result.results_url ?? result.resultsUrl,
|
|
5226
6696
|
resultsUrl: result.resultsUrl ?? result.results_url,
|
|
5227
6697
|
delivery_status: result.delivery_status ?? result.deliveryStatus,
|
|
5228
|
-
deliveryStatus: result.deliveryStatus ?? result.delivery_status
|
|
6698
|
+
deliveryStatus: result.deliveryStatus ?? result.delivery_status,
|
|
6699
|
+
summary: normalizeOpsResultsSummary(result.summary)
|
|
6700
|
+
};
|
|
6701
|
+
}
|
|
6702
|
+
function normalizeOpsWaitForResultsPoll(value, fallbackPoll) {
|
|
6703
|
+
const raw = asRecord2(value);
|
|
6704
|
+
const checkedAt = stringValue2(raw.checked_at ?? raw.checkedAt);
|
|
6705
|
+
const resultsCount = raw.results_count ?? raw.resultsCount;
|
|
6706
|
+
const runId = raw.run_id ?? raw.runId ?? null;
|
|
6707
|
+
const nextAction = raw.next_action ?? raw.nextAction;
|
|
6708
|
+
return {
|
|
6709
|
+
...raw,
|
|
6710
|
+
poll: numberValue(raw.poll) || fallbackPoll,
|
|
6711
|
+
checked_at: checkedAt,
|
|
6712
|
+
checkedAt,
|
|
6713
|
+
status: stringValue2(raw.status, "unknown"),
|
|
6714
|
+
phase: optionalString(raw.phase),
|
|
6715
|
+
results_count: resultsCount === void 0 ? void 0 : numberValue(resultsCount),
|
|
6716
|
+
resultsCount: resultsCount === void 0 ? void 0 : numberValue(resultsCount),
|
|
6717
|
+
run_id: runId === null ? null : optionalString(runId),
|
|
6718
|
+
runId: runId === null ? null : optionalString(runId),
|
|
6719
|
+
next_action: optionalString(nextAction),
|
|
6720
|
+
nextAction: optionalString(nextAction)
|
|
6721
|
+
};
|
|
6722
|
+
}
|
|
6723
|
+
function normalizeOpsWaitForResultsResult(result, options) {
|
|
6724
|
+
const opId = stringValue2(result.op_id ?? result.opId ?? options.op_id);
|
|
6725
|
+
const routineId = stringValue2(result.routine_id ?? result.routineId ?? opId);
|
|
6726
|
+
const runId = result.run_id ?? result.runId ?? null;
|
|
6727
|
+
const timedOut = Boolean(result.timed_out ?? result.timedOut);
|
|
6728
|
+
const statusRaw = asRecord2(result.status_result ?? result.statusResult);
|
|
6729
|
+
const resultsRaw = asRecord2(result.results_result ?? result.resultsResult);
|
|
6730
|
+
const historySource = Array.isArray(result.poll_history) ? result.poll_history : Array.isArray(result.history) ? result.history : [];
|
|
6731
|
+
const history = historySource.map((item, index) => normalizeOpsWaitForResultsPoll(item, index + 1));
|
|
6732
|
+
const status = normalizeOpsStatusResult(withExecutionRefs({
|
|
6733
|
+
success: result.success !== false,
|
|
6734
|
+
op_id: opId,
|
|
6735
|
+
routine_id: routineId,
|
|
6736
|
+
run_id: runId,
|
|
6737
|
+
status: stringValue2(result.status, "unknown"),
|
|
6738
|
+
phase: stringValue2(result.phase, "unknown"),
|
|
6739
|
+
next_action: stringValue2(result.next_action ?? result.nextAction),
|
|
6740
|
+
results_count: numberValue(result.results_count ?? result.resultsCount),
|
|
6741
|
+
results_url: optionalString(result.results_url ?? result.resultsUrl),
|
|
6742
|
+
delivery_status: optionalString(result.delivery_status ?? result.deliveryStatus),
|
|
6743
|
+
...statusRaw
|
|
6744
|
+
}));
|
|
6745
|
+
const includeResults = options.include_results !== false && options.includeResults !== false;
|
|
6746
|
+
const hasResultsPacket = Object.keys(resultsRaw).length > 0 || Array.isArray(result.results);
|
|
6747
|
+
const results = includeResults && hasResultsPacket ? normalizeOpsResultsResult(withExecutionRefs({
|
|
6748
|
+
success: result.success !== false,
|
|
6749
|
+
op_id: opId,
|
|
6750
|
+
routine_id: routineId,
|
|
6751
|
+
run_id: runId,
|
|
6752
|
+
status: stringValue2(result.status, status.status),
|
|
6753
|
+
phase: stringValue2(result.phase, status.phase),
|
|
6754
|
+
results_count: numberValue(result.results_count ?? result.resultsCount),
|
|
6755
|
+
results_total: result.results_total ?? result.resultsTotal ?? null,
|
|
6756
|
+
results: Array.isArray(result.results) ? result.results : [],
|
|
6757
|
+
next_cursor: result.next_cursor ?? result.nextCursor ?? null,
|
|
6758
|
+
has_more: Boolean(result.has_more ?? result.hasMore),
|
|
6759
|
+
next_action: stringValue2(result.next_action ?? result.nextAction),
|
|
6760
|
+
results_url: optionalString(result.results_url ?? result.resultsUrl),
|
|
6761
|
+
delivery_status: optionalString(result.delivery_status ?? result.deliveryStatus),
|
|
6762
|
+
...resultsRaw
|
|
6763
|
+
})) : void 0;
|
|
6764
|
+
const polls = numberValue(result.polls) || history.length;
|
|
6765
|
+
const maxPolls = result.max_polls ?? result.maxPolls;
|
|
6766
|
+
const intervalMs = result.interval_ms ?? result.intervalMs;
|
|
6767
|
+
const timeoutMs = result.timeout_ms ?? result.timeoutMs;
|
|
6768
|
+
const stopReason = result.stop_reason ?? result.stopReason;
|
|
6769
|
+
const nextAction = result.next_action ?? result.nextAction ?? results?.next_action ?? status.next_action;
|
|
6770
|
+
return {
|
|
6771
|
+
...result,
|
|
6772
|
+
success: result.success !== false && !timedOut,
|
|
6773
|
+
op_id: opId,
|
|
6774
|
+
opId,
|
|
6775
|
+
routine_id: routineId,
|
|
6776
|
+
routineId,
|
|
6777
|
+
run_id: runId === null ? null : optionalString(runId),
|
|
6778
|
+
runId: runId === null ? null : optionalString(runId),
|
|
6779
|
+
status,
|
|
6780
|
+
results,
|
|
6781
|
+
timed_out: timedOut,
|
|
6782
|
+
timedOut,
|
|
6783
|
+
polls,
|
|
6784
|
+
max_polls: maxPolls === void 0 ? void 0 : numberValue(maxPolls),
|
|
6785
|
+
maxPolls: maxPolls === void 0 ? void 0 : numberValue(maxPolls),
|
|
6786
|
+
interval_ms: intervalMs === void 0 ? void 0 : numberValue(intervalMs),
|
|
6787
|
+
intervalMs: intervalMs === void 0 ? void 0 : numberValue(intervalMs),
|
|
6788
|
+
timeout_ms: timeoutMs === void 0 ? void 0 : numberValue(timeoutMs),
|
|
6789
|
+
timeoutMs: timeoutMs === void 0 ? void 0 : numberValue(timeoutMs),
|
|
6790
|
+
stop_reason: optionalString(stopReason),
|
|
6791
|
+
stopReason: optionalString(stopReason),
|
|
6792
|
+
history,
|
|
6793
|
+
next_action: optionalString(nextAction),
|
|
6794
|
+
nextAction: optionalString(nextAction),
|
|
6795
|
+
execution_refs: mergeExecutionRefsFrom([result, status, results, { history }])
|
|
5229
6796
|
};
|
|
5230
6797
|
}
|
|
5231
6798
|
function normalizeOpsProofResult(data) {
|
|
@@ -5305,11 +6872,107 @@ function normalizeOpsProofResult(data) {
|
|
|
5305
6872
|
raw: data
|
|
5306
6873
|
};
|
|
5307
6874
|
}
|
|
6875
|
+
function normalizeOpsAutopilotSchedulePacket(rawPacket) {
|
|
6876
|
+
const packet = asRecord2(rawPacket);
|
|
6877
|
+
return {
|
|
6878
|
+
...packet,
|
|
6879
|
+
cadence: stringValue2(packet.cadence, "manual"),
|
|
6880
|
+
recurrence: stringValue2(packet.recurrence),
|
|
6881
|
+
activate_with: stringValue2(packet.activate_with ?? packet.activateWith),
|
|
6882
|
+
activateWith: stringValue2(packet.activate_with ?? packet.activateWith),
|
|
6883
|
+
run_now_with: stringValue2(packet.run_now_with ?? packet.runNowWith),
|
|
6884
|
+
runNowWith: stringValue2(packet.run_now_with ?? packet.runNowWith),
|
|
6885
|
+
monitor_with: stringValue2(packet.monitor_with ?? packet.monitorWith),
|
|
6886
|
+
monitorWith: stringValue2(packet.monitor_with ?? packet.monitorWith),
|
|
6887
|
+
retrieve_with: stringValue2(packet.retrieve_with ?? packet.retrieveWith),
|
|
6888
|
+
retrieveWith: stringValue2(packet.retrieve_with ?? packet.retrieveWith)
|
|
6889
|
+
};
|
|
6890
|
+
}
|
|
6891
|
+
function normalizeOpsAutopilotNangoRoutePacket(rawPacket) {
|
|
6892
|
+
if (!rawPacket || typeof rawPacket !== "object" || Array.isArray(rawPacket)) return void 0;
|
|
6893
|
+
const packet = asRecord2(rawPacket);
|
|
6894
|
+
const requiredFields = Array.isArray(packet.required_fields) ? packet.required_fields.map(String) : Array.isArray(packet.requiredFields) ? packet.requiredFields.map(String) : [];
|
|
6895
|
+
return {
|
|
6896
|
+
...packet,
|
|
6897
|
+
enabled: packet.enabled !== false,
|
|
6898
|
+
route_label: stringValue2(packet.route_label ?? packet.routeLabel),
|
|
6899
|
+
routeLabel: stringValue2(packet.route_label ?? packet.routeLabel),
|
|
6900
|
+
connect_tool: stringValue2(packet.connect_tool ?? packet.connectTool),
|
|
6901
|
+
connectTool: stringValue2(packet.connect_tool ?? packet.connectTool),
|
|
6902
|
+
discover_tool: stringValue2(packet.discover_tool ?? packet.discoverTool),
|
|
6903
|
+
discoverTool: stringValue2(packet.discover_tool ?? packet.discoverTool),
|
|
6904
|
+
dry_run_tool: stringValue2(packet.dry_run_tool ?? packet.dryRunTool),
|
|
6905
|
+
dryRunTool: stringValue2(packet.dry_run_tool ?? packet.dryRunTool),
|
|
6906
|
+
execute_tool: stringValue2(packet.execute_tool ?? packet.executeTool),
|
|
6907
|
+
executeTool: stringValue2(packet.execute_tool ?? packet.executeTool),
|
|
6908
|
+
execute_and_wait_tool: stringValue2(packet.execute_and_wait_tool ?? packet.executeAndWaitTool),
|
|
6909
|
+
executeAndWaitTool: stringValue2(packet.execute_and_wait_tool ?? packet.executeAndWaitTool),
|
|
6910
|
+
schedule_tool: stringValue2(packet.schedule_tool ?? packet.scheduleTool),
|
|
6911
|
+
scheduleTool: stringValue2(packet.schedule_tool ?? packet.scheduleTool),
|
|
6912
|
+
schedule_and_wait_tool: stringValue2(packet.schedule_and_wait_tool ?? packet.scheduleAndWaitTool),
|
|
6913
|
+
scheduleAndWaitTool: stringValue2(packet.schedule_and_wait_tool ?? packet.scheduleAndWaitTool),
|
|
6914
|
+
result_tool: stringValue2(packet.result_tool ?? packet.resultTool),
|
|
6915
|
+
resultTool: stringValue2(packet.result_tool ?? packet.resultTool),
|
|
6916
|
+
write_gate: stringValue2(packet.write_gate ?? packet.writeGate),
|
|
6917
|
+
writeGate: stringValue2(packet.write_gate ?? packet.writeGate),
|
|
6918
|
+
required_fields: requiredFields,
|
|
6919
|
+
requiredFields,
|
|
6920
|
+
placeholders: asRecord2(packet.placeholders),
|
|
6921
|
+
dry_run_arguments: asRecord2(packet.dry_run_arguments ?? packet.dryRunArguments),
|
|
6922
|
+
dryRunArguments: asRecord2(packet.dry_run_arguments ?? packet.dryRunArguments),
|
|
6923
|
+
execute_arguments: asRecord2(packet.execute_arguments ?? packet.executeArguments),
|
|
6924
|
+
executeArguments: asRecord2(packet.execute_arguments ?? packet.executeArguments),
|
|
6925
|
+
execute_and_wait_arguments: asRecord2(packet.execute_and_wait_arguments ?? packet.executeAndWaitArguments),
|
|
6926
|
+
executeAndWaitArguments: asRecord2(packet.execute_and_wait_arguments ?? packet.executeAndWaitArguments),
|
|
6927
|
+
schedule_arguments: asRecord2(packet.schedule_arguments ?? packet.scheduleArguments),
|
|
6928
|
+
scheduleArguments: asRecord2(packet.schedule_arguments ?? packet.scheduleArguments),
|
|
6929
|
+
schedule_and_wait_arguments: asRecord2(packet.schedule_and_wait_arguments ?? packet.scheduleAndWaitArguments),
|
|
6930
|
+
scheduleAndWaitArguments: asRecord2(packet.schedule_and_wait_arguments ?? packet.scheduleAndWaitArguments),
|
|
6931
|
+
result_arguments: asRecord2(packet.result_arguments ?? packet.resultArguments),
|
|
6932
|
+
resultArguments: asRecord2(packet.result_arguments ?? packet.resultArguments)
|
|
6933
|
+
};
|
|
6934
|
+
}
|
|
6935
|
+
function normalizeOpsAutopilotResultPacket(rawPacket) {
|
|
6936
|
+
const packet = asRecord2(rawPacket);
|
|
6937
|
+
const resultShape = Array.isArray(packet.result_shape) ? packet.result_shape.map(String) : Array.isArray(packet.resultShape) ? packet.resultShape.map(String) : [];
|
|
6938
|
+
const deliveryReceipts = Array.isArray(packet.delivery_receipts) ? packet.delivery_receipts.map(String) : Array.isArray(packet.deliveryReceipts) ? packet.deliveryReceipts.map(String) : [];
|
|
6939
|
+
return {
|
|
6940
|
+
...packet,
|
|
6941
|
+
retrieve_tool: stringValue2(packet.retrieve_tool ?? packet.retrieveTool),
|
|
6942
|
+
retrieveTool: stringValue2(packet.retrieve_tool ?? packet.retrieveTool),
|
|
6943
|
+
result_shape: resultShape,
|
|
6944
|
+
resultShape,
|
|
6945
|
+
delivery_receipts: deliveryReceipts,
|
|
6946
|
+
deliveryReceipts,
|
|
6947
|
+
empty_result_recovery: stringValue2(packet.empty_result_recovery ?? packet.emptyResultRecovery),
|
|
6948
|
+
emptyResultRecovery: stringValue2(packet.empty_result_recovery ?? packet.emptyResultRecovery)
|
|
6949
|
+
};
|
|
6950
|
+
}
|
|
6951
|
+
function normalizeOpsAutopilotOperatingPacket(rawPacket) {
|
|
6952
|
+
if (!rawPacket || typeof rawPacket !== "object" || Array.isArray(rawPacket)) return void 0;
|
|
6953
|
+
const packet = asRecord2(rawPacket);
|
|
6954
|
+
const nangoRoute = normalizeOpsAutopilotNangoRoutePacket(packet.nango_route ?? packet.nangoRoute);
|
|
6955
|
+
const approvalBoundaries = Array.isArray(packet.approval_boundaries) ? packet.approval_boundaries.map(String) : Array.isArray(packet.approvalBoundaries) ? packet.approvalBoundaries.map(String) : [];
|
|
6956
|
+
return {
|
|
6957
|
+
...packet,
|
|
6958
|
+
north_star: stringValue2(packet.north_star ?? packet.northStar),
|
|
6959
|
+
northStar: stringValue2(packet.north_star ?? packet.northStar),
|
|
6960
|
+
schedule: normalizeOpsAutopilotSchedulePacket(packet.schedule),
|
|
6961
|
+
...nangoRoute ? { nango_route: nangoRoute, nangoRoute } : {},
|
|
6962
|
+
result_contract: normalizeOpsAutopilotResultPacket(packet.result_contract ?? packet.resultContract),
|
|
6963
|
+
resultContract: normalizeOpsAutopilotResultPacket(packet.result_contract ?? packet.resultContract),
|
|
6964
|
+
approval_boundaries: approvalBoundaries,
|
|
6965
|
+
approvalBoundaries,
|
|
6966
|
+
saved_command_hint: stringValue2(packet.saved_command_hint ?? packet.savedCommandHint),
|
|
6967
|
+
savedCommandHint: stringValue2(packet.saved_command_hint ?? packet.savedCommandHint)
|
|
6968
|
+
};
|
|
6969
|
+
}
|
|
5308
6970
|
function normalizeOpsAutopilotMotion(rawMotion) {
|
|
5309
6971
|
const motion = asRecord2(rawMotion);
|
|
5310
6972
|
const targetCount = numberValue(motion.target_count ?? motion.targetCount);
|
|
5311
6973
|
const estimatedCredits = numberValue(motion.estimated_credits ?? motion.estimatedCredits);
|
|
5312
6974
|
const mcpSequence = Array.isArray(motion.mcp_sequence) ? motion.mcp_sequence : Array.isArray(motion.mcpSequence) ? motion.mcpSequence : [];
|
|
6975
|
+
const operatingPacket = normalizeOpsAutopilotOperatingPacket(motion.operating_packet ?? motion.operatingPacket);
|
|
5313
6976
|
return {
|
|
5314
6977
|
...motion,
|
|
5315
6978
|
id: stringValue2(motion.id),
|
|
@@ -5332,12 +6995,16 @@ function normalizeOpsAutopilotMotion(rawMotion) {
|
|
|
5332
6995
|
cli_command: optionalString(motion.cli_command ?? motion.cliCommand),
|
|
5333
6996
|
cliCommand: optionalString(motion.cli_command ?? motion.cliCommand),
|
|
5334
6997
|
mcp_sequence: mcpSequence,
|
|
5335
|
-
mcpSequence
|
|
6998
|
+
mcpSequence,
|
|
6999
|
+
...operatingPacket ? { operating_packet: operatingPacket, operatingPacket } : {}
|
|
5336
7000
|
};
|
|
5337
7001
|
}
|
|
5338
7002
|
function normalizeOpsAutopilotResult(result) {
|
|
5339
7003
|
const primary = normalizeOpsAutopilotMotion(result.primary_motion ?? result.primaryMotion);
|
|
5340
7004
|
const motions = Array.isArray(result.motions) ? result.motions.map(normalizeOpsAutopilotMotion) : [];
|
|
7005
|
+
const operatingPacket = normalizeOpsAutopilotOperatingPacket(
|
|
7006
|
+
result.operating_packet ?? result.operatingPacket ?? primary.operating_packet ?? primary.operatingPacket
|
|
7007
|
+
);
|
|
5341
7008
|
const queryErrors = Array.isArray(result.query_errors) ? result.query_errors.map(String) : Array.isArray(result.queryErrors) ? result.queryErrors.map(String) : [];
|
|
5342
7009
|
return {
|
|
5343
7010
|
...result,
|
|
@@ -5353,6 +7020,7 @@ function normalizeOpsAutopilotResult(result) {
|
|
|
5353
7020
|
scaleRule: optionalString(result.scale_rule ?? result.scaleRule),
|
|
5354
7021
|
agent_handoff: optionalString(result.agent_handoff ?? result.agentHandoff),
|
|
5355
7022
|
agentHandoff: optionalString(result.agent_handoff ?? result.agentHandoff),
|
|
7023
|
+
...operatingPacket ? { operating_packet: operatingPacket, operatingPacket } : {},
|
|
5356
7024
|
proof_state: optionalString(result.proof_state ?? result.proofState),
|
|
5357
7025
|
proofState: optionalString(result.proof_state ?? result.proofState),
|
|
5358
7026
|
proof_summary: result.proof_summary ?? result.proofSummary,
|
|
@@ -5617,11 +7285,125 @@ function normalizeOpsRoutineTickItemsResult(result) {
|
|
|
5617
7285
|
hasMore
|
|
5618
7286
|
};
|
|
5619
7287
|
}
|
|
7288
|
+
function buildOpsNangoScheduleBody(input) {
|
|
7289
|
+
const {
|
|
7290
|
+
workspaceConnectionId,
|
|
7291
|
+
workspace_connection_id,
|
|
7292
|
+
connectionId,
|
|
7293
|
+
connection_id,
|
|
7294
|
+
providerConfigKey,
|
|
7295
|
+
provider_config_key,
|
|
7296
|
+
integrationId,
|
|
7297
|
+
integration_id,
|
|
7298
|
+
nangoConnectionId,
|
|
7299
|
+
nango_connection_id,
|
|
7300
|
+
actionName,
|
|
7301
|
+
action_name,
|
|
7302
|
+
toolName,
|
|
7303
|
+
tool_name,
|
|
7304
|
+
proxyPath,
|
|
7305
|
+
proxy_path,
|
|
7306
|
+
nangoProxyPath,
|
|
7307
|
+
nango_proxy_path,
|
|
7308
|
+
method,
|
|
7309
|
+
httpMethod,
|
|
7310
|
+
http_method,
|
|
7311
|
+
input: nangoInput,
|
|
7312
|
+
arguments: nangoArguments,
|
|
7313
|
+
fieldMap,
|
|
7314
|
+
field_map,
|
|
7315
|
+
requiredFields,
|
|
7316
|
+
required_fields,
|
|
7317
|
+
writeConfirmed,
|
|
7318
|
+
write_confirmed,
|
|
7319
|
+
agentWriteConfirmed,
|
|
7320
|
+
agent_write_confirmed,
|
|
7321
|
+
config,
|
|
7322
|
+
destinations: _destinations,
|
|
7323
|
+
...schedule
|
|
7324
|
+
} = input;
|
|
7325
|
+
return {
|
|
7326
|
+
...buildOpsCreateBody({
|
|
7327
|
+
...schedule,
|
|
7328
|
+
cadence: schedule.cadence ?? "daily"
|
|
7329
|
+
}),
|
|
7330
|
+
workspace_connection_id: workspace_connection_id ?? workspaceConnectionId,
|
|
7331
|
+
connection_id: connection_id ?? connectionId,
|
|
7332
|
+
provider_config_key: provider_config_key ?? providerConfigKey,
|
|
7333
|
+
integration_id: integration_id ?? integrationId,
|
|
7334
|
+
nango_connection_id: nango_connection_id ?? nangoConnectionId,
|
|
7335
|
+
action_name: action_name ?? actionName,
|
|
7336
|
+
tool_name: tool_name ?? toolName,
|
|
7337
|
+
proxy_path: proxy_path ?? proxyPath ?? nango_proxy_path ?? nangoProxyPath,
|
|
7338
|
+
nango_proxy_path: nango_proxy_path ?? nangoProxyPath,
|
|
7339
|
+
method: method ?? http_method ?? httpMethod,
|
|
7340
|
+
input: nangoInput ?? nangoArguments,
|
|
7341
|
+
field_map: field_map ?? fieldMap,
|
|
7342
|
+
required_fields: required_fields ?? requiredFields,
|
|
7343
|
+
write_confirmed: write_confirmed ?? writeConfirmed,
|
|
7344
|
+
agent_write_confirmed: agent_write_confirmed ?? agentWriteConfirmed,
|
|
7345
|
+
config
|
|
7346
|
+
};
|
|
7347
|
+
}
|
|
7348
|
+
function buildOpsNangoScheduleAndWaitOptions(params) {
|
|
7349
|
+
const {
|
|
7350
|
+
force,
|
|
7351
|
+
instruction,
|
|
7352
|
+
nextCursor,
|
|
7353
|
+
includeFailedRuns,
|
|
7354
|
+
intervalMs,
|
|
7355
|
+
maxPolls,
|
|
7356
|
+
timeoutMs,
|
|
7357
|
+
includeResults,
|
|
7358
|
+
cursor,
|
|
7359
|
+
state,
|
|
7360
|
+
limit,
|
|
7361
|
+
include_failed_runs,
|
|
7362
|
+
interval_ms,
|
|
7363
|
+
max_polls,
|
|
7364
|
+
timeout_ms,
|
|
7365
|
+
include_results,
|
|
7366
|
+
...schedule
|
|
7367
|
+
} = params;
|
|
7368
|
+
return {
|
|
7369
|
+
schedule: {
|
|
7370
|
+
...schedule,
|
|
7371
|
+
cadence: schedule.cadence ?? "daily"
|
|
7372
|
+
},
|
|
7373
|
+
run: {
|
|
7374
|
+
force,
|
|
7375
|
+
instruction
|
|
7376
|
+
},
|
|
7377
|
+
wait: {
|
|
7378
|
+
cursor: cursor ?? nextCursor,
|
|
7379
|
+
state,
|
|
7380
|
+
limit,
|
|
7381
|
+
include_failed_runs: include_failed_runs ?? includeFailedRuns,
|
|
7382
|
+
interval_ms: interval_ms ?? intervalMs,
|
|
7383
|
+
max_polls: max_polls ?? maxPolls,
|
|
7384
|
+
timeout_ms: timeout_ms ?? timeoutMs,
|
|
7385
|
+
include_results: include_results ?? includeResults
|
|
7386
|
+
}
|
|
7387
|
+
};
|
|
7388
|
+
}
|
|
7389
|
+
function buildOpsNangoScheduleAndWaitBody(options) {
|
|
7390
|
+
const waitBody = buildOpsWaitBody(options.wait);
|
|
7391
|
+
const { op_id: _opId, ...waitWithoutOp } = waitBody;
|
|
7392
|
+
return {
|
|
7393
|
+
...buildOpsNangoScheduleBody(options.schedule),
|
|
7394
|
+
...waitWithoutOp,
|
|
7395
|
+
instruction: options.run.instruction,
|
|
7396
|
+
force: options.run.force
|
|
7397
|
+
};
|
|
7398
|
+
}
|
|
5620
7399
|
function buildOpsPlanBody(params) {
|
|
5621
|
-
const { targetCount, companyDomains, customAiPrompt, signalPrompt, outputPrompt, ...rest } = params;
|
|
7400
|
+
const { targetCount, wakeOnEvents, companyDomains, customAiPrompt, signalPrompt, outputPrompt, ...rest } = params;
|
|
7401
|
+
const destinations = Array.isArray(rest.destinations) ? rest.destinations.map(normalizeOpsDestinationRequest) : rest.destinations;
|
|
5622
7402
|
return {
|
|
5623
7403
|
...rest,
|
|
7404
|
+
destinations,
|
|
5624
7405
|
target_count: rest.target_count ?? targetCount,
|
|
7406
|
+
wake_on_events: rest.wake_on_events ?? wakeOnEvents,
|
|
5625
7407
|
company_domains: rest.company_domains ?? companyDomains,
|
|
5626
7408
|
custom_ai_prompt: rest.custom_ai_prompt ?? customAiPrompt,
|
|
5627
7409
|
signal_prompt: rest.signal_prompt ?? signalPrompt,
|
|
@@ -5644,6 +7426,95 @@ function buildOpsExecuteBody(params) {
|
|
|
5644
7426
|
output_format: rest.output_format ?? outputFormat
|
|
5645
7427
|
};
|
|
5646
7428
|
}
|
|
7429
|
+
function buildOpsExecuteAndWaitOptions(params) {
|
|
7430
|
+
const {
|
|
7431
|
+
nextCursor,
|
|
7432
|
+
includeFailedRuns,
|
|
7433
|
+
intervalMs,
|
|
7434
|
+
maxPolls,
|
|
7435
|
+
timeoutMs,
|
|
7436
|
+
includeResults,
|
|
7437
|
+
cursor,
|
|
7438
|
+
state,
|
|
7439
|
+
limit,
|
|
7440
|
+
include_failed_runs,
|
|
7441
|
+
interval_ms,
|
|
7442
|
+
max_polls,
|
|
7443
|
+
timeout_ms,
|
|
7444
|
+
include_results,
|
|
7445
|
+
...execute
|
|
7446
|
+
} = params;
|
|
7447
|
+
return {
|
|
7448
|
+
execute: {
|
|
7449
|
+
...execute,
|
|
7450
|
+
auto_run: execute.auto_run ?? execute.autoRun ?? true
|
|
7451
|
+
},
|
|
7452
|
+
wait: {
|
|
7453
|
+
cursor: cursor ?? nextCursor,
|
|
7454
|
+
state,
|
|
7455
|
+
limit,
|
|
7456
|
+
include_failed_runs: include_failed_runs ?? includeFailedRuns,
|
|
7457
|
+
interval_ms: interval_ms ?? intervalMs,
|
|
7458
|
+
max_polls: max_polls ?? maxPolls,
|
|
7459
|
+
timeout_ms: timeout_ms ?? timeoutMs,
|
|
7460
|
+
include_results: include_results ?? includeResults
|
|
7461
|
+
}
|
|
7462
|
+
};
|
|
7463
|
+
}
|
|
7464
|
+
function buildOpsScheduleAndWaitOptions(params) {
|
|
7465
|
+
const {
|
|
7466
|
+
force,
|
|
7467
|
+
instruction,
|
|
7468
|
+
nextCursor,
|
|
7469
|
+
includeFailedRuns,
|
|
7470
|
+
intervalMs,
|
|
7471
|
+
maxPolls,
|
|
7472
|
+
timeoutMs,
|
|
7473
|
+
includeResults,
|
|
7474
|
+
cursor,
|
|
7475
|
+
state,
|
|
7476
|
+
limit,
|
|
7477
|
+
include_failed_runs,
|
|
7478
|
+
interval_ms,
|
|
7479
|
+
max_polls,
|
|
7480
|
+
timeout_ms,
|
|
7481
|
+
include_results,
|
|
7482
|
+
...schedule
|
|
7483
|
+
} = params;
|
|
7484
|
+
return {
|
|
7485
|
+
schedule: {
|
|
7486
|
+
...schedule,
|
|
7487
|
+
cadence: schedule.cadence ?? "daily"
|
|
7488
|
+
},
|
|
7489
|
+
run: {
|
|
7490
|
+
force,
|
|
7491
|
+
instruction
|
|
7492
|
+
},
|
|
7493
|
+
wait: {
|
|
7494
|
+
cursor: cursor ?? nextCursor,
|
|
7495
|
+
state,
|
|
7496
|
+
limit,
|
|
7497
|
+
include_failed_runs: include_failed_runs ?? includeFailedRuns,
|
|
7498
|
+
interval_ms: interval_ms ?? intervalMs,
|
|
7499
|
+
max_polls: max_polls ?? maxPolls,
|
|
7500
|
+
timeout_ms: timeout_ms ?? timeoutMs,
|
|
7501
|
+
include_results: include_results ?? includeResults
|
|
7502
|
+
}
|
|
7503
|
+
};
|
|
7504
|
+
}
|
|
7505
|
+
function buildOpsScheduleAndWaitBody(options) {
|
|
7506
|
+
const waitBody = buildOpsWaitBody(options.wait);
|
|
7507
|
+
const { op_id: _opId, ...waitWithoutOp } = waitBody;
|
|
7508
|
+
return {
|
|
7509
|
+
...buildOpsCreateBody({
|
|
7510
|
+
...options.schedule,
|
|
7511
|
+
cadence: options.schedule.cadence ?? "daily"
|
|
7512
|
+
}),
|
|
7513
|
+
...waitWithoutOp,
|
|
7514
|
+
instruction: options.run.instruction,
|
|
7515
|
+
force: options.run.force
|
|
7516
|
+
};
|
|
7517
|
+
}
|
|
5647
7518
|
function buildOpsRunBody(params) {
|
|
5648
7519
|
const { opId, ...rest } = params;
|
|
5649
7520
|
return {
|
|
@@ -5651,6 +7522,28 @@ function buildOpsRunBody(params) {
|
|
|
5651
7522
|
op_id: rest.op_id ?? opId
|
|
5652
7523
|
};
|
|
5653
7524
|
}
|
|
7525
|
+
function buildOpsRunAndWaitOptions(params) {
|
|
7526
|
+
const {
|
|
7527
|
+
opId,
|
|
7528
|
+
nextCursor,
|
|
7529
|
+
includeFailedRuns,
|
|
7530
|
+
intervalMs,
|
|
7531
|
+
maxPolls,
|
|
7532
|
+
timeoutMs,
|
|
7533
|
+
includeResults,
|
|
7534
|
+
...rest
|
|
7535
|
+
} = params;
|
|
7536
|
+
return {
|
|
7537
|
+
...rest,
|
|
7538
|
+
op_id: rest.op_id ?? opId,
|
|
7539
|
+
cursor: rest.cursor ?? nextCursor,
|
|
7540
|
+
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns,
|
|
7541
|
+
interval_ms: rest.interval_ms ?? intervalMs,
|
|
7542
|
+
max_polls: rest.max_polls ?? maxPolls,
|
|
7543
|
+
timeout_ms: rest.timeout_ms ?? timeoutMs,
|
|
7544
|
+
include_results: rest.include_results ?? includeResults
|
|
7545
|
+
};
|
|
7546
|
+
}
|
|
5654
7547
|
function buildOpsStatusBody(params) {
|
|
5655
7548
|
const { opId, ...rest } = params;
|
|
5656
7549
|
return {
|
|
@@ -5667,6 +7560,50 @@ function buildOpsResultsBody(params) {
|
|
|
5667
7560
|
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns
|
|
5668
7561
|
};
|
|
5669
7562
|
}
|
|
7563
|
+
function buildOpsWaitForResultsOptions(params) {
|
|
7564
|
+
const {
|
|
7565
|
+
opId,
|
|
7566
|
+
nextCursor,
|
|
7567
|
+
includeFailedRuns,
|
|
7568
|
+
intervalMs,
|
|
7569
|
+
maxPolls,
|
|
7570
|
+
timeoutMs,
|
|
7571
|
+
includeResults,
|
|
7572
|
+
...rest
|
|
7573
|
+
} = params;
|
|
7574
|
+
return {
|
|
7575
|
+
...rest,
|
|
7576
|
+
op_id: rest.op_id ?? opId,
|
|
7577
|
+
cursor: rest.cursor ?? nextCursor,
|
|
7578
|
+
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns,
|
|
7579
|
+
interval_ms: rest.interval_ms ?? intervalMs,
|
|
7580
|
+
max_polls: rest.max_polls ?? maxPolls,
|
|
7581
|
+
timeout_ms: rest.timeout_ms ?? timeoutMs,
|
|
7582
|
+
include_results: rest.include_results ?? includeResults
|
|
7583
|
+
};
|
|
7584
|
+
}
|
|
7585
|
+
function buildOpsWaitBody(params) {
|
|
7586
|
+
const {
|
|
7587
|
+
opId,
|
|
7588
|
+
nextCursor,
|
|
7589
|
+
includeFailedRuns,
|
|
7590
|
+
intervalMs,
|
|
7591
|
+
maxPolls,
|
|
7592
|
+
timeoutMs,
|
|
7593
|
+
includeResults,
|
|
7594
|
+
...rest
|
|
7595
|
+
} = params;
|
|
7596
|
+
return {
|
|
7597
|
+
...rest,
|
|
7598
|
+
op_id: rest.op_id ?? opId,
|
|
7599
|
+
cursor: rest.cursor ?? nextCursor,
|
|
7600
|
+
include_failed_runs: rest.include_failed_runs ?? includeFailedRuns,
|
|
7601
|
+
interval_ms: rest.interval_ms ?? intervalMs,
|
|
7602
|
+
max_polls: rest.max_polls ?? maxPolls,
|
|
7603
|
+
timeout_ms: rest.timeout_ms ?? timeoutMs,
|
|
7604
|
+
include_results: rest.include_results ?? includeResults
|
|
7605
|
+
};
|
|
7606
|
+
}
|
|
5670
7607
|
function buildOpsDebugOptions(params) {
|
|
5671
7608
|
const {
|
|
5672
7609
|
opId,
|
|
@@ -5744,6 +7681,8 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5744
7681
|
nangoAction,
|
|
5745
7682
|
proxyPath,
|
|
5746
7683
|
nangoProxyPath,
|
|
7684
|
+
method,
|
|
7685
|
+
httpMethod,
|
|
5747
7686
|
fieldMap,
|
|
5748
7687
|
requiredFields,
|
|
5749
7688
|
writeConfirmed,
|
|
@@ -5762,6 +7701,7 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5762
7701
|
const nango_action = rest.nango_action ?? nangoAction;
|
|
5763
7702
|
const proxy_path = rest.proxy_path ?? proxyPath;
|
|
5764
7703
|
const nango_proxy_path = rest.nango_proxy_path ?? nangoProxyPath;
|
|
7704
|
+
const http_method = rest.http_method ?? httpMethod;
|
|
5765
7705
|
const field_map = rest.field_map ?? fieldMap;
|
|
5766
7706
|
const required_fields = rest.required_fields ?? requiredFields;
|
|
5767
7707
|
const write_confirmed = rest.write_confirmed ?? writeConfirmed;
|
|
@@ -5776,6 +7716,9 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5776
7716
|
if (nango_action !== void 0 && normalizedConfig.nango_action === void 0) normalizedConfig.nango_action = nango_action;
|
|
5777
7717
|
if (proxy_path !== void 0 && normalizedConfig.proxy_path === void 0) normalizedConfig.proxy_path = proxy_path;
|
|
5778
7718
|
if (nango_proxy_path !== void 0 && normalizedConfig.nango_proxy_path === void 0) normalizedConfig.nango_proxy_path = nango_proxy_path;
|
|
7719
|
+
if (method !== void 0 && normalizedConfig.method === void 0) normalizedConfig.method = method;
|
|
7720
|
+
if (http_method !== void 0 && normalizedConfig.http_method === void 0) normalizedConfig.http_method = http_method;
|
|
7721
|
+
if (normalizedConfig.method === void 0 && http_method !== void 0) normalizedConfig.method = http_method;
|
|
5779
7722
|
if (field_map !== void 0 && normalizedConfig.field_map === void 0) normalizedConfig.field_map = field_map;
|
|
5780
7723
|
if (required_fields !== void 0 && normalizedConfig.required_fields === void 0) normalizedConfig.required_fields = required_fields;
|
|
5781
7724
|
if (write_confirmed !== void 0 && normalizedConfig.write_confirmed === void 0) normalizedConfig.write_confirmed = write_confirmed;
|
|
@@ -5795,6 +7738,8 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5795
7738
|
nango_action,
|
|
5796
7739
|
proxy_path,
|
|
5797
7740
|
nango_proxy_path,
|
|
7741
|
+
method,
|
|
7742
|
+
http_method,
|
|
5798
7743
|
field_map,
|
|
5799
7744
|
required_fields,
|
|
5800
7745
|
write_confirmed,
|
|
@@ -5802,6 +7747,10 @@ function normalizeOpsSinkRequest(sink) {
|
|
|
5802
7747
|
config: normalizedConfig
|
|
5803
7748
|
};
|
|
5804
7749
|
}
|
|
7750
|
+
function normalizeOpsDestinationRequest(destination) {
|
|
7751
|
+
if (!destination || typeof destination !== "object" || Array.isArray(destination)) return destination;
|
|
7752
|
+
return normalizeOpsSinkRequest(destination);
|
|
7753
|
+
}
|
|
5805
7754
|
function normalizeOpsSinkConfigRequest(config) {
|
|
5806
7755
|
const out = { ...config ?? {} };
|
|
5807
7756
|
if (out.connection_id === void 0 && out.connectionId !== void 0) out.connection_id = out.connectionId;
|
|
@@ -5815,6 +7764,8 @@ function normalizeOpsSinkConfigRequest(config) {
|
|
|
5815
7764
|
if (out.nango_action === void 0 && out.nangoAction !== void 0) out.nango_action = out.nangoAction;
|
|
5816
7765
|
if (out.proxy_path === void 0 && out.proxyPath !== void 0) out.proxy_path = out.proxyPath;
|
|
5817
7766
|
if (out.nango_proxy_path === void 0 && out.nangoProxyPath !== void 0) out.nango_proxy_path = out.nangoProxyPath;
|
|
7767
|
+
if (out.http_method === void 0 && out.httpMethod !== void 0) out.http_method = out.httpMethod;
|
|
7768
|
+
if (out.method === void 0 && out.http_method !== void 0) out.method = out.http_method;
|
|
5818
7769
|
if (out.field_map === void 0 && out.fieldMap !== void 0) out.field_map = out.fieldMap;
|
|
5819
7770
|
if (out.required_fields === void 0 && out.requiredFields !== void 0) out.required_fields = out.requiredFields;
|
|
5820
7771
|
if (out.write_confirmed === void 0 && out.writeConfirmed !== void 0) out.write_confirmed = out.writeConfirmed;
|
|
@@ -5888,7 +7839,6 @@ function toSnakeConfig(params) {
|
|
|
5888
7839
|
return {
|
|
5889
7840
|
system_prompt: params.systemPrompt || params.system_prompt || "You are a senior business research analyst. Use multi-model evidence carefully and return concise structured enrichment.",
|
|
5890
7841
|
user_template: params.userTemplate || params.user_template || params.prompt,
|
|
5891
|
-
model: params.model,
|
|
5892
7842
|
temperature: params.temperature,
|
|
5893
7843
|
max_concurrency: params.maxConcurrency || params.max_concurrency,
|
|
5894
7844
|
max_tokens: params.maxTokens || params.max_tokens,
|
|
@@ -5912,13 +7862,10 @@ var Ai = class {
|
|
|
5912
7862
|
/**
|
|
5913
7863
|
* Run Custom AI Enrichment - Multi Model.
|
|
5914
7864
|
*
|
|
5915
|
-
* Uses
|
|
5916
|
-
*
|
|
7865
|
+
* Uses the hosted default model with bounded synthesis, then returns the
|
|
7866
|
+
* requested structured output fields.
|
|
5917
7867
|
*/
|
|
5918
7868
|
async multiModel(params) {
|
|
5919
|
-
if (!params.model) {
|
|
5920
|
-
throw new Error('model is required. Use an OpenRouter id such as "anthropic/claude-sonnet-4" or "google/gemini-2.5-flash".');
|
|
5921
|
-
}
|
|
5922
7869
|
if (!params.prompt && !params.userTemplate && !params.user_template) {
|
|
5923
7870
|
throw new Error("prompt or userTemplate is required.");
|
|
5924
7871
|
}
|
|
@@ -6135,6 +8082,10 @@ var GtmKernel = class {
|
|
|
6135
8082
|
days: options.days,
|
|
6136
8083
|
network_days: options.networkDays,
|
|
6137
8084
|
min_sample_size: options.minSampleSize,
|
|
8085
|
+
holdout_min_sample_size: options.holdoutMinSampleSize,
|
|
8086
|
+
predictive_min_labeled_outcomes: options.predictiveMinLabeledOutcomes,
|
|
8087
|
+
predictive_min_positive_outcomes: options.predictiveMinPositiveOutcomes,
|
|
8088
|
+
predictive_min_memory_sample_size: options.predictiveMinMemorySampleSize,
|
|
6138
8089
|
min_workspace_count: options.minWorkspaceCount,
|
|
6139
8090
|
min_privacy_k: options.minPrivacyK,
|
|
6140
8091
|
include_memory: options.includeMemory,
|
|
@@ -6201,9 +8152,11 @@ var GtmKernel = class {
|
|
|
6201
8152
|
write_routine_outcomes: input.writeRoutineOutcomes
|
|
6202
8153
|
});
|
|
6203
8154
|
}
|
|
6204
|
-
/** Start a background Instantly webhook-events pull and route results into the GTM feedback loop. */
|
|
8155
|
+
/** Start a background Instantly webhook-events or email-history pull and route results into the GTM feedback loop. */
|
|
6205
8156
|
async pullInstantlyFeedback(input) {
|
|
6206
8157
|
return this.callMcp("gtm_instantly_feedback_pull", {
|
|
8158
|
+
source: input.source,
|
|
8159
|
+
instantly_profile: input.instantlyProfile,
|
|
6207
8160
|
campaign_id: input.campaignId,
|
|
6208
8161
|
campaign_build_id: input.campaignBuildId,
|
|
6209
8162
|
provider_link_id: input.providerLinkId,
|
|
@@ -6215,6 +8168,9 @@ var GtmKernel = class {
|
|
|
6215
8168
|
to: input.to,
|
|
6216
8169
|
limit: input.limit,
|
|
6217
8170
|
max_pages: input.maxPages,
|
|
8171
|
+
email_type: input.emailType,
|
|
8172
|
+
mode: input.mode,
|
|
8173
|
+
sort_order: input.sortOrder,
|
|
6218
8174
|
create_memory: input.createMemory,
|
|
6219
8175
|
write_routine_outcomes: input.writeRoutineOutcomes,
|
|
6220
8176
|
dry_run: input.dryRun,
|
|
@@ -6285,6 +8241,16 @@ var GtmKernel = class {
|
|
|
6285
8241
|
min_privacy_k: input.minPrivacyK
|
|
6286
8242
|
});
|
|
6287
8243
|
}
|
|
8244
|
+
/** Queue a dry-run-first bridge from imported historical feedback to attribution-only Campaign Build surrogates. */
|
|
8245
|
+
async runHistoricalCampaignBuildBridge(input = {}) {
|
|
8246
|
+
return this.callMcp("gtm_historical_campaign_build_bridge_run", {
|
|
8247
|
+
dry_run: input.dryRun,
|
|
8248
|
+
write_approved: input.writeApproved,
|
|
8249
|
+
max_events: input.maxEvents,
|
|
8250
|
+
max_campaigns: input.maxCampaigns,
|
|
8251
|
+
min_feedback_events: input.minFeedbackEvents
|
|
8252
|
+
});
|
|
8253
|
+
}
|
|
6288
8254
|
/** Prepare a provider-agnostic feedback webhook URL for Smartlead, HeyReach, Airbyte, or custom sender events. */
|
|
6289
8255
|
async prepareFeedbackWebhook(input) {
|
|
6290
8256
|
return this.callMcp("gtm_feedback_webhook_prepare", {
|
|
@@ -6344,6 +8310,7 @@ var GtmKernel = class {
|
|
|
6344
8310
|
days: input.days,
|
|
6345
8311
|
network_days: input.networkDays,
|
|
6346
8312
|
min_sample_size: input.minSampleSize,
|
|
8313
|
+
holdout_min_sample_size: input.holdoutMinSampleSize,
|
|
6347
8314
|
min_workspace_count: input.minWorkspaceCount,
|
|
6348
8315
|
min_privacy_k: input.minPrivacyK,
|
|
6349
8316
|
include_memory: input.includeMemory,
|
|
@@ -6364,6 +8331,7 @@ var GtmKernel = class {
|
|
|
6364
8331
|
days: input.days,
|
|
6365
8332
|
network_days: input.networkDays,
|
|
6366
8333
|
min_sample_size: input.minSampleSize,
|
|
8334
|
+
holdout_min_sample_size: input.holdoutMinSampleSize,
|
|
6367
8335
|
min_workspace_count: input.minWorkspaceCount,
|
|
6368
8336
|
min_privacy_k: input.minPrivacyK,
|
|
6369
8337
|
include_memory: input.includeMemory,
|
|
@@ -6488,6 +8456,29 @@ var GtmKernel = class {
|
|
|
6488
8456
|
include_details: options.includeDetails
|
|
6489
8457
|
});
|
|
6490
8458
|
}
|
|
8459
|
+
/** Search the Agency Autopilot safe-action catalog for agency-style lead lists, Clay tables, and GTM motions. */
|
|
8460
|
+
async agencyAutopilotCapabilityCatalog(options = {}) {
|
|
8461
|
+
return this.callMcp("gtm_agency_autopilot_capability_catalog", {
|
|
8462
|
+
query: options.query,
|
|
8463
|
+
family: options.family,
|
|
8464
|
+
phase: options.phase,
|
|
8465
|
+
account_label: options.accountLabel,
|
|
8466
|
+
workspace_label: options.workspaceLabel,
|
|
8467
|
+
target_count: options.targetCount,
|
|
8468
|
+
limit: options.limit,
|
|
8469
|
+
include_agent_prompts: options.includeAgentPrompts
|
|
8470
|
+
});
|
|
8471
|
+
}
|
|
8472
|
+
/** Search agency operating playbooks Agency Autopilot can use for lead lists, Clay tables, GTM motions, and proof gates. */
|
|
8473
|
+
async agencyAutopilotPlaybookCatalog(options = {}) {
|
|
8474
|
+
return this.callMcp("gtm_agency_autopilot_playbook_catalog", {
|
|
8475
|
+
query: options.query,
|
|
8476
|
+
playbook_slug: options.playbookSlug,
|
|
8477
|
+
outcome_type: options.outcomeType,
|
|
8478
|
+
limit: options.limit,
|
|
8479
|
+
include_required_fields: options.includeRequiredFields
|
|
8480
|
+
});
|
|
8481
|
+
}
|
|
6491
8482
|
/** Build the read-only Memory, Brain, risk, and provider-route runbook needed before planning a campaign. */
|
|
6492
8483
|
async campaignStartContext(input = {}) {
|
|
6493
8484
|
return this.callMcp("gtm_campaign_start_context", {
|
|
@@ -6846,6 +8837,35 @@ var GtmKernel = class {
|
|
|
6846
8837
|
user_display_name: input.userDisplayName
|
|
6847
8838
|
});
|
|
6848
8839
|
}
|
|
8840
|
+
/** Prepare the full Nango provider search, connect, pull/export, Ops, and campaign-route flow. */
|
|
8841
|
+
async prepareNangoIntegrationFlow(input = {}) {
|
|
8842
|
+
return this.callMcp("nango_integration_flow_prepare", {
|
|
8843
|
+
query: input.query,
|
|
8844
|
+
search: input.search,
|
|
8845
|
+
provider_id: input.providerId,
|
|
8846
|
+
provider: input.provider,
|
|
8847
|
+
integration_id: input.integrationId,
|
|
8848
|
+
provider_config_key: input.providerConfigKey,
|
|
8849
|
+
workspace_connection_id: input.workspaceConnectionId,
|
|
8850
|
+
connection_id: input.connectionId,
|
|
8851
|
+
nango_connection_id: input.nangoConnectionId,
|
|
8852
|
+
intent: input.intent,
|
|
8853
|
+
action_name: input.actionName,
|
|
8854
|
+
tool_name: input.toolName,
|
|
8855
|
+
proxy_path: input.proxyPath,
|
|
8856
|
+
method: input.method,
|
|
8857
|
+
input: input.input,
|
|
8858
|
+
cadence: input.cadence,
|
|
8859
|
+
field_map: input.fieldMap,
|
|
8860
|
+
required_fields: input.requiredFields,
|
|
8861
|
+
confirm_spend: input.confirmSpend,
|
|
8862
|
+
write_confirmed: input.writeConfirmed,
|
|
8863
|
+
layer: input.layer,
|
|
8864
|
+
campaign_id: input.campaignId,
|
|
8865
|
+
limit: input.limit,
|
|
8866
|
+
include_provider_catalog: input.includeProviderCatalog
|
|
8867
|
+
});
|
|
8868
|
+
}
|
|
6849
8869
|
/** List Nango-backed action tools for a workspace connection without executing them. */
|
|
6850
8870
|
async listNangoTools(options = {}) {
|
|
6851
8871
|
return this.callMcp("nango_mcp_tools_list", {
|
|
@@ -6868,6 +8888,12 @@ var GtmKernel = class {
|
|
|
6868
8888
|
nango_connection_id: input.nangoConnectionId,
|
|
6869
8889
|
action_name: input.actionName,
|
|
6870
8890
|
tool_name: input.toolName,
|
|
8891
|
+
delivery_mode: input.deliveryMode,
|
|
8892
|
+
proxy_path: input.proxyPath,
|
|
8893
|
+
nango_proxy_path: input.nangoProxyPath,
|
|
8894
|
+
method: input.method,
|
|
8895
|
+
http_method: input.httpMethod,
|
|
8896
|
+
proxy_headers: input.proxyHeaders,
|
|
6871
8897
|
input: input.input,
|
|
6872
8898
|
async: input.async,
|
|
6873
8899
|
max_retries: input.maxRetries,
|
|
@@ -7017,6 +9043,7 @@ function compact2(value) {
|
|
|
7017
9043
|
}
|
|
7018
9044
|
|
|
7019
9045
|
// src/index.ts
|
|
9046
|
+
var MCP_TOOL_CACHE_TTL_MS = 3e4;
|
|
7020
9047
|
function inferMcpToolCategory(toolName) {
|
|
7021
9048
|
if (typeof toolName !== "string" || !toolName) return void 0;
|
|
7022
9049
|
if (toolName.startsWith("ops_") || toolName === "get_ops_readiness" || toolName === "get_gtm_ops_readiness" || toolName.startsWith("gtm_") || [
|
|
@@ -7148,6 +9175,21 @@ var Signaliz = class {
|
|
|
7148
9175
|
}
|
|
7149
9176
|
/** List all available MCP tools */
|
|
7150
9177
|
async listTools() {
|
|
9178
|
+
const now = Date.now();
|
|
9179
|
+
if (this.toolListCache && this.toolListCache.expiresAt > now) {
|
|
9180
|
+
return this.toolListCache.promise;
|
|
9181
|
+
}
|
|
9182
|
+
const promise = this.fetchTools().catch((error) => {
|
|
9183
|
+
if (this.toolListCache?.promise === promise) this.toolListCache = void 0;
|
|
9184
|
+
throw error;
|
|
9185
|
+
});
|
|
9186
|
+
this.toolListCache = {
|
|
9187
|
+
expiresAt: now + MCP_TOOL_CACHE_TTL_MS,
|
|
9188
|
+
promise
|
|
9189
|
+
};
|
|
9190
|
+
return promise;
|
|
9191
|
+
}
|
|
9192
|
+
async fetchTools() {
|
|
7151
9193
|
try {
|
|
7152
9194
|
const manifest = await this.client.mcp("tools/call", {
|
|
7153
9195
|
name: "get_tool_manifest",
|