deepline 0.3.115 → 0.3.117

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 (28) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +356 -12
  2. package/dist/bundling-sources/sdk/src/index.ts +12 -1
  3. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  4. package/dist/bundling-sources/shared_libs/monitors/billing/state.ts +36 -6
  5. package/dist/bundling-sources/shared_libs/monitors/billing/types.ts +0 -1
  6. package/dist/bundling-sources/shared_libs/monitors/deactivation-reasons.ts +6 -3
  7. package/dist/bundling-sources/shared_libs/monitors/fleets/verdict.ts +52 -15
  8. package/dist/bundling-sources/shared_libs/monitors/monitor-job-state.ts +44 -0
  9. package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
  10. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +76 -3
  11. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-state.ts +81 -6
  12. package/dist/bundling-sources/shared_libs/monitors/provider-monitor-status.ts +26 -10
  13. package/dist/bundling-sources/shared_libs/observability/queue-health.ts +128 -0
  14. package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +18 -0
  15. package/dist/bundling-sources/shared_libs/observability/scheduled-work-manual.ts +1 -0
  16. package/dist/bundling-sources/shared_libs/plays/share/static-pipeline-summary.ts +2 -2
  17. package/dist/cli/index.js +413 -68
  18. package/dist/cli/index.mjs +413 -68
  19. package/dist/index.d.mts +155 -13
  20. package/dist/index.d.ts +155 -13
  21. package/dist/index.js +137 -2
  22. package/dist/index.mjs +134 -2
  23. package/dist/install-integrity.json +1 -0
  24. package/dist/release.d.mts +1 -1
  25. package/dist/release.d.ts +1 -1
  26. package/dist/release.js +1 -1
  27. package/dist/release.mjs +1 -1
  28. package/package.json +1 -1
@@ -1271,7 +1271,7 @@ var SDK_RELEASE = {
1271
1271
  // getters keep their established compatibility behavior.
1272
1272
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1273
1273
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
1274
- version: "0.3.115",
1274
+ version: "0.3.117",
1275
1275
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
1276
1276
  packageCapabilities: {
1277
1277
  updatePreferences: 1
@@ -5195,6 +5195,7 @@ var DeeplineClient = class {
5195
5195
  available: (toolIdOrOptions, options2) => this.getMonitorsAvailable(toolIdOrOptions, options2),
5196
5196
  check: (definition) => this.checkMonitor(definition),
5197
5197
  deploy: (definition, options2) => this.deployMonitor(definition, options2),
5198
+ sync: (definition, options2) => options2?.dryRun ? this.deployMonitor(definition, { dryRun: true }) : this.syncScalarMonitor(definition, options2),
5198
5199
  list: (options2) => this.listMonitors(options2),
5199
5200
  get: (key) => this.getMonitor(key),
5200
5201
  test: (key, payload, options2) => this.testMonitorWebhook(key, payload, options2),
@@ -5203,6 +5204,18 @@ var DeeplineClient = class {
5203
5204
  update: (key, patch) => this.updateMonitor(key, patch),
5204
5205
  delete: (key, options2) => this.deleteMonitor(key, options2),
5205
5206
  reactivate: (key, options2) => this.reactivateMonitor(key, options2),
5207
+ start: (key, options2) => options2?.dryRun ? this.submitMonitorBatch({
5208
+ kind: "reactivate",
5209
+ scope: { kind: "keys", monitorKeys: [key] },
5210
+ dryRun: true,
5211
+ idempotencyKey: options2.idempotencyKey ?? this.monitorJobIdempotencyKey(`start-${key}`)
5212
+ }) : this.submitScalarMonitorLifecycle(key, "start", options2),
5213
+ stop: (key, options2) => options2?.dryRun ? this.submitMonitorBatch({
5214
+ kind: "deactivate",
5215
+ scope: { kind: "keys", monitorKeys: [key] },
5216
+ dryRun: true,
5217
+ idempotencyKey: options2.idempotencyKey ?? this.monitorJobIdempotencyKey(`stop-${key}`)
5218
+ }) : this.submitScalarMonitorLifecycle(key, "stop", options2),
5206
5219
  audit: (options2) => this.auditMonitors(options2),
5207
5220
  repair: (options2) => this.repairMonitors(options2),
5208
5221
  health: (options2) => this.readMonitorsHealth(options2),
@@ -5211,6 +5224,12 @@ var DeeplineClient = class {
5211
5224
  submit: (options2) => this.submitMonitorBatch(options2),
5212
5225
  get: (operationId, options2) => this.getMonitorBatch(operationId, options2)
5213
5226
  },
5227
+ batches: {
5228
+ sync: (batchId, definitions, options2) => this.syncNamedMonitorBatch(batchId, definitions, options2),
5229
+ start: (batchId, options2) => this.startNamedMonitorBatch(batchId, options2),
5230
+ stop: (batchId, options2) => this.stopNamedMonitorBatch(batchId, options2),
5231
+ get: (batchId) => this.getNamedMonitorBatch(batchId)
5232
+ },
5214
5233
  jobs: {
5215
5234
  get: (jobId) => this.getMonitorJob(jobId),
5216
5235
  logs: (jobId, options2) => this.getMonitorJobLogs(jobId, options2),
@@ -5224,6 +5243,8 @@ var DeeplineClient = class {
5224
5243
  list: () => this.listMonitorFleets(),
5225
5244
  deactivate: (fleetId, options2) => this.deactivateMonitorFleet(fleetId, options2),
5226
5245
  reactivate: (fleetId, options2) => this.reactivateMonitorFleet(fleetId, options2),
5246
+ start: (fleetId, options2) => this.reactivateMonitorFleet(fleetId, options2),
5247
+ stop: (fleetId, options2) => this.deactivateMonitorFleet(fleetId, options2),
5227
5248
  waitForConvergence: (fleetId, options2) => this.waitForMonitorFleetConvergence(fleetId, options2)
5228
5249
  }
5229
5250
  };
@@ -7874,7 +7895,8 @@ var DeeplineClient = class {
7874
7895
  /** List deployed monitors. Prefer `client.monitors.list(...)`. */
7875
7896
  async listMonitors(options) {
7876
7897
  const params = new URLSearchParams();
7877
- if (options?.status) params.set("status", options.status);
7898
+ if (options?.state) params.set("state", options.state);
7899
+ else if (options?.status) params.set("status", options.status);
7878
7900
  if (options?.limit !== void 0)
7879
7901
  params.set("limit", String(options.limit));
7880
7902
  if (options?.cursor) params.set("cursor", options.cursor);
@@ -8013,6 +8035,92 @@ var DeeplineClient = class {
8013
8035
  }
8014
8036
  );
8015
8037
  }
8038
+ namedMonitorBatchPath(batchId) {
8039
+ return `/api/v2/monitors/batches/${encodeURIComponent(batchId)}`;
8040
+ }
8041
+ async syncNamedMonitorBatch(batchId, definitions, options) {
8042
+ return this.http.request(
8043
+ this.namedMonitorBatchPath(batchId),
8044
+ {
8045
+ method: "PUT",
8046
+ body: {
8047
+ version: 1,
8048
+ kind: "batch",
8049
+ monitors: definitions,
8050
+ ...options?.expectedGeneration === void 0 ? {} : { expected_generation: options.expectedGeneration }
8051
+ },
8052
+ headers: this.monitorJobHeaders(
8053
+ `batch-sync-${batchId}`,
8054
+ options?.idempotencyKey
8055
+ ),
8056
+ maxRetries: 0,
8057
+ exactUrlOnly: true
8058
+ }
8059
+ );
8060
+ }
8061
+ async startNamedMonitorBatch(batchId, options) {
8062
+ return this.http.request(
8063
+ `${this.namedMonitorBatchPath(batchId)}/start`,
8064
+ {
8065
+ method: "POST",
8066
+ body: {},
8067
+ headers: this.monitorJobHeaders(
8068
+ `batch-start-${batchId}`,
8069
+ options?.idempotencyKey
8070
+ ),
8071
+ maxRetries: 0,
8072
+ exactUrlOnly: true
8073
+ }
8074
+ );
8075
+ }
8076
+ async stopNamedMonitorBatch(batchId, options) {
8077
+ return this.http.request(
8078
+ this.namedMonitorBatchPath(batchId),
8079
+ {
8080
+ method: "DELETE",
8081
+ body: {},
8082
+ headers: this.monitorJobHeaders(
8083
+ `batch-stop-${batchId}`,
8084
+ options?.idempotencyKey
8085
+ ),
8086
+ maxRetries: 0,
8087
+ exactUrlOnly: true
8088
+ }
8089
+ );
8090
+ }
8091
+ async getNamedMonitorBatch(batchId) {
8092
+ return this.http.request(
8093
+ this.namedMonitorBatchPath(batchId),
8094
+ { method: "GET" }
8095
+ );
8096
+ }
8097
+ async submitScalarMonitorLifecycle(monitorKey, action, options) {
8098
+ return this.http.request(
8099
+ `/api/v2/monitors/deployed/${encodeURIComponent(monitorKey)}/${action}`,
8100
+ {
8101
+ method: "POST",
8102
+ body: {},
8103
+ headers: this.monitorJobHeaders(
8104
+ `${action}-${monitorKey}`,
8105
+ options?.idempotencyKey
8106
+ ),
8107
+ maxRetries: 0,
8108
+ exactUrlOnly: true
8109
+ }
8110
+ );
8111
+ }
8112
+ async syncScalarMonitor(definition, options) {
8113
+ return this.http.request("/api/v2/monitors/sync", {
8114
+ method: "POST",
8115
+ body: definition,
8116
+ headers: this.monitorJobHeaders(
8117
+ `sync-${definition.key}`,
8118
+ options?.idempotencyKey
8119
+ ),
8120
+ maxRetries: 0,
8121
+ exactUrlOnly: true
8122
+ });
8123
+ }
8016
8124
  async getMonitorJob(jobId) {
8017
8125
  return this.http.request(
8018
8126
  `/api/v2/monitors/jobs/${encodeURIComponent(jobId)}`,
@@ -33683,6 +33791,40 @@ function asRecord2(value) {
33683
33791
  function asString(value) {
33684
33792
  return typeof value === "string" && value.trim() ? value : void 0;
33685
33793
  }
33794
+ var MONITOR_STATES = /* @__PURE__ */ new Set([
33795
+ "active",
33796
+ "billing_suspended",
33797
+ "disabled"
33798
+ ]);
33799
+ function customerMonitorState(value) {
33800
+ if (typeof value === "string" && MONITOR_STATES.has(value)) {
33801
+ return value;
33802
+ }
33803
+ return void 0;
33804
+ }
33805
+ function readMonitorState(record3) {
33806
+ const state = customerMonitorState(record3.state);
33807
+ if (state) return state;
33808
+ const legacyStatus = asString(record3.status);
33809
+ if (legacyStatus === "active") return "active";
33810
+ if (legacyStatus === "billing_suspended") return "billing_suspended";
33811
+ if (legacyStatus === "disabled") return "disabled";
33812
+ if (legacyStatus === "inactive") return "disabled";
33813
+ if (typeof record3.active === "boolean") {
33814
+ return record3.active ? "active" : "disabled";
33815
+ }
33816
+ return void 0;
33817
+ }
33818
+ function monitorStateFilter(value) {
33819
+ if (value === "all") return "all";
33820
+ return customerMonitorState(value);
33821
+ }
33822
+ function monitorStateFilterLabel(value, fallback = "active") {
33823
+ const canonical = monitorStateFilter(value);
33824
+ if (canonical) return canonical;
33825
+ if (value === "inactive") return "disabled";
33826
+ return fallback;
33827
+ }
33686
33828
  function asFiniteNumber(value) {
33687
33829
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
33688
33830
  }
@@ -33773,14 +33915,14 @@ function renderMonitorDeployCompletion(payload) {
33773
33915
  if (!key || streams.length === 0) return void 0;
33774
33916
  const toolId = tool ?? (monitor ? asString(monitor.tool) : void 0) ?? "<tool>";
33775
33917
  const name = monitor ? asString(monitor.name) : void 0;
33776
- const status = monitor ? asString(monitor.status) : void 0;
33918
+ const state = monitor ? readMonitorState(monitor) : void 0;
33777
33919
  const pricingLine = monitorPricingLine(monitor?.pricing ?? payload.pricing);
33778
33920
  const eventStreams = streams.filter((stream) => stream.isEvent);
33779
33921
  const matched = eventStreams.filter((stream) => stream.matchesPayload);
33780
33922
  const shown = matched.length ? matched : eventStreams.length ? eventStreams : streams;
33781
33923
  const primary = shown[0];
33782
33924
  const lines = [
33783
- `\u2713 Deployed monitor "${key}"${name ? ` (${name})` : ""} \u2014 tool ${toolId}${status ? `, status ${status}` : ""}`,
33925
+ `\u2713 Deployed monitor "${key}"${name ? ` (${name})` : ""} \u2014 tool ${toolId}${state ? `, status ${state}` : ""}`,
33784
33926
  "",
33785
33927
  "Output \u2192 Customer DB:"
33786
33928
  ];
@@ -33881,10 +34023,10 @@ function renderMonitorDeployPlan(payload) {
33881
34023
  const key = candidate ? asString(candidate.key) : void 0;
33882
34024
  if (!candidate || !key) return [];
33883
34025
  const name = asString(candidate.name);
33884
- const status = asString(candidate.status);
34026
+ const state = readMonitorState(candidate);
33885
34027
  const covers = asString(candidate.covers);
33886
34028
  return [
33887
- ` ${key}${name ? ` (${name})` : ""}${status ? ` \u2014 ${status}` : ""}${covers ? `; covers ${covers}` : ""}`
34029
+ ` ${key}${name ? ` (${name})` : ""}${state ? ` \u2014 ${state}` : ""}${covers ? `; covers ${covers}` : ""}`
33888
34030
  ];
33889
34031
  });
33890
34032
  if (candidateLines.length > 0) {
@@ -34063,7 +34205,7 @@ async function handleMonitorsAvailable(toolId, options) {
34063
34205
  text: tool ? void 0 : renderAvailableToolsText(payload)
34064
34206
  });
34065
34207
  }
34066
- function renderDeployedListText(payload, requestedStatus) {
34208
+ function renderDeployedListText(payload, requestedStatus, filterKind = "status") {
34067
34209
  const monitors = Array.isArray(payload.monitors) ? payload.monitors : null;
34068
34210
  if (!monitors) return void 0;
34069
34211
  const total = asFiniteNumber(payload.total);
@@ -34073,7 +34215,7 @@ function renderDeployedListText(payload, requestedStatus) {
34073
34215
  const entry = asRecord2(raw);
34074
34216
  const key = entry ? asString(entry.key) ?? asString(entry.monitor_key) : void 0;
34075
34217
  if (!entry || !key) continue;
34076
- const status = asString(entry.status);
34218
+ const state = readMonitorState(entry);
34077
34219
  const tool = asString(entry.tool);
34078
34220
  const monitorType = asString(entry.type);
34079
34221
  const name = asString(entry.name);
@@ -34084,7 +34226,7 @@ function renderDeployedListText(payload, requestedStatus) {
34084
34226
  const lastReceivedEvent = asString(entry.last_received_event);
34085
34227
  const boundPlays = Array.isArray(entry.bound_plays) ? entry.bound_plays.length : void 0;
34086
34228
  lines.push(
34087
- ` ${key}${status ? ` ${status}` : ""}${tool ? ` ${tool}` : ""}${name ? ` (${name})` : ""}`
34229
+ ` ${key}${state ? ` ${state}` : ""}${tool ? ` ${tool}` : ""}${name ? ` (${name})` : ""}`
34088
34230
  );
34089
34231
  if (outputTable || monitorType || webhookState || executionType || boundPlays !== void 0) {
34090
34232
  lines.push(
@@ -34106,30 +34248,38 @@ function renderDeployedListText(payload, requestedStatus) {
34106
34248
  const playName = asString(play?.name) ?? "unnamed Play";
34107
34249
  const health = asRecord2(play?.consumer_health);
34108
34250
  const healthRequested = Boolean(play && "consumer_health" in play);
34109
- const state = healthRequested ? asString(health?.last_run_status) ?? "no delivery yet" : "health not requested";
34251
+ const state2 = healthRequested ? asString(health?.last_run_status) ?? "no delivery yet" : "health not requested";
34110
34252
  const lastError = asString(health?.last_error);
34111
34253
  lines.push(
34112
- ` consumer: ${playName} \u2014 ${state}${lastError ? ` (${lastError})` : ""}`
34254
+ ` consumer: ${playName} \u2014 ${state2}${lastError ? ` (${lastError})` : ""}`
34113
34255
  );
34114
34256
  }
34115
34257
  }
34116
34258
  }
34117
- const applied = asString(payload.status_filter_applied) ?? requestedStatus ?? "active";
34259
+ const applied = monitorStateFilterLabel(
34260
+ payload.state_filter_applied ?? payload.status_filter_applied,
34261
+ monitorStateFilterLabel(requestedStatus)
34262
+ );
34118
34263
  lines.push(
34119
- `Status filter: ${applied}${requestedStatus === void 0 && applied === "active" ? " (default)" : ""} \u2014 use --status all to include inactive monitors.`
34264
+ `State filter: ${applied}${requestedStatus === void 0 && applied === "active" ? " (default)" : ""} \u2014 use --state all to include all monitors.`
34120
34265
  );
34121
- const summary = Array.isArray(payload.status_summary) ? payload.status_summary.flatMap((raw) => {
34266
+ const rawSummary = Array.isArray(payload.state_summary) ? payload.state_summary : Array.isArray(payload.status_summary) ? payload.status_summary : [];
34267
+ const summary = rawSummary.flatMap((raw) => {
34122
34268
  const item = asRecord2(raw);
34123
- const status = item ? asString(item.status) : void 0;
34269
+ const state = item ? readMonitorState(item) : void 0;
34124
34270
  const count = item ? asFiniteNumber(item.count) : void 0;
34125
- return status && count !== void 0 ? [`${status}: ${count}`] : [];
34126
- }).join(" ") : "";
34127
- if (summary) lines.push(`All monitor states: ${summary}`);
34271
+ return state && count !== void 0 ? [`${state}: ${count}`] : [];
34272
+ }).join(" ");
34273
+ if (summary) {
34274
+ lines.push(
34275
+ `${payload.state_summary_scope === "filter_total" ? "Matching monitors" : "Current page states"}: ${summary}`
34276
+ );
34277
+ }
34128
34278
  if (payload.has_more === true || payload.is_truncated === true) {
34129
34279
  const nextCursor = asString(payload.next_cursor);
34130
34280
  lines.push(
34131
34281
  total !== void 0 ? `List truncated \u2014 showing ${monitors.length} of ${total}. Before concluding "no matching monitor exists," page the full registry:` : 'List truncated. Before concluding "no matching monitor exists," page the full registry:',
34132
- nextCursor ? ` deepline monitors list${requestedStatus ? ` --status ${requestedStatus}` : ""} --cursor ${nextCursor}` : " raise --limit above the reported total."
34282
+ nextCursor ? ` deepline monitors list${requestedStatus ? ` --${filterKind} ${filterKind === "state" ? monitorStateFilterLabel(requestedStatus) : requestedStatus}` : ""} --cursor ${nextCursor}` : " raise --limit above the reported total."
34133
34283
  );
34134
34284
  }
34135
34285
  if (monitors.length > 0) {
@@ -34139,12 +34289,19 @@ function renderDeployedListText(payload, requestedStatus) {
34139
34289
  `;
34140
34290
  }
34141
34291
  async function handleMonitorsList(options) {
34292
+ const state = options.state ? monitorStateFilter(options.state) : void 0;
34293
+ if (options.state !== void 0 && !state) {
34294
+ throw new MonitorsUsageError(
34295
+ `--state must be active, billing_suspended, disabled, or all; received ${options.state}.`
34296
+ );
34297
+ }
34142
34298
  if (options.compact) {
34143
34299
  process.stderr.write(
34144
34300
  "`--compact` is deprecated and now does nothing; returning the complete monitor records.\n"
34145
34301
  );
34146
34302
  }
34147
34303
  const payload = await new DeeplineClient().monitors.list({
34304
+ ...state ? { state } : {},
34148
34305
  ...options.status ? { status: options.status } : {},
34149
34306
  ...options.limit ? { limit: options.limit } : {},
34150
34307
  ...options.cursor ? { cursor: options.cursor } : {},
@@ -34152,7 +34309,11 @@ async function handleMonitorsList(options) {
34152
34309
  });
34153
34310
  printCommandEnvelope(payload, {
34154
34311
  json: options.json,
34155
- text: renderDeployedListText(payload, options.status)
34312
+ text: renderDeployedListText(
34313
+ payload,
34314
+ options.state ?? options.status,
34315
+ options.state !== void 0 ? "state" : "status"
34316
+ )
34156
34317
  });
34157
34318
  }
34158
34319
  async function handleMonitorsCheck(definition, options) {
@@ -34197,6 +34358,40 @@ async function handleMonitorsDeploy(definition, options) {
34197
34358
  text: renderMonitorDeployCompletion(payload)
34198
34359
  });
34199
34360
  }
34361
+ async function handleMonitorsSync(definition, options) {
34362
+ const body = resolveMonitorJsonBody({
34363
+ positional: definition,
34364
+ file: options.file,
34365
+ argLabel: "<definition>",
34366
+ command: "deepline monitors sync"
34367
+ });
34368
+ const payload = await new DeeplineClient().monitors.sync(body, {
34369
+ ...options.dryRun ? { dryRun: true } : {},
34370
+ idempotencyKey: options.idempotencyKey ?? monitorJobIdempotencyKey("scalar-sync", void 0)
34371
+ });
34372
+ if (options.dryRun) {
34373
+ const plan = payload;
34374
+ printCommandEnvelope(
34375
+ { dry_run: true, ...plan },
34376
+ { json: options.json, text: renderMonitorDeployPlan(plan) }
34377
+ );
34378
+ return;
34379
+ }
34380
+ printCommandEnvelope(payload, {
34381
+ json: options.json,
34382
+ text: renderMonitorJob(payload)
34383
+ });
34384
+ }
34385
+ async function handleScalarMonitorLifecycle(action, key, options) {
34386
+ const payload = await new DeeplineClient().monitors[action](key, {
34387
+ ...options.dryRun ? { dryRun: true } : {},
34388
+ idempotencyKey: options.idempotencyKey ?? monitorJobIdempotencyKey(`${action}-${key}`, void 0)
34389
+ });
34390
+ printCommandEnvelope(payload, {
34391
+ json: options.json,
34392
+ text: options.dryRun ? void 0 : renderMonitorJob(payload)
34393
+ });
34394
+ }
34200
34395
  function fleetIntegerOption(raw, flag) {
34201
34396
  if (raw === void 0) return void 0;
34202
34397
  const value = Number(raw);
@@ -34250,7 +34445,7 @@ function renderMonitorJob(payload) {
34250
34445
  ];
34251
34446
  if (counts) {
34252
34447
  lines.push(
34253
- `Counts: requested ${asFiniteNumber(counts.requested) ?? 0}, created ${asFiniteNumber(counts.created) ?? 0}, unchanged ${asFiniteNumber(counts.unchanged) ?? 0}, verified ${asFiniteNumber(counts.verified) ?? 0}, failed ${asFiniteNumber(counts.failed) ?? 0}`
34448
+ `Counts: requested ${asFiniteNumber(counts.requested) ?? 0}, created ${asFiniteNumber(counts.created) ?? 0}, updated ${asFiniteNumber(counts.updated) ?? 0}, removed ${asFiniteNumber(counts.removed) ?? 0}, unchanged ${asFiniteNumber(counts.unchanged) ?? 0}, verified ${asFiniteNumber(counts.verified) ?? 0}, failed ${asFiniteNumber(counts.failed) ?? 0}`
34254
34449
  );
34255
34450
  }
34256
34451
  if (reconciliation) {
@@ -34290,6 +34485,93 @@ async function handleMonitorJobBatchDeploy(options, idempotencyKey) {
34290
34485
  { json: options.json, text: renderMonitorJob(payload) }
34291
34486
  );
34292
34487
  }
34488
+ function namedBatchIdempotencyKey(batchId, intent, supplied) {
34489
+ return supplied?.trim() || `monitor-batch-${intent}-${batchId}-${randomUUID5()}`;
34490
+ }
34491
+ async function handleNamedMonitorBatchSync(batchId, options) {
34492
+ if (!options.file) {
34493
+ throw new MonitorsUsageError(
34494
+ "monitors batches sync requires --file <batch.json>."
34495
+ );
34496
+ }
34497
+ const lint = lintMonitorBatchInput(
34498
+ readMonitorDefinitionsJsonFile(options.file)
34499
+ );
34500
+ if (!lint.normalized) {
34501
+ throw new MonitorsUsageError(
34502
+ lint.issues.filter((issue) => issue.severity === "error").map((issue) => `${issue.path || "batch"}: ${issue.message}`).join("; ")
34503
+ );
34504
+ }
34505
+ const parsedGeneration = options.expectedGeneration === void 0 ? void 0 : Number(options.expectedGeneration);
34506
+ if (parsedGeneration !== void 0 && (!Number.isSafeInteger(parsedGeneration) || parsedGeneration < 0)) {
34507
+ throw new MonitorsUsageError(
34508
+ "--expected-generation must be a non-negative integer."
34509
+ );
34510
+ }
34511
+ if (options.dryRun) {
34512
+ printCommandEnvelope(
34513
+ {
34514
+ ok: true,
34515
+ dry_run: true,
34516
+ batch: { id: batchId, desired_count: lint.normalized.monitors.length },
34517
+ issues: lint.issues,
34518
+ next: `deepline monitors batches sync ${batchId} --file ${options.file} --idempotency-key <stable-key> --json`
34519
+ },
34520
+ { json: options.json }
34521
+ );
34522
+ return;
34523
+ }
34524
+ const idempotencyKey = namedBatchIdempotencyKey(
34525
+ batchId,
34526
+ "sync",
34527
+ options.idempotencyKey
34528
+ );
34529
+ const payload = await new DeeplineClient().monitors.batches.sync(
34530
+ batchId,
34531
+ lint.normalized.monitors,
34532
+ {
34533
+ idempotencyKey,
34534
+ ...parsedGeneration === void 0 ? {} : { expectedGeneration: parsedGeneration }
34535
+ }
34536
+ );
34537
+ printCommandEnvelope(
34538
+ { ...payload, idempotency_key: idempotencyKey },
34539
+ { json: options.json, text: renderMonitorJob(payload) }
34540
+ );
34541
+ }
34542
+ async function handleNamedMonitorBatchLifecycle(batchId, intent, options) {
34543
+ if (options.dryRun) {
34544
+ printCommandEnvelope(
34545
+ {
34546
+ ok: true,
34547
+ dry_run: true,
34548
+ batch: { id: batchId, intent },
34549
+ next: `deepline monitors batches ${intent} ${batchId} --idempotency-key <stable-key> --json`
34550
+ },
34551
+ { json: options.json }
34552
+ );
34553
+ return;
34554
+ }
34555
+ const idempotencyKey = namedBatchIdempotencyKey(
34556
+ batchId,
34557
+ intent,
34558
+ options.idempotencyKey
34559
+ );
34560
+ const payload = await new DeeplineClient().monitors.batches[intent](batchId, {
34561
+ idempotencyKey
34562
+ });
34563
+ printCommandEnvelope(
34564
+ { ...payload, idempotency_key: idempotencyKey },
34565
+ { json: options.json, text: renderMonitorJob(payload) }
34566
+ );
34567
+ }
34568
+ async function handleNamedMonitorBatchGet(batchId, options) {
34569
+ const payload = await new DeeplineClient().monitors.batches.get(batchId);
34570
+ printCommandEnvelope(payload, {
34571
+ json: options.json,
34572
+ text: renderMonitorJob(payload)
34573
+ });
34574
+ }
34293
34575
  async function handleMonitorBatchLint(options) {
34294
34576
  if (!options.file) {
34295
34577
  throw new MonitorsUsageError(
@@ -34539,9 +34821,10 @@ function renderFleetSync(payload, input2) {
34539
34821
  }
34540
34822
  function renderFleetGet(payload) {
34541
34823
  const id = asString(payload.id) ?? "unknown";
34542
- const status = fleetStatus(payload) ?? "unknown";
34824
+ const state = readMonitorState(payload) ?? "unknown";
34825
+ const status = fleetStatus(payload);
34543
34826
  const lines = [
34544
- `Fleet ${id} \u2014 ${status}`,
34827
+ `Fleet ${id} \u2014 state ${state}`,
34545
34828
  ` monitors ${asFiniteNumber(payload.live) ?? 0} live / ${asFiniteNumber(payload.expected) ?? 0} expected`,
34546
34829
  ` counts ${fleetCountsLine(payload)}`,
34547
34830
  ` generation ${asFiniteNumber(payload.generation) ?? "unknown"} \xB7 converged generation ${asFiniteNumber(payload.converged_generation) ?? "none"}`
@@ -34620,8 +34903,8 @@ function renderFleetList(payload) {
34620
34903
  (max, fleet) => Math.max(max, (asString(fleet.id) ?? "").length),
34621
34904
  0
34622
34905
  );
34623
- const statusWidth = fleets.reduce(
34624
- (max, fleet) => Math.max(max, (fleetStatus(fleet) ?? "unknown").length),
34906
+ const stateWidth = fleets.reduce(
34907
+ (max, fleet) => Math.max(max, (readMonitorState(fleet) ?? "unknown").length),
34625
34908
  0
34626
34909
  );
34627
34910
  const lines = [`Fleets (${fleets.length})`];
@@ -34632,7 +34915,7 @@ function renderFleetList(payload) {
34632
34915
  counts.failed ? `failed ${counts.failed}` : ""
34633
34916
  ].filter(Boolean);
34634
34917
  lines.push(
34635
- ` ${(asString(fleet.id) ?? "-").padEnd(idWidth)} ${(fleetStatus(fleet) ?? "unknown").padEnd(statusWidth)} ${asFiniteNumber(fleet.live) ?? 0}/${asFiniteNumber(fleet.expected) ?? 0}${trouble.length ? ` ${trouble.join(" \xB7 ")}` : ""}`
34918
+ ` ${(asString(fleet.id) ?? "-").padEnd(idWidth)} ${(readMonitorState(fleet) ?? "unknown").padEnd(stateWidth)} ${asFiniteNumber(fleet.live) ?? 0}/${asFiniteNumber(fleet.expected) ?? 0}${trouble.length ? ` ${trouble.join(" \xB7 ")}` : ""}`
34636
34919
  );
34637
34920
  }
34638
34921
  return `${lines.join("\n")}
@@ -34973,7 +35256,7 @@ async function handleMonitorFleetsReactivate(fleetId, options, idempotencyKey) {
34973
35256
  if (!options.wait) {
34974
35257
  printCommandEnvelope(accepted, {
34975
35258
  json: options.json,
34976
- text: `Fleet ${fleetId} \u2014 ${asString(payload.status) ?? "billing_reactivating"}
35259
+ text: `Fleet ${fleetId} \u2014 ${readMonitorState(payload) ? `state ${readMonitorState(payload)}` : "reactivation accepted"}
34977
35260
  idempotency key ${idempotencyKey}
34978
35261
  `
34979
35262
  });
@@ -35091,7 +35374,7 @@ Preview the blast radius first:
35091
35374
  });
35092
35375
  return;
35093
35376
  }
35094
- const acceptedText = `Fleet ${fleetId} \u2014 ${asString(payload.status) ?? "deactivating"}
35377
+ const acceptedText = `Fleet ${fleetId} \u2014 ${readMonitorState(payload) ? `state ${readMonitorState(payload)}` : "deactivation accepted"}
35095
35378
  idempotency key ${idempotencyKey}
35096
35379
  ` + (fleetServerNext(payload) ? `Next: ${fleetServerNext(payload)}
35097
35380
  ` : "");
@@ -35165,7 +35448,7 @@ function renderMonitorGet(payload) {
35165
35448
  const key = asString(payload.key);
35166
35449
  const tool = asString(payload.tool);
35167
35450
  if (!key || !tool) return void 0;
35168
- const status = asString(payload.status);
35451
+ const state = readMonitorState(payload);
35169
35452
  const monitorType = asString(payload.type);
35170
35453
  const hasLastReceivedEvent = "last_received_event" in payload;
35171
35454
  const lastReceivedEvent = asString(payload.last_received_event);
@@ -35185,7 +35468,7 @@ function renderMonitorGet(payload) {
35185
35468
  `Monitor: ${key}`,
35186
35469
  `Tool: ${tool}`,
35187
35470
  ...monitorType ? [`Type: ${monitorType}`] : [],
35188
- ...status ? [`Status: ${status}`] : [],
35471
+ ...state ? [`Status: ${state}`] : [],
35189
35472
  ...hasLastReceivedEvent ? [`Latest inbound event: ${lastReceivedEvent ?? "never"}`] : [],
35190
35473
  ...pricingLine ? [`Pricing: ${pricingLine}`] : [],
35191
35474
  ...nextRenewalAt ? [`Next renewal: ${nextRenewalAt}`] : []
@@ -35622,27 +35905,15 @@ function monitorBatchScope(options, kind) {
35622
35905
  function monitorBatchIdempotencyKey(kind, value) {
35623
35906
  return value?.trim() || `monitor-batch-${kind}-${randomUUID5()}`;
35624
35907
  }
35625
- function legacyDryRunManifest(raw) {
35626
- let parsed;
35908
+ function isCanonicalBatchJsonDocument(raw) {
35627
35909
  try {
35628
- parsed = JSON.parse(raw);
35910
+ const parsed = JSON.parse(raw);
35911
+ if (Array.isArray(parsed)) return true;
35912
+ const input2 = asRecord2(parsed);
35913
+ return input2 !== null && (input2.kind === "batch" || Object.prototype.hasOwnProperty.call(input2, "monitors") || Object.prototype.hasOwnProperty.call(input2, "version"));
35629
35914
  } catch {
35630
- return raw;
35631
- }
35632
- const object = asRecord2(parsed);
35633
- if (object && asString(object.key) && asString(object.tool)) {
35634
- return raw;
35635
- }
35636
- const isBatchDocument = Array.isArray(parsed) || object !== null && (Object.prototype.hasOwnProperty.call(object, "monitors") || object.kind === "batch");
35637
- if (!isBatchDocument) return raw;
35638
- const lint = lintMonitorBatchInput(parsed);
35639
- if (!lint.normalized) {
35640
- throw new MonitorsUsageError(
35641
- lint.issues.filter((issue) => issue.severity === "error").map((issue) => `${issue.path || "batch"}: ${issue.message}`).join("; ")
35642
- );
35915
+ return false;
35643
35916
  }
35644
- return `${lint.normalized.monitors.map((monitor) => JSON.stringify(monitor)).join("\n")}
35645
- `;
35646
35917
  }
35647
35918
  async function handleMonitorBatchDeploy(options) {
35648
35919
  if (!options.file?.trim()) {
@@ -35666,8 +35937,10 @@ async function handleMonitorBatchDeploy(options) {
35666
35937
  if (!manifestNdjson.trim()) {
35667
35938
  throw new MonitorsUsageError("Monitor batch manifest is empty.");
35668
35939
  }
35669
- if (options.dryRun === true) {
35670
- manifestNdjson = legacyDryRunManifest(manifestNdjson);
35940
+ if (isCanonicalBatchJsonDocument(manifestNdjson)) {
35941
+ throw new MonitorsUsageError(
35942
+ "Canonical Batch JSON cannot use --dry-run or --yes; those flags select the retained legacy NDJSON operation. Run `deepline monitors batch lint --file <batch.json> --json`, then submit the Monitor Job with `deepline monitors batch deploy --file <batch.json> --idempotency-key <key> --json`."
35943
+ );
35671
35944
  }
35672
35945
  const idempotencyKey = monitorBatchIdempotencyKey(
35673
35946
  "deploy",
@@ -35869,7 +36142,7 @@ Examples:
35869
36142
  ).requiredOption(
35870
36143
  "--file <path>",
35871
36144
  'Batch JSON ({"version":1,"kind":"batch","monitors":[...]}), or legacy NDJSON with --yes/--dry-run'
35872
- ).option("--dry-run", "Use the retained legacy batch-operation plan").option("--yes", "Use the retained legacy NDJSON batch operation").option(
36145
+ ).option("--dry-run", "Preview a retained legacy NDJSON batch operation").option("--yes", "Confirm a retained legacy NDJSON batch operation").option(
35873
36146
  "--idempotency-key <key>",
35874
36147
  "Stable retry key (generated when omitted)"
35875
36148
  )
@@ -35936,6 +36209,46 @@ Examples:
35936
36209
  withJsonOption(
35937
36210
  batch.command("get <operation-id>").description("Read batch progress and one bounded evidence page.").option("--cursor <cursor>", "Read the next retained evidence page")
35938
36211
  ).action(monitorsAction(handleMonitorBatchGet));
36212
+ const namedBatches = monitors.command("batches").description(
36213
+ "Manage stable named Batches whose omitted members are stopped."
36214
+ );
36215
+ withJsonOption(namedBatches);
36216
+ withJsonOption(
36217
+ namedBatches.command("sync <batch-id>").description(
36218
+ "Publish the complete desired member set and return one Monitor Job."
36219
+ ).requiredOption(
36220
+ "--file <path>",
36221
+ "Canonical Batch JSON file, or - for stdin"
36222
+ ).option(
36223
+ "--dry-run",
36224
+ "Validate and show the desired count without publishing"
36225
+ ).option("--expected-generation <n>", "Reject a stale concurrent update").option("--idempotency-key <key>", "Stable retry key")
36226
+ ).action(monitorsAction(handleNamedMonitorBatchSync));
36227
+ withJsonOption(
36228
+ namedBatches.command("start <batch-id>").description("Reapply the retained member set through one Monitor Job.").option(
36229
+ "--dry-run",
36230
+ "Show the retained-intent operation without publishing"
36231
+ ).option("--idempotency-key <key>", "Stable retry key")
36232
+ ).action(
36233
+ monitorsAction(
36234
+ (batchId, options) => handleNamedMonitorBatchLifecycle(batchId, "start", options)
36235
+ )
36236
+ );
36237
+ withJsonOption(
36238
+ namedBatches.command("stop <batch-id>").description(
36239
+ "Publish an empty desired set while retaining members for start."
36240
+ ).option(
36241
+ "--dry-run",
36242
+ "Show the retained-intent operation without publishing"
36243
+ ).option("--idempotency-key <key>", "Stable retry key")
36244
+ ).action(
36245
+ monitorsAction(
36246
+ (batchId, options) => handleNamedMonitorBatchLifecycle(batchId, "stop", options)
36247
+ )
36248
+ );
36249
+ withJsonOption(
36250
+ namedBatches.command("get <batch-id>").description("Read named Batch intent and its latest Monitor Job.")
36251
+ ).action(monitorsAction(handleNamedMonitorBatchGet));
35939
36252
  withJsonOption(
35940
36253
  monitors.command("status").description("Check whether you have access to Deepline monitors.").addHelpText(
35941
36254
  "after",
@@ -35987,9 +36300,11 @@ Examples:
35987
36300
  "after",
35988
36301
  `
35989
36302
  Notes:
35990
- Read-only. A monitor state is active or inactive; provider disagreement is
35991
- reported separately by audit/health. The output echoes the state filter that
35992
- was applied. The response reports
36303
+ Read-only. A monitor has one of three customer states: active,
36304
+ billing_suspended, or disabled. Provisioning, cleanup, retries, and failures
36305
+ are reported by Monitor Jobs; provider disagreement is reported separately by
36306
+ audit/health. The output echoes the canonical state filter that was applied.
36307
+ The legacy --status flag remains accepted for installed clients. The response reports
35993
36308
  total (the true registry count, not the page size), returned, has_more, and
35994
36309
  next_cursor. When has_more is true, page with --cursor <next_cursor> until it
35995
36310
  is false \u2014 a "no matching
@@ -36001,13 +36316,18 @@ Notes:
36001
36316
 
36002
36317
  Examples:
36003
36318
  deepline monitors list
36319
+ deepline monitors list --state billing_suspended --json
36320
+ deepline monitors list --state all --json
36004
36321
  deepline monitors list --status all --json
36005
36322
  deepline monitors list --status all --cursor <next_cursor> --json
36006
36323
  deepline monitors list --include-consumers --limit 20 --json
36007
36324
  `
36325
+ ).option(
36326
+ "--state <state>",
36327
+ "Filter by customer state: active (default), billing_suspended, disabled, or all"
36008
36328
  ).option(
36009
36329
  "--status <status>",
36010
- "Filter by monitor state: active (default), inactive, or all"
36330
+ "Deprecated compatibility filter; use --state (active, billing_suspended, disabled, or all)"
36011
36331
  ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
36012
36332
  "--cursor <cursor>",
36013
36333
  "Page past a truncated result using the next_cursor from a prior list response"
@@ -36105,13 +36425,10 @@ Notes:
36105
36425
  no separate repair command or retry queue: rerun the same deploy/update.
36106
36426
  Scheduled reconciliation can also finish that exact saved cleanup; it never
36107
36427
  creates another monitor.
36108
- For TamRadar, deliberately changing payload.updates_since on an initial or
36109
- active definition is an explicit historical replay request. A disabled
36110
- monitor cannot stage this change; Deepline rejects that update. Filter-only
36111
- deploys and ordinary reactivation omit the field and start the provider
36112
- resource at creation instead.
36113
- New Hire and Promotion source dates use calendar-month precision upstream,
36114
- so Deepline rejects current-month updates_since values for those radar types.
36428
+ For TamRadar, deliberately changing payload.updates_since is an explicit
36429
+ historical replay request, including when redeploying a disabled monitor.
36430
+ Deepline preserves that selected boundary; filter-only deploys and ordinary
36431
+ reactivation start from a fresh future-only source boundary instead.
36115
36432
  Operational controls are Deepline-managed. A monitor writes rows; downstream
36116
36433
  automation belongs in a Play with sqlListeners.
36117
36434
 
@@ -36128,6 +36445,17 @@ Examples:
36128
36445
  "Validate and show the deploy plan (cost, reuse candidates) without deploying"
36129
36446
  )
36130
36447
  ).action(monitorsAction(handleMonitorsDeploy));
36448
+ withJsonOption(
36449
+ monitors.command("sync [definition]").description(
36450
+ "Publish one complete desired monitor definition and return a Monitor Job."
36451
+ ).option(
36452
+ "-f, --file <path>",
36453
+ "Read definition JSON from a file, or - for stdin"
36454
+ ).option(
36455
+ "--dry-run",
36456
+ "Validate and show the deploy plan without publishing"
36457
+ ).option("--idempotency-key <key>", "Stable retry key")
36458
+ ).action(monitorsAction(handleMonitorsSync));
36131
36459
  withJsonOption(
36132
36460
  monitors.command("update <key> [patch]").description("Update a deployed monitor by its public key.").addHelpText(
36133
36461
  "after",
@@ -36143,9 +36471,7 @@ For TamRadar, changing payload.updates_since on an initial or active definition
36143
36471
  is an explicit historical replay request. Deepline passes that requested boundary upstream, but previously
36144
36472
  delivered canonical findings are deduplicated before dispatch and billing; only
36145
36473
  previously unseen historical findings are chargeable. Filter-only updates,
36146
- repair, and reactivation instead omit the field and start the provider resource
36147
- at creation. New Hire and Promotion source dates use calendar-month precision,
36148
- so current-month updates_since values are rejected for those radar types.
36474
+ repair, and reactivation instead use a fresh future-only source boundary.
36149
36475
 
36150
36476
  Examples:
36151
36477
  deepline monitors update my-monitor '{"name":"Interested replies"}' --json
@@ -36198,6 +36524,22 @@ Examples:
36198
36524
  `
36199
36525
  ).option("--dry-run", "Show the reactivation cost without reactivating")
36200
36526
  ).action(monitorsAction(handleMonitorsReactivate));
36527
+ withJsonOption(
36528
+ monitors.command("start <key>").description("Apply the retained definition for a stopped monitor.").option("--dry-run", "Show the start plan without changing anything").option("--idempotency-key <key>", "Stable retry key")
36529
+ ).action(
36530
+ monitorsAction(
36531
+ (key, options) => handleScalarMonitorLifecycle("start", key, options)
36532
+ )
36533
+ );
36534
+ withJsonOption(
36535
+ monitors.command("stop <key>").description(
36536
+ "Stop a monitor upstream while retaining its definition for `start`."
36537
+ ).option("--dry-run", "Show the stop plan without changing anything").option("--idempotency-key <key>", "Stable retry key")
36538
+ ).action(
36539
+ monitorsAction(
36540
+ (key, options) => handleScalarMonitorLifecycle("stop", key, options)
36541
+ )
36542
+ );
36201
36543
  const jobs = monitors.command("jobs").description("Read, wait for, inspect, or cancel Monitor Jobs.");
36202
36544
  withJsonOption(jobs);
36203
36545
  withJsonOption(
@@ -36377,7 +36719,7 @@ Examples:
36377
36719
  )
36378
36720
  ).action(monitorsAction(handleMonitorFleetsGet));
36379
36721
  withJsonOption(
36380
- fleets.command("deactivate <fleet-id>").description("Deactivate a fleet and the monitors it owns.").addHelpText(
36722
+ fleets.command("deactivate <fleet-id>").alias("stop").description("Deactivate a fleet and the monitors it owns.").addHelpText(
36381
36723
  "after",
36382
36724
  `
36383
36725
  Notes:
@@ -36416,7 +36758,7 @@ Examples:
36416
36758
  }
36417
36759
  });
36418
36760
  withJsonOption(
36419
- fleets.command("reactivate <fleet-id>").description(
36761
+ fleets.command("reactivate <fleet-id>").alias("start").description(
36420
36762
  "Explicitly recreate a fleet after a credit-triggered suspension."
36421
36763
  ).addHelpText(
36422
36764
  "after",
@@ -36451,8 +36793,11 @@ Example:
36451
36793
  });
36452
36794
  const deployed = withJsonOption(
36453
36795
  monitors.command("deployed", { hidden: true }).description("Alias of `monitors list` (plus get/update/delete aliases).").option(
36796
+ "--state <state>",
36797
+ "Filter by customer state: active (default), billing_suspended, disabled, or all"
36798
+ ).option(
36454
36799
  "--status <status>",
36455
- "Filter by monitor state: active (default), inactive, or all"
36800
+ "Deprecated compatibility filter; use --state (active, billing_suspended, disabled, or all)"
36456
36801
  ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
36457
36802
  "--cursor <cursor>",
36458
36803
  "Page past a truncated result using the next_cursor from a prior list response"