@signaliz/cli 1.0.15 → 1.0.17
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 +47 -3
- package/dist/bin.js +1221 -72
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -9,18 +9,23 @@ var import_node_readline = require("readline");
|
|
|
9
9
|
var import_node_child_process = require("child_process");
|
|
10
10
|
var CONFIG_DIR = (0, import_node_path.join)((0, import_node_os.homedir)(), ".signaliz");
|
|
11
11
|
var CONFIG_FILE = (0, import_node_path.join)(CONFIG_DIR, "config.json");
|
|
12
|
-
|
|
12
|
+
var cachedConfig;
|
|
13
|
+
function loadConfig(options = {}) {
|
|
14
|
+
if (cachedConfig && !options.refresh) return cachedConfig;
|
|
13
15
|
try {
|
|
14
16
|
if ((0, import_node_fs.existsSync)(CONFIG_FILE)) {
|
|
15
|
-
|
|
17
|
+
cachedConfig = JSON.parse((0, import_node_fs.readFileSync)(CONFIG_FILE, "utf8"));
|
|
18
|
+
return cachedConfig;
|
|
16
19
|
}
|
|
17
20
|
} catch {
|
|
18
21
|
}
|
|
19
|
-
|
|
22
|
+
cachedConfig = {};
|
|
23
|
+
return cachedConfig;
|
|
20
24
|
}
|
|
21
25
|
function saveConfig(config) {
|
|
22
26
|
(0, import_node_fs.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
23
27
|
(0, import_node_fs.writeFileSync)(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 });
|
|
28
|
+
cachedConfig = config;
|
|
24
29
|
}
|
|
25
30
|
function arg(name) {
|
|
26
31
|
const found = process.argv.find((a) => a.startsWith(`--${name}=`));
|
|
@@ -98,6 +103,7 @@ function normalizeCampaignBuildInput(raw) {
|
|
|
98
103
|
const signals = nested("signals", "signals");
|
|
99
104
|
const copy = nested("copy", "copy");
|
|
100
105
|
const delivery = nested("delivery", "delivery");
|
|
106
|
+
const learningHoldout = nested("learning_holdout", "learningHoldout");
|
|
101
107
|
return {
|
|
102
108
|
name: get("name", "name"),
|
|
103
109
|
prompt: get("prompt", "prompt"),
|
|
@@ -110,6 +116,14 @@ function normalizeCampaignBuildInput(raw) {
|
|
|
110
116
|
dedupKeys: get("dedup_keys", "dedupKeys"),
|
|
111
117
|
brainPreflight: get("brain_preflight", "brainPreflight"),
|
|
112
118
|
brainDefaults: get("brain_defaults", "brainDefaults"),
|
|
119
|
+
learningHoldout: learningHoldout ? {
|
|
120
|
+
...learningHoldout,
|
|
121
|
+
controlPercentage: learningHoldout.control_percentage ?? learningHoldout.controlPercentage,
|
|
122
|
+
minControlSize: learningHoldout.min_control_size ?? learningHoldout.minControlSize,
|
|
123
|
+
experimentKey: learningHoldout.experiment_key ?? learningHoldout.experimentKey,
|
|
124
|
+
sourceCampaignId: learningHoldout.source_campaign_id ?? learningHoldout.sourceCampaignId,
|
|
125
|
+
primaryMetric: learningHoldout.primary_metric ?? learningHoldout.primaryMetric
|
|
126
|
+
} : void 0,
|
|
113
127
|
deliveryRisk: get("delivery_risk", "deliveryRisk"),
|
|
114
128
|
icp: nested("icp", "icp"),
|
|
115
129
|
policy: policy ? {
|
|
@@ -145,7 +159,6 @@ var promptValueFlags = /* @__PURE__ */ new Set([
|
|
|
145
159
|
"action-name",
|
|
146
160
|
"actor-id",
|
|
147
161
|
"actor-type",
|
|
148
|
-
"analysis-models",
|
|
149
162
|
"attachment-field",
|
|
150
163
|
"attachment-fields",
|
|
151
164
|
"attachment-file",
|
|
@@ -193,6 +206,8 @@ var promptValueFlags = /* @__PURE__ */ new Set([
|
|
|
193
206
|
"domains",
|
|
194
207
|
"enhancers-file",
|
|
195
208
|
"enhancers-json",
|
|
209
|
+
"field-map-file",
|
|
210
|
+
"field-map-json",
|
|
196
211
|
"file-url",
|
|
197
212
|
"integration-id",
|
|
198
213
|
"image-url",
|
|
@@ -203,13 +218,14 @@ var promptValueFlags = /* @__PURE__ */ new Set([
|
|
|
203
218
|
"icp",
|
|
204
219
|
"integration-display-name",
|
|
205
220
|
"integration-route",
|
|
206
|
-
"
|
|
221
|
+
"interval-ms",
|
|
207
222
|
"layer",
|
|
208
223
|
"layers",
|
|
209
224
|
"limit",
|
|
210
225
|
"lead-count",
|
|
211
226
|
"log-limit",
|
|
212
227
|
"max-concurrency",
|
|
228
|
+
"max-polls",
|
|
213
229
|
"max-retries",
|
|
214
230
|
"max-tokens",
|
|
215
231
|
"max-credits",
|
|
@@ -218,9 +234,18 @@ var promptValueFlags = /* @__PURE__ */ new Set([
|
|
|
218
234
|
"memory-type",
|
|
219
235
|
"model",
|
|
220
236
|
"name",
|
|
237
|
+
"holdout-min-sample-size",
|
|
238
|
+
"holdout-control-percentage",
|
|
239
|
+
"holdout-experiment-key",
|
|
240
|
+
"holdout-min-control-size",
|
|
241
|
+
"holdout-primary-metric",
|
|
242
|
+
"holdout-source-campaign-id",
|
|
243
|
+
"http-method",
|
|
221
244
|
"min-sample-size",
|
|
222
245
|
"min-workspace-count",
|
|
223
246
|
"nango-connection-id",
|
|
247
|
+
"nango-action",
|
|
248
|
+
"nango-proxy-path",
|
|
224
249
|
"network-days",
|
|
225
250
|
"output-format",
|
|
226
251
|
"output-file",
|
|
@@ -245,11 +270,14 @@ var promptValueFlags = /* @__PURE__ */ new Set([
|
|
|
245
270
|
"provider-link-id",
|
|
246
271
|
"provider-name",
|
|
247
272
|
"provider-workspace-id",
|
|
273
|
+
"proxy-path",
|
|
248
274
|
"qualification-file",
|
|
249
275
|
"qualification-json",
|
|
250
276
|
"request-file",
|
|
251
277
|
"records-file",
|
|
252
278
|
"records-json",
|
|
279
|
+
"required-field",
|
|
280
|
+
"required-fields",
|
|
253
281
|
"revenue-motion",
|
|
254
282
|
"readiness-json",
|
|
255
283
|
"rationale",
|
|
@@ -275,12 +303,20 @@ var promptValueFlags = /* @__PURE__ */ new Set([
|
|
|
275
303
|
"target-icp-file",
|
|
276
304
|
"target-icp-json",
|
|
277
305
|
"temperature",
|
|
306
|
+
"timeout-ms",
|
|
278
307
|
"tool-name",
|
|
279
308
|
"url",
|
|
280
309
|
"user-display-name",
|
|
281
310
|
"user-email",
|
|
282
311
|
"video-url",
|
|
312
|
+
"wait-interval-ms",
|
|
313
|
+
"wait-max-polls",
|
|
314
|
+
"wait-timeout-ms",
|
|
283
315
|
"write-mode",
|
|
316
|
+
"timezone",
|
|
317
|
+
"wake-event",
|
|
318
|
+
"wake-events",
|
|
319
|
+
"wake-on-events",
|
|
284
320
|
"workspace-connection-id",
|
|
285
321
|
"workspace-integration-id",
|
|
286
322
|
"workspace-label",
|
|
@@ -291,6 +327,7 @@ var promptValueFlags = /* @__PURE__ */ new Set([
|
|
|
291
327
|
"brain-defaults-file",
|
|
292
328
|
"memory-dimension-filters-file",
|
|
293
329
|
"memory-dimension-filters-json",
|
|
330
|
+
"method",
|
|
294
331
|
"metadata-file",
|
|
295
332
|
"metadata-json",
|
|
296
333
|
"plan-file",
|
|
@@ -361,6 +398,9 @@ function commandBooleanFlag(flags, name, defaultValue = false) {
|
|
|
361
398
|
if (Array.isArray(value)) return value.length > 0 ? parseCommandBoolean(value.at(-1), defaultValue) : defaultValue;
|
|
362
399
|
return parseCommandBoolean(value, defaultValue);
|
|
363
400
|
}
|
|
401
|
+
function commandOptionalBooleanFlag(flags, name) {
|
|
402
|
+
return commandFlagValue(flags, name) === void 0 ? void 0 : commandBooleanFlag(flags, name);
|
|
403
|
+
}
|
|
364
404
|
function parseCommandBoolean(value, defaultValue) {
|
|
365
405
|
if (value === void 0) return defaultValue;
|
|
366
406
|
if (typeof value === "boolean") return value;
|
|
@@ -609,6 +649,50 @@ function printExecutionRefs(refs) {
|
|
|
609
649
|
if (ref.replay_command) console.log(` replay: ${ref.replay_command}`);
|
|
610
650
|
}
|
|
611
651
|
}
|
|
652
|
+
function combineExecutionRefs(...groups) {
|
|
653
|
+
const refs = /* @__PURE__ */ new Map();
|
|
654
|
+
for (const group of groups) {
|
|
655
|
+
if (!Array.isArray(group)) continue;
|
|
656
|
+
for (const ref of group) {
|
|
657
|
+
if (!ref?.kind || !ref?.id) continue;
|
|
658
|
+
refs.set(`${ref.kind}:${ref.id}`, ref);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return Array.from(refs.values());
|
|
662
|
+
}
|
|
663
|
+
function opsWaitOptions() {
|
|
664
|
+
return {
|
|
665
|
+
interval_ms: numberFlag("interval-ms") ?? numberFlag("wait-interval-ms"),
|
|
666
|
+
max_polls: numberFlag("max-polls") ?? numberFlag("wait-max-polls"),
|
|
667
|
+
timeout_ms: numberFlag("timeout-ms") ?? numberFlag("wait-timeout-ms"),
|
|
668
|
+
limit: numberFlag("limit"),
|
|
669
|
+
cursor: flagArg("cursor"),
|
|
670
|
+
include_failed_runs: hasFlag("include-failed-runs"),
|
|
671
|
+
include_results: !hasFlag("no-results")
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
function printOpsWaitForResults(result) {
|
|
675
|
+
const status = result.status || {};
|
|
676
|
+
console.log(`Op: ${result.op_id || result.opId || status.op_id || status.opId || "unknown"}`);
|
|
677
|
+
console.log(`Status: ${status.status || "unknown"}`);
|
|
678
|
+
console.log(`Phase: ${status.phase || "unknown"}`);
|
|
679
|
+
console.log(`Polls: ${result.polls ?? 0}${result.timed_out || result.timedOut ? " (timed out)" : ""}`);
|
|
680
|
+
if (result.results) {
|
|
681
|
+
const summary = result.results.summary || {};
|
|
682
|
+
const count = summary.results_count ?? summary.resultsCount ?? result.results.results_count ?? result.results.resultsCount ?? 0;
|
|
683
|
+
const total = summary.results_total ?? summary.resultsTotal ?? result.results.results_total ?? result.results.resultsTotal;
|
|
684
|
+
const delivery = summary.delivery_status ?? summary.deliveryStatus ?? result.results.delivery_status ?? result.results.deliveryStatus;
|
|
685
|
+
console.log(`Results: ${count}`);
|
|
686
|
+
if (total !== void 0 && total !== null) console.log(`Total: ${total}`);
|
|
687
|
+
if (delivery) console.log(`Deliver: ${delivery}`);
|
|
688
|
+
if (Array.isArray(result.results.results) && result.results.results.length) {
|
|
689
|
+
console.log("\nRows");
|
|
690
|
+
for (const row of result.results.results.slice(0, 10)) console.log(JSON.stringify(row));
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
if (result.next_action || result.nextAction) console.log(`Next: ${result.next_action || result.nextAction}`);
|
|
694
|
+
printExecutionRefs(result.execution_refs || result.executionRefs);
|
|
695
|
+
}
|
|
612
696
|
function printQueueProducerEnvelope(envelope) {
|
|
613
697
|
if (!envelope || typeof envelope !== "object") return;
|
|
614
698
|
const queueName = envelope.queue_name ?? envelope.queueName;
|
|
@@ -635,6 +719,52 @@ function printPrimitiveGraph(primitives) {
|
|
|
635
719
|
console.log(`- ${primitive.id || "unknown"}@${primitive.version || "unknown"} (${primitive.permission_level || "unknown"}, ${retry}, ${concurrency}, ${rate})`);
|
|
636
720
|
}
|
|
637
721
|
}
|
|
722
|
+
function printOpsExecutionContract(plan) {
|
|
723
|
+
const contract = record(plan?.execution_contract || plan?.executionContract);
|
|
724
|
+
if (!Object.keys(contract).length) return;
|
|
725
|
+
const runNow = record(contract.run_now || contract.runNow);
|
|
726
|
+
const schedule = record(contract.schedule);
|
|
727
|
+
const approval = record(contract.approval);
|
|
728
|
+
const monitor = record(contract.monitor);
|
|
729
|
+
const resultContract = record(contract.result_contract || contract.resultContract);
|
|
730
|
+
const sequence = firstArray(contract.sequence);
|
|
731
|
+
const nangoRoute = record(contract.nango_route || contract.nangoRoute);
|
|
732
|
+
const createTool = schedule.create_tool || schedule.createTool || "ops_create";
|
|
733
|
+
const activateTool = schedule.activate_tool || schedule.activateTool || "ops_execute";
|
|
734
|
+
const schedulePath = createTool === activateTool ? String(createTool) : `${createTool} -> ${activateTool}`;
|
|
735
|
+
const statusTool = monitor.status_tool || monitor.statusTool || "ops_status";
|
|
736
|
+
const waitTool = monitor.wait_tool || monitor.waitTool || resultContract.wait_tool || resultContract.waitTool || "ops_wait";
|
|
737
|
+
const resultsTool = monitor.results_tool || monitor.resultsTool || "ops_results";
|
|
738
|
+
const resultShape = firstArray(resultContract.shape).map(String);
|
|
739
|
+
console.log("\nExecution contract");
|
|
740
|
+
console.log(`- Mode: ${contract.mode || "run_once"}`);
|
|
741
|
+
console.log(`- Run now: ${runNow.tool || "ops_execute"}`);
|
|
742
|
+
console.log(`- Schedule: ${schedule.cadence || "manual"} via ${schedulePath}`);
|
|
743
|
+
if (schedule.recurrence) console.log(`- Recurrence: ${schedule.recurrence}`);
|
|
744
|
+
console.log(`- Monitor/results: ${waitTool} (or ${statusTool} -> ${resultsTool})`);
|
|
745
|
+
if (resultShape.length) console.log(`- Result shape: ${resultShape.join(", ")}`);
|
|
746
|
+
if (approval.tool) {
|
|
747
|
+
console.log(`- Approval: ${approval.required ? `${approval.tool} required` : "not required"}${approval.reason ? ` - ${approval.reason}` : ""}`);
|
|
748
|
+
}
|
|
749
|
+
if (sequence.length) {
|
|
750
|
+
console.log(`- Sequence: ${sequence.map((step) => step.tool || "unknown_tool").join(" -> ")}`);
|
|
751
|
+
}
|
|
752
|
+
if (Object.keys(nangoRoute).length) {
|
|
753
|
+
console.log("\nNango API route");
|
|
754
|
+
console.log(`- Connect: ${nangoRoute.connect_tool || nangoRoute.connectTool || "nango_connect_session_create"}`);
|
|
755
|
+
console.log(`- Discover: ${nangoRoute.discover_tool || nangoRoute.discoverTool || "nango_mcp_tools_list"}`);
|
|
756
|
+
console.log(`- Dry run: ${nangoRoute.dry_run_tool || nangoRoute.dryRunTool || "nango_mcp_tool_call"}`);
|
|
757
|
+
console.log(`- Execute: ${nangoRoute.execute_tool || nangoRoute.executeTool || "nango_mcp_tool_call"} after approval`);
|
|
758
|
+
if (nangoRoute.execute_and_wait_tool || nangoRoute.executeAndWaitTool) {
|
|
759
|
+
console.log(`- Execute and wait: ${nangoRoute.execute_and_wait_tool || nangoRoute.executeAndWaitTool}`);
|
|
760
|
+
}
|
|
761
|
+
const nangoScheduleTool = nangoRoute.schedule_and_wait_tool || nangoRoute.scheduleAndWaitTool || nangoRoute.schedule_tool || nangoRoute.scheduleTool;
|
|
762
|
+
if (nangoScheduleTool) {
|
|
763
|
+
console.log(`- Schedule: ${nangoScheduleTool} after approval`);
|
|
764
|
+
}
|
|
765
|
+
if (nangoRoute.write_gate || nangoRoute.writeGate) console.log(`- Gate: ${nangoRoute.write_gate || nangoRoute.writeGate}`);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
638
768
|
function normalizeSavedCommandArgs(args) {
|
|
639
769
|
const separator = args.indexOf("--");
|
|
640
770
|
const raw = separator === -1 ? args : args.slice(separator + 1);
|
|
@@ -758,7 +888,7 @@ function opsSaved(sub, rest) {
|
|
|
758
888
|
stdio: "inherit",
|
|
759
889
|
env: process.env
|
|
760
890
|
});
|
|
761
|
-
const latest = loadConfig();
|
|
891
|
+
const latest = loadConfig({ refresh: true });
|
|
762
892
|
const latestSaved = latest.saved_commands || {};
|
|
763
893
|
const latestCommand = latestSaved[name];
|
|
764
894
|
if (latestCommand) {
|
|
@@ -860,6 +990,28 @@ function getCampaignBuilderBuildKitFactory() {
|
|
|
860
990
|
throw new Error(`Unable to load campaign build kit helper: ${primaryMessage}; fallback failed: ${fallbackError.message}`);
|
|
861
991
|
}
|
|
862
992
|
}
|
|
993
|
+
function getCampaignBuilderMemoryKitFactory() {
|
|
994
|
+
let primaryError;
|
|
995
|
+
try {
|
|
996
|
+
const sdk = require("@signaliz/sdk");
|
|
997
|
+
if (typeof sdk.createCampaignBuilderMemoryKit === "function") {
|
|
998
|
+
return sdk.createCampaignBuilderMemoryKit;
|
|
999
|
+
}
|
|
1000
|
+
primaryError = new Error("SDK missing createCampaignBuilderMemoryKit");
|
|
1001
|
+
} catch (err) {
|
|
1002
|
+
primaryError = err;
|
|
1003
|
+
}
|
|
1004
|
+
try {
|
|
1005
|
+
const sdk = require((0, import_node_path.join)(__dirname, "..", "..", "sdk", "dist", "index.js"));
|
|
1006
|
+
if (typeof sdk.createCampaignBuilderMemoryKit === "function") {
|
|
1007
|
+
return sdk.createCampaignBuilderMemoryKit;
|
|
1008
|
+
}
|
|
1009
|
+
throw new Error("local SDK missing createCampaignBuilderMemoryKit");
|
|
1010
|
+
} catch (fallbackError) {
|
|
1011
|
+
const primaryMessage = primaryError instanceof Error ? primaryError.message : String(primaryError || "SDK missing campaign memory kit helper");
|
|
1012
|
+
throw new Error(`Unable to load campaign memory kit helper: ${primaryMessage}; fallback failed: ${fallbackError.message}`);
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
863
1015
|
function prompt(question) {
|
|
864
1016
|
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stderr });
|
|
865
1017
|
return new Promise((resolve) => {
|
|
@@ -921,11 +1073,9 @@ Discovery:
|
|
|
921
1073
|
--category NAME Optional category filter, e.g. ops or enrichment
|
|
922
1074
|
|
|
923
1075
|
AI:
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
OpenRouter model id, e.g. google/gemini-2.5-flash
|
|
928
|
-
--records-file FILE JSON array, or object with records/inputs/data
|
|
1076
|
+
ai multi-model Run Custom AI Enrichment - Multi Model
|
|
1077
|
+
--prompt "..." Prompt/template for each record (required)
|
|
1078
|
+
--records-file FILE JSON array, or object with records/inputs/data
|
|
929
1079
|
--input-file FILE Single JSON record
|
|
930
1080
|
--output-fields a:text,b:number
|
|
931
1081
|
Structured fields to return
|
|
@@ -933,12 +1083,10 @@ AI:
|
|
|
933
1083
|
--pdf-url URL Attach a PDF URL to all records
|
|
934
1084
|
--attachment-file FILE
|
|
935
1085
|
Attach a local image/PDF/audio/video as base64
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
--judge-model MODEL Optional Fusion judge model
|
|
941
|
-
--confirm-spend Required to run spendful Fusion enrichment
|
|
1086
|
+
--attachment-fields a,b
|
|
1087
|
+
Record fields containing attachment URLs/arrays
|
|
1088
|
+
--max-concurrency N Record concurrency, default 3, maximum 5
|
|
1089
|
+
--confirm-spend Required to run spendful AI enrichment
|
|
942
1090
|
|
|
943
1091
|
Lead Generation:
|
|
944
1092
|
lead generate Start a B2B lead-generation job
|
|
@@ -1024,9 +1172,13 @@ GTM Kernel:
|
|
|
1024
1172
|
gtm learning <id> Plan Brain learning for a campaign
|
|
1025
1173
|
--include-network Include privacy-safe network lanes
|
|
1026
1174
|
--write-mode MODE dry_run or write
|
|
1175
|
+
--holdout-min-sample-size N
|
|
1176
|
+
Minimum control/treatment subjects for measured lift
|
|
1027
1177
|
gtm learning-run <id> Queue ready Brain learning phases
|
|
1028
1178
|
--phases a,b Optional phase allow-list
|
|
1029
1179
|
--write-mode MODE dry_run or write, default dry_run
|
|
1180
|
+
--holdout-min-sample-size N
|
|
1181
|
+
Minimum control/treatment subjects for measured lift
|
|
1030
1182
|
gtm calibrate <id> Calibrate deliverability predictions
|
|
1031
1183
|
--min-sample-size N Default server-side
|
|
1032
1184
|
--write Write calibrations/patterns; otherwise dry-run
|
|
@@ -1050,6 +1202,12 @@ GTM Kernel:
|
|
|
1050
1202
|
--provider NAME instantly, smartlead, heyreach, airbyte, custom_webhook
|
|
1051
1203
|
--campaign-id ID Optional campaign scope
|
|
1052
1204
|
--write-mode MODE Brain-cycle mode, default dry_run
|
|
1205
|
+
gtm feedback-pull Pull Instantly feedback into the learning loop
|
|
1206
|
+
--source SOURCE webhook_events or emails, default webhook_events
|
|
1207
|
+
--campaign-id ID Optional campaign scope
|
|
1208
|
+
--provider-campaign-id ID
|
|
1209
|
+
Instantly campaign id
|
|
1210
|
+
--confirm Write feedback/memory rows; otherwise dry-run
|
|
1053
1211
|
|
|
1054
1212
|
Native GTM Data Sources:
|
|
1055
1213
|
Use these when you already know the exact source you want to run.
|
|
@@ -1088,6 +1246,8 @@ Campaign Builder:
|
|
|
1088
1246
|
--output-file FILE Optional request file to write
|
|
1089
1247
|
campaign-agent kit Emit request JSON, CLI commands, MCP calls, SDK example, and BYO pattern
|
|
1090
1248
|
--kit-file FILE Optional kit JSON file to write
|
|
1249
|
+
campaign-agent memory-kit
|
|
1250
|
+
Emit memory readiness, seed runner, MCP calls, and proof commands
|
|
1091
1251
|
campaign-agent plan Compose an approval-gated strategy-template MCP flow
|
|
1092
1252
|
--goal "..." Campaign goal or brief
|
|
1093
1253
|
--request-file FILE Reusable JSON CampaignBuilderAgentRequest
|
|
@@ -1140,8 +1300,12 @@ Campaign Builder:
|
|
|
1140
1300
|
campaign rows <id> Retrieve build rows
|
|
1141
1301
|
--limit N Page size (default: 50, max: 500)
|
|
1142
1302
|
--cursor <id> Pagination cursor
|
|
1303
|
+
--include-data Include generated copy and rich row data
|
|
1304
|
+
--include-raw Include raw provider payloads
|
|
1143
1305
|
--all Dump all rows (caution: unbounded)
|
|
1144
1306
|
campaign artifacts <id> List artifacts with download URLs
|
|
1307
|
+
campaign download <id> Generate fresh signed artifact URLs
|
|
1308
|
+
--format csv|ndjson Artifact format (default: csv)
|
|
1145
1309
|
campaign approve <id> Approve pending delivery
|
|
1146
1310
|
--destination-type json|csv|webhook
|
|
1147
1311
|
--destination-id ID Optional destination/sink ID
|
|
@@ -1149,12 +1313,18 @@ Campaign Builder:
|
|
|
1149
1313
|
campaign cancel <id> Cancel a running build
|
|
1150
1314
|
|
|
1151
1315
|
Ops:
|
|
1152
|
-
Canonical path: ops plan -> ops
|
|
1316
|
+
Canonical path: ops plan -> ops execute -> ops wait
|
|
1153
1317
|
ops plan "..." Preview a prompt-first Op plan
|
|
1154
1318
|
--blueprint NAME monitor_companies|build_leads|enrich_list|route_signals|launch_campaign
|
|
1155
1319
|
--target-count N Target row count
|
|
1156
1320
|
--cadence NAME manual|hourly|daily|weekly
|
|
1321
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
1157
1322
|
--destinations a,b Destinations such as slack,csv,google_sheets,webhook,airbyte,nango
|
|
1323
|
+
--workspace-connection-id ID
|
|
1324
|
+
Nango workspace connection for API delivery
|
|
1325
|
+
--provider-config-key KEY
|
|
1326
|
+
Nango integration/provider key
|
|
1327
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
1158
1328
|
--company-domains a,b
|
|
1159
1329
|
Company domains for monitor/list-based Ops
|
|
1160
1330
|
--ai-prompt TEXT Custom AI enrichment or scoring instruction
|
|
@@ -1171,7 +1341,21 @@ Ops:
|
|
|
1171
1341
|
--confirm-spend Acknowledge estimated credits/external writes
|
|
1172
1342
|
--auto-run Run immediately after create when safe
|
|
1173
1343
|
--no-auto-run Create only
|
|
1344
|
+
--wait Auto-run, poll status, and fetch results
|
|
1345
|
+
--interval-ms N Polling interval for --wait, default 5000
|
|
1346
|
+
--max-polls N Polling limit for --wait, default 12, max 30
|
|
1347
|
+
--timeout-ms N Total wait timeout for --wait, default 60000
|
|
1348
|
+
--limit N Result rows after terminal status
|
|
1349
|
+
--no-results Stop after final status without fetching results
|
|
1350
|
+
--cadence NAME manual|hourly|daily|weekly
|
|
1351
|
+
--timezone TZ IANA timezone for recurring Ops, e.g. America/Phoenix
|
|
1352
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
1174
1353
|
--destinations a,b Destinations such as slack,csv,google_sheets,webhook,airbyte,nango
|
|
1354
|
+
--workspace-connection-id ID
|
|
1355
|
+
Nango workspace connection for API delivery
|
|
1356
|
+
--provider-config-key KEY
|
|
1357
|
+
Nango integration/provider key
|
|
1358
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
1175
1359
|
--company-domains a,b
|
|
1176
1360
|
Company domains for monitor/list-based Ops
|
|
1177
1361
|
--ai-prompt TEXT Custom AI enrichment or scoring instruction
|
|
@@ -1180,19 +1364,78 @@ Ops:
|
|
|
1180
1364
|
ops create "..." Create an Op from a prompt
|
|
1181
1365
|
--confirm-spend Acknowledge estimated credits/external writes
|
|
1182
1366
|
--activate Create as active instead of draft
|
|
1367
|
+
--cadence NAME manual|hourly|daily|weekly
|
|
1368
|
+
--timezone TZ IANA timezone for recurring Ops, e.g. America/Phoenix
|
|
1369
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
1183
1370
|
--destinations a,b Destinations such as slack,csv,google_sheets,webhook,airbyte,nango
|
|
1371
|
+
--workspace-connection-id ID
|
|
1372
|
+
Nango workspace connection for API delivery
|
|
1373
|
+
--provider-config-key KEY
|
|
1374
|
+
Nango integration/provider key
|
|
1375
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
1376
|
+
--company-domains a,b
|
|
1377
|
+
Company domains for monitor/list-based Ops
|
|
1378
|
+
--ai-prompt TEXT Custom AI enrichment or scoring instruction
|
|
1379
|
+
--signal-prompt TEXT Custom signal-finding instruction
|
|
1380
|
+
--output-prompt TEXT Clean result formatting instruction
|
|
1381
|
+
ops schedule "..." Create and activate a recurring Op, daily by default
|
|
1382
|
+
ops recur "..." Alias for ops schedule
|
|
1383
|
+
--confirm-spend Acknowledge estimated credits/external writes
|
|
1384
|
+
--wait Run first tick and fetch results through ops_schedule_and_wait
|
|
1385
|
+
--interval-ms N Polling interval for --wait, default 5000
|
|
1386
|
+
--max-polls N Polling limit for --wait, default 12, max 30
|
|
1387
|
+
--timeout-ms N Total wait timeout for --wait, default 60000
|
|
1388
|
+
--limit N Result rows after terminal status
|
|
1389
|
+
--cadence NAME hourly|daily|weekly (default: daily)
|
|
1390
|
+
--timezone TZ IANA timezone for recurring Ops, e.g. America/Phoenix
|
|
1391
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
1392
|
+
--destinations a,b Destinations such as slack,csv,google_sheets,webhook,airbyte,nango
|
|
1393
|
+
--workspace-connection-id ID
|
|
1394
|
+
Nango workspace connection for API delivery
|
|
1395
|
+
--provider-config-key KEY
|
|
1396
|
+
Nango integration/provider key
|
|
1397
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
1184
1398
|
--company-domains a,b
|
|
1185
1399
|
Company domains for monitor/list-based Ops
|
|
1186
1400
|
--ai-prompt TEXT Custom AI enrichment or scoring instruction
|
|
1187
1401
|
--signal-prompt TEXT Custom signal-finding instruction
|
|
1188
1402
|
--output-prompt TEXT Clean result formatting instruction
|
|
1189
1403
|
ops run <op_id> Run an Op immediately
|
|
1404
|
+
--wait Poll status and fetch results after queueing
|
|
1405
|
+
--interval-ms N Polling interval for --wait, default 5000
|
|
1406
|
+
--max-polls N Polling limit for --wait, default 12, max 30
|
|
1407
|
+
--timeout-ms N Total wait timeout for --wait, default 60000
|
|
1408
|
+
--limit N Result rows after terminal status
|
|
1409
|
+
--no-results Stop after final status without fetching results
|
|
1190
1410
|
ops status <op_id> Check simple Op status
|
|
1191
1411
|
ops results <op_id> Retrieve latest Op results
|
|
1192
1412
|
--limit N Page size, default 100, max 500
|
|
1193
1413
|
--cursor ID Pagination cursor
|
|
1194
1414
|
--include-failed-runs
|
|
1195
1415
|
Include failed run output when supported
|
|
1416
|
+
ops wait <op_id> Wait for an Op and return results (MCP parity: ops_wait)
|
|
1417
|
+
--interval-ms N Polling interval, default 5000
|
|
1418
|
+
--max-polls N Polling limit, default 12, max 30
|
|
1419
|
+
--timeout-ms N Total wait timeout, default 60000
|
|
1420
|
+
--limit N Result page size after terminal status
|
|
1421
|
+
--no-results Stop after final status without fetching results
|
|
1422
|
+
ops nango <subcommand> Connect, discover, call, schedule, and poll Nango tools
|
|
1423
|
+
flow|search Prepare a provider search/connect/Ops route plan
|
|
1424
|
+
connect Start Nango Connect auth for a provider
|
|
1425
|
+
tools List action tools for a workspace connection
|
|
1426
|
+
call <action> Dry-run or execute a Nango action
|
|
1427
|
+
proof|audit|read-write
|
|
1428
|
+
Audit connected rows and optional live read/write probes
|
|
1429
|
+
--read-proxy-path PATH
|
|
1430
|
+
Provider API path for approved live read proof
|
|
1431
|
+
--write-proxy-path PATH
|
|
1432
|
+
Provider API path for approved live write proof
|
|
1433
|
+
--execute-read-probe --confirm
|
|
1434
|
+
Run the read probe
|
|
1435
|
+
--execute-write-probe --confirm-write
|
|
1436
|
+
Run the write probe with safe test input
|
|
1437
|
+
schedule|recur Create a recurring Nango-backed Op; add --wait for first results
|
|
1438
|
+
result Poll async Nango action result
|
|
1196
1439
|
ops run-status <run_id>
|
|
1197
1440
|
Inspect a Trigger.dev run or batch with --run-ids a,b
|
|
1198
1441
|
--watch Poll until all runs reach a terminal state
|
|
@@ -1343,6 +1586,7 @@ Status and repair:
|
|
|
1343
1586
|
provider-prepare Build read-only recipe, route, and preview arguments
|
|
1344
1587
|
activate-route Dry-run or confirm provider route setup
|
|
1345
1588
|
feedback-webhook Prepare feedback ingress
|
|
1589
|
+
feedback-pull Dry-run or confirm Instantly feedback pull
|
|
1346
1590
|
learning <id> Plan Brain learning
|
|
1347
1591
|
learning-run <id> Queue Brain learning phases
|
|
1348
1592
|
calibrate <id> Calibrate deliverability
|
|
@@ -1746,6 +1990,35 @@ Options:
|
|
|
1746
1990
|
readiness: `signaliz gtm readiness <campaign_id> [options]
|
|
1747
1991
|
|
|
1748
1992
|
Alias for signaliz gtm execution.
|
|
1993
|
+
`,
|
|
1994
|
+
"feedback-pull": `signaliz gtm feedback-pull [options]
|
|
1995
|
+
|
|
1996
|
+
Dry-run or confirm an Instantly feedback pull. Dry-run is the default and
|
|
1997
|
+
counts provider records without writing feedback rows, memory, routine outcomes,
|
|
1998
|
+
or sync cursors. Confirmed writes require --confirm or --confirm-write.
|
|
1999
|
+
|
|
2000
|
+
Options:
|
|
2001
|
+
--source SOURCE webhook_events or emails, default webhook_events
|
|
2002
|
+
--provider-campaign-id ID
|
|
2003
|
+
Instantly campaign id
|
|
2004
|
+
--campaign-id ID Optional linked GTM campaign id
|
|
2005
|
+
--campaign-build-id ID Optional Campaign Builder build id
|
|
2006
|
+
--provider-link-id ID Optional provider link id
|
|
2007
|
+
--integration-id ID Optional Instantly integration id
|
|
2008
|
+
--from DATE Webhook-event pull window start
|
|
2009
|
+
--to DATE Webhook-event pull window end
|
|
2010
|
+
--limit N Page size, default server-side, max 100
|
|
2011
|
+
--max-pages N Max pages, default server-side, max 20
|
|
2012
|
+
--email-type TYPE received, sent, or manual when source=emails
|
|
2013
|
+
--mode MODE emode_focused, emode_others, or emode_all
|
|
2014
|
+
--sort-order ORDER asc or desc
|
|
2015
|
+
--no-memory Do not create memory rows on confirmed writes
|
|
2016
|
+
--no-routine-outcomes Do not write routine outcomes
|
|
2017
|
+
--no-brain-cycle Do not queue feedback-triggered Brain learning
|
|
2018
|
+
--write-mode MODE Brain-cycle mode, default dry_run
|
|
2019
|
+
--confirm Write feedback/memory rows; otherwise dry-run
|
|
2020
|
+
--confirm-write Alias for --confirm
|
|
2021
|
+
--json Machine-readable output
|
|
1749
2022
|
`,
|
|
1750
2023
|
campaigns: `signaliz gtm campaigns [options]
|
|
1751
2024
|
|
|
@@ -1810,7 +2083,13 @@ Options:
|
|
|
1810
2083
|
--blueprint NAME monitor_companies|build_leads|enrich_list|route_signals|launch_campaign
|
|
1811
2084
|
--target-count N Target row count
|
|
1812
2085
|
--cadence NAME manual|hourly|daily|weekly
|
|
2086
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
1813
2087
|
--destinations a,b Destinations such as json,csv,slack,airbyte,nango
|
|
2088
|
+
--workspace-connection-id ID
|
|
2089
|
+
Nango workspace connection for API delivery
|
|
2090
|
+
--provider-config-key KEY
|
|
2091
|
+
Nango integration/provider key
|
|
2092
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
1814
2093
|
--company-domains a,b Explicit account/domain list
|
|
1815
2094
|
--json Machine-readable output
|
|
1816
2095
|
|
|
@@ -1826,12 +2105,52 @@ Options:
|
|
|
1826
2105
|
--confirm-spend Acknowledge estimated credits/external writes
|
|
1827
2106
|
--activate Create as active instead of draft
|
|
1828
2107
|
--target-count N Target row count
|
|
2108
|
+
--cadence NAME manual|hourly|daily|weekly
|
|
2109
|
+
--timezone TZ IANA timezone for recurring Ops, e.g. America/Phoenix
|
|
2110
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
1829
2111
|
--destinations a,b Destinations such as json,csv,slack,airbyte,nango
|
|
2112
|
+
--workspace-connection-id ID
|
|
2113
|
+
Nango workspace connection for API delivery
|
|
2114
|
+
--provider-config-key KEY
|
|
2115
|
+
Nango integration/provider key
|
|
2116
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
1830
2117
|
--company-domains a,b Explicit account/domain list
|
|
1831
2118
|
--json Machine-readable output
|
|
1832
2119
|
|
|
1833
2120
|
Safe next step:
|
|
1834
2121
|
signaliz ops run <op_id>
|
|
2122
|
+
`,
|
|
2123
|
+
schedule: `signaliz ops schedule "plain-English recurring GTM goal" [options]
|
|
2124
|
+
|
|
2125
|
+
Create and activate a recurring Op from a prompt. Defaults to daily cadence
|
|
2126
|
+
unless --cadence is provided. Requires --confirm-spend for spendful work.
|
|
2127
|
+
|
|
2128
|
+
Options:
|
|
2129
|
+
--confirm-spend Acknowledge estimated credits/external writes
|
|
2130
|
+
--wait Create the recurring Op, run the first tick, and fetch results
|
|
2131
|
+
--interval-ms N Polling interval for --wait, default 5000
|
|
2132
|
+
--max-polls N Polling limit for --wait, default 12, max 30
|
|
2133
|
+
--timeout-ms N Total wait timeout for --wait, default 60000
|
|
2134
|
+
--limit N Result rows after terminal status
|
|
2135
|
+
--target-count N Target row count
|
|
2136
|
+
--cadence NAME hourly|daily|weekly (default: daily)
|
|
2137
|
+
--timezone TZ IANA timezone for recurring Ops, e.g. America/Phoenix
|
|
2138
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
2139
|
+
--destinations a,b Destinations such as json,csv,slack,airbyte,nango
|
|
2140
|
+
--workspace-connection-id ID
|
|
2141
|
+
Nango workspace connection for API delivery
|
|
2142
|
+
--provider-config-key KEY
|
|
2143
|
+
Nango integration/provider key
|
|
2144
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
2145
|
+
--company-domains a,b Explicit account/domain list
|
|
2146
|
+
--json Machine-readable output
|
|
2147
|
+
|
|
2148
|
+
Safe next step:
|
|
2149
|
+
signaliz ops status <op_id>
|
|
2150
|
+
`,
|
|
2151
|
+
recur: `signaliz ops recur "plain-English recurring GTM goal" [options]
|
|
2152
|
+
|
|
2153
|
+
Alias for signaliz ops schedule.
|
|
1835
2154
|
`,
|
|
1836
2155
|
execute: `signaliz ops execute "plain-English GTM goal" [options]
|
|
1837
2156
|
|
|
@@ -1842,13 +2161,38 @@ Options:
|
|
|
1842
2161
|
--confirm-spend Acknowledge estimated credits/external writes
|
|
1843
2162
|
--auto-run Run immediately after create when safe
|
|
1844
2163
|
--no-auto-run Create only
|
|
2164
|
+
--wait Auto-run, poll status, and fetch results
|
|
2165
|
+
--interval-ms N Polling interval for --wait, default 5000
|
|
2166
|
+
--max-polls N Polling limit for --wait, default 12, max 30
|
|
2167
|
+
--timeout-ms N Total wait timeout for --wait, default 60000
|
|
2168
|
+
--limit N Result rows to return after terminal status
|
|
2169
|
+
--no-results Stop after final status without fetching results
|
|
1845
2170
|
--target-count N Target row count
|
|
2171
|
+
--cadence NAME manual|hourly|daily|weekly
|
|
2172
|
+
--timezone TZ IANA timezone for recurring Ops, e.g. America/Phoenix
|
|
2173
|
+
--wake-on-events a,b Event triggers such as company_funded,crm.updated
|
|
1846
2174
|
--destinations a,b Destinations such as json,csv,slack,airbyte,nango
|
|
2175
|
+
--workspace-connection-id ID
|
|
2176
|
+
Nango workspace connection for API delivery
|
|
2177
|
+
--provider-config-key KEY
|
|
2178
|
+
Nango integration/provider key
|
|
2179
|
+
--action-name NAME Nango action; use --proxy-path PATH for proxy mode
|
|
1847
2180
|
--json Machine-readable output
|
|
1848
2181
|
`,
|
|
1849
2182
|
run: `signaliz ops run <op_id> [options]
|
|
1850
2183
|
|
|
1851
2184
|
Run a created Op immediately.
|
|
2185
|
+
|
|
2186
|
+
Options:
|
|
2187
|
+
--force Force a run when supported
|
|
2188
|
+
--instruction TEXT Optional run instruction
|
|
2189
|
+
--wait Poll status and fetch results after queueing
|
|
2190
|
+
--interval-ms N Polling interval for --wait, default 5000
|
|
2191
|
+
--max-polls N Polling limit for --wait, default 12, max 30
|
|
2192
|
+
--timeout-ms N Total wait timeout for --wait, default 60000
|
|
2193
|
+
--limit N Result rows to return after terminal status
|
|
2194
|
+
--no-results Stop after final status without fetching results
|
|
2195
|
+
--json Machine-readable output
|
|
1852
2196
|
`,
|
|
1853
2197
|
status: `signaliz ops status <op_id> [options]
|
|
1854
2198
|
|
|
@@ -1863,6 +2207,51 @@ Options:
|
|
|
1863
2207
|
--cursor ID Pagination cursor
|
|
1864
2208
|
--include-failed-runs Include failed run output when supported
|
|
1865
2209
|
--json Machine-readable output
|
|
2210
|
+
`,
|
|
2211
|
+
wait: `signaliz ops wait <op_id> [options]
|
|
2212
|
+
|
|
2213
|
+
Poll Op status until it completes, blocks, fails, or needs action, then fetch
|
|
2214
|
+
the latest results automatically.
|
|
2215
|
+
|
|
2216
|
+
Options:
|
|
2217
|
+
--interval-ms N Polling interval, default 5000
|
|
2218
|
+
--max-polls N Polling limit, default 12, max 30
|
|
2219
|
+
--timeout-ms N Total wait timeout, default 60000
|
|
2220
|
+
--limit N Result rows to return after terminal status
|
|
2221
|
+
--include-failed-runs Include failed run output when fetching results
|
|
2222
|
+
--no-results Only wait for terminal status; do not fetch results
|
|
2223
|
+
--json Machine-readable output
|
|
2224
|
+
`,
|
|
2225
|
+
nango: `signaliz ops nango <flow|search|connect|tools|call|proof|schedule|result> [options]
|
|
2226
|
+
|
|
2227
|
+
Connect and operate customer-owned vendor APIs through Nango from the Ops
|
|
2228
|
+
namespace. This is the Ops-first route for "connect to any tool, do the work,
|
|
2229
|
+
and get the result" flows.
|
|
2230
|
+
|
|
2231
|
+
Examples:
|
|
2232
|
+
signaliz ops nango search hubspot
|
|
2233
|
+
signaliz ops nango connect --provider-id hubspot
|
|
2234
|
+
signaliz ops nango tools --workspace-connection-id <id> --provider-config-key hubspot
|
|
2235
|
+
signaliz ops nango call upsert-contact --workspace-connection-id <id> --input-json '{"email":"buyer@example.com"}' --dry-run
|
|
2236
|
+
signaliz ops nango call --workspace-connection-id <id> --proxy-path /v2/leads/list --method GET --dry-run
|
|
2237
|
+
signaliz ops nango call upsert-contact --workspace-connection-id <id> --input-json '{"email":"buyer@example.com"}' --execute --confirm --wait
|
|
2238
|
+
signaliz ops nango proof --json
|
|
2239
|
+
signaliz ops nango proof --workspace-connection-id <id> --read-proxy-path /v2/accounts --execute-read-probe --confirm
|
|
2240
|
+
signaliz ops nango proof --workspace-connection-id <id> --write-proxy-path /v2/custom-tags --method POST --write-input-json '{"label":"safe-proof"}' --execute-write-probe --confirm-write
|
|
2241
|
+
signaliz ops nango schedule "Monitor accounts daily and upsert approved rows" --workspace-connection-id <id> --provider-config-key hubspot --action-name upsert-contact --confirm-spend --wait
|
|
2242
|
+
signaliz ops nango result --status-url /action/<action_id>
|
|
2243
|
+
|
|
2244
|
+
Subcommands:
|
|
2245
|
+
flow|search Prepare provider search, connect, action, and Ops route calls
|
|
2246
|
+
connect Start Nango Connect auth for a provider
|
|
2247
|
+
tools List Nango action tools for a workspace connection
|
|
2248
|
+
call <action> Dry-run by default; add --execute --confirm for approved writes, --wait for result readback
|
|
2249
|
+
accepts --proxy-path for direct Nango proxy mode
|
|
2250
|
+
proof|audit|read-write Audit connected Nango rows, tools, proxy readiness, and optional live read/write probes
|
|
2251
|
+
accepts --read-proxy-path, --write-proxy-path, --execute-read-probe, --execute-write-probe
|
|
2252
|
+
schedule|recur PROMPT Create a recurring Nango-backed Op through ops_nango_schedule; --wait uses ops_nango_schedule_and_wait
|
|
2253
|
+
accepts --input-json/--input-file, --field-map-json, and --required-fields
|
|
2254
|
+
result Poll async Nango action result
|
|
1866
2255
|
`
|
|
1867
2256
|
};
|
|
1868
2257
|
function opsHelpFor(sub) {
|
|
@@ -1877,7 +2266,7 @@ Canonical path:
|
|
|
1877
2266
|
signaliz ops results <op_id>
|
|
1878
2267
|
|
|
1879
2268
|
Common commands:
|
|
1880
|
-
proof, autopilot, plan, execute, create, run, status, results, doctor, connections
|
|
2269
|
+
proof, autopilot, plan, execute, create, schedule, run, status, results, wait, nango, doctor, connections
|
|
1881
2270
|
|
|
1882
2271
|
Run: signaliz ops help <command>
|
|
1883
2272
|
`;
|
|
@@ -1908,6 +2297,13 @@ Options:
|
|
|
1908
2297
|
--outputs json,csv Delivery outputs, default json
|
|
1909
2298
|
--dry-run Validate and plan without launching spendful work
|
|
1910
2299
|
--allow-downscale Allow oversized target counts to be clamped
|
|
2300
|
+
--learning-holdout Assign explicit control vs learned cohorts
|
|
2301
|
+
--holdout-control-percentage N
|
|
2302
|
+
Control share, e.g. 0.2 or 20 for 20%
|
|
2303
|
+
--holdout-min-control-size N
|
|
2304
|
+
Minimum control rows for large builds, default 50
|
|
2305
|
+
--holdout-experiment-key KEY
|
|
2306
|
+
Stable experiment key for feedback attribution
|
|
1911
2307
|
--confirm-spend Acknowledge spendful generation
|
|
1912
2308
|
--input-file FILE JSON config file from campaign scope or gtm prepare-build
|
|
1913
2309
|
--wait Poll until completion
|
|
@@ -1929,12 +2325,22 @@ Options:
|
|
|
1929
2325
|
--cursor ID Pagination cursor
|
|
1930
2326
|
--qualified Only qualified rows
|
|
1931
2327
|
--disqualified Only disqualified rows
|
|
2328
|
+
--include-data Include rich row data such as generated copy
|
|
2329
|
+
--include-raw Include raw provider/qualification payloads
|
|
1932
2330
|
--all Dump all rows
|
|
1933
2331
|
--json Machine-readable output
|
|
1934
2332
|
`,
|
|
1935
2333
|
artifacts: `signaliz campaign artifacts <campaign_build_id> [options]
|
|
1936
2334
|
|
|
1937
2335
|
List generated artifacts and signed download URLs.
|
|
2336
|
+
`,
|
|
2337
|
+
download: `signaliz campaign download <campaign_build_id> [options]
|
|
2338
|
+
|
|
2339
|
+
Generate fresh signed URLs for a downloadable artifact.
|
|
2340
|
+
|
|
2341
|
+
Options:
|
|
2342
|
+
--format csv|ndjson Artifact format, default csv
|
|
2343
|
+
--json Machine-readable output
|
|
1938
2344
|
`,
|
|
1939
2345
|
approve: `signaliz campaign approve <campaign_build_id> --destination-type <json|csv|webhook>
|
|
1940
2346
|
|
|
@@ -1955,9 +2361,10 @@ Canonical path:
|
|
|
1955
2361
|
signaliz campaign build --prompt "VP Sales at B2B SaaS" --confirm-spend --wait
|
|
1956
2362
|
signaliz campaign rows <campaign_build_id> --limit 100
|
|
1957
2363
|
signaliz campaign artifacts <campaign_build_id>
|
|
2364
|
+
signaliz campaign download <campaign_build_id> --format csv
|
|
1958
2365
|
|
|
1959
2366
|
Commands:
|
|
1960
|
-
scope, build, status, rows, artifacts, approve, cancel
|
|
2367
|
+
scope, build, status, rows, artifacts, download, approve, cancel
|
|
1961
2368
|
|
|
1962
2369
|
Run: signaliz campaign help <command>
|
|
1963
2370
|
`;
|
|
@@ -2370,20 +2777,20 @@ function aiAttachmentsFromFlags() {
|
|
|
2370
2777
|
}
|
|
2371
2778
|
async function ai(sub, rest) {
|
|
2372
2779
|
if (sub !== "multi-model" && sub !== "multimodel") {
|
|
2373
|
-
die('Usage: signaliz ai multi-model --prompt "..." --
|
|
2780
|
+
die('Usage: signaliz ai multi-model --prompt "..." --confirm-spend');
|
|
2781
|
+
}
|
|
2782
|
+
if (flagArg("model") !== void 0 || hasFlag("model") || flagArg("analysis-models") !== void 0 || hasFlag("analysis-models") || flagArg("judge-model") !== void 0 || hasFlag("judge-model")) {
|
|
2783
|
+
die("Custom AI model selection is no longer supported. Signaliz-hosted custom AI uses the default model and returns model readback metadata.");
|
|
2374
2784
|
}
|
|
2375
2785
|
const promptText = promptArg(rest);
|
|
2376
|
-
|
|
2377
|
-
if (!promptText) die('Usage: signaliz ai multi-model --prompt "..." --model provider/model --confirm-spend');
|
|
2378
|
-
if (!model) die("--model is required. Use an OpenRouter id such as google/gemini-2.5-flash.");
|
|
2786
|
+
if (!promptText) die('Usage: signaliz ai multi-model --prompt "..." --confirm-spend');
|
|
2379
2787
|
if (!hasFlag("confirm-spend")) {
|
|
2380
|
-
die("This
|
|
2788
|
+
die("This runs custom AI enrichment and can spend credits. Re-run with --confirm-spend to approve.");
|
|
2381
2789
|
}
|
|
2382
2790
|
const sdk = getSdk();
|
|
2383
2791
|
const records = aiRecordsFromFlags();
|
|
2384
2792
|
const result = await sdk.ai.multiModel({
|
|
2385
2793
|
prompt: promptText,
|
|
2386
|
-
model,
|
|
2387
2794
|
records,
|
|
2388
2795
|
systemPrompt: flagArg("system-prompt"),
|
|
2389
2796
|
temperature: numberFlag("temperature"),
|
|
@@ -2394,15 +2801,12 @@ async function ai(sub, rest) {
|
|
|
2394
2801
|
attachmentFields: csvFlag("attachment-fields") || csvFlag("attachment-field"),
|
|
2395
2802
|
pdfEngine: flagArg("pdf-engine"),
|
|
2396
2803
|
fusion: {
|
|
2397
|
-
required: !hasFlag("no-require-fusion"),
|
|
2398
|
-
analysis_models: csvFlag("analysis-models"),
|
|
2399
|
-
judge_model: flagArg("judge-model"),
|
|
2400
2804
|
include_raw_analysis: hasFlag("include-raw-analysis")
|
|
2401
2805
|
}
|
|
2402
2806
|
});
|
|
2403
2807
|
return output(result, () => {
|
|
2404
2808
|
console.log("Custom AI Enrichment - Multi Model complete");
|
|
2405
|
-
console.log(` Model: ${result.model ||
|
|
2809
|
+
console.log(` Model: ${result.model || "google/gemini-2.5-flash"}`);
|
|
2406
2810
|
console.log(` Records: ${result.results.length}`);
|
|
2407
2811
|
console.log(` Credits: ${result.creditsUsed}`);
|
|
2408
2812
|
console.log(` Attachments: ${result.multimodalCount}`);
|
|
@@ -2438,6 +2842,16 @@ async function campaignBuild() {
|
|
|
2438
2842
|
if (hasFlag("dry-run")) config.dryRun = true;
|
|
2439
2843
|
if (hasFlag("allow-downscale")) config.allowDownscale = true;
|
|
2440
2844
|
if (hasFlag("confirm-spend")) config.confirmSpend = true;
|
|
2845
|
+
if (hasFlag("learning-holdout") || flagArg("holdout-control-percentage") || flagArg("holdout-min-control-size") || flagArg("holdout-experiment-key")) {
|
|
2846
|
+
config.learningHoldout = {
|
|
2847
|
+
enabled: true,
|
|
2848
|
+
controlPercentage: numberFlag("holdout-control-percentage") ?? 0.2,
|
|
2849
|
+
minControlSize: numberFlag("holdout-min-control-size") ?? 50,
|
|
2850
|
+
experimentKey: flagArg("holdout-experiment-key") || void 0,
|
|
2851
|
+
sourceCampaignId: flagArg("holdout-source-campaign-id") || void 0,
|
|
2852
|
+
primaryMetric: flagArg("holdout-primary-metric") || void 0
|
|
2853
|
+
};
|
|
2854
|
+
}
|
|
2441
2855
|
const outputs = (flagArg("outputs") || "json").split(",").map((s) => s.trim());
|
|
2442
2856
|
const webhookUrl = flagArg("webhook-url");
|
|
2443
2857
|
if (outputs.includes("csv") || outputs.includes("webhook") || webhookUrl) {
|
|
@@ -2480,6 +2894,7 @@ async function campaignBuild() {
|
|
|
2480
2894
|
console.log(` Planned: ${result.plannedTargetCount ?? result.requestedTargetCount ?? config.targetCount ?? 50} leads`);
|
|
2481
2895
|
if (result.estimatedCredits !== void 0) console.log(` Credits: ~${result.estimatedCredits}`);
|
|
2482
2896
|
if (result.estimatedDurationSeconds !== void 0) console.log(` Duration: ~${result.estimatedDurationSeconds}s`);
|
|
2897
|
+
if (result.learningHoldout?.enabled) console.log(` Holdout: enabled (${Math.round(Number(result.learningHoldout.control_percentage || 0) * 100)}% control)`);
|
|
2483
2898
|
if (result.targetLimitApplied) console.log(` Note: ${result.targetLimitReason || "target count downscaled"}`);
|
|
2484
2899
|
hint("Remove --dry-run and add --confirm-spend when ready to launch.");
|
|
2485
2900
|
});
|
|
@@ -2493,6 +2908,7 @@ async function campaignBuild() {
|
|
|
2493
2908
|
console.log(` Status: ${result.status}`);
|
|
2494
2909
|
console.log(` Phase: ${result.currentPhase}`);
|
|
2495
2910
|
console.log(` Target: ${config.targetCount || 50} leads`);
|
|
2911
|
+
if (result.learningHoldout?.enabled) console.log(` Holdout: enabled (${Math.round(Number(result.learningHoldout.control_percentage || 0) * 100)}% control)`);
|
|
2496
2912
|
hint(`signaliz campaign status ${result.campaignBuildId}`);
|
|
2497
2913
|
});
|
|
2498
2914
|
}
|
|
@@ -2522,6 +2938,7 @@ async function campaignBuild() {
|
|
|
2522
2938
|
\u2713 Build ${finalStatus.status}`);
|
|
2523
2939
|
console.log(` Rows: ${finalStatus.recordsSucceeded}/${finalStatus.recordsTotal} succeeded`);
|
|
2524
2940
|
console.log(` Artifacts: ${finalStatus.artifactCount}`);
|
|
2941
|
+
printCampaignArtifactDownloadHint(finalStatus, result.campaignBuildId);
|
|
2525
2942
|
if (finalStatus.status === "completed") {
|
|
2526
2943
|
hint(`signaliz campaign rows ${result.campaignBuildId} --limit 100`);
|
|
2527
2944
|
}
|
|
@@ -2565,6 +2982,35 @@ async function campaignScope() {
|
|
|
2565
2982
|
hint("Next: run signaliz campaign build --input-file with the buildCampaignArgs JSON, or call build_campaign with the returned dry-run args.");
|
|
2566
2983
|
});
|
|
2567
2984
|
}
|
|
2985
|
+
function campaignArtifactDownloads(status) {
|
|
2986
|
+
const downloads = Array.isArray(status?.artifactDownloads) ? status.artifactDownloads : Array.isArray(status?.artifact_downloads) ? status.artifact_downloads : [];
|
|
2987
|
+
return downloads.map(record);
|
|
2988
|
+
}
|
|
2989
|
+
function campaignArtifactDownloadUrl(download) {
|
|
2990
|
+
const url = download.downloadUrl || download.download_url || download.signedUrl || download.signed_url;
|
|
2991
|
+
return typeof url === "string" && url.trim() ? url.trim() : null;
|
|
2992
|
+
}
|
|
2993
|
+
function campaignPreferredArtifactDownload(status) {
|
|
2994
|
+
const downloads = campaignArtifactDownloads(status);
|
|
2995
|
+
if (downloads.length === 0) return null;
|
|
2996
|
+
return downloads.find((download) => {
|
|
2997
|
+
const format = String(download.format || download.artifactType || download.artifact_type || "").toLowerCase();
|
|
2998
|
+
return format === "csv";
|
|
2999
|
+
}) || downloads[0];
|
|
3000
|
+
}
|
|
3001
|
+
function printCampaignArtifactDownloadHint(status, buildId) {
|
|
3002
|
+
const download = campaignPreferredArtifactDownload(status);
|
|
3003
|
+
const url = download ? campaignArtifactDownloadUrl(download) : null;
|
|
3004
|
+
if (url) {
|
|
3005
|
+
const format = String(download?.format || download?.artifactType || download?.artifact_type || "artifact");
|
|
3006
|
+
const rowCount = Number(download?.rowCount ?? download?.row_count ?? 0);
|
|
3007
|
+
console.log(`Download: ${format}${rowCount > 0 ? `, ${rowCount} rows` : ""}`);
|
|
3008
|
+
console.log(` ${url}`);
|
|
3009
|
+
return;
|
|
3010
|
+
}
|
|
3011
|
+
const artifactCount = Number(status?.artifactCount ?? status?.artifact_count ?? 0);
|
|
3012
|
+
if (artifactCount > 0) hint(`signaliz campaign download ${buildId} --format csv`);
|
|
3013
|
+
}
|
|
2568
3014
|
async function campaignStatus() {
|
|
2569
3015
|
const buildId = positionalAfter("status") || flagArg("campaign-build-id");
|
|
2570
3016
|
if (!buildId) die("Usage: signaliz campaign status <campaign_build_id>");
|
|
@@ -2576,7 +3022,9 @@ async function campaignStatus() {
|
|
|
2576
3022
|
console.log(`Status: ${status.status}`);
|
|
2577
3023
|
console.log(`Phase: ${status.currentPhase || "N/A"}`);
|
|
2578
3024
|
console.log(`Rows: ${status.recordsSucceeded}/${status.recordsTotal} succeeded, ${status.recordsFailed} failed`);
|
|
3025
|
+
printCampaignCustomerRowCounts(status);
|
|
2579
3026
|
console.log(`Artifacts: ${status.artifactCount}`);
|
|
3027
|
+
printCampaignArtifactDownloadHint(status, buildId);
|
|
2580
3028
|
if (status.triggerRunId) console.log(`Trigger: ${status.triggerRunId}`);
|
|
2581
3029
|
if (status.staleRunningPhase) {
|
|
2582
3030
|
const age = typeof status.phaseAgeSeconds === "number" ? `${status.phaseAgeSeconds}s` : "unknown age";
|
|
@@ -2590,12 +3038,18 @@ async function campaignStatus() {
|
|
|
2590
3038
|
console.log(`Errors: ${status.errors.length}`);
|
|
2591
3039
|
for (const error of status.errors.slice(0, 3)) console.log(` - ${error}`);
|
|
2592
3040
|
}
|
|
2593
|
-
if (status.status === "completed") {
|
|
3041
|
+
if (status.status === "completed" && status.nextAction) {
|
|
3042
|
+
hint(status.nextAction);
|
|
3043
|
+
} else if (status.status === "completed") {
|
|
2594
3044
|
hint(`signaliz campaign rows ${buildId} --limit 100`);
|
|
2595
3045
|
} else if (status.staleRunningPhase && status.triggerRunId) {
|
|
2596
3046
|
hint(`signaliz ops run-status ${status.triggerRunId} --watch`);
|
|
2597
3047
|
} else if (status.status === "running" || status.status === "queued") {
|
|
2598
3048
|
hint(`signaliz campaign status ${buildId} (poll again in ~10s)`);
|
|
3049
|
+
} else if (status.status === "pending_approval" && status.approvalAction) {
|
|
3050
|
+
hint(status.approvalAction);
|
|
3051
|
+
} else if (status.status === "pending_approval" && status.nextAction) {
|
|
3052
|
+
hint(status.nextAction);
|
|
2599
3053
|
} else if (status.status === "pending_approval") {
|
|
2600
3054
|
hint(`signaliz campaign approve ${buildId} --destination-type webhook`);
|
|
2601
3055
|
} else if (status.status === "failed" && status.nextAction) {
|
|
@@ -2603,6 +3057,22 @@ async function campaignStatus() {
|
|
|
2603
3057
|
}
|
|
2604
3058
|
});
|
|
2605
3059
|
}
|
|
3060
|
+
function printCampaignCustomerRowCounts(status) {
|
|
3061
|
+
const counts = status?.customerRowCounts || status?.customer_row_counts;
|
|
3062
|
+
if (!counts || typeof counts !== "object") return;
|
|
3063
|
+
const value = (camel, snake) => counts[camel] ?? counts[snake] ?? "n/a";
|
|
3064
|
+
const requested = value("requestedTarget", "requested_target");
|
|
3065
|
+
console.log(`Customer rows: accepted ${value("acceptedRows", "accepted_rows")}/${requested}, copied ${value("copiedRows", "copied_rows")}, approval-ready ${value("approvalReadyRows", "approval_ready_rows")}, QA-ready ${value("qaReadyRows", "qa_ready_rows")}, delivered ${value("deliveredRows", "delivered_rows")}`);
|
|
3066
|
+
const shortfalls = [
|
|
3067
|
+
["accepted", value("acceptedShortfall", "accepted_shortfall")],
|
|
3068
|
+
["usable", value("usableShortfall", "usable_shortfall")],
|
|
3069
|
+
["QA-ready", value("qaReadyShortfall", "qa_ready_shortfall")],
|
|
3070
|
+
["delivery", value("deliveryShortfall", "delivery_shortfall")]
|
|
3071
|
+
].filter(([, count]) => typeof count === "number" && count > 0);
|
|
3072
|
+
if (shortfalls.length > 0) {
|
|
3073
|
+
console.log(`Shortfalls: ${shortfalls.map(([label, count]) => `${label} ${count}`).join(", ")}`);
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
2606
3076
|
async function campaignRows() {
|
|
2607
3077
|
const buildId = positionalAfter("rows") || flagArg("campaign-build-id");
|
|
2608
3078
|
if (!buildId) die("Usage: signaliz campaign rows <campaign_build_id>");
|
|
@@ -2617,6 +3087,8 @@ async function campaignRows() {
|
|
|
2617
3087
|
do {
|
|
2618
3088
|
const opts = { limit: Math.min(limit, 500) };
|
|
2619
3089
|
if (nextCursor) opts.cursor = nextCursor;
|
|
3090
|
+
if (hasFlag("include-data")) opts.includeData = true;
|
|
3091
|
+
if (hasFlag("include-raw")) opts.includeRaw = true;
|
|
2620
3092
|
const segment = flagArg("segment");
|
|
2621
3093
|
if (segment) opts.segment = segment;
|
|
2622
3094
|
const rowStatus = flagArg("row-status");
|
|
@@ -2641,6 +3113,8 @@ async function campaignRows() {
|
|
|
2641
3113
|
} else {
|
|
2642
3114
|
const opts = { limit: Math.min(limit, 500) };
|
|
2643
3115
|
if (cursor) opts.cursor = cursor;
|
|
3116
|
+
if (hasFlag("include-data")) opts.includeData = true;
|
|
3117
|
+
if (hasFlag("include-raw")) opts.includeRaw = true;
|
|
2644
3118
|
const segment = flagArg("segment");
|
|
2645
3119
|
if (segment) opts.segment = segment;
|
|
2646
3120
|
const rowStatus = flagArg("row-status");
|
|
@@ -2666,6 +3140,7 @@ async function campaignRows() {
|
|
|
2666
3140
|
status: r.status || "",
|
|
2667
3141
|
score: r.score ?? ""
|
|
2668
3142
|
})));
|
|
3143
|
+
printCampaignCopySnippets(operatorResult.rows);
|
|
2669
3144
|
console.log(`
|
|
2670
3145
|
Showing ${operatorResult.rows.length} row(s)${operatorResult.hasMore ? " (more available)" : ""}`);
|
|
2671
3146
|
if (operatorResult.nextCursor) {
|
|
@@ -2678,14 +3153,15 @@ function formatCampaignRowsForOperator(rows) {
|
|
|
2678
3153
|
return rows.map((row) => {
|
|
2679
3154
|
const rowRecord = record(row);
|
|
2680
3155
|
const data = record(rowRecord.data);
|
|
3156
|
+
const copyData = record(data.copy);
|
|
2681
3157
|
const rawCopy = record(data.raw_copy);
|
|
2682
3158
|
const copy = {
|
|
2683
|
-
subject: data.subject || rawCopy.subject || null,
|
|
2684
|
-
opener: data.opener || rawCopy.opener || null,
|
|
2685
|
-
body: data.body || rawCopy.body || null,
|
|
2686
|
-
cta: data.cta || rawCopy.cta || null,
|
|
2687
|
-
engine: data.copy_engine || rawCopy.engine || null,
|
|
2688
|
-
model: data.copy_model || null
|
|
3159
|
+
subject: data.subject || copyData.subject || rawCopy.subject || null,
|
|
3160
|
+
opener: data.opener || copyData.opener || rawCopy.opener || null,
|
|
3161
|
+
body: data.body || copyData.body || rawCopy.body || null,
|
|
3162
|
+
cta: data.cta || copyData.cta || rawCopy.cta || null,
|
|
3163
|
+
engine: data.copy_engine || copyData.engine || rawCopy.engine || null,
|
|
3164
|
+
model: data.copy_model || copyData.model || null
|
|
2689
3165
|
};
|
|
2690
3166
|
return {
|
|
2691
3167
|
...rowRecord,
|
|
@@ -2715,6 +3191,26 @@ function formatCampaignRowsForOperator(rows) {
|
|
|
2715
3191
|
};
|
|
2716
3192
|
});
|
|
2717
3193
|
}
|
|
3194
|
+
function printCampaignCopySnippets(rows, limit = 5) {
|
|
3195
|
+
const rowsWithCopy = rows.filter((row) => {
|
|
3196
|
+
const copy = record(row.copy);
|
|
3197
|
+
return Boolean(copy.subject || copy.opener || copy.body || copy.cta);
|
|
3198
|
+
});
|
|
3199
|
+
if (rowsWithCopy.length === 0) return;
|
|
3200
|
+
console.log("\nCopy:");
|
|
3201
|
+
for (const row of rowsWithCopy.slice(0, limit)) {
|
|
3202
|
+
const copy = record(row.copy);
|
|
3203
|
+
const label = row.email || row.name || row.company || `row ${row.index ?? ""}`.toString().trim();
|
|
3204
|
+
console.log(`- ${label}`);
|
|
3205
|
+
if (copy.subject) console.log(` Subject: ${copy.subject}`);
|
|
3206
|
+
if (copy.opener) console.log(` Opener: ${copy.opener}`);
|
|
3207
|
+
if (copy.body) console.log(` Body: ${copy.body}`);
|
|
3208
|
+
if (copy.cta) console.log(` CTA: ${copy.cta}`);
|
|
3209
|
+
}
|
|
3210
|
+
if (rowsWithCopy.length > limit) {
|
|
3211
|
+
console.log(` ...${rowsWithCopy.length - limit} more row(s) with copy`);
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
2718
3214
|
async function campaignArtifacts() {
|
|
2719
3215
|
const buildId = positionalAfter("artifacts") || flagArg("campaign-build-id");
|
|
2720
3216
|
if (!buildId) die("Usage: signaliz campaign artifacts <campaign_build_id>");
|
|
@@ -2732,6 +3228,24 @@ async function campaignArtifacts() {
|
|
|
2732
3228
|
}
|
|
2733
3229
|
});
|
|
2734
3230
|
}
|
|
3231
|
+
async function campaignDownload() {
|
|
3232
|
+
const buildId = positionalAfter("download") || flagArg("campaign-build-id");
|
|
3233
|
+
if (!buildId) die("Usage: signaliz campaign download <campaign_build_id> [--format csv|ndjson]");
|
|
3234
|
+
const sdk = getSdk();
|
|
3235
|
+
const format = flagArg("format") || "csv";
|
|
3236
|
+
const result = await sdk.campaigns.downloadCampaignArtifact(buildId, { format });
|
|
3237
|
+
output(result, () => {
|
|
3238
|
+
console.log(`Artifact: ${result.format} (${result.rowCount} rows)`);
|
|
3239
|
+
if (result.partCount > 1) console.log(`Parts: ${result.partCount}`);
|
|
3240
|
+
const parts = Array.isArray(result.parts) ? result.parts : [];
|
|
3241
|
+
for (const part of parts) {
|
|
3242
|
+
const url = part.signedUrl;
|
|
3243
|
+
if (!url) continue;
|
|
3244
|
+
const label = result.partCount > 1 ? `part ${part.partIndex}` : "download";
|
|
3245
|
+
console.log(`${label}: ${url}`);
|
|
3246
|
+
}
|
|
3247
|
+
});
|
|
3248
|
+
}
|
|
2735
3249
|
async function campaignApprove() {
|
|
2736
3250
|
const buildId = positionalAfter("approve") || positionalAfter("approve-delivery") || flagArg("campaign-build-id");
|
|
2737
3251
|
if (!buildId) die("Usage: signaliz campaign approve <campaign_build_id> --destination-type <json|csv|webhook>");
|
|
@@ -2787,6 +3301,8 @@ async function campaign(sub) {
|
|
|
2787
3301
|
return campaignRows();
|
|
2788
3302
|
case "artifacts":
|
|
2789
3303
|
return campaignArtifacts();
|
|
3304
|
+
case "download":
|
|
3305
|
+
return campaignDownload();
|
|
2790
3306
|
case "approve":
|
|
2791
3307
|
case "approve-delivery":
|
|
2792
3308
|
return campaignApprove();
|
|
@@ -2794,7 +3310,7 @@ async function campaign(sub) {
|
|
|
2794
3310
|
return campaignCancel();
|
|
2795
3311
|
default:
|
|
2796
3312
|
die(`Unknown campaign subcommand: ${sub}
|
|
2797
|
-
Available: scope, build, status, rows, artifacts, approve, cancel`);
|
|
3313
|
+
Available: scope, build, status, rows, artifacts, download, approve, cancel`);
|
|
2798
3314
|
}
|
|
2799
3315
|
}
|
|
2800
3316
|
var CAMPAIGN_AGENT_APPROVAL_TYPES = [
|
|
@@ -2816,6 +3332,7 @@ var CAMPAIGN_AGENT_HELP = `signaliz campaign-agent <command> [options]
|
|
|
2816
3332
|
Strategy-template campaign builder:
|
|
2817
3333
|
init Emit reusable CampaignBuilderAgentRequest JSON
|
|
2818
3334
|
kit Emit request JSON, CLI commands, MCP calls, SDK example, and BYO pattern
|
|
3335
|
+
memory-kit Emit memory readiness, seed runner, MCP calls, and proof commands
|
|
2819
3336
|
plan Compose an approval-gated strategy-template MCP flow
|
|
2820
3337
|
doctor Inspect built-in lanes, BYO routes, Memory, Brain, and approvals
|
|
2821
3338
|
proof Prove memory, plan, approvals, and build dry-run without spend
|
|
@@ -2831,6 +3348,7 @@ Strategy-template campaign builder:
|
|
|
2831
3348
|
Examples:
|
|
2832
3349
|
signaliz campaign-agent init --strategy-template non-medical-home-care --target-count 250 --use-local-leads --json > campaign-request.json
|
|
2833
3350
|
signaliz campaign-agent kit --strategy-template non-medical-home-care --target-count 250 --use-local-leads --json
|
|
3351
|
+
signaliz campaign-agent memory-kit --strategy-template non-medical-home-care --target-count 250 --use-local-leads --json
|
|
2834
3352
|
signaliz campaign-agent doctor --request-file campaign-request.json --json
|
|
2835
3353
|
signaliz campaign-agent plan --goal "Build a strategy-template campaign for my ICP" --strategy-template non-medical-home-care --target-count 500 --builtins lead_generation,email_finding,email_verification,signals
|
|
2836
3354
|
signaliz campaign-agent proof --goal "Build a strategy-template campaign for my ICP" --strategy-template non-medical-home-care --target-count 100 --json
|
|
@@ -2838,14 +3356,17 @@ Examples:
|
|
|
2838
3356
|
signaliz campaign-agent dry-run --goal "Build a local services campaign" --target-count 250 --use-local-leads --json
|
|
2839
3357
|
signaliz campaign-agent build-approved --goal "Build a strategy-template campaign" --confirm-launch --approve-all --approved-by operator@example.com --spend-limit 500
|
|
2840
3358
|
signaliz campaign-agent build-approved --request-file campaign-builder-agent-request.json --confirm-launch --approve-all --approved-by operator@example.com --spend-limit 500 --wait --approve-delivery --delivery-destination-type json
|
|
2841
|
-
signaliz campaign-agent review <campaign_build_id> --limit 100 --json
|
|
3359
|
+
signaliz campaign-agent review <campaign_build_id> --limit 100 --include-data --json
|
|
2842
3360
|
signaliz campaign-agent status <campaign_build_id> --json
|
|
2843
|
-
signaliz campaign-agent rows <campaign_build_id> --limit 100 --json
|
|
3361
|
+
signaliz campaign-agent rows <campaign_build_id> --limit 100 --include-data --json
|
|
2844
3362
|
|
|
2845
3363
|
Plan options:
|
|
2846
3364
|
--goal TEXT Campaign goal or brief
|
|
2847
3365
|
--output-file FILE Write init output to a reusable request JSON file
|
|
2848
3366
|
--kit-file FILE Write campaign-agent kit output to a JSON file
|
|
3367
|
+
--seed-manifest-file FILE
|
|
3368
|
+
Manifest path for memory-kit seed dry-runs
|
|
3369
|
+
--source NAME memory-kit seed source: north-star, agency, workflow-patterns, instantly-feedback, or all
|
|
2849
3370
|
--request-output-file FILE
|
|
2850
3371
|
Request filename to reference inside kit commands
|
|
2851
3372
|
--request-file FILE Reusable JSON CampaignBuilderAgentRequest; flags override file fields
|
|
@@ -2900,7 +3421,7 @@ async function campaignAgent(sub, rest) {
|
|
|
2900
3421
|
await campaignAgentReview(sub, rest);
|
|
2901
3422
|
return;
|
|
2902
3423
|
}
|
|
2903
|
-
if (!["init", "template", "request-template", "new", "kit", "build-kit", "blueprint", "plan", "doctor", "readiness", "preflight", "proof", "smoke", "commit-plan", "dry-run", "build-approved", "launch-approved"].includes(sub)) {
|
|
3424
|
+
if (!["init", "template", "request-template", "new", "kit", "build-kit", "blueprint", "memory-kit", "seed-kit", "memory", "plan", "doctor", "readiness", "preflight", "proof", "smoke", "commit-plan", "dry-run", "build-approved", "launch-approved"].includes(sub)) {
|
|
2904
3425
|
process.stdout.write(CAMPAIGN_AGENT_HELP);
|
|
2905
3426
|
return;
|
|
2906
3427
|
}
|
|
@@ -2946,6 +3467,38 @@ async function campaignAgent(sub, rest) {
|
|
|
2946
3467
|
if (proof?.command) console.log(`Next: ${proof.command}`);
|
|
2947
3468
|
return;
|
|
2948
3469
|
}
|
|
3470
|
+
if (["memory-kit", "seed-kit", "memory"].includes(sub)) {
|
|
3471
|
+
const requestFromFile2 = campaignAgentRequestFileFromFlags(flags);
|
|
3472
|
+
const goal2 = commandStringFlag(flags, "goal", "brief") || promptArg(rest) || campaignAgentStringValue(requestFromFile2?.goal) || "Build a strategy-template campaign for mature operators in the target ICP.";
|
|
3473
|
+
const request2 = requestFromFile2 ? mergeCampaignAgentRequests(
|
|
3474
|
+
requestFromFile2,
|
|
3475
|
+
campaignAgentRequestFromFlags(goal2, flags, { includeDefaults: false })
|
|
3476
|
+
) : campaignAgentRequestTemplateFromFlags(flags, rest);
|
|
3477
|
+
const createMemoryKit = getCampaignBuilderMemoryKitFactory();
|
|
3478
|
+
const kit = createMemoryKit({
|
|
3479
|
+
...request2,
|
|
3480
|
+
includeLocalLeads: commandBooleanFlag(flags, "use-local-leads"),
|
|
3481
|
+
includeCustomToolPlaceholder: commandBooleanFlag(flags, "with-byo-placeholder") || commandBooleanFlag(flags, "include-custom-tool-placeholder") || commandBooleanFlag(flags, "include-byo-placeholder"),
|
|
3482
|
+
includeNango: !commandBooleanFlag(flags, "no-nango-catalog"),
|
|
3483
|
+
requestFile: commandStringFlag(flags, "request-output-file", "request-file-name") || commandStringFlag(flags, "request-file") || "campaign-request.json",
|
|
3484
|
+
seedManifestFile: commandStringFlag(flags, "seed-manifest-file", "manifest") || ".gtm-kernel-import-state/campaign-memory-dry-run.json",
|
|
3485
|
+
source: commandStringFlag(flags, "source", "memory-source", "seed-source"),
|
|
3486
|
+
workspaceId: commandStringFlag(flags, "workspace-id"),
|
|
3487
|
+
cliPackage: commandStringFlag(flags, "cli-package"),
|
|
3488
|
+
sdkPackage: commandStringFlag(flags, "sdk-package")
|
|
3489
|
+
});
|
|
3490
|
+
const outputFile = commandStringFlag(flags, "kit-file", "output-file", "out");
|
|
3491
|
+
if (outputFile) {
|
|
3492
|
+
(0, import_node_fs.writeFileSync)(outputFile, `${JSON.stringify(kit, null, 2)}
|
|
3493
|
+
`, "utf8");
|
|
3494
|
+
}
|
|
3495
|
+
if (!outputFile || jsonMode()) return output(kit, () => printCampaignAgentMemoryKit(kit));
|
|
3496
|
+
console.log(`Campaign memory kit written: ${outputFile}`);
|
|
3497
|
+
const commands = firstArray(kit.cli_commands);
|
|
3498
|
+
const status = commands.find((command) => command.id === "memory_status");
|
|
3499
|
+
if (status?.command) console.log(`Next: ${status.command}`);
|
|
3500
|
+
return;
|
|
3501
|
+
}
|
|
2949
3502
|
const requestFromFile = campaignAgentRequestFileFromFlags(flags);
|
|
2950
3503
|
const isDoctor = sub === "doctor" || sub === "readiness" || sub === "preflight";
|
|
2951
3504
|
const goal = commandStringFlag(flags, "goal", "brief") || promptArg(rest) || campaignAgentStringValue(requestFromFile?.goal) || (isDoctor ? "Build a strategy-template campaign for the target ICP." : void 0);
|
|
@@ -3057,6 +3610,8 @@ async function campaignAgentReview(sub, rest) {
|
|
|
3057
3610
|
cursor: commandStringFlag(flags, "cursor"),
|
|
3058
3611
|
segment: commandStringFlag(flags, "segment"),
|
|
3059
3612
|
rowStatus: commandStringFlag(flags, "row-status"),
|
|
3613
|
+
includeData: commandOptionalBooleanFlag(flags, "include-data"),
|
|
3614
|
+
includeRaw: commandOptionalBooleanFlag(flags, "include-raw"),
|
|
3060
3615
|
qualified: commandBooleanFlag(flags, "qualified") ? true : commandBooleanFlag(flags, "disqualified") ? false : void 0
|
|
3061
3616
|
};
|
|
3062
3617
|
const review = await agent.reviewBuild?.(buildId, rowOptions) || await campaignAgentBuildReviewFromCampaignApis(agent, campaigns, buildId, rowOptions);
|
|
@@ -3080,6 +3635,8 @@ async function campaignAgentReview(sub, rest) {
|
|
|
3080
3635
|
cursor: commandStringFlag(flags, "cursor"),
|
|
3081
3636
|
segment: commandStringFlag(flags, "segment"),
|
|
3082
3637
|
rowStatus: commandStringFlag(flags, "row-status"),
|
|
3638
|
+
includeData: commandOptionalBooleanFlag(flags, "include-data"),
|
|
3639
|
+
includeRaw: commandOptionalBooleanFlag(flags, "include-raw"),
|
|
3083
3640
|
qualified: commandBooleanFlag(flags, "qualified") ? true : commandBooleanFlag(flags, "disqualified") ? false : void 0
|
|
3084
3641
|
};
|
|
3085
3642
|
const result2 = await (agent.getBuildRows?.bind(agent) || campaigns.rows?.bind(campaigns) || campaigns.getCampaignBuildRows?.bind(campaigns))?.(buildId, rowOptions);
|
|
@@ -3604,6 +4161,39 @@ function printCampaignAgentBuildKit(kit) {
|
|
|
3604
4161
|
for (const action of nextActions.slice(0, 4)) console.log(`- ${action}`);
|
|
3605
4162
|
}
|
|
3606
4163
|
}
|
|
4164
|
+
function printCampaignAgentMemoryKit(kit) {
|
|
4165
|
+
console.log(`Campaign memory kit: ${kit.strategy_template || "custom strategy"}`);
|
|
4166
|
+
if (kit.request_file) console.log(`Request file: ${kit.request_file}`);
|
|
4167
|
+
if (kit.seed_manifest_file) console.log(`Seed manifest: ${kit.seed_manifest_file}`);
|
|
4168
|
+
const sources = firstArray(kit.memory_sources);
|
|
4169
|
+
console.log(`Sources: ${sources.map((source) => source.id || source.seed_source).filter(Boolean).join(", ") || "none"}`);
|
|
4170
|
+
console.log(`Playbooks: ${firstArray(kit.operating_playbooks).join(", ") || "none"}`);
|
|
4171
|
+
const commands = firstArray(kit.cli_commands);
|
|
4172
|
+
if (commands.length) {
|
|
4173
|
+
console.log("\nCLI:");
|
|
4174
|
+
for (const command of commands.slice(0, 4)) {
|
|
4175
|
+
console.log(`- ${command.label || command.id}: ${command.command}`);
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
const calls = firstArray(kit.mcp_calls);
|
|
4179
|
+
if (calls.length) {
|
|
4180
|
+
console.log("\nMCP:");
|
|
4181
|
+
for (const call of calls.slice(0, 3)) {
|
|
4182
|
+
console.log(`- ${call.tool}: ${call.safety}`);
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
const seedRunner = record(kit.seed_runner);
|
|
4186
|
+
if (seedRunner.dry_run_command) {
|
|
4187
|
+
console.log("\nSeed runner:");
|
|
4188
|
+
console.log(`- Dry run: ${seedRunner.dry_run_command}`);
|
|
4189
|
+
if (seedRunner.verify_manifest_command) console.log(`- Verify: ${seedRunner.verify_manifest_command}`);
|
|
4190
|
+
}
|
|
4191
|
+
const nextActions = firstArray(kit.next_actions);
|
|
4192
|
+
if (nextActions.length) {
|
|
4193
|
+
console.log("\nNext:");
|
|
4194
|
+
for (const action of nextActions.slice(0, 4)) console.log(`- ${action}`);
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
3607
4197
|
function printCampaignAgentPlan(plan) {
|
|
3608
4198
|
console.log(`Plan: ${plan.campaignName || plan.goal || plan.planId}`);
|
|
3609
4199
|
if (plan.planId) console.log(`Plan ID: ${plan.planId}`);
|
|
@@ -3638,7 +4228,9 @@ function printCampaignAgentBuildStatus(status) {
|
|
|
3638
4228
|
console.log(`Status: ${status.status}`);
|
|
3639
4229
|
console.log(`Phase: ${status.currentPhase || "N/A"}`);
|
|
3640
4230
|
console.log(`Rows: ${status.recordsSucceeded}/${status.recordsTotal} succeeded, ${status.recordsFailed} failed`);
|
|
4231
|
+
printCampaignCustomerRowCounts(status);
|
|
3641
4232
|
console.log(`Artifacts: ${status.artifactCount}`);
|
|
4233
|
+
if (status.campaignBuildId) printCampaignArtifactDownloadHint(status, status.campaignBuildId);
|
|
3642
4234
|
if (status.triggerRunId) console.log(`Trigger: ${status.triggerRunId}`);
|
|
3643
4235
|
if (Array.isArray(status.warnings) && status.warnings.length) {
|
|
3644
4236
|
console.log(`Warnings: ${status.warnings.length}`);
|
|
@@ -3648,8 +4240,14 @@ function printCampaignAgentBuildStatus(status) {
|
|
|
3648
4240
|
console.log(`Errors: ${status.errors.length}`);
|
|
3649
4241
|
for (const error of status.errors.slice(0, 3)) console.log(` - ${error}`);
|
|
3650
4242
|
}
|
|
3651
|
-
if (status.status === "completed") {
|
|
4243
|
+
if (status.status === "completed" && status.nextAction) {
|
|
4244
|
+
hint(status.nextAction);
|
|
4245
|
+
} else if (status.status === "completed") {
|
|
3652
4246
|
hint(`signaliz campaign-agent rows ${status.campaignBuildId} --limit 100`);
|
|
4247
|
+
} else if (status.status === "pending_approval" && status.approvalAction) {
|
|
4248
|
+
hint(status.approvalAction);
|
|
4249
|
+
} else if (status.status === "pending_approval" && status.nextAction) {
|
|
4250
|
+
hint(status.nextAction);
|
|
3653
4251
|
} else if (status.status === "pending_approval") {
|
|
3654
4252
|
hint(`signaliz campaign-agent approve ${status.campaignBuildId} --destination-type webhook`);
|
|
3655
4253
|
} else if ((status.status === "running" || status.status === "queued") && status.triggerRunId) {
|
|
@@ -3667,6 +4265,7 @@ function printCampaignAgentBuildReview(review) {
|
|
|
3667
4265
|
console.log(`Emails: ${summary.rowsWithEmail || 0}`);
|
|
3668
4266
|
console.log(`Copy ready: ${summary.copyReadyRows || 0}`);
|
|
3669
4267
|
console.log(`Artifacts: ${summary.artifactCount || 0}`);
|
|
4268
|
+
if (review.campaignBuildId) printCampaignArtifactDownloadHint(status, review.campaignBuildId);
|
|
3670
4269
|
console.log(`Delivery approval ready: ${summary.readyForDeliveryApproval === true ? "yes" : "no"}`);
|
|
3671
4270
|
const gates = Array.isArray(review.gates) ? review.gates : [];
|
|
3672
4271
|
if (gates.length) {
|
|
@@ -3804,6 +4403,7 @@ function printCampaignAgentRows(result) {
|
|
|
3804
4403
|
status: row.status || "",
|
|
3805
4404
|
score: row.score ?? ""
|
|
3806
4405
|
})));
|
|
4406
|
+
printCampaignCopySnippets(result.rows);
|
|
3807
4407
|
console.log(`
|
|
3808
4408
|
Showing ${result.rows.length} row(s)${result.hasMore ? " (more available)" : ""}`);
|
|
3809
4409
|
if (result.nextCursor) {
|
|
@@ -4596,6 +5196,7 @@ async function gtm(sub, rest) {
|
|
|
4596
5196
|
days: numberFlag("days"),
|
|
4597
5197
|
networkDays: numberFlag("network-days"),
|
|
4598
5198
|
minSampleSize: numberFlag("min-sample-size"),
|
|
5199
|
+
holdoutMinSampleSize: numberFlag("holdout-min-sample-size"),
|
|
4599
5200
|
minWorkspaceCount: numberFlag("min-workspace-count"),
|
|
4600
5201
|
limit: numberFlag("limit")
|
|
4601
5202
|
});
|
|
@@ -4606,6 +5207,10 @@ async function gtm(sub, rest) {
|
|
|
4606
5207
|
console.log("GTM Brain learning plan");
|
|
4607
5208
|
console.log(` Campaign: ${campaignId}`);
|
|
4608
5209
|
console.log(` Lanes: ${ready}/${lanes.length} ready`);
|
|
5210
|
+
if (result.holdout_lift?.status) {
|
|
5211
|
+
const delta = result.holdout_lift?.lift?.primary_metric_delta;
|
|
5212
|
+
console.log(` Holdout: ${result.holdout_lift.status}${delta !== void 0 ? ` (${delta} ${result.holdout_lift.primary_metric || "primary_metric"})` : ""}`);
|
|
5213
|
+
}
|
|
4609
5214
|
console.log(` Calls: ${calls.length}`);
|
|
4610
5215
|
for (const call of calls.slice(0, 5)) {
|
|
4611
5216
|
const state = call.ready === false ? "blocked" : "ready";
|
|
@@ -4627,6 +5232,7 @@ async function gtm(sub, rest) {
|
|
|
4627
5232
|
days: numberFlag("days"),
|
|
4628
5233
|
networkDays: numberFlag("network-days"),
|
|
4629
5234
|
minSampleSize: numberFlag("min-sample-size"),
|
|
5235
|
+
holdoutMinSampleSize: numberFlag("holdout-min-sample-size"),
|
|
4630
5236
|
minWorkspaceCount: numberFlag("min-workspace-count"),
|
|
4631
5237
|
minPrivacyK: numberFlag("min-privacy-k"),
|
|
4632
5238
|
limit: numberFlag("limit")
|
|
@@ -4880,6 +5486,103 @@ async function gtm(sub, rest) {
|
|
|
4880
5486
|
hint(`signaliz gtm bootstrap${common.campaignId ? ` --campaign-id ${common.campaignId}` : ""} --include-samples`);
|
|
4881
5487
|
});
|
|
4882
5488
|
}
|
|
5489
|
+
if (sub === "feedback-pull" || sub === "instantly-feedback-pull" || sub === "pull-feedback") {
|
|
5490
|
+
const provider = (flagArg("provider") || "instantly").toLowerCase();
|
|
5491
|
+
if (provider !== "instantly") {
|
|
5492
|
+
die("gtm feedback-pull currently supports --provider instantly. Use gtm feedback-webhook for provider-agnostic ingress.");
|
|
5493
|
+
}
|
|
5494
|
+
const source = flagArg("source") || flagArg("pull-source") || "webhook_events";
|
|
5495
|
+
if (!["webhook_events", "emails"].includes(source)) {
|
|
5496
|
+
die("--source must be webhook_events or emails");
|
|
5497
|
+
}
|
|
5498
|
+
if (flagArg("source") && flagArg("pull-source") && flagArg("source") !== flagArg("pull-source")) {
|
|
5499
|
+
die("--source and --pull-source must match when both are provided");
|
|
5500
|
+
}
|
|
5501
|
+
const campaignId = flagArg("campaign-id");
|
|
5502
|
+
const campaignBuildId = flagArg("campaign-build-id") || flagArg("build-id");
|
|
5503
|
+
const providerLinkId = flagArg("provider-link-id");
|
|
5504
|
+
const providerCampaignId = flagArg("provider-campaign-id") || flagArg("instantly-campaign-id") || positionalAfter(sub);
|
|
5505
|
+
if (!campaignId && !campaignBuildId && !providerLinkId && !providerCampaignId) {
|
|
5506
|
+
die("Usage: signaliz gtm feedback-pull --provider-campaign-id <instantly_campaign_id> [--source webhook_events|emails] [--confirm]");
|
|
5507
|
+
}
|
|
5508
|
+
const hasEmailHistoryFlags = Boolean(flagArg("email-type") || flagArg("mode") || flagArg("sort-order"));
|
|
5509
|
+
if (hasEmailHistoryFlags && source !== "emails") {
|
|
5510
|
+
die("--email-type, --mode, and --sort-order require --source emails");
|
|
5511
|
+
}
|
|
5512
|
+
const emailType = source === "emails" ? flagArg("email-type") || "received" : void 0;
|
|
5513
|
+
if (emailType !== void 0 && !["received", "sent", "manual"].includes(emailType)) {
|
|
5514
|
+
die("--email-type must be received, sent, or manual");
|
|
5515
|
+
}
|
|
5516
|
+
const mode = source === "emails" ? flagArg("mode") || "emode_all" : void 0;
|
|
5517
|
+
if (mode !== void 0 && !["emode_focused", "emode_others", "emode_all"].includes(mode)) {
|
|
5518
|
+
die("--mode must be emode_focused, emode_others, or emode_all");
|
|
5519
|
+
}
|
|
5520
|
+
const sortOrder = source === "emails" ? flagArg("sort-order") || "asc" : void 0;
|
|
5521
|
+
if (sortOrder !== void 0 && !["asc", "desc"].includes(sortOrder)) {
|
|
5522
|
+
die("--sort-order must be asc or desc");
|
|
5523
|
+
}
|
|
5524
|
+
if (hasFlag("write") && !hasFlag("confirm") && !hasFlag("confirm-write")) {
|
|
5525
|
+
die("Write-mode feedback pulls require --confirm or --confirm-write. Run without --confirm first for a dry-run count.");
|
|
5526
|
+
}
|
|
5527
|
+
const confirmed = hasFlag("confirm") || hasFlag("confirm-write");
|
|
5528
|
+
const dryRun = !confirmed;
|
|
5529
|
+
const result = await sdk.gtm.pullInstantlyFeedback({
|
|
5530
|
+
campaignId,
|
|
5531
|
+
campaignBuildId,
|
|
5532
|
+
providerLinkId,
|
|
5533
|
+
providerCampaignId,
|
|
5534
|
+
instantlyCampaignId: flagArg("instantly-campaign-id"),
|
|
5535
|
+
integrationId: flagArg("integration-id"),
|
|
5536
|
+
source,
|
|
5537
|
+
instantlyProfile: flagArg("instantly-profile") || flagArg("profile"),
|
|
5538
|
+
cursor: flagArg("cursor"),
|
|
5539
|
+
from: flagArg("from") || flagArg("since"),
|
|
5540
|
+
to: flagArg("to") || flagArg("until"),
|
|
5541
|
+
limit: numberFlag("limit"),
|
|
5542
|
+
maxPages: numberFlag("max-pages"),
|
|
5543
|
+
emailType,
|
|
5544
|
+
mode,
|
|
5545
|
+
sortOrder,
|
|
5546
|
+
createMemory: !hasFlag("no-memory"),
|
|
5547
|
+
writeRoutineOutcomes: !hasFlag("no-routine-outcomes"),
|
|
5548
|
+
dryRun,
|
|
5549
|
+
runBrainCycle: !hasFlag("no-brain-cycle"),
|
|
5550
|
+
brainCycleWriteMode: flagArg("write-mode") || "dry_run",
|
|
5551
|
+
brainCyclePhases: csvFlag("brain-cycle-phases"),
|
|
5552
|
+
brainCycleMinIngested: numberFlag("brain-cycle-min-ingested"),
|
|
5553
|
+
brainCycleMinIntervalMinutes: numberFlag("brain-cycle-min-interval-minutes")
|
|
5554
|
+
});
|
|
5555
|
+
return output(result, () => {
|
|
5556
|
+
console.log("GTM Instantly feedback pull");
|
|
5557
|
+
console.log(` Mode: ${dryRun ? "dry_run" : "write"}`);
|
|
5558
|
+
console.log(` Source: ${result.source || source}`);
|
|
5559
|
+
if (result.provider_campaign_id || providerCampaignId) console.log(` Campaign: ${result.provider_campaign_id || providerCampaignId}`);
|
|
5560
|
+
if (result.run_id) console.log(` Run ID: ${result.run_id}`);
|
|
5561
|
+
if (result.status) console.log(` Status: ${result.status}`);
|
|
5562
|
+
if (result.max_pages !== void 0) console.log(` Pages: ${result.max_pages}`);
|
|
5563
|
+
const countFields = [
|
|
5564
|
+
["Seen", result.webhook_events_seen ?? result.email_records_seen ?? result.source_events],
|
|
5565
|
+
["Normalized", result.feedback_events_synced ?? result.events_normalized],
|
|
5566
|
+
["Ingested", result.ingested],
|
|
5567
|
+
["Duplicates", result.duplicates],
|
|
5568
|
+
["Unmatched", result.unmatched]
|
|
5569
|
+
];
|
|
5570
|
+
for (const [label, value] of countFields) {
|
|
5571
|
+
if (value !== void 0 && value !== null) console.log(` ${label}: ${value}`);
|
|
5572
|
+
}
|
|
5573
|
+
if (Array.isArray(result.blockers) && result.blockers.length) console.log(` Blockers: ${result.blockers.join("; ")}`);
|
|
5574
|
+
if (dryRun) {
|
|
5575
|
+
if (result.run_id) hint(`signaliz ops run-status ${result.run_id} --watch`);
|
|
5576
|
+
hint("Review the dry-run counts before writing feedback, memory, and outcomes: rerun with --confirm.");
|
|
5577
|
+
} else if (campaignId) {
|
|
5578
|
+
hint(`signaliz gtm learning ${campaignId} --include-network`);
|
|
5579
|
+
} else if (campaignBuildId) {
|
|
5580
|
+
hint(`signaliz gtm execution --campaign-build-id ${campaignBuildId}`);
|
|
5581
|
+
} else {
|
|
5582
|
+
hint("After the pull completes, run signaliz gtm bootstrap --include-samples to verify feedback and memory readiness.");
|
|
5583
|
+
}
|
|
5584
|
+
});
|
|
5585
|
+
}
|
|
4883
5586
|
if (sub === "nango") return gtmNango(rest[0], rest.slice(1));
|
|
4884
5587
|
if (!sub || sub === "list" || sub === "sources") {
|
|
4885
5588
|
const result = await sdk.leads.listNativeGtmCapabilities(flagArg("category"));
|
|
@@ -4940,7 +5643,7 @@ ${i + 1}. ${m.capability_id} (score ${m.score}) \u2014 ${m.label}`);
|
|
|
4940
5643
|
const result = await sdk.leads.checkStatus(jobId);
|
|
4941
5644
|
return output(result);
|
|
4942
5645
|
}
|
|
4943
|
-
die("Usage: signaliz gtm <context|bootstrap|strategy-memory|agent-template|agent-plan|plan|commit-plan|prepare-build|campaigns|campaign|existing-campaigns|audit-existing|memory|learning|execution|integrations|provider-prepare|activate-route|list|find|run|status|nango>");
|
|
5646
|
+
die("Usage: signaliz gtm <context|bootstrap|strategy-memory|agent-template|agent-plan|plan|commit-plan|prepare-build|campaigns|campaign|existing-campaigns|audit-existing|memory|learning|execution|integrations|provider-prepare|activate-route|feedback-webhook|feedback-pull|list|find|run|status|nango>");
|
|
4944
5647
|
}
|
|
4945
5648
|
function nangoActionInput() {
|
|
4946
5649
|
const fromFile = readJsonFlag("input-file");
|
|
@@ -4957,30 +5660,146 @@ function nangoBaseOptions() {
|
|
|
4957
5660
|
nangoConnectionId: flagArg("nango-connection-id")
|
|
4958
5661
|
};
|
|
4959
5662
|
}
|
|
4960
|
-
function nangoConnectOptions() {
|
|
5663
|
+
function nangoConnectOptions(defaultSurface = "gtm_kernel") {
|
|
4961
5664
|
return {
|
|
4962
5665
|
providerId: flagArg("provider-id") || flagArg("provider"),
|
|
4963
5666
|
integrationId: flagArg("integration-id") || flagArg("provider-config-key"),
|
|
4964
5667
|
providerDisplayName: flagArg("provider-display-name") || flagArg("provider-name"),
|
|
4965
5668
|
integrationDisplayName: flagArg("integration-display-name"),
|
|
4966
5669
|
allowedIntegrations: csvFlag("allowed-integrations"),
|
|
4967
|
-
surface: flagArg("surface") ||
|
|
5670
|
+
surface: flagArg("surface") || defaultSurface,
|
|
4968
5671
|
source: flagArg("source") || "signaliz_cli",
|
|
4969
5672
|
userEmail: flagArg("user-email"),
|
|
4970
5673
|
userDisplayName: flagArg("user-display-name")
|
|
4971
5674
|
};
|
|
4972
5675
|
}
|
|
5676
|
+
function nangoPositionalValues(rest = []) {
|
|
5677
|
+
const values = [];
|
|
5678
|
+
for (let index = 0; index < rest.length; index++) {
|
|
5679
|
+
const value = rest[index];
|
|
5680
|
+
if (value.startsWith("--")) {
|
|
5681
|
+
if (!value.includes("=") && rest[index + 1] && !rest[index + 1].startsWith("--")) index++;
|
|
5682
|
+
continue;
|
|
5683
|
+
}
|
|
5684
|
+
values.push(value);
|
|
5685
|
+
}
|
|
5686
|
+
return values;
|
|
5687
|
+
}
|
|
5688
|
+
function nangoFlowOptions(rest = []) {
|
|
5689
|
+
const positionalSearch = nangoPositionalValues(rest).join(" ");
|
|
5690
|
+
const search = flagArg("search") || flagArg("query") || positionalSearch || void 0;
|
|
5691
|
+
return {
|
|
5692
|
+
...nangoBaseOptions(),
|
|
5693
|
+
query: flagArg("query"),
|
|
5694
|
+
search,
|
|
5695
|
+
providerId: flagArg("provider-id") || flagArg("provider"),
|
|
5696
|
+
provider: flagArg("provider"),
|
|
5697
|
+
intent: flagArg("intent"),
|
|
5698
|
+
actionName: flagArg("action-name") || flagArg("action"),
|
|
5699
|
+
toolName: flagArg("tool-name"),
|
|
5700
|
+
proxyPath: flagArg("proxy-path") || flagArg("nango-proxy-path"),
|
|
5701
|
+
method: flagArg("method"),
|
|
5702
|
+
input: nangoActionInput(),
|
|
5703
|
+
cadence: flagArg("cadence"),
|
|
5704
|
+
fieldMap: readInlineJsonFlag("field-map-json") || readJsonFlag("field-map-file"),
|
|
5705
|
+
requiredFields: csvFlag("required-fields") || csvFlag("required-field"),
|
|
5706
|
+
confirmSpend: hasFlag("confirm-spend"),
|
|
5707
|
+
writeConfirmed: hasFlag("write-confirmed") || hasFlag("confirm-write") || void 0,
|
|
5708
|
+
layer: flagArg("layer"),
|
|
5709
|
+
campaignId: flagArg("campaign-id"),
|
|
5710
|
+
limit: numberFlag("limit"),
|
|
5711
|
+
includeProviderCatalog: hasFlag("skip-provider-catalog") ? false : hasFlag("include-provider-catalog") ? true : void 0
|
|
5712
|
+
};
|
|
5713
|
+
}
|
|
4973
5714
|
function nangoStatusUrl(result) {
|
|
4974
5715
|
return result?.status_url || result?.statusUrl || result?.nango_result?.status_url || result?.nango_result?.statusUrl;
|
|
4975
5716
|
}
|
|
4976
|
-
|
|
5717
|
+
function nangoActionId(result) {
|
|
5718
|
+
return result?.action_id || result?.actionId || result?.nango_result?.action_id || result?.nango_result?.actionId || result?.nango_result?.id;
|
|
5719
|
+
}
|
|
5720
|
+
function nangoActionStatus(result) {
|
|
5721
|
+
return result?.status || result?.nango_result?.status;
|
|
5722
|
+
}
|
|
5723
|
+
function isTerminalNangoActionStatus(status) {
|
|
5724
|
+
return ["completed", "succeeded", "success", "failed", "error", "cancelled", "canceled"].includes(String(status || "").toLowerCase());
|
|
5725
|
+
}
|
|
5726
|
+
async function waitForNangoActionResult(nango, call, opts = {}) {
|
|
5727
|
+
const intervalMs = Math.max(250, Number(opts.intervalMs ?? 5e3));
|
|
5728
|
+
const maxPolls = Math.max(1, Math.min(60, Math.trunc(Number(opts.maxPolls ?? 12))));
|
|
5729
|
+
const timeoutMs = Math.max(250, Number(opts.timeoutMs ?? 6e4));
|
|
5730
|
+
let statusUrl = nangoStatusUrl(call);
|
|
5731
|
+
let actionId = nangoActionId(call);
|
|
5732
|
+
let latest = statusUrl || actionId ? void 0 : call;
|
|
5733
|
+
let polls = 0;
|
|
5734
|
+
const startedAt = Date.now();
|
|
5735
|
+
while ((statusUrl || actionId) && polls < maxPolls && Date.now() - startedAt <= timeoutMs) {
|
|
5736
|
+
polls += 1;
|
|
5737
|
+
latest = await nango.getNangoActionResult({ actionId, statusUrl });
|
|
5738
|
+
statusUrl = nangoStatusUrl(latest) || statusUrl;
|
|
5739
|
+
actionId = nangoActionId(latest) || actionId;
|
|
5740
|
+
if (isTerminalNangoActionStatus(nangoActionStatus(latest))) break;
|
|
5741
|
+
if (polls < maxPolls && Date.now() - startedAt < timeoutMs) await sleep(intervalMs);
|
|
5742
|
+
}
|
|
5743
|
+
const status = nangoActionStatus(latest || call);
|
|
5744
|
+
const timedOut = Boolean((statusUrl || actionId) && !isTerminalNangoActionStatus(status) && (polls >= maxPolls || Date.now() - startedAt > timeoutMs));
|
|
5745
|
+
return {
|
|
5746
|
+
call,
|
|
5747
|
+
result: latest,
|
|
5748
|
+
status,
|
|
5749
|
+
action_id: actionId,
|
|
5750
|
+
actionId,
|
|
5751
|
+
status_url: statusUrl,
|
|
5752
|
+
statusUrl,
|
|
5753
|
+
polls,
|
|
5754
|
+
max_polls: maxPolls,
|
|
5755
|
+
maxPolls,
|
|
5756
|
+
interval_ms: intervalMs,
|
|
5757
|
+
intervalMs,
|
|
5758
|
+
timeout_ms: timeoutMs,
|
|
5759
|
+
timeoutMs,
|
|
5760
|
+
timed_out: timedOut,
|
|
5761
|
+
timedOut
|
|
5762
|
+
};
|
|
5763
|
+
}
|
|
5764
|
+
async function gtmNango(sub, rest, namespace = "gtm") {
|
|
4977
5765
|
const sdk = getSdk();
|
|
5766
|
+
const nango = namespace === "ops" ? sdk.ops : sdk.gtm;
|
|
5767
|
+
const commandPrefix = namespace === "ops" ? "signaliz ops nango" : "signaliz gtm nango";
|
|
5768
|
+
const defaultSurface = namespace === "ops" ? "ops_destinations" : "gtm_kernel";
|
|
5769
|
+
if (sub === "flow" || sub === "plan" || sub === "prepare" || sub === "search") {
|
|
5770
|
+
const result = await nango.prepareNangoIntegrationFlow(nangoFlowOptions(rest));
|
|
5771
|
+
return output(result, () => {
|
|
5772
|
+
console.log(`Nango integration flow: ${result?.status || "prepared"}`);
|
|
5773
|
+
if (result?.provider_id) console.log(` Provider: ${result.provider_id}`);
|
|
5774
|
+
if (result?.integration_id) console.log(` Integration: ${result.integration_id}`);
|
|
5775
|
+
if (result?.selected_connection?.id) console.log(` Workspace connection: ${result.selected_connection.id}`);
|
|
5776
|
+
const providers = Array.isArray(result?.provider_library?.providers) ? result.provider_library.providers : [];
|
|
5777
|
+
if (providers.length) {
|
|
5778
|
+
console.log(" Provider matches:");
|
|
5779
|
+
for (const provider of providers.slice(0, 5)) console.log(` - ${provider.name || provider.id} (${provider.id})`);
|
|
5780
|
+
}
|
|
5781
|
+
const connections = Array.isArray(result?.matched_connections) ? result.matched_connections : [];
|
|
5782
|
+
if (connections.length) {
|
|
5783
|
+
console.log(" Saved connections:");
|
|
5784
|
+
for (const connection of connections.slice(0, 5)) {
|
|
5785
|
+
const ready = connection.ready_for_route ? "ready" : connection.needs_attention ? "needs reconnect" : "not ready";
|
|
5786
|
+
console.log(` - ${connection.connector_name || connection.provider_config_key || connection.id}: ${ready} (${connection.id})`);
|
|
5787
|
+
}
|
|
5788
|
+
}
|
|
5789
|
+
const nextActions = Array.isArray(result?.next_actions) ? result.next_actions : [];
|
|
5790
|
+
if (nextActions.length) {
|
|
5791
|
+
console.log(" Next calls:");
|
|
5792
|
+
for (const action of nextActions.slice(0, 5)) console.log(` - ${action.tool}: ${action.reason || "next step"}`);
|
|
5793
|
+
}
|
|
5794
|
+
if (result?.next_action) hint(result.next_action);
|
|
5795
|
+
});
|
|
5796
|
+
}
|
|
4978
5797
|
if (sub === "connect" || sub === "auth" || sub === "authorize") {
|
|
4979
|
-
const options = nangoConnectOptions();
|
|
5798
|
+
const options = nangoConnectOptions(defaultSurface);
|
|
4980
5799
|
if (!options.providerId && !options.integrationId && (!options.allowedIntegrations || options.allowedIntegrations.length === 0)) {
|
|
4981
|
-
die(
|
|
5800
|
+
die(`Usage: ${commandPrefix} connect --provider-id <provider> [--integration-id <key>] [--allowed-integrations a,b]`);
|
|
4982
5801
|
}
|
|
4983
|
-
const result = await
|
|
5802
|
+
const result = await nango.createNangoConnectSession(options);
|
|
4984
5803
|
return output(result, () => {
|
|
4985
5804
|
console.log(`Nango connect session: ${result?.status || "created"}`);
|
|
4986
5805
|
if (result?.provider_id || options.providerId) console.log(` Provider: ${result?.provider_id || options.providerId}`);
|
|
@@ -4988,11 +5807,11 @@ async function gtmNango(sub, rest) {
|
|
|
4988
5807
|
if (result?.connect_link || result?.auth_window_url) console.log(` Auth link: ${result.connect_link || result.auth_window_url}`);
|
|
4989
5808
|
if (result?.expires_at) console.log(` Expires: ${result.expires_at}`);
|
|
4990
5809
|
if (result?.next_action) console.log(` Next: ${result.next_action}`);
|
|
4991
|
-
hint(
|
|
5810
|
+
hint(`After authorization finishes, run ${commandPrefix} tools --workspace-connection-id <id> --provider-config-key <key>`);
|
|
4992
5811
|
});
|
|
4993
5812
|
}
|
|
4994
5813
|
if (!sub || sub === "tools" || sub === "list") {
|
|
4995
|
-
const result = await
|
|
5814
|
+
const result = await nango.listNangoTools({
|
|
4996
5815
|
...nangoBaseOptions(),
|
|
4997
5816
|
format: flagArg("format"),
|
|
4998
5817
|
includeRaw: hasFlag("include-raw")
|
|
@@ -5003,39 +5822,153 @@ async function gtmNango(sub, rest) {
|
|
|
5003
5822
|
for (const tool of tools2.slice(0, 10)) {
|
|
5004
5823
|
console.log(`- ${tool.name || tool.action_name || tool.id}: ${tool.description || tool.type || "action"}`);
|
|
5005
5824
|
}
|
|
5006
|
-
hint(
|
|
5825
|
+
hint(`${commandPrefix} call <action_name> --workspace-connection-id <id> --input-json '{"email":"buyer@example.com"}' --dry-run`);
|
|
5826
|
+
});
|
|
5827
|
+
}
|
|
5828
|
+
if (namespace === "ops" && (sub === "proof" || sub === "audit" || sub === "read-write")) {
|
|
5829
|
+
const result = await nango.proveNangoReadWrite({
|
|
5830
|
+
...nangoBaseOptions(),
|
|
5831
|
+
limit: numberFlag("limit"),
|
|
5832
|
+
includeRaw: hasFlag("include-raw"),
|
|
5833
|
+
readProxyPath: flagArg("read-proxy-path") || flagArg("proxy-path"),
|
|
5834
|
+
writeProxyPath: flagArg("write-proxy-path"),
|
|
5835
|
+
method: flagArg("method") || flagArg("http-method"),
|
|
5836
|
+
executeReadProbe: hasFlag("execute-read-probe"),
|
|
5837
|
+
executeWriteProbe: hasFlag("execute-write-probe"),
|
|
5838
|
+
confirm: hasFlag("confirm"),
|
|
5839
|
+
confirmWrite: hasFlag("confirm-write") || hasFlag("confirm"),
|
|
5840
|
+
input: nangoActionInput(),
|
|
5841
|
+
writeInput: readInlineJsonFlag("write-input-json") || readJsonFlag("write-input-file")
|
|
5842
|
+
});
|
|
5843
|
+
return output(result, () => {
|
|
5844
|
+
const summary = result?.summary || {};
|
|
5845
|
+
const connectedRows = summary.connected_connection_rows ?? summary.connection_rows ?? 0;
|
|
5846
|
+
const connectedUnique = summary.connected_unique_connections ?? summary.unique_connections ?? 0;
|
|
5847
|
+
console.log(`Nango proof: ${result?.status || "unknown"}`);
|
|
5848
|
+
console.log(`Connections: ${summary.connection_rows ?? 0} rows / ${summary.unique_connections ?? 0} unique`);
|
|
5849
|
+
console.log(`Connected: ${connectedRows} rows / ${connectedUnique} unique`);
|
|
5850
|
+
console.log(`Reconnect required: ${summary.reconnect_required ?? summary.needs_attention_connection_rows ?? 0}`);
|
|
5851
|
+
console.log(`Action tools: ${summary.action_tools ?? 0}`);
|
|
5852
|
+
console.log(`Runtime reads: ${summary.runtime_read_verified ?? 0}/${connectedRows}`);
|
|
5853
|
+
console.log(`Writes: ${summary.write_verified ?? 0}/${connectedRows}`);
|
|
5854
|
+
if (summary.duplicate_connection_rows) console.log(`Duplicates: ${summary.duplicate_connection_rows}`);
|
|
5855
|
+
if (summary.duplicate_connected_connection_rows) console.log(`Connected duplicates: ${summary.duplicate_connected_connection_rows}`);
|
|
5856
|
+
if (result?.next_action) console.log(`Next: ${result.next_action}`);
|
|
5857
|
+
});
|
|
5858
|
+
}
|
|
5859
|
+
if (namespace === "ops" && (sub === "schedule" || sub === "recur")) {
|
|
5860
|
+
const promptText = promptArg(rest);
|
|
5861
|
+
if (!promptText) {
|
|
5862
|
+
die(`Usage: ${commandPrefix} ${sub} "plain-English recurring goal" --workspace-connection-id <id> --action-name <action> [--confirm-spend] [--wait]`);
|
|
5863
|
+
}
|
|
5864
|
+
const scheduleInput = {
|
|
5865
|
+
prompt: promptText,
|
|
5866
|
+
blueprint: flagArg("blueprint"),
|
|
5867
|
+
targetCount: numberFlag("target-count"),
|
|
5868
|
+
cadence: flagArg("cadence") || "daily",
|
|
5869
|
+
wakeOnEvents: csvFlag("wake-on-events") || csvFlag("wake-events") || csvFlag("wake-event"),
|
|
5870
|
+
timezone: flagArg("timezone"),
|
|
5871
|
+
companyDomains: csvFlag("company-domains") || csvFlag("domains"),
|
|
5872
|
+
customAiPrompt: flagArg("ai-prompt") || flagArg("custom-ai-prompt"),
|
|
5873
|
+
signalPrompt: flagArg("signal-prompt"),
|
|
5874
|
+
outputPrompt: flagArg("output-prompt") || flagArg("result-prompt"),
|
|
5875
|
+
confirmSpend: hasFlag("confirm-spend"),
|
|
5876
|
+
...nangoBaseOptions(),
|
|
5877
|
+
actionName: flagArg("action-name") || flagArg("action") || flagArg("nango-action"),
|
|
5878
|
+
toolName: flagArg("tool-name"),
|
|
5879
|
+
proxyPath: flagArg("proxy-path") || flagArg("nango-proxy-path"),
|
|
5880
|
+
method: flagArg("method") || flagArg("http-method"),
|
|
5881
|
+
input: nangoActionInput(),
|
|
5882
|
+
fieldMap: readInlineJsonFlag("field-map-json") || readJsonFlag("field-map-file"),
|
|
5883
|
+
requiredFields: csvFlag("required-fields") || csvFlag("required-field"),
|
|
5884
|
+
writeConfirmed: hasFlag("write-confirmed") || hasFlag("confirm") || hasFlag("confirm-write") || void 0,
|
|
5885
|
+
agentWriteConfirmed: hasFlag("agent-write-confirmed") || void 0
|
|
5886
|
+
};
|
|
5887
|
+
if (hasFlag("wait")) {
|
|
5888
|
+
const combined = await nango.scheduleNangoActionAndWait({
|
|
5889
|
+
...scheduleInput,
|
|
5890
|
+
force: hasFlag("force"),
|
|
5891
|
+
instruction: flagArg("instruction"),
|
|
5892
|
+
intervalMs: numberFlag("interval-ms") ?? numberFlag("wait-interval-ms"),
|
|
5893
|
+
maxPolls: numberFlag("max-polls") ?? numberFlag("wait-max-polls"),
|
|
5894
|
+
timeoutMs: numberFlag("timeout-ms") ?? numberFlag("wait-timeout-ms"),
|
|
5895
|
+
limit: numberFlag("limit"),
|
|
5896
|
+
cursor: flagArg("cursor"),
|
|
5897
|
+
includeFailedRuns: hasFlag("include-failed-runs"),
|
|
5898
|
+
includeResults: !hasFlag("no-results")
|
|
5899
|
+
});
|
|
5900
|
+
return output(combined, () => {
|
|
5901
|
+
console.log(`Nango Op scheduled: ${combined.schedule?.op_id || combined.op_id}`);
|
|
5902
|
+
printOpsWaitForResults(combined);
|
|
5903
|
+
});
|
|
5904
|
+
}
|
|
5905
|
+
const result = await nango.scheduleNangoAction(scheduleInput);
|
|
5906
|
+
return output(result, () => {
|
|
5907
|
+
if (result.approval_required || result.error_code === "APPROVAL_REQUIRED") {
|
|
5908
|
+
console.log("Approval required");
|
|
5909
|
+
if (result.plan) {
|
|
5910
|
+
console.log(`Plan: ${result.plan.title || result.plan.plan_id || "pending approval"}`);
|
|
5911
|
+
if (result.plan.ui_summary) console.log(`Summary: ${result.plan.ui_summary}`);
|
|
5912
|
+
printPlanSchedule(result.plan);
|
|
5913
|
+
printOpsExecutionContract(result.plan);
|
|
5914
|
+
}
|
|
5915
|
+
console.log(`Next: ${result.next_action || "Retry with --confirm-spend after review."}`);
|
|
5916
|
+
hint(`${commandPrefix} ${sub} ${JSON.stringify(promptText)} --confirm-spend`);
|
|
5917
|
+
return;
|
|
5918
|
+
}
|
|
5919
|
+
console.log(`Nango Op scheduled: ${result.op_id}`);
|
|
5920
|
+
console.log(`Status: ${result.status || "scheduled"}`);
|
|
5921
|
+
if (result.plan) printOpsExecutionContract(result.plan);
|
|
5922
|
+
console.log(`Next: ${result.next_action || "Run or wait for the next scheduled tick."}`);
|
|
5923
|
+
if (result.op_id) hint(`signaliz ops wait ${result.op_id}`);
|
|
5007
5924
|
});
|
|
5008
5925
|
}
|
|
5009
5926
|
if (sub === "call" || sub === "run") {
|
|
5010
|
-
const actionName = rest[0] || flagArg("action-name");
|
|
5927
|
+
const actionName = nangoPositionalValues(rest)[0] || flagArg("action-name");
|
|
5011
5928
|
const toolName = flagArg("tool-name");
|
|
5012
|
-
|
|
5013
|
-
|
|
5929
|
+
const proxyPath = flagArg("proxy-path") || flagArg("nango-proxy-path");
|
|
5930
|
+
if (!actionName && !toolName && !proxyPath) {
|
|
5931
|
+
die(`Usage: ${commandPrefix} call <action_name> --workspace-connection-id <id> --input-json '{"email":"buyer@example.com"}' [--execute --confirm], or ${commandPrefix} call --workspace-connection-id <id> --proxy-path /provider/path --method GET`);
|
|
5014
5932
|
}
|
|
5015
|
-
const
|
|
5933
|
+
const callOptions = {
|
|
5016
5934
|
...nangoBaseOptions(),
|
|
5017
5935
|
actionName,
|
|
5018
5936
|
toolName,
|
|
5937
|
+
deliveryMode: proxyPath ? "proxy" : void 0,
|
|
5938
|
+
proxyPath,
|
|
5939
|
+
method: flagArg("method") || flagArg("http-method"),
|
|
5019
5940
|
input: nangoActionInput(),
|
|
5020
|
-
async: hasFlag("async") || void 0,
|
|
5941
|
+
async: hasFlag("async") || hasFlag("wait") || void 0,
|
|
5021
5942
|
maxRetries: numberFlag("max-retries"),
|
|
5022
5943
|
dryRun: hasFlag("execute") ? false : hasFlag("dry-run") ? true : void 0,
|
|
5023
5944
|
confirm: hasFlag("confirm") || void 0,
|
|
5024
5945
|
confirmWrite: hasFlag("confirm-write") || void 0
|
|
5025
|
-
}
|
|
5026
|
-
|
|
5946
|
+
};
|
|
5947
|
+
const waitOptions = {
|
|
5948
|
+
intervalMs: numberFlag("interval-ms") ?? numberFlag("wait-interval-ms"),
|
|
5949
|
+
maxPolls: numberFlag("max-polls") ?? numberFlag("wait-max-polls"),
|
|
5950
|
+
timeoutMs: numberFlag("timeout-ms") ?? numberFlag("wait-timeout-ms")
|
|
5951
|
+
};
|
|
5952
|
+
const waited = hasFlag("wait") && namespace === "ops" ? await nango.callNangoToolAndWait({ ...callOptions, ...waitOptions }) : null;
|
|
5953
|
+
const result = waited?.call || await nango.callNangoTool(callOptions);
|
|
5954
|
+
const finalResult = waited || (hasFlag("wait") ? await waitForNangoActionResult(nango, result, waitOptions) : result);
|
|
5955
|
+
return output(finalResult, () => {
|
|
5027
5956
|
console.log(`Nango action ${result?.status || "submitted"}: ${actionName || toolName}`);
|
|
5028
5957
|
const statusUrl = nangoStatusUrl(result);
|
|
5029
5958
|
if (statusUrl) console.log(` Status URL: ${statusUrl}`);
|
|
5959
|
+
if (finalResult !== result) {
|
|
5960
|
+
console.log(` Result: ${finalResult.status || "unknown"} (${finalResult.polls}/${finalResult.max_polls} polls)`);
|
|
5961
|
+
if (finalResult.timed_out) console.log(" Timed out before a terminal Nango result.");
|
|
5962
|
+
}
|
|
5030
5963
|
if (result?.next_action) console.log(` Next: ${result.next_action}`);
|
|
5031
|
-
if (statusUrl) hint(
|
|
5964
|
+
if (statusUrl && finalResult === result) hint(`${commandPrefix} result --status-url ${statusUrl}`);
|
|
5032
5965
|
});
|
|
5033
5966
|
}
|
|
5034
5967
|
if (sub === "result" || sub === "status") {
|
|
5035
|
-
const actionId = rest[0] || flagArg("action-id");
|
|
5968
|
+
const actionId = nangoPositionalValues(rest)[0] || flagArg("action-id");
|
|
5036
5969
|
const statusUrl = flagArg("status-url");
|
|
5037
|
-
if (!actionId && !statusUrl) die(
|
|
5038
|
-
const result = await
|
|
5970
|
+
if (!actionId && !statusUrl) die(`Usage: ${commandPrefix} result --action-id <id> OR --status-url /action/<id>`);
|
|
5971
|
+
const result = await nango.getNangoActionResult({ actionId, statusUrl });
|
|
5039
5972
|
return output(result, () => {
|
|
5040
5973
|
console.log(`Nango action result: ${result?.status || "unknown"}`);
|
|
5041
5974
|
if (result?.action_id || actionId) console.log(` Action ID: ${result?.action_id || actionId}`);
|
|
@@ -5043,7 +5976,7 @@ async function gtmNango(sub, rest) {
|
|
|
5043
5976
|
if (nextStatusUrl) console.log(` Status URL: ${nextStatusUrl}`);
|
|
5044
5977
|
});
|
|
5045
5978
|
}
|
|
5046
|
-
die(
|
|
5979
|
+
die(`Usage: ${commandPrefix} <flow|search|connect|tools|call|schedule|result>`);
|
|
5047
5980
|
}
|
|
5048
5981
|
async function email(sub, rest) {
|
|
5049
5982
|
const sdk = getSdk();
|
|
@@ -5248,26 +6181,74 @@ async function ops(sub, rest) {
|
|
|
5248
6181
|
const savedRest = sub === "save" ? rest : rest.slice(1);
|
|
5249
6182
|
return opsSaved(savedSub, savedRest);
|
|
5250
6183
|
}
|
|
6184
|
+
if (sub === "nango") return gtmNango(rest[0], rest.slice(1), "ops");
|
|
5251
6185
|
if (sub === "plan" && !promptArg(rest)) {
|
|
5252
6186
|
die('Usage: signaliz ops plan "monitor these companies daily..."');
|
|
5253
6187
|
}
|
|
5254
6188
|
if (sub === "create" && !promptArg(rest)) {
|
|
5255
6189
|
die('Usage: signaliz ops create "build 100 leads that fit..." [--confirm-spend]');
|
|
5256
6190
|
}
|
|
6191
|
+
if ((sub === "schedule" || sub === "recur") && !promptArg(rest)) {
|
|
6192
|
+
die('Usage: signaliz ops schedule "monitor these companies daily..." [--confirm-spend]');
|
|
6193
|
+
}
|
|
5257
6194
|
if (sub === "execute" && !promptArg(rest)) {
|
|
5258
6195
|
die('Usage: signaliz ops execute "launch a campaign for this ICP..." [--dry-run|--confirm-spend]');
|
|
5259
6196
|
}
|
|
5260
6197
|
const sdk = getSdk();
|
|
6198
|
+
const opsOptionalBooleanFlag = (name) => {
|
|
6199
|
+
const value = flagArg(name);
|
|
6200
|
+
if (value !== void 0) return !["0", "false", "no", "off"].includes(value.toLowerCase());
|
|
6201
|
+
return hasFlag(name) ? true : void 0;
|
|
6202
|
+
};
|
|
6203
|
+
const opsNangoDestination = () => {
|
|
6204
|
+
const destination = { type: "nango" };
|
|
6205
|
+
let hasDetails = false;
|
|
6206
|
+
const set = (key, value) => {
|
|
6207
|
+
if (value === void 0 || value === null || value === "") return;
|
|
6208
|
+
destination[key] = value;
|
|
6209
|
+
hasDetails = true;
|
|
6210
|
+
};
|
|
6211
|
+
const nangoAction = flagArg("nango-action");
|
|
6212
|
+
const nangoProxyPath = flagArg("nango-proxy-path");
|
|
6213
|
+
set("connectionId", flagArg("workspace-connection-id") || flagArg("connection-id"));
|
|
6214
|
+
set("providerConfigKey", flagArg("provider-config-key"));
|
|
6215
|
+
set("integrationId", flagArg("integration-id"));
|
|
6216
|
+
set("nangoConnectionId", flagArg("nango-connection-id"));
|
|
6217
|
+
set("actionName", flagArg("action-name") || nangoAction);
|
|
6218
|
+
set("nangoAction", nangoAction);
|
|
6219
|
+
set("proxyPath", flagArg("proxy-path") || nangoProxyPath);
|
|
6220
|
+
set("nangoProxyPath", nangoProxyPath);
|
|
6221
|
+
set("method", flagArg("method") || flagArg("http-method"));
|
|
6222
|
+
set("writeConfirmed", opsOptionalBooleanFlag("write-confirmed"));
|
|
6223
|
+
set("agentWriteConfirmed", opsOptionalBooleanFlag("agent-write-confirmed"));
|
|
6224
|
+
return hasDetails ? destination : void 0;
|
|
6225
|
+
};
|
|
6226
|
+
const isNangoDestinationType = (type) => {
|
|
6227
|
+
const normalized = type.toLowerCase().replace(/[-\s]/g, "_");
|
|
6228
|
+
return ["nango", "api", "managed_api", "customer_api", "external_api", "nango_api"].includes(normalized);
|
|
6229
|
+
};
|
|
5261
6230
|
const opsDestinations = () => {
|
|
5262
6231
|
const destinations = csvFlag("destinations") || csvFlag("destination");
|
|
5263
|
-
|
|
6232
|
+
const nangoDestination = opsNangoDestination();
|
|
6233
|
+
const out = (destinations || []).map((type) => nangoDestination && isNangoDestinationType(type) ? { ...nangoDestination, type } : { type });
|
|
6234
|
+
if (nangoDestination && !out.some((destination) => isNangoDestinationType(String(destination.type)))) {
|
|
6235
|
+
out.push(nangoDestination);
|
|
6236
|
+
}
|
|
6237
|
+
return out.length > 0 ? out : void 0;
|
|
5264
6238
|
};
|
|
6239
|
+
const opsWakeEvents = () => csvFlag("wake-on-events") || csvFlag("wake-events") || csvFlag("wake-event");
|
|
5265
6240
|
const opsCompanyDomains = () => csvFlag("company-domains") || csvFlag("domains");
|
|
5266
6241
|
const opsCustomPrompts = () => ({
|
|
5267
6242
|
custom_ai_prompt: flagArg("ai-prompt") || flagArg("custom-ai-prompt"),
|
|
5268
6243
|
signal_prompt: flagArg("signal-prompt"),
|
|
5269
6244
|
output_prompt: flagArg("output-prompt") || flagArg("result-prompt")
|
|
5270
6245
|
});
|
|
6246
|
+
const printPlanSchedule2 = (plan) => {
|
|
6247
|
+
if (!plan || typeof plan !== "object") return;
|
|
6248
|
+
const wakeEvents = Array.isArray(plan.wake_on_events) ? plan.wake_on_events : plan.wakeOnEvents;
|
|
6249
|
+
console.log(`Schedule: ${plan.cadence || "manual"}`);
|
|
6250
|
+
console.log(`Wake: ${Array.isArray(wakeEvents) && wakeEvents.length ? wakeEvents.join(", ") : "cadence only"}`);
|
|
6251
|
+
};
|
|
5271
6252
|
if (sub === "plan") {
|
|
5272
6253
|
const promptText = promptArg(rest);
|
|
5273
6254
|
const result = await sdk.ops.plan({
|
|
@@ -5275,6 +6256,7 @@ async function ops(sub, rest) {
|
|
|
5275
6256
|
blueprint: flagArg("blueprint"),
|
|
5276
6257
|
target_count: numberFlag("target-count"),
|
|
5277
6258
|
cadence: flagArg("cadence"),
|
|
6259
|
+
wake_on_events: opsWakeEvents(),
|
|
5278
6260
|
destinations: opsDestinations(),
|
|
5279
6261
|
company_domains: opsCompanyDomains(),
|
|
5280
6262
|
...opsCustomPrompts()
|
|
@@ -5284,10 +6266,11 @@ async function ops(sub, rest) {
|
|
|
5284
6266
|
if (result.ui_summary) console.log(`Summary: ${result.ui_summary}`);
|
|
5285
6267
|
console.log(`Status: ${result.status}`);
|
|
5286
6268
|
console.log(`Outcome: ${result.blueprint}`);
|
|
5287
|
-
|
|
6269
|
+
printPlanSchedule2(result);
|
|
5288
6270
|
console.log(`Target: ${result.target_count}`);
|
|
5289
6271
|
console.log(`Credits: ${result.estimated_credits}`);
|
|
5290
6272
|
if (result.destination_status) console.log(`Deliver: ${result.destination_status}`);
|
|
6273
|
+
printOpsExecutionContract(result);
|
|
5291
6274
|
printPrimitiveGraph(result.primitive_graph);
|
|
5292
6275
|
console.log(`Next: ${result.next_action}`);
|
|
5293
6276
|
});
|
|
@@ -5306,6 +6289,26 @@ async function ops(sub, rest) {
|
|
|
5306
6289
|
console.log(`${primary.title}: ${primary.outcome}`);
|
|
5307
6290
|
console.log(`Prompt: ${primary.prompt}`);
|
|
5308
6291
|
console.log(`CLI: ${primary.cli_command}`);
|
|
6292
|
+
const packet = primary.operating_packet || primary.operatingPacket || result.operating_packet || result.operatingPacket;
|
|
6293
|
+
if (packet?.schedule) {
|
|
6294
|
+
console.log(`Schedule: ${packet.schedule.cadence} - ${packet.schedule.recurrence}`);
|
|
6295
|
+
console.log(`Results: ${packet.result_contract?.wait_tool || packet.resultContract?.waitTool || packet.result_contract?.retrieve_tool || packet.resultContract?.retrieveTool || "ops_wait"}`);
|
|
6296
|
+
}
|
|
6297
|
+
const nangoRoute = packet?.nango_route || packet?.nangoRoute;
|
|
6298
|
+
if (nangoRoute?.enabled) {
|
|
6299
|
+
console.log("\nNango route");
|
|
6300
|
+
console.log(`- Discover: ${nangoRoute.discover_tool || nangoRoute.discoverTool}`);
|
|
6301
|
+
console.log(`- Dry run: ${nangoRoute.dry_run_tool || nangoRoute.dryRunTool}`);
|
|
6302
|
+
console.log(`- Execute: ${nangoRoute.execute_tool || nangoRoute.executeTool} after confirm=true`);
|
|
6303
|
+
if (nangoRoute.execute_and_wait_tool || nangoRoute.executeAndWaitTool) {
|
|
6304
|
+
console.log(`- Wait: ${nangoRoute.execute_and_wait_tool || nangoRoute.executeAndWaitTool}`);
|
|
6305
|
+
}
|
|
6306
|
+
const nangoScheduleTool = nangoRoute.schedule_and_wait_tool || nangoRoute.scheduleAndWaitTool || nangoRoute.schedule_tool || nangoRoute.scheduleTool;
|
|
6307
|
+
if (nangoScheduleTool) {
|
|
6308
|
+
console.log(`- Schedule: ${nangoScheduleTool} after approval`);
|
|
6309
|
+
}
|
|
6310
|
+
console.log(`- Gate: ${nangoRoute.write_gate || nangoRoute.writeGate}`);
|
|
6311
|
+
}
|
|
5309
6312
|
if (primary.mcp_sequence?.length) {
|
|
5310
6313
|
console.log("\nMCP flow");
|
|
5311
6314
|
for (const [index, step] of primary.mcp_sequence.entries()) {
|
|
@@ -5317,22 +6320,49 @@ async function ops(sub, rest) {
|
|
|
5317
6320
|
}
|
|
5318
6321
|
if (sub === "execute") {
|
|
5319
6322
|
const promptText = promptArg(rest);
|
|
6323
|
+
const shouldWait = hasFlag("wait");
|
|
5320
6324
|
const result = await sdk.ops.execute({
|
|
5321
6325
|
prompt: promptText,
|
|
5322
6326
|
blueprint: flagArg("blueprint"),
|
|
5323
6327
|
target_count: numberFlag("target-count"),
|
|
5324
6328
|
cadence: flagArg("cadence"),
|
|
6329
|
+
wake_on_events: opsWakeEvents(),
|
|
6330
|
+
timezone: flagArg("timezone"),
|
|
5325
6331
|
destinations: opsDestinations(),
|
|
5326
6332
|
company_domains: opsCompanyDomains(),
|
|
5327
6333
|
...opsCustomPrompts(),
|
|
5328
6334
|
confirm_spend: hasFlag("confirm-spend"),
|
|
5329
6335
|
dry_run: hasFlag("dry-run"),
|
|
5330
|
-
auto_run: hasFlag("auto-run") ? true : hasFlag("no-auto-run") ? false : void 0,
|
|
6336
|
+
auto_run: hasFlag("auto-run") ? true : hasFlag("no-auto-run") ? false : shouldWait ? true : void 0,
|
|
5331
6337
|
output_format: flagArg("output-format") === "markdown" ? "markdown" : "json"
|
|
5332
6338
|
});
|
|
6339
|
+
if (shouldWait && result.op_id && !result.approval_required && result.error_code !== "APPROVAL_REQUIRED" && !hasFlag("dry-run")) {
|
|
6340
|
+
const waited = await sdk.ops.waitForResults({
|
|
6341
|
+
op_id: result.op_id,
|
|
6342
|
+
...opsWaitOptions()
|
|
6343
|
+
});
|
|
6344
|
+
const combined = {
|
|
6345
|
+
...waited,
|
|
6346
|
+
execute: result,
|
|
6347
|
+
run_id: result.run_id ?? waited.status?.run_id ?? waited.status?.runId,
|
|
6348
|
+
runId: result.runId ?? result.run_id ?? waited.status?.runId ?? waited.status?.run_id,
|
|
6349
|
+
execution_refs: combineExecutionRefs(result.execution_refs, waited.execution_refs)
|
|
6350
|
+
};
|
|
6351
|
+
return output(combined, () => {
|
|
6352
|
+
if (result.run_id || result.runId) console.log(`Run: ${result.run_id || result.runId}`);
|
|
6353
|
+
printOpsWaitForResults(combined);
|
|
6354
|
+
});
|
|
6355
|
+
}
|
|
5333
6356
|
return output(result, () => {
|
|
5334
6357
|
if (result.approval_required || result.error_code === "APPROVAL_REQUIRED") {
|
|
5335
6358
|
console.log("Approval required");
|
|
6359
|
+
if (result.plan) {
|
|
6360
|
+
console.log(`Plan: ${result.plan.title || result.plan.plan_id || "pending approval"}`);
|
|
6361
|
+
if (result.plan.ui_summary) console.log(`Summary: ${result.plan.ui_summary}`);
|
|
6362
|
+
console.log(`Status: ${result.plan.status || result.status || "needs_approval"}`);
|
|
6363
|
+
printPlanSchedule2(result.plan);
|
|
6364
|
+
printOpsExecutionContract(result.plan);
|
|
6365
|
+
}
|
|
5336
6366
|
if (result.estimated_credits !== void 0) console.log(`Credits: ${result.estimated_credits}`);
|
|
5337
6367
|
console.log(`Next: ${result.next_action || "Retry with --confirm-spend after approval."}`);
|
|
5338
6368
|
hint(`signaliz ops execute ${JSON.stringify(promptText)} --confirm-spend`);
|
|
@@ -5342,13 +6372,19 @@ async function ops(sub, rest) {
|
|
|
5342
6372
|
console.log(`Dry run: ${result.plan.title}`);
|
|
5343
6373
|
if (result.plan.ui_summary) console.log(`Summary: ${result.plan.ui_summary}`);
|
|
5344
6374
|
console.log(`Status: ${result.plan.status}`);
|
|
6375
|
+
printPlanSchedule2(result.plan);
|
|
5345
6376
|
console.log(`Credits: ${result.plan.estimated_credits}`);
|
|
6377
|
+
printOpsExecutionContract(result.plan);
|
|
5346
6378
|
console.log(`Next: ${result.next_action || result.plan.next_action}`);
|
|
5347
6379
|
return;
|
|
5348
6380
|
}
|
|
5349
6381
|
console.log(`Op: ${result.op_id || "not created"}`);
|
|
5350
6382
|
if (result.run_id) console.log(`Run: ${result.run_id}`);
|
|
5351
6383
|
console.log(`Status: ${result.status || "unknown"}`);
|
|
6384
|
+
if (result.plan) {
|
|
6385
|
+
printPlanSchedule2(result.plan);
|
|
6386
|
+
printOpsExecutionContract(result.plan);
|
|
6387
|
+
}
|
|
5352
6388
|
console.log(`Next: ${result.next_action || "Check status for progress."}`);
|
|
5353
6389
|
if (result.op_id) hint(`signaliz ops status ${result.op_id}`);
|
|
5354
6390
|
});
|
|
@@ -5411,6 +6447,8 @@ Available: ${result.available_types.join(", ")}`);
|
|
|
5411
6447
|
blueprint: flagArg("blueprint"),
|
|
5412
6448
|
target_count: numberFlag("target-count"),
|
|
5413
6449
|
cadence: flagArg("cadence"),
|
|
6450
|
+
wake_on_events: opsWakeEvents(),
|
|
6451
|
+
timezone: flagArg("timezone"),
|
|
5414
6452
|
destinations: opsDestinations(),
|
|
5415
6453
|
company_domains: opsCompanyDomains(),
|
|
5416
6454
|
...opsCustomPrompts(),
|
|
@@ -5418,15 +6456,99 @@ Available: ${result.available_types.join(", ")}`);
|
|
|
5418
6456
|
activate: hasFlag("activate")
|
|
5419
6457
|
});
|
|
5420
6458
|
return output(result, () => {
|
|
6459
|
+
if (result.approval_required || result.error_code === "APPROVAL_REQUIRED") {
|
|
6460
|
+
console.log("Approval required");
|
|
6461
|
+
if (result.plan) {
|
|
6462
|
+
console.log(`Plan: ${result.plan.title || result.plan.plan_id || "pending approval"}`);
|
|
6463
|
+
if (result.plan.ui_summary) console.log(`Summary: ${result.plan.ui_summary}`);
|
|
6464
|
+
console.log(`Status: ${result.plan.status || result.status || "needs_approval"}`);
|
|
6465
|
+
printPlanSchedule2(result.plan);
|
|
6466
|
+
printOpsExecutionContract(result.plan);
|
|
6467
|
+
}
|
|
6468
|
+
if (result.estimated_credits !== void 0) console.log(`Credits: ${result.estimated_credits}`);
|
|
6469
|
+
console.log(`Next: ${result.next_action || "Retry with --confirm-spend after approval."}`);
|
|
6470
|
+
hint(`signaliz ops create ${JSON.stringify(promptText)} --confirm-spend`);
|
|
6471
|
+
return;
|
|
6472
|
+
}
|
|
5421
6473
|
console.log(`Op created: ${result.op_id}`);
|
|
5422
6474
|
console.log(`Status: ${result.status}`);
|
|
6475
|
+
if (result.plan) {
|
|
6476
|
+
printPlanSchedule2(result.plan);
|
|
6477
|
+
printOpsExecutionContract(result.plan);
|
|
6478
|
+
}
|
|
5423
6479
|
console.log(`Next: ${result.next_action}`);
|
|
5424
6480
|
hint(`signaliz ops run ${result.op_id}`);
|
|
5425
6481
|
});
|
|
5426
6482
|
}
|
|
6483
|
+
if (sub === "schedule" || sub === "recur") {
|
|
6484
|
+
const promptText = promptArg(rest);
|
|
6485
|
+
const shouldWait = hasFlag("wait");
|
|
6486
|
+
const scheduleInput = {
|
|
6487
|
+
prompt: promptText,
|
|
6488
|
+
blueprint: flagArg("blueprint"),
|
|
6489
|
+
target_count: numberFlag("target-count"),
|
|
6490
|
+
cadence: flagArg("cadence") || "daily",
|
|
6491
|
+
wake_on_events: opsWakeEvents(),
|
|
6492
|
+
timezone: flagArg("timezone"),
|
|
6493
|
+
destinations: opsDestinations(),
|
|
6494
|
+
company_domains: opsCompanyDomains(),
|
|
6495
|
+
...opsCustomPrompts(),
|
|
6496
|
+
confirm_spend: hasFlag("confirm-spend")
|
|
6497
|
+
};
|
|
6498
|
+
if (shouldWait) {
|
|
6499
|
+
const combined = await sdk.ops.scheduleAndWait({
|
|
6500
|
+
...scheduleInput,
|
|
6501
|
+
force: hasFlag("force"),
|
|
6502
|
+
instruction: flagArg("instruction"),
|
|
6503
|
+
...opsWaitOptions()
|
|
6504
|
+
});
|
|
6505
|
+
return output(combined, () => {
|
|
6506
|
+
console.log(`Op scheduled: ${combined.schedule?.op_id || combined.op_id}`);
|
|
6507
|
+
printOpsWaitForResults(combined);
|
|
6508
|
+
});
|
|
6509
|
+
}
|
|
6510
|
+
const result = await sdk.ops.schedule(scheduleInput);
|
|
6511
|
+
return output(result, () => {
|
|
6512
|
+
if (result.approval_required || result.error_code === "APPROVAL_REQUIRED") {
|
|
6513
|
+
console.log("Approval required");
|
|
6514
|
+
if (result.plan) {
|
|
6515
|
+
console.log(`Plan: ${result.plan.title || result.plan.plan_id || "pending approval"}`);
|
|
6516
|
+
if (result.plan.ui_summary) console.log(`Summary: ${result.plan.ui_summary}`);
|
|
6517
|
+
console.log(`Status: ${result.plan.status || result.status || "needs_approval"}`);
|
|
6518
|
+
printPlanSchedule2(result.plan);
|
|
6519
|
+
printOpsExecutionContract(result.plan);
|
|
6520
|
+
}
|
|
6521
|
+
if (result.estimated_credits !== void 0) console.log(`Credits: ${result.estimated_credits}`);
|
|
6522
|
+
console.log(`Next: ${result.next_action || "Retry with --confirm-spend after approval."}`);
|
|
6523
|
+
hint(`signaliz ops schedule ${JSON.stringify(promptText)} --confirm-spend`);
|
|
6524
|
+
return;
|
|
6525
|
+
}
|
|
6526
|
+
console.log(`Op scheduled: ${result.op_id}`);
|
|
6527
|
+
if (result.run_id) console.log(`Run: ${result.run_id}`);
|
|
6528
|
+
console.log(`Status: ${result.status}`);
|
|
6529
|
+
if (result.plan) {
|
|
6530
|
+
printPlanSchedule2(result.plan);
|
|
6531
|
+
printOpsExecutionContract(result.plan);
|
|
6532
|
+
}
|
|
6533
|
+
console.log(`Next: ${result.next_action}`);
|
|
6534
|
+
if (result.op_id) hint(`signaliz ops run ${result.op_id} --wait --limit 100`);
|
|
6535
|
+
});
|
|
6536
|
+
}
|
|
5427
6537
|
if (sub === "run") {
|
|
5428
6538
|
const opId = rest[0];
|
|
5429
6539
|
if (!opId) die("Usage: signaliz ops run <op_id>");
|
|
6540
|
+
if (hasFlag("wait")) {
|
|
6541
|
+
const result2 = await sdk.ops.runAndWait({
|
|
6542
|
+
op_id: opId,
|
|
6543
|
+
force: hasFlag("force"),
|
|
6544
|
+
instruction: flagArg("instruction"),
|
|
6545
|
+
...opsWaitOptions()
|
|
6546
|
+
});
|
|
6547
|
+
return output(result2, () => {
|
|
6548
|
+
if (result2.run?.run_id || result2.run?.runId) console.log(`Run: ${result2.run.run_id || result2.run.runId}`);
|
|
6549
|
+
printOpsWaitForResults(result2);
|
|
6550
|
+
});
|
|
6551
|
+
}
|
|
5430
6552
|
const result = await sdk.ops.run({ op_id: opId, force: hasFlag("force"), instruction: flagArg("instruction") });
|
|
5431
6553
|
return output(result, () => {
|
|
5432
6554
|
console.log(`Op running: ${result.op_id}`);
|
|
@@ -5459,14 +6581,38 @@ Available: ${result.available_types.join(", ")}`);
|
|
|
5459
6581
|
include_failed_runs: hasFlag("include-failed-runs")
|
|
5460
6582
|
});
|
|
5461
6583
|
return output(result, () => {
|
|
5462
|
-
const
|
|
5463
|
-
const
|
|
5464
|
-
|
|
5465
|
-
|
|
6584
|
+
const summary = result.summary || {};
|
|
6585
|
+
const hasMore = summary.has_more ?? summary.hasMore ?? result.has_more ?? result.hasMore;
|
|
6586
|
+
const nextCursor = summary.next_cursor ?? summary.nextCursor ?? result.next_cursor ?? result.nextCursor;
|
|
6587
|
+
const resultsCount = summary.results_count ?? summary.resultsCount ?? result.results_count ?? result.resultsCount ?? 0;
|
|
6588
|
+
const resultsTotal = summary.results_total ?? summary.resultsTotal ?? result.results_total ?? result.resultsTotal;
|
|
6589
|
+
const deliveryStatus = summary.delivery_status ?? summary.deliveryStatus ?? result.delivery_status ?? result.deliveryStatus;
|
|
6590
|
+
const resultsUrl = summary.results_url ?? summary.resultsUrl ?? result.results_url ?? result.resultsUrl;
|
|
6591
|
+
const nextAction = summary.next_action ?? summary.nextAction ?? result.next_action ?? result.nextAction;
|
|
6592
|
+
console.log(`Results: ${resultsCount}${hasMore ? " (more available)" : ""}`);
|
|
6593
|
+
if (summary.label) console.log(`Summary: ${summary.label}`);
|
|
6594
|
+
console.log(`Status: ${summary.status || result.status || "unknown"} (${summary.phase || result.phase || "unknown"})`);
|
|
6595
|
+
if (resultsTotal !== void 0 && resultsTotal !== null) console.log(`Total: ${resultsTotal}`);
|
|
6596
|
+
if (deliveryStatus) console.log(`Deliver: ${deliveryStatus}`);
|
|
6597
|
+
if (resultsUrl) console.log(`Open: ${resultsUrl}`);
|
|
6598
|
+
if (nextAction) console.log(`Next: ${nextAction}`);
|
|
6599
|
+
if (result.results.length) {
|
|
6600
|
+
console.log("\nRows");
|
|
6601
|
+
for (const row of result.results.slice(0, 10)) console.log(JSON.stringify(row));
|
|
6602
|
+
}
|
|
5466
6603
|
if (hasMore && nextCursor) hint(`signaliz ops results ${opId} --cursor ${nextCursor}`);
|
|
5467
6604
|
printExecutionRefs(result.execution_refs);
|
|
5468
6605
|
});
|
|
5469
6606
|
}
|
|
6607
|
+
if (sub === "wait" || sub === "await") {
|
|
6608
|
+
const opId = rest[0] || flagArg("op-id");
|
|
6609
|
+
if (!opId) die("Usage: signaliz ops wait <op_id>");
|
|
6610
|
+
const result = await sdk.ops.waitForResults({
|
|
6611
|
+
op_id: opId,
|
|
6612
|
+
...opsWaitOptions()
|
|
6613
|
+
});
|
|
6614
|
+
return output(result, () => printOpsWaitForResults(result));
|
|
6615
|
+
}
|
|
5470
6616
|
if (sub === "run-status" || sub === "trigger-status" || sub === "watch") {
|
|
5471
6617
|
const runIds = csvFlag("run-ids");
|
|
5472
6618
|
const runId = rest[0] || flagArg("run-id");
|
|
@@ -5795,13 +6941,15 @@ Available: ${result.available_types.join(", ")}`);
|
|
|
5795
6941
|
const result = await sdk.ops.attachSinkToRoutine({ routine_id: routineId, sink_id: sinkId });
|
|
5796
6942
|
return output(result);
|
|
5797
6943
|
}
|
|
5798
|
-
die("Usage: signaliz ops <proof|autopilot|plan|execute|quickstart|create|run|status|results|run-status|queue|logs|replay|dashboard|doctor|connections|sinks|routines|routine|attach-sink|saved>");
|
|
6944
|
+
die("Usage: signaliz ops <proof|autopilot|plan|execute|quickstart|create|schedule|run|status|results|wait|nango|run-status|queue|logs|replay|dashboard|doctor|connections|sinks|routines|routine|attach-sink|saved>");
|
|
5799
6945
|
}
|
|
5800
6946
|
var OPS_SHORTCUTS = {
|
|
5801
6947
|
"/plan": "plan",
|
|
5802
6948
|
plan: "plan",
|
|
5803
6949
|
"/goal": "create",
|
|
5804
6950
|
goal: "create",
|
|
6951
|
+
schedule: "schedule",
|
|
6952
|
+
recur: "schedule",
|
|
5805
6953
|
quickstart: "quickstart",
|
|
5806
6954
|
template: "template",
|
|
5807
6955
|
proof: "proof",
|
|
@@ -5810,6 +6958,7 @@ var OPS_SHORTCUTS = {
|
|
|
5810
6958
|
run: "run",
|
|
5811
6959
|
status: "status",
|
|
5812
6960
|
results: "results",
|
|
6961
|
+
wait: "wait",
|
|
5813
6962
|
queue: "queue",
|
|
5814
6963
|
debug: "debug",
|
|
5815
6964
|
watch: "watch",
|