@signaliz/cli 1.0.90 → 1.0.92

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.
Files changed (3) hide show
  1. package/README.md +13 -4
  2. package/dist/bin.js +334 -6
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -217,14 +217,18 @@ signaliz campaign-os audience-draft --client-id <uuid> --name "Launch ICP" \
217
217
  --audience-role campaign_segment --source-mode signaliz_owned \
218
218
  --idempotency-key launch-audience-v1 --json
219
219
  signaliz campaign-os materialize-cache-audience --client-id <uuid> \
220
- --audience-id <uuid> --target-count 500 \
220
+ --audience-id <uuid> --campaign-id <uuid> --target-count 500 \
221
221
  --idempotency-key launch-cache-materialization-v1 --json
222
222
  signaliz campaign-os audience-preview --client-id <uuid> \
223
223
  --audience-id <uuid> --idempotency-key launch-preview-v1 --json
224
224
  signaliz campaign-os compile --client-id <uuid> --campaign-id <uuid> \
225
225
  --providers all --json
226
226
  signaliz campaign-os request --client-id <uuid> --campaign-id <uuid> \
227
- --agent devin --action provider_activation --instructions "Prepare for review" --json
227
+ --agent devin --action provider_activation --instructions "Prepare for review" \
228
+ --preflight-inputs-file action-preflight.json \
229
+ --idempotency-key launch-activation-request-v1 --json
230
+ signaliz campaign-os prepare-preflight --client-id <uuid> \
231
+ --request-id <approved-request-uuid> --json
228
232
  signaliz campaign-os receipts --client-id <uuid> --json
229
233
  ```
230
234
 
@@ -233,6 +237,11 @@ approval boundaries, and receipt semantics without returning credentials or
233
237
  calling the provider. `build`, `audience-draft`, `materialize-cache-audience`,
234
238
  `audience-preview`, and `compile` do not need CMM-admin approval and keep
235
239
  providers locked. Cache materialization is capped at 500 members and returns
236
- exact zero-provider/Clay usage plus a terminal reconciliation receipt. `request`
237
- creates only an auditable review request for paid sourcing, provider load,
240
+ exact zero-provider/Clay usage plus a terminal reconciliation receipt; optional
241
+ `--campaign-id` links that run to its campaign lifecycle. `request` requires a
242
+ nonblank `--idempotency-key` and creates only an auditable review request for paid sourcing, provider load,
238
243
  activation, real-time arming, queueing, or sending; it does not execute them.
244
+ `--preflight-inputs-file` accepts one JSON object containing only exact,
245
+ non-secret provider and artifact identifiers. After a Signaliz superadmin
246
+ approves that proposal, `prepare-preflight` appends or reads the immutable
247
+ no-call continuation and reports missing inputs or unavailable adapters.
package/dist/bin.js CHANGED
@@ -63,11 +63,23 @@ Product commands:
63
63
  signaliz campaign-os build --client-id <uuid> --name "Campaign" --objective "Goal" --target-count 500 --idempotency-key <key>
64
64
  signaliz campaign-os build-status --build-run-id <uuid>
65
65
  signaliz campaign-os draft --client-id <uuid> --name "Campaign" --campaign-spec-file campaign-spec.json --idempotency-key <key> [--agent codex]
66
+ signaliz campaign-os refine --client-id <uuid> --campaign-id <uuid> --expected-spec-version-id <uuid> --campaign-spec-file campaign-spec.json --change-reason "What changed" --idempotency-key <key> [--agent codex]
66
67
  signaliz campaign-os audience-draft --client-id <uuid> --name "Audience" --definition-file audience.json --entity-type people --audience-role campaign_segment --source-mode signaliz_owned --idempotency-key <key>
67
- signaliz campaign-os materialize-cache-audience --client-id <uuid> --audience-id <uuid> --target-count <1-500> --idempotency-key <key>
68
+ signaliz campaign-os materialize-cache-audience --client-id <uuid> --audience-id <uuid> [--campaign-id <uuid>] --target-count <1-500> --idempotency-key <key>
69
+ signaliz campaign-os audience-schedule --client-id <uuid> --audience-id <uuid> [--campaign-id <uuid>] [--cadence-minutes 1440] [--per-run-cap 100] [--source-policy cache_only|cache_then_review] [--enabled yes|no] [--run-now]
68
70
  signaliz campaign-os audience-preview --client-id <uuid> --audience-id <uuid> --idempotency-key <key>
69
71
  signaliz campaign-os compile --client-id <uuid> --campaign-id <uuid> [--providers all]
70
- signaliz campaign-os request --client-id <uuid> [--campaign-id <uuid>] --agent codex --action provider_load --instructions "..." [--idempotency-key <key>]
72
+ signaliz campaign-os alpha-plan --client-id <uuid> --client-name "Velox" --offer-summary "..." --icp-summary "..." --idempotency-key <key>
73
+ signaliz campaign-os alpha-discover --client-id <uuid> --client-name "Velox" --offer-summary "..." --icp-summary "..." --idempotency-key <key> --confirm-spend
74
+ signaliz campaign-os alpha-status --alpha-run-id <uuid>
75
+ signaliz campaign-os alpha-validate --client-id <uuid> --campaign-id <uuid> --alpha-run-id <uuid> --candidate-index 0 --sample-file sample.json --idempotency-key <key> --confirm-spend
76
+ signaliz campaign-os alpha-validation-status --validation-run-id <uuid>
77
+ signaliz campaign-os alpha-apply --validation-run-id <uuid>
78
+ signaliz campaign-os connections --client-id <uuid>
79
+ signaliz campaign-os source-binding --client-id <uuid> --binding-id <uuid> --name "CRM list" --source-kind audience --selector-file selector.json --idempotency-key <key>
80
+ signaliz campaign-os source-preflight --client-id <uuid> --source-binding-id <uuid> --idempotency-key <key> [--max-records 25]
81
+ signaliz campaign-os request --client-id <uuid> [--campaign-id <uuid>] --agent codex --action provider_load --instructions "..." [--preflight-inputs-file inputs.json] --idempotency-key <key>
82
+ signaliz campaign-os prepare-preflight --client-id <uuid> --request-id <uuid>
71
83
  signaliz campaign-os receipts [--client-id <uuid>] [--campaign-id <uuid>] [--limit 50]
72
84
 
73
85
  Access and connection:
@@ -2292,6 +2304,44 @@ async function campaignOs(args) {
2292
2304
  });
2293
2305
  return;
2294
2306
  }
2307
+ if (action === "refine") {
2308
+ const clientId = flag("client-id");
2309
+ const campaignId = flag("campaign-id");
2310
+ const expectedCampaignSpecVersionId = flag("expected-spec-version-id");
2311
+ const campaignSpecFile = flag("campaign-spec-file");
2312
+ const changeReason = flag("change-reason");
2313
+ const idempotencyKey = flag("idempotency-key");
2314
+ if (!clientId || !campaignId || !expectedCampaignSpecVersionId || !campaignSpecFile || !changeReason || !idempotencyKey) {
2315
+ throw new CliInputError("signaliz campaign-os refine requires --client-id, --campaign-id, --expected-spec-version-id, --campaign-spec-file, --change-reason, and --idempotency-key");
2316
+ }
2317
+ let campaignSpec;
2318
+ try {
2319
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(campaignSpecFile, "utf8"));
2320
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
2321
+ throw new Error("file must contain one JSON object");
2322
+ }
2323
+ campaignSpec = parsed;
2324
+ } catch (error) {
2325
+ throw new CliInputError(`Unable to read --campaign-spec-file: ${error instanceof Error ? error.message : String(error)}`);
2326
+ }
2327
+ const result = await client.refineCampaignOsCampaign({
2328
+ clientId,
2329
+ campaignId,
2330
+ expectedCampaignSpecVersionId,
2331
+ knowledgeSnapshotId: flag("knowledge-snapshot-id"),
2332
+ campaignSpec,
2333
+ changeReason,
2334
+ agentVendor: campaignOsAgentFlag(),
2335
+ idempotencyKey
2336
+ });
2337
+ output(result, () => {
2338
+ const campaign = record(result.campaign);
2339
+ process.stdout.write(`CampaignSpec v${String(campaign.campaign_spec_version || "")} appended to ${String(campaign.name || campaignId)}.
2340
+ `);
2341
+ process.stdout.write("Prior provider approvals were invalidated. Provider load, activation, and send remain locked.\n");
2342
+ });
2343
+ return;
2344
+ }
2295
2345
  if (action === "audience-draft") {
2296
2346
  const clientId = flag("client-id");
2297
2347
  const name = flag("name");
@@ -2344,6 +2394,7 @@ async function campaignOs(args) {
2344
2394
  if (action === "materialize-cache-audience") {
2345
2395
  const clientId = flag("client-id");
2346
2396
  const audienceId = flag("audience-id");
2397
+ const campaignId = flag("campaign-id");
2347
2398
  const targetCount = numberFlag("target-count");
2348
2399
  const idempotencyKey = flag("idempotency-key");
2349
2400
  if (!clientId || !audienceId || targetCount === void 0 || !idempotencyKey) {
@@ -2353,6 +2404,7 @@ async function campaignOs(args) {
2353
2404
  const result = await client.materializeCampaignOsCacheAudience({
2354
2405
  clientId,
2355
2406
  audienceId,
2407
+ campaignId,
2356
2408
  targetCount,
2357
2409
  idempotencyKey
2358
2410
  });
@@ -2369,6 +2421,40 @@ async function campaignOs(args) {
2369
2421
  });
2370
2422
  return;
2371
2423
  }
2424
+ if (action === "audience-schedule") {
2425
+ const clientId = flag("client-id");
2426
+ const audienceId = flag("audience-id");
2427
+ if (!clientId || !audienceId) {
2428
+ throw new CliInputError("signaliz campaign-os audience-schedule requires --client-id and --audience-id");
2429
+ }
2430
+ const cadenceMinutes = numberFlag("cadence-minutes") ?? 1440;
2431
+ const perRunCap = numberFlag("per-run-cap") ?? 100;
2432
+ requireIntegerInRange(cadenceMinutes, "--cadence-minutes", 15, 10080);
2433
+ requireIntegerInRange(perRunCap, "--per-run-cap", 1, 500);
2434
+ const sourcePolicy = flag("source-policy") || "cache_only";
2435
+ if (!["cache_only", "cache_then_review"].includes(sourcePolicy)) {
2436
+ throw new CliInputError("--source-policy must be cache_only or cache_then_review");
2437
+ }
2438
+ const result = await client.upsertCampaignOsAudienceSchedule({
2439
+ clientId,
2440
+ audienceId,
2441
+ campaignId: flag("campaign-id"),
2442
+ enabled: yesNoFlag("enabled") ?? true,
2443
+ sourcePolicy,
2444
+ cadenceMinutes,
2445
+ perRunCap,
2446
+ timezone: flag("timezone") || "UTC",
2447
+ startAt: flag("start-at"),
2448
+ runNow: hasFlag("run-now")
2449
+ });
2450
+ output(result, () => {
2451
+ const schedule = record(result.schedule);
2452
+ process.stdout.write(`Audience schedule: ${String(schedule.status || "unknown")} \xB7 next ${String(schedule.next_run_at || "not scheduled")}
2453
+ `);
2454
+ process.stdout.write("Cache deltas need no CMM-admin approval. Standing Clay approval: false.\n");
2455
+ });
2456
+ return;
2457
+ }
2372
2458
  if (action === "compile") {
2373
2459
  const clientId = flag("client-id");
2374
2460
  const campaignId = flag("campaign-id");
@@ -2379,23 +2465,247 @@ async function campaignOs(args) {
2379
2465
  output(result, () => process.stdout.write("Compile preview recorded \xB7 provider calls 0 \xB7 no campaign created or sent\n"));
2380
2466
  return;
2381
2467
  }
2468
+ if (action === "alpha-plan" || action === "alpha-discover") {
2469
+ const clientId = flag("client-id");
2470
+ const clientName = flag("client-name");
2471
+ const offerSummary = flag("offer-summary");
2472
+ const icpSummary = flag("icp-summary");
2473
+ const idempotencyKey = flag("idempotency-key")?.trim();
2474
+ if (!clientId || !clientName || !offerSummary || !icpSummary || !idempotencyKey) {
2475
+ throw new CliInputError(`signaliz campaign-os ${action} requires --client-id, --client-name, --offer-summary, --icp-summary, and --idempotency-key`);
2476
+ }
2477
+ const params = {
2478
+ clientId,
2479
+ campaignId: flag("campaign-id"),
2480
+ clientName,
2481
+ offerSummary,
2482
+ icpSummary,
2483
+ buyerPersonas: csvFlag("buyer-personas"),
2484
+ knownEvidence: csvFlag("known-evidence"),
2485
+ preferredSources: csvFlag("preferred-sources"),
2486
+ idempotencyKey
2487
+ };
2488
+ if (action === "alpha-plan") {
2489
+ const result2 = await client.planCampaignOsAlpha(params);
2490
+ output(result2, () => {
2491
+ process.stdout.write("Signaliz Alpha plan ready \xB7 model calls 0 \xB7 web searches 0 \xB7 spend $0.00\n");
2492
+ process.stdout.write("Candidates will remain unvalidated until a measured sample proves them.\n");
2493
+ });
2494
+ return;
2495
+ }
2496
+ if (!hasFlag("confirm-spend")) {
2497
+ throw new CliInputError("signaliz campaign-os alpha-discover requires --confirm-spend for the $0.10 authorization ceiling");
2498
+ }
2499
+ const result = await client.startCampaignOsAlphaDiscovery(params);
2500
+ output(result, () => {
2501
+ const run = record(result.run);
2502
+ process.stdout.write(`Signaliz Alpha discovery started: ${String(run.id || "")} \xB7 ${String(run.status || "queued")} \xB7 authorized ceiling $0.10
2503
+ `);
2504
+ process.stdout.write("Output is candidate-only. Clay, audience creation, provider load, activation, queue, and send remain locked.\n");
2505
+ });
2506
+ return;
2507
+ }
2508
+ if (action === "alpha-status") {
2509
+ const alphaRunId = flag("alpha-run-id");
2510
+ if (!alphaRunId) {
2511
+ throw new CliInputError("signaliz campaign-os alpha-status requires --alpha-run-id <uuid>");
2512
+ }
2513
+ const result = await client.getCampaignOsAlphaRun(alphaRunId);
2514
+ output(result, () => {
2515
+ const run = record(result.run);
2516
+ process.stdout.write(`Signaliz Alpha run: ${String(run.status || "unknown")} \xB7 ${String(run.id || alphaRunId)}
2517
+ `);
2518
+ process.stdout.write("Completed output remains a source-cited candidate until a measured validation receipt exists.\n");
2519
+ });
2520
+ return;
2521
+ }
2522
+ if (action === "alpha-validate") {
2523
+ const clientId = flag("client-id");
2524
+ const campaignId = flag("campaign-id");
2525
+ const alphaRunId = flag("alpha-run-id");
2526
+ const candidateIndex = numberFlag("candidate-index");
2527
+ const sampleFile = flag("sample-file");
2528
+ const idempotencyKey = flag("idempotency-key")?.trim();
2529
+ if (!clientId || !campaignId || !alphaRunId || candidateIndex === void 0 || !sampleFile || !idempotencyKey) {
2530
+ throw new CliInputError("signaliz campaign-os alpha-validate requires --client-id, --campaign-id, --alpha-run-id, --candidate-index, --sample-file, and --idempotency-key");
2531
+ }
2532
+ requireIntegerInRange(candidateIndex, "--candidate-index", 0, 4);
2533
+ if (!hasFlag("confirm-spend")) {
2534
+ throw new CliInputError("signaliz campaign-os alpha-validate requires --confirm-spend for the fixed $0.25 maximum");
2535
+ }
2536
+ let sampleEntities;
2537
+ try {
2538
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(sampleFile, "utf8"));
2539
+ if (!Array.isArray(parsed) || parsed.length < 3 || parsed.length > 20) {
2540
+ throw new Error("file must contain a JSON array of 3-20 sample entities");
2541
+ }
2542
+ sampleEntities = parsed;
2543
+ } catch (error) {
2544
+ throw new CliInputError(`Unable to read --sample-file: ${error instanceof Error ? error.message : String(error)}`);
2545
+ }
2546
+ const result = await client.startCampaignOsAlphaValidation({
2547
+ clientId,
2548
+ campaignId,
2549
+ alphaRunId,
2550
+ candidateIndex,
2551
+ sampleEntities,
2552
+ idempotencyKey
2553
+ });
2554
+ output(result, () => {
2555
+ const run = record(result.run);
2556
+ process.stdout.write(`Signaliz Alpha validation started: ${String(run.id || "")} \xB7 ${String(run.status || "queued")} \xB7 maximum $0.25
2557
+ `);
2558
+ process.stdout.write("Passing status is receipt-derived. Clay and delivery providers remain locked.\n");
2559
+ });
2560
+ return;
2561
+ }
2562
+ if (action === "alpha-validation-status" || action === "alpha-apply") {
2563
+ const validationRunId = flag("validation-run-id");
2564
+ if (!validationRunId) {
2565
+ throw new CliInputError(`signaliz campaign-os ${action} requires --validation-run-id <uuid>`);
2566
+ }
2567
+ const result = action === "alpha-apply" ? await client.applyCampaignOsValidatedAlpha(validationRunId) : await client.getCampaignOsAlphaValidationRun(validationRunId);
2568
+ output(result, () => {
2569
+ const run = record(result.run);
2570
+ if (action === "alpha-apply") {
2571
+ process.stdout.write(`Validated Alpha applied to immutable CampaignSpec: ${String(run.applied_spec_version_id || "complete")}
2572
+ `);
2573
+ process.stdout.write("Provider load, activation, queue, and send remain locked.\n");
2574
+ } else {
2575
+ process.stdout.write(`Signaliz Alpha validation: ${String(run.status || "unknown")} \xB7 ${String(run.matched_count || 0)}/${String(run.sample_size || 0)} matched
2576
+ `);
2577
+ process.stdout.write(`Validation passed: ${run.validation_passed === true ? "yes" : "no"}
2578
+ `);
2579
+ }
2580
+ });
2581
+ return;
2582
+ }
2583
+ if (action === "connections") {
2584
+ const clientId = flag("client-id");
2585
+ if (!clientId) throw new CliInputError("signaliz campaign-os connections requires --client-id <uuid>");
2586
+ const result = await client.listCampaignOsConnections(clientId);
2587
+ output(result, () => {
2588
+ process.stdout.write(`${result.bindings.length} client binding(s) \xB7 ${result.source_bindings.length} exact source binding(s)
2589
+ `);
2590
+ process.stdout.write("OAuth tokens and raw provider values were not returned; no provider call occurred.\n");
2591
+ });
2592
+ return;
2593
+ }
2594
+ if (action === "source-binding" || action === "source-policy") {
2595
+ const clientId = flag("client-id");
2596
+ const bindingId = flag("binding-id");
2597
+ const name = flag("name");
2598
+ const sourceKind = flag("source-kind");
2599
+ const selectorFile = flag("selector-file");
2600
+ const idempotencyKey = flag("idempotency-key")?.trim();
2601
+ if (!clientId || !bindingId || !name || !sourceKind || !selectorFile || !idempotencyKey) {
2602
+ throw new CliInputError("signaliz campaign-os source-binding requires --client-id, --binding-id, --name, --source-kind, --selector-file, and --idempotency-key");
2603
+ }
2604
+ if (!["memory", "data", "audience", "trigger"].includes(sourceKind)) {
2605
+ throw new CliInputError("--source-kind must be memory, data, audience, or trigger");
2606
+ }
2607
+ let selector;
2608
+ try {
2609
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(selectorFile, "utf8"));
2610
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("file must contain one JSON object");
2611
+ selector = parsed;
2612
+ } catch (error) {
2613
+ throw new CliInputError(`Unable to read --selector-file: ${error instanceof Error ? error.message : String(error)}`);
2614
+ }
2615
+ const result = await client.createCampaignOsSourceBinding({
2616
+ clientId,
2617
+ bindingId,
2618
+ name,
2619
+ sourceKind,
2620
+ remoteObjectType: flag("remote-object-type"),
2621
+ remoteRef: flag("remote-ref"),
2622
+ selector,
2623
+ audienceId: flag("audience-id"),
2624
+ idempotencyKey
2625
+ });
2626
+ output(result, () => {
2627
+ const sourceBinding = record(result.source_binding);
2628
+ process.stdout.write(`Draft source binding: ${String(sourceBinding.name || name)} (${String(sourceBinding.id || "")})
2629
+ `);
2630
+ process.stdout.write("Provider calls: 0 \xB7 hydration: locked \xB7 realtime armed: false \xB7 send authorized: false\n");
2631
+ });
2632
+ return;
2633
+ }
2634
+ if (action === "source-preflight") {
2635
+ const clientId = flag("client-id");
2636
+ const sourceBindingId = flag("source-binding-id") || flag("source-policy-id");
2637
+ const idempotencyKey = flag("idempotency-key")?.trim();
2638
+ const maxRecords = numberFlag("max-records") ?? 25;
2639
+ if (!clientId || !sourceBindingId || !idempotencyKey) {
2640
+ throw new CliInputError("signaliz campaign-os source-preflight requires --client-id, --source-binding-id, and --idempotency-key");
2641
+ }
2642
+ requireIntegerInRange(maxRecords, "--max-records", 1, 25);
2643
+ const result = await client.preflightCampaignOsSourceBinding(clientId, sourceBindingId, idempotencyKey, maxRecords);
2644
+ output(result, () => {
2645
+ process.stdout.write("Source binding preflight recorded \xB7 provider calls 0 \xB7 source approval unchanged\n");
2646
+ });
2647
+ return;
2648
+ }
2382
2649
  if (action === "request") {
2383
2650
  const clientId = flag("client-id");
2384
2651
  const actionType = flag("action");
2385
2652
  const instructions = flag("instructions");
2386
- if (!clientId || !actionType || !instructions) {
2387
- throw new CliInputError('signaliz campaign-os request requires --client-id <uuid> --action <type> --instructions "..."');
2653
+ const idempotencyKey = flag("idempotency-key")?.trim();
2654
+ if (!clientId || !actionType || !instructions || !idempotencyKey) {
2655
+ throw new CliInputError('signaliz campaign-os request requires --client-id <uuid> --action <type> --instructions "..." --idempotency-key <key>');
2388
2656
  }
2389
2657
  if (!CAMPAIGN_OS_ACTIONS.has(actionType)) {
2390
2658
  throw new CliInputError(`--action must be one of: ${Array.from(CAMPAIGN_OS_ACTIONS).join(", ")}`);
2391
2659
  }
2660
+ let preflightInputs;
2661
+ const preflightInputsFile = flag("preflight-inputs-file");
2662
+ if (preflightInputsFile) {
2663
+ try {
2664
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(preflightInputsFile, "utf8"));
2665
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
2666
+ throw new Error("expected one JSON object");
2667
+ }
2668
+ const input = parsed;
2669
+ const allowed = /* @__PURE__ */ new Set([
2670
+ "provider",
2671
+ "provider_connection_id",
2672
+ "audience_id",
2673
+ "audience_run_id",
2674
+ "provider_artifact_id",
2675
+ "policy_id",
2676
+ "delivery_id",
2677
+ "provider_campaign_id",
2678
+ "target_count",
2679
+ "verification_max_age_days"
2680
+ ]);
2681
+ const unsupported = Object.keys(input).filter((key) => !allowed.has(key));
2682
+ if (unsupported.length) {
2683
+ throw new Error(`unsupported fields: ${unsupported.join(", ")}`);
2684
+ }
2685
+ preflightInputs = {
2686
+ provider: input.provider,
2687
+ providerConnectionId: input.provider_connection_id,
2688
+ audienceId: input.audience_id,
2689
+ audienceRunId: input.audience_run_id,
2690
+ providerArtifactId: input.provider_artifact_id,
2691
+ policyId: input.policy_id,
2692
+ deliveryId: input.delivery_id,
2693
+ providerCampaignId: input.provider_campaign_id,
2694
+ targetCount: input.target_count,
2695
+ verificationMaxAgeDays: input.verification_max_age_days
2696
+ };
2697
+ } catch (error) {
2698
+ throw new CliInputError(`Unable to read --preflight-inputs-file: ${error instanceof Error ? error.message : String(error)}`);
2699
+ }
2700
+ }
2392
2701
  const result = await client.submitCampaignOsActionRequest({
2393
2702
  clientId,
2394
2703
  campaignId: flag("campaign-id"),
2395
2704
  agentVendor: campaignOsAgentFlag(),
2396
2705
  actionType,
2397
2706
  instructions,
2398
- idempotencyKey: flag("idempotency-key")
2707
+ preflightInputs,
2708
+ idempotencyKey
2399
2709
  });
2400
2710
  output(result, () => {
2401
2711
  const request = record(result.request);
@@ -2405,6 +2715,24 @@ async function campaignOs(args) {
2405
2715
  });
2406
2716
  return;
2407
2717
  }
2718
+ if (action === "prepare-preflight") {
2719
+ const clientId = flag("client-id");
2720
+ const requestId = flag("request-id");
2721
+ if (!clientId || !requestId) {
2722
+ throw new CliInputError("signaliz campaign-os prepare-preflight requires --client-id <uuid> --request-id <uuid>");
2723
+ }
2724
+ const result = await client.prepareCampaignOsActionPreflight(clientId, requestId);
2725
+ output(result, () => {
2726
+ const receipt = record(result.continuation_receipt);
2727
+ const missing = Array.isArray(receipt.missing_inputs) ? receipt.missing_inputs : [];
2728
+ const blockers = Array.isArray(receipt.system_blockers) ? receipt.system_blockers : [];
2729
+ process.stdout.write(`Action preflight continuation: ${String(receipt.implementation_status || "blocked")}
2730
+ `);
2731
+ process.stdout.write(`${missing.length} missing input(s) \xB7 ${blockers.length} system blocker(s) \xB7 provider calls 0
2732
+ `);
2733
+ });
2734
+ return;
2735
+ }
2408
2736
  if (action === "receipts") {
2409
2737
  const limit = numberFlag("limit") ?? 50;
2410
2738
  requireIntegerInRange(limit, "--limit", 1, 200);
@@ -2422,7 +2750,7 @@ async function campaignOs(args) {
2422
2750
  });
2423
2751
  return;
2424
2752
  }
2425
- throw new CliInputError("Usage: signaliz campaign-os clients|context|knowledge|provider-runtime|build|build-status|draft|audience-draft|materialize-cache-audience|audience-preview|compile|request|receipts");
2753
+ throw new CliInputError("Usage: signaliz campaign-os clients|context|knowledge|provider-runtime|build|build-status|draft|refine|audience-draft|materialize-cache-audience|audience-schedule|audience-preview|compile|alpha-plan|alpha-discover|alpha-status|alpha-validate|alpha-validation-status|alpha-apply|connections|source-binding|source-preflight|request|prepare-preflight|receipts");
2426
2754
  }
2427
2755
  async function main() {
2428
2756
  const [, , command, ...args] = process.argv;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaliz/cli",
3
- "version": "1.0.90",
3
+ "version": "1.0.92",
4
4
  "description": "Signaliz CLI for Campaign OS, core products, Signal Awareness, Signaliz Flow, and reusable managed builds.",
5
5
  "bin": {
6
6
  "signaliz": "dist/bin.js"
@@ -30,7 +30,7 @@
30
30
  "node": ">=18"
31
31
  },
32
32
  "dependencies": {
33
- "@signaliz/sdk": "^1.0.94"
33
+ "@signaliz/sdk": "^1.0.96"
34
34
  },
35
35
  "devDependencies": {
36
36
  "tsup": "^8.0.0",