@odla-ai/cli 0.25.10 → 0.25.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -72,10 +72,13 @@ snapshot instead of scraping Studio or composing collector routes themselves:
72
72
  npx odla-ai o11y status --app <appId> --env prod --minutes 60 --json
73
73
  ```
74
74
 
75
- Schema v4 keeps application RED, reconciled live-sync load/freshness and
75
+ Schema v5 keeps application RED, reconciled live-sync load/freshness and
76
76
  subscription recompute/fanout/payload/commit-to-send performance, the exact
77
77
  latest protected commit-to-visible canary, collector ingest/scheduler trust,
78
- and Cloudflare-owned Worker runtime evidence separate. It derives one
78
+ the live Cloudflare Worker read, and 30-day-retained provider snapshot history
79
+ with a seven-day maximum per read separate. Scheduled collection failures,
80
+ source age, expected cadence, collection lag, and history truncation remain
81
+ machine-readable. It derives one
79
82
  `healthy`, `degraded`, or `unhealthy` verdict with stable reason codes while
80
83
  retaining every source response for diagnosis. Provider unavailability,
81
84
  adaptive sampling, publication delay, collector loss, quota rejection, stale
package/dist/bin.cjs CHANGED
@@ -8115,6 +8115,7 @@ function statusVerdict(reads) {
8115
8115
  sourceHttp(reasons, "canary", reads.canary);
8116
8116
  sourceHttp(reasons, "collector", reads.collector);
8117
8117
  sourceHttp(reasons, "provider", reads.provider);
8118
+ sourceHttp(reasons, "provider", reads.providerHistory, "provider_history_");
8118
8119
  const liveStatus = String(reads.liveSync.body.status ?? "");
8119
8120
  if (liveStatus === "partial") {
8120
8121
  reasons.push({
@@ -8186,6 +8187,14 @@ function statusVerdict(reads) {
8186
8187
  severity: "degraded"
8187
8188
  });
8188
8189
  }
8190
+ const providerHistoryStatus = String(reads.providerHistory.body.status ?? "");
8191
+ if (providerHistoryStatus && providerHistoryStatus !== "observed" && providerHistoryStatus !== "no_data") {
8192
+ reasons.push({
8193
+ source: "provider",
8194
+ code: `provider_history_${providerHistoryStatus}`,
8195
+ severity: "degraded"
8196
+ });
8197
+ }
8189
8198
  return {
8190
8199
  status: reasons.some((reason) => reason.severity === "unhealthy") ? "unhealthy" : reasons.length > 0 ? "degraded" : "healthy",
8191
8200
  reasons
@@ -8205,11 +8214,11 @@ function collectorReason(read3, fallback) {
8205
8214
  );
8206
8215
  return typeof first?.code === "string" && first.code ? first.code : fallback;
8207
8216
  }
8208
- function sourceHttp(reasons, source, read3) {
8217
+ function sourceHttp(reasons, source, read3, prefix = "") {
8209
8218
  if (read3.httpStatus >= 200 && read3.httpStatus < 300) return;
8210
8219
  reasons.push({
8211
8220
  source,
8212
- code: `http_${read3.httpStatus}`,
8221
+ code: `${prefix}http_${read3.httpStatus}`,
8213
8222
  severity: read3.httpStatus >= 500 && read3.httpStatus !== 501 ? "unhealthy" : "degraded"
8214
8223
  });
8215
8224
  }
@@ -8251,7 +8260,7 @@ async function o11yCommand(parsed, deps = {}) {
8251
8260
  const base = `${cfg.platformUrl}/o11y/${encodeURIComponent(appId)}`;
8252
8261
  const query = new URLSearchParams({ env, minutes: String(minutes) });
8253
8262
  const headers = { authorization: `Bearer ${token}` };
8254
- const [application, liveSync, canary, collector, provider] = await Promise.all([
8263
+ const [application, liveSync, canary, collector, provider, providerHistory] = await Promise.all([
8255
8264
  read2(`${base}/metrics/red?${query}`, headers, doFetch),
8256
8265
  read2(
8257
8266
  `${base}/live-sync/health?${query}`,
@@ -8264,17 +8273,19 @@ async function o11yCommand(parsed, deps = {}) {
8264
8273
  doFetch
8265
8274
  ),
8266
8275
  read2(`${base}/self-health?${query}`, headers, doFetch),
8267
- read2(`${base}/provider/cloudflare?${query}`, headers, doFetch)
8276
+ read2(`${base}/provider/cloudflare?${query}`, headers, doFetch),
8277
+ read2(`${base}/provider/cloudflare/history?${query}`, headers, doFetch)
8268
8278
  ]);
8269
8279
  const verdict = statusVerdict({
8270
8280
  application,
8271
8281
  liveSync,
8272
8282
  canary,
8273
8283
  collector,
8274
- provider
8284
+ provider,
8285
+ providerHistory
8275
8286
  });
8276
8287
  const status = {
8277
- schemaVersion: 4,
8288
+ schemaVersion: 5,
8278
8289
  scope: { appId, env, minutes },
8279
8290
  observedAt: (/* @__PURE__ */ new Date()).toISOString(),
8280
8291
  verdict,
@@ -8282,7 +8293,8 @@ async function o11yCommand(parsed, deps = {}) {
8282
8293
  liveSync,
8283
8294
  canary,
8284
8295
  collector,
8285
- provider
8296
+ provider,
8297
+ providerHistory
8286
8298
  };
8287
8299
  if (parsed.options.json === true) {
8288
8300
  out.log(JSON.stringify(status, null, 2));
@@ -8342,6 +8354,11 @@ function printStatus2(status, out) {
8342
8354
  out.log(
8343
8355
  `cloudflare ${status.provider.httpStatus} ${String(status.provider.body.status ?? status.provider.body.error ?? "unavailable")} ${numeric3(providerMetrics.requests)} invocations ${numeric3(providerMetrics.errors)} runtime errors`
8344
8356
  );
8357
+ const providerPoints = Array.isArray(status.providerHistory.body.points) ? status.providerHistory.body.points.length : 0;
8358
+ const providerFreshness = record6(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
8359
+ out.log(
8360
+ `cloudflare-history ${status.providerHistory.httpStatus} ${String(status.providerHistory.body.status ?? status.providerHistory.body.error ?? "unavailable")} ${providerPoints} snapshots ${optionalAge(providerFreshness.ageMs)} old`
8361
+ );
8345
8362
  out.log(
8346
8363
  `verdict ${status.verdict.status} ${status.verdict.reasons.map((reason) => `${reason.source}:${reason.code}`).join(", ") || "all required signals healthy"}`
8347
8364
  );
@@ -8360,6 +8377,10 @@ function numeric3(value) {
8360
8377
  function optionalNumeric(value) {
8361
8378
  return typeof value === "number" && Number.isFinite(value) ? `${value} ms` : "\u2014";
8362
8379
  }
8380
+ function optionalAge(value) {
8381
+ if (typeof value !== "number" || !Number.isFinite(value)) return "unknown";
8382
+ return `${Math.max(0, Math.round(value / 1e3))}s`;
8383
+ }
8363
8384
 
8364
8385
  // src/provision.ts
8365
8386
  var import_apps5 = require("@odla-ai/apps");