@signaliz/cli 1.0.89 → 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 +18 -4
  2. package/dist/bin.js +174 -7
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -216,18 +216,32 @@ signaliz campaign-os audience-draft --client-id <uuid> --name "Launch ICP" \
216
216
  --definition-file audience.json --entity-type people \
217
217
  --audience-role campaign_segment --source-mode signaliz_owned \
218
218
  --idempotency-key launch-audience-v1 --json
219
+ signaliz campaign-os materialize-cache-audience --client-id <uuid> \
220
+ --audience-id <uuid> --campaign-id <uuid> --target-count 500 \
221
+ --idempotency-key launch-cache-materialization-v1 --json
219
222
  signaliz campaign-os audience-preview --client-id <uuid> \
220
223
  --audience-id <uuid> --idempotency-key launch-preview-v1 --json
221
224
  signaliz campaign-os compile --client-id <uuid> --campaign-id <uuid> \
222
225
  --providers all --json
223
226
  signaliz campaign-os request --client-id <uuid> --campaign-id <uuid> \
224
- --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
225
232
  signaliz campaign-os receipts --client-id <uuid> --json
226
233
  ```
227
234
 
228
235
  `provider-runtime` explains the safe Clay or Instantly route, adapter source,
229
236
  approval boundaries, and receipt semantics without returning credentials or
230
- calling the provider. `build`, `audience-draft`, `audience-preview`, and
231
- `compile` do not need CMM-admin approval and keep providers locked. `request`
232
- creates only an auditable review request for paid sourcing, provider load,
237
+ calling the provider. `build`, `audience-draft`, `materialize-cache-audience`,
238
+ `audience-preview`, and `compile` do not need CMM-admin approval and keep
239
+ providers locked. Cache materialization is capped at 500 members and returns
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,
233
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,10 +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>
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]
67
70
  signaliz campaign-os audience-preview --client-id <uuid> --audience-id <uuid> --idempotency-key <key>
68
71
  signaliz campaign-os compile --client-id <uuid> --campaign-id <uuid> [--providers all]
69
- 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>
70
74
  signaliz campaign-os receipts [--client-id <uuid>] [--campaign-id <uuid>] [--limit 50]
71
75
 
72
76
  Access and connection:
@@ -2239,7 +2243,7 @@ async function campaignOs(args) {
2239
2243
  const campaign = record(result.campaign);
2240
2244
  process.stdout.write(`Campaign Brain build: ${String(build.status || "unknown")}
2241
2245
  `);
2242
- if (campaign.id) process.stdout.write(`Review-held campaign: ${String(campaign.name || "")} (${String(campaign.id)})
2246
+ if (campaign.id) process.stdout.write(`Provider-locked campaign: ${String(campaign.name || "")} (${String(campaign.id)})
2243
2247
  `);
2244
2248
  process.stdout.write("Provider execution remains locked.\n");
2245
2249
  });
@@ -2284,13 +2288,51 @@ async function campaignOs(args) {
2284
2288
  });
2285
2289
  output(result, () => {
2286
2290
  const campaign = record(result.campaign);
2287
- process.stdout.write(`Review-held draft created: ${String(campaign.name || name)} (${String(campaign.id || "")})
2291
+ process.stdout.write(`Provider-locked draft created without admin approval: ${String(campaign.name || name)} (${String(campaign.id || "")})
2288
2292
  `);
2289
2293
  process.stdout.write("Provider load: locked \xB7 activation: locked \xB7 send: locked\n");
2290
2294
  process.stdout.write("No Clay, Instantly, Smartlead, or Bison mutation was performed.\n");
2291
2295
  });
2292
2296
  return;
2293
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
+ }
2294
2336
  if (action === "audience-draft") {
2295
2337
  const clientId = flag("client-id");
2296
2338
  const name = flag("name");
@@ -2340,6 +2382,70 @@ async function campaignOs(args) {
2340
2382
  output(result, () => process.stdout.write("No-spend Audience preview recorded \xB7 provider calls 0 \xB7 Clay usage 0\n"));
2341
2383
  return;
2342
2384
  }
2385
+ if (action === "materialize-cache-audience") {
2386
+ const clientId = flag("client-id");
2387
+ const audienceId = flag("audience-id");
2388
+ const campaignId = flag("campaign-id");
2389
+ const targetCount = numberFlag("target-count");
2390
+ const idempotencyKey = flag("idempotency-key");
2391
+ if (!clientId || !audienceId || targetCount === void 0 || !idempotencyKey) {
2392
+ throw new CliInputError("signaliz campaign-os materialize-cache-audience requires --client-id, --audience-id, --target-count <1-500>, and --idempotency-key");
2393
+ }
2394
+ requireIntegerInRange(targetCount, "--target-count", 1, 500);
2395
+ const result = await client.materializeCampaignOsCacheAudience({
2396
+ clientId,
2397
+ audienceId,
2398
+ campaignId,
2399
+ targetCount,
2400
+ idempotencyKey
2401
+ });
2402
+ output(result, () => {
2403
+ const usage = record(result.usage_receipt);
2404
+ const reconciliation = record(result.terminal_reconciliation_receipt);
2405
+ process.stdout.write(`Cache Audience materialized: target ${targetCount}
2406
+ `);
2407
+ process.stdout.write(`Provider calls: ${String(usage.provider_calls)} \xB7 Clay Search allowance: ${String(usage.clay_search_allowance_used)} \xB7 Clay Actions: ${String(usage.clay_actions_used)} \xB7 Clay Data Credits: ${String(usage.clay_data_credits_used)}
2408
+ `);
2409
+ process.stdout.write(`Terminal reconciliation receipt: ${JSON.stringify(reconciliation)}
2410
+ `);
2411
+ process.stdout.write("No provider approval was requested.\n");
2412
+ });
2413
+ return;
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
+ }
2343
2449
  if (action === "compile") {
2344
2450
  const clientId = flag("client-id");
2345
2451
  const campaignId = flag("campaign-id");
@@ -2354,19 +2460,62 @@ async function campaignOs(args) {
2354
2460
  const clientId = flag("client-id");
2355
2461
  const actionType = flag("action");
2356
2462
  const instructions = flag("instructions");
2357
- if (!clientId || !actionType || !instructions) {
2358
- 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>');
2359
2466
  }
2360
2467
  if (!CAMPAIGN_OS_ACTIONS.has(actionType)) {
2361
2468
  throw new CliInputError(`--action must be one of: ${Array.from(CAMPAIGN_OS_ACTIONS).join(", ")}`);
2362
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
+ }
2363
2511
  const result = await client.submitCampaignOsActionRequest({
2364
2512
  clientId,
2365
2513
  campaignId: flag("campaign-id"),
2366
2514
  agentVendor: campaignOsAgentFlag(),
2367
2515
  actionType,
2368
2516
  instructions,
2369
- idempotencyKey: flag("idempotency-key")
2517
+ preflightInputs,
2518
+ idempotencyKey
2370
2519
  });
2371
2520
  output(result, () => {
2372
2521
  const request = record(result.request);
@@ -2376,6 +2525,24 @@ async function campaignOs(args) {
2376
2525
  });
2377
2526
  return;
2378
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
+ }
2379
2546
  if (action === "receipts") {
2380
2547
  const limit = numberFlag("limit") ?? 50;
2381
2548
  requireIntegerInRange(limit, "--limit", 1, 200);
@@ -2393,7 +2560,7 @@ async function campaignOs(args) {
2393
2560
  });
2394
2561
  return;
2395
2562
  }
2396
- throw new CliInputError("Usage: signaliz campaign-os clients|context|knowledge|provider-runtime|build|build-status|draft|audience-draft|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");
2397
2564
  }
2398
2565
  async function main() {
2399
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.89",
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.93"
33
+ "@signaliz/sdk": "^1.0.95"
34
34
  },
35
35
  "devDependencies": {
36
36
  "tsup": "^8.0.0",