@signaliz/cli 1.0.90 → 1.0.91

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 +144 -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,14 @@ 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 request --client-id <uuid> [--campaign-id <uuid>] --agent codex --action provider_load --instructions "..." [--preflight-inputs-file inputs.json] --idempotency-key <key>
73
+ signaliz campaign-os prepare-preflight --client-id <uuid> --request-id <uuid>
71
74
  signaliz campaign-os receipts [--client-id <uuid>] [--campaign-id <uuid>] [--limit 50]
72
75
 
73
76
  Access and connection:
@@ -2292,6 +2295,44 @@ async function campaignOs(args) {
2292
2295
  });
2293
2296
  return;
2294
2297
  }
2298
+ if (action === "refine") {
2299
+ const clientId = flag("client-id");
2300
+ const campaignId = flag("campaign-id");
2301
+ const expectedCampaignSpecVersionId = flag("expected-spec-version-id");
2302
+ const campaignSpecFile = flag("campaign-spec-file");
2303
+ const changeReason = flag("change-reason");
2304
+ const idempotencyKey = flag("idempotency-key");
2305
+ if (!clientId || !campaignId || !expectedCampaignSpecVersionId || !campaignSpecFile || !changeReason || !idempotencyKey) {
2306
+ throw new CliInputError("signaliz campaign-os refine requires --client-id, --campaign-id, --expected-spec-version-id, --campaign-spec-file, --change-reason, and --idempotency-key");
2307
+ }
2308
+ let campaignSpec;
2309
+ try {
2310
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(campaignSpecFile, "utf8"));
2311
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
2312
+ throw new Error("file must contain one JSON object");
2313
+ }
2314
+ campaignSpec = parsed;
2315
+ } catch (error) {
2316
+ throw new CliInputError(`Unable to read --campaign-spec-file: ${error instanceof Error ? error.message : String(error)}`);
2317
+ }
2318
+ const result = await client.refineCampaignOsCampaign({
2319
+ clientId,
2320
+ campaignId,
2321
+ expectedCampaignSpecVersionId,
2322
+ knowledgeSnapshotId: flag("knowledge-snapshot-id"),
2323
+ campaignSpec,
2324
+ changeReason,
2325
+ agentVendor: campaignOsAgentFlag(),
2326
+ idempotencyKey
2327
+ });
2328
+ output(result, () => {
2329
+ const campaign = record(result.campaign);
2330
+ process.stdout.write(`CampaignSpec v${String(campaign.campaign_spec_version || "")} appended to ${String(campaign.name || campaignId)}.
2331
+ `);
2332
+ process.stdout.write("Prior provider approvals were invalidated. Provider load, activation, and send remain locked.\n");
2333
+ });
2334
+ return;
2335
+ }
2295
2336
  if (action === "audience-draft") {
2296
2337
  const clientId = flag("client-id");
2297
2338
  const name = flag("name");
@@ -2344,6 +2385,7 @@ async function campaignOs(args) {
2344
2385
  if (action === "materialize-cache-audience") {
2345
2386
  const clientId = flag("client-id");
2346
2387
  const audienceId = flag("audience-id");
2388
+ const campaignId = flag("campaign-id");
2347
2389
  const targetCount = numberFlag("target-count");
2348
2390
  const idempotencyKey = flag("idempotency-key");
2349
2391
  if (!clientId || !audienceId || targetCount === void 0 || !idempotencyKey) {
@@ -2353,6 +2395,7 @@ async function campaignOs(args) {
2353
2395
  const result = await client.materializeCampaignOsCacheAudience({
2354
2396
  clientId,
2355
2397
  audienceId,
2398
+ campaignId,
2356
2399
  targetCount,
2357
2400
  idempotencyKey
2358
2401
  });
@@ -2369,6 +2412,40 @@ async function campaignOs(args) {
2369
2412
  });
2370
2413
  return;
2371
2414
  }
2415
+ if (action === "audience-schedule") {
2416
+ const clientId = flag("client-id");
2417
+ const audienceId = flag("audience-id");
2418
+ if (!clientId || !audienceId) {
2419
+ throw new CliInputError("signaliz campaign-os audience-schedule requires --client-id and --audience-id");
2420
+ }
2421
+ const cadenceMinutes = numberFlag("cadence-minutes") ?? 1440;
2422
+ const perRunCap = numberFlag("per-run-cap") ?? 100;
2423
+ requireIntegerInRange(cadenceMinutes, "--cadence-minutes", 15, 10080);
2424
+ requireIntegerInRange(perRunCap, "--per-run-cap", 1, 500);
2425
+ const sourcePolicy = flag("source-policy") || "cache_only";
2426
+ if (!["cache_only", "cache_then_review"].includes(sourcePolicy)) {
2427
+ throw new CliInputError("--source-policy must be cache_only or cache_then_review");
2428
+ }
2429
+ const result = await client.upsertCampaignOsAudienceSchedule({
2430
+ clientId,
2431
+ audienceId,
2432
+ campaignId: flag("campaign-id"),
2433
+ enabled: yesNoFlag("enabled") ?? true,
2434
+ sourcePolicy,
2435
+ cadenceMinutes,
2436
+ perRunCap,
2437
+ timezone: flag("timezone") || "UTC",
2438
+ startAt: flag("start-at"),
2439
+ runNow: hasFlag("run-now")
2440
+ });
2441
+ output(result, () => {
2442
+ const schedule = record(result.schedule);
2443
+ process.stdout.write(`Audience schedule: ${String(schedule.status || "unknown")} \xB7 next ${String(schedule.next_run_at || "not scheduled")}
2444
+ `);
2445
+ process.stdout.write("Cache deltas need no CMM-admin approval. Standing Clay approval: false.\n");
2446
+ });
2447
+ return;
2448
+ }
2372
2449
  if (action === "compile") {
2373
2450
  const clientId = flag("client-id");
2374
2451
  const campaignId = flag("campaign-id");
@@ -2383,19 +2460,62 @@ async function campaignOs(args) {
2383
2460
  const clientId = flag("client-id");
2384
2461
  const actionType = flag("action");
2385
2462
  const instructions = flag("instructions");
2386
- if (!clientId || !actionType || !instructions) {
2387
- throw new CliInputError('signaliz campaign-os request requires --client-id <uuid> --action <type> --instructions "..."');
2463
+ const idempotencyKey = flag("idempotency-key")?.trim();
2464
+ if (!clientId || !actionType || !instructions || !idempotencyKey) {
2465
+ throw new CliInputError('signaliz campaign-os request requires --client-id <uuid> --action <type> --instructions "..." --idempotency-key <key>');
2388
2466
  }
2389
2467
  if (!CAMPAIGN_OS_ACTIONS.has(actionType)) {
2390
2468
  throw new CliInputError(`--action must be one of: ${Array.from(CAMPAIGN_OS_ACTIONS).join(", ")}`);
2391
2469
  }
2470
+ let preflightInputs;
2471
+ const preflightInputsFile = flag("preflight-inputs-file");
2472
+ if (preflightInputsFile) {
2473
+ try {
2474
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(preflightInputsFile, "utf8"));
2475
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
2476
+ throw new Error("expected one JSON object");
2477
+ }
2478
+ const input = parsed;
2479
+ const allowed = /* @__PURE__ */ new Set([
2480
+ "provider",
2481
+ "provider_connection_id",
2482
+ "audience_id",
2483
+ "audience_run_id",
2484
+ "provider_artifact_id",
2485
+ "policy_id",
2486
+ "delivery_id",
2487
+ "provider_campaign_id",
2488
+ "target_count",
2489
+ "verification_max_age_days"
2490
+ ]);
2491
+ const unsupported = Object.keys(input).filter((key) => !allowed.has(key));
2492
+ if (unsupported.length) {
2493
+ throw new Error(`unsupported fields: ${unsupported.join(", ")}`);
2494
+ }
2495
+ preflightInputs = {
2496
+ provider: input.provider,
2497
+ providerConnectionId: input.provider_connection_id,
2498
+ audienceId: input.audience_id,
2499
+ audienceRunId: input.audience_run_id,
2500
+ providerArtifactId: input.provider_artifact_id,
2501
+ policyId: input.policy_id,
2502
+ deliveryId: input.delivery_id,
2503
+ providerCampaignId: input.provider_campaign_id,
2504
+ targetCount: input.target_count,
2505
+ verificationMaxAgeDays: input.verification_max_age_days
2506
+ };
2507
+ } catch (error) {
2508
+ throw new CliInputError(`Unable to read --preflight-inputs-file: ${error instanceof Error ? error.message : String(error)}`);
2509
+ }
2510
+ }
2392
2511
  const result = await client.submitCampaignOsActionRequest({
2393
2512
  clientId,
2394
2513
  campaignId: flag("campaign-id"),
2395
2514
  agentVendor: campaignOsAgentFlag(),
2396
2515
  actionType,
2397
2516
  instructions,
2398
- idempotencyKey: flag("idempotency-key")
2517
+ preflightInputs,
2518
+ idempotencyKey
2399
2519
  });
2400
2520
  output(result, () => {
2401
2521
  const request = record(result.request);
@@ -2405,6 +2525,24 @@ async function campaignOs(args) {
2405
2525
  });
2406
2526
  return;
2407
2527
  }
2528
+ if (action === "prepare-preflight") {
2529
+ const clientId = flag("client-id");
2530
+ const requestId = flag("request-id");
2531
+ if (!clientId || !requestId) {
2532
+ throw new CliInputError("signaliz campaign-os prepare-preflight requires --client-id <uuid> --request-id <uuid>");
2533
+ }
2534
+ const result = await client.prepareCampaignOsActionPreflight(clientId, requestId);
2535
+ output(result, () => {
2536
+ const receipt = record(result.continuation_receipt);
2537
+ const missing = Array.isArray(receipt.missing_inputs) ? receipt.missing_inputs : [];
2538
+ const blockers = Array.isArray(receipt.system_blockers) ? receipt.system_blockers : [];
2539
+ process.stdout.write(`Action preflight continuation: ${String(receipt.implementation_status || "blocked")}
2540
+ `);
2541
+ process.stdout.write(`${missing.length} missing input(s) \xB7 ${blockers.length} system blocker(s) \xB7 provider calls 0
2542
+ `);
2543
+ });
2544
+ return;
2545
+ }
2408
2546
  if (action === "receipts") {
2409
2547
  const limit = numberFlag("limit") ?? 50;
2410
2548
  requireIntegerInRange(limit, "--limit", 1, 200);
@@ -2422,7 +2560,7 @@ async function campaignOs(args) {
2422
2560
  });
2423
2561
  return;
2424
2562
  }
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");
2563
+ 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|request|prepare-preflight|receipts");
2426
2564
  }
2427
2565
  async function main() {
2428
2566
  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.91",
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.95"
34
34
  },
35
35
  "devDependencies": {
36
36
  "tsup": "^8.0.0",