@odla-ai/cli 0.25.11 → 0.25.12
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 +3 -1
- package/dist/bin.cjs +86 -64
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-FYSV7POZ.js → chunk-MFC4TX6W.js} +87 -65
- package/dist/chunk-MFC4TX6W.js.map +1 -0
- package/dist/index.cjs +86 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/skills/odla-o11y-debug/SKILL.md +15 -3
- package/dist/chunk-FYSV7POZ.js.map +0 -1
package/README.md
CHANGED
|
@@ -72,7 +72,9 @@ 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
|
|
75
|
+
Schema v6 keeps application RED, an `applicationVersions` breakdown of
|
|
76
|
+
request/error/latency evidence by exact Cloudflare Worker version, reconciled
|
|
77
|
+
live-sync load/freshness and
|
|
76
78
|
subscription recompute/fanout/payload/commit-to-send performance, the exact
|
|
77
79
|
latest protected commit-to-visible canary, collector ingest/scheduler trust,
|
|
78
80
|
the live Cloudflare Worker read, and 30-day-retained provider snapshot history
|
package/dist/bin.cjs
CHANGED
|
@@ -2388,7 +2388,7 @@ var CAPABILITIES = {
|
|
|
2388
2388
|
"compose declared app-capability schema/rules, create guarded seeds when absent, and configure platform AI, auth, and deployment links",
|
|
2389
2389
|
"apply Google Calendar booking config, then drive state-bound consent, status, discovery, and disconnect flows (bookings run live through the platform proxy)",
|
|
2390
2390
|
"validate integration contracts offline and smoke-test a provisioned db environment plus anonymous capability routes",
|
|
2391
|
-
"read one versioned o11y status envelope spanning application RED, current live-sync freshness/load, the protected commit-to-visible canary, collector ingest/scheduler trust, provider-owned runtime metrics, and a bounded machine verdict",
|
|
2391
|
+
"read one versioned o11y status envelope spanning application RED, exact Worker versions observed in traffic, current live-sync freshness/load, the protected commit-to-visible canary, collector ingest/scheduler trust, provider-owned runtime metrics, and a bounded machine verdict",
|
|
2392
2392
|
"inspect durable agent wakeups as a versioned JSON envelope and explicitly requeue one dead-lettered job with a scoped environment credential",
|
|
2393
2393
|
"run app-attributed hosted security discovery and independent validation without provider keys",
|
|
2394
2394
|
"connect/revoke source-read-only GitHub sources and drive commit-pinned hosted security jobs without PATs or provider keys",
|
|
@@ -2410,7 +2410,7 @@ var CAPABILITIES = {
|
|
|
2410
2410
|
"approve GitHub App repository access separately from redacted-snippet disclosure"
|
|
2411
2411
|
],
|
|
2412
2412
|
studio: [
|
|
2413
|
-
"view application telemetry, reconciled live-sync load/freshness, commit-to-visible canary health, provider-owned Worker runtime metrics, and environment state",
|
|
2413
|
+
"view application telemetry grouped by exact Worker version, reconciled live-sync load/freshness, commit-to-visible canary health, provider-owned Worker runtime metrics, and environment state",
|
|
2414
2414
|
"let signed-in users inventory/revoke their own agent grants and admins audit/global-revoke them",
|
|
2415
2415
|
"review calendar connection, granted read scope, selected calendars, and sync health without exposing provider tokens",
|
|
2416
2416
|
"perform manual credential recovery \u2014 for the primary owner or any co-owner \u2014 when the CLI's local shown-once copy is unavailable",
|
|
@@ -8223,6 +8223,71 @@ function sourceHttp(reasons, source, read3, prefix = "") {
|
|
|
8223
8223
|
});
|
|
8224
8224
|
}
|
|
8225
8225
|
|
|
8226
|
+
// src/o11y-output.ts
|
|
8227
|
+
function printO11yStatus(status, out) {
|
|
8228
|
+
out.log(
|
|
8229
|
+
`o11y status ${status.scope.appId}/${status.scope.env} (${status.scope.minutes}m)`
|
|
8230
|
+
);
|
|
8231
|
+
const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record6) : [];
|
|
8232
|
+
const requests = routes.reduce(
|
|
8233
|
+
(total, row) => total + numeric3(row.requests),
|
|
8234
|
+
0
|
|
8235
|
+
);
|
|
8236
|
+
const errors = routes.reduce(
|
|
8237
|
+
(total, row) => total + numeric3(row.errors),
|
|
8238
|
+
0
|
|
8239
|
+
);
|
|
8240
|
+
out.log(
|
|
8241
|
+
`application ${status.application.httpStatus} ${requests} requests ${errors} errors`
|
|
8242
|
+
);
|
|
8243
|
+
const versions = Array.isArray(status.applicationVersions.body.rows) ? status.applicationVersions.body.rows.filter(record6) : [];
|
|
8244
|
+
out.log(
|
|
8245
|
+
`application-versions ${status.applicationVersions.httpStatus} ${versions.length ? versions.slice(0, 5).map(
|
|
8246
|
+
(row) => `${String(row.value || "(unattributed)")}:${numeric3(row.requests)}`
|
|
8247
|
+
).join(", ") : "none observed"}`
|
|
8248
|
+
);
|
|
8249
|
+
out.log(liveSyncLine(status.liveSync));
|
|
8250
|
+
const canaryDurations = record6(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
|
|
8251
|
+
out.log(
|
|
8252
|
+
`canary ${status.canary.httpStatus} ${String(status.canary.body.status ?? status.canary.body.error ?? "unavailable")} ${optionalNumeric(canaryDurations.publishToVisibleMs)} publish-to-visible`
|
|
8253
|
+
);
|
|
8254
|
+
const collectorIngest = record6(status.collector.body.ingest) ? status.collector.body.ingest : {};
|
|
8255
|
+
const collectorStorage = record6(collectorIngest.storage) ? collectorIngest.storage : {};
|
|
8256
|
+
out.log(
|
|
8257
|
+
`collector ${status.collector.httpStatus} ${String(status.collector.body.status ?? status.collector.body.error ?? "unavailable")} ${numeric3(collectorStorage.affectedPoints)} affected points`
|
|
8258
|
+
);
|
|
8259
|
+
const providerMetrics = record6(status.provider.body.metrics) ? status.provider.body.metrics : {};
|
|
8260
|
+
out.log(
|
|
8261
|
+
`cloudflare ${status.provider.httpStatus} ${String(status.provider.body.status ?? status.provider.body.error ?? "unavailable")} ${numeric3(providerMetrics.requests)} invocations ${numeric3(providerMetrics.errors)} runtime errors`
|
|
8262
|
+
);
|
|
8263
|
+
const providerPoints = Array.isArray(status.providerHistory.body.points) ? status.providerHistory.body.points.length : 0;
|
|
8264
|
+
const providerFreshness = record6(status.providerHistory.body.freshness) ? status.providerHistory.body.freshness : {};
|
|
8265
|
+
out.log(
|
|
8266
|
+
`cloudflare-history ${status.providerHistory.httpStatus} ${String(status.providerHistory.body.status ?? status.providerHistory.body.error ?? "unavailable")} ${providerPoints} snapshots ${optionalAge(providerFreshness.ageMs)} old`
|
|
8267
|
+
);
|
|
8268
|
+
out.log(
|
|
8269
|
+
`verdict ${status.verdict.status} ${status.verdict.reasons.map((reason) => `${reason.source}:${reason.code}`).join(", ") || "all required signals healthy"}`
|
|
8270
|
+
);
|
|
8271
|
+
}
|
|
8272
|
+
function liveSyncLine(read3) {
|
|
8273
|
+
const performance = record6(read3.body.performance) ? read3.body.performance : {};
|
|
8274
|
+
const commitToSend = record6(performance.commitToSend) ? performance.commitToSend : {};
|
|
8275
|
+
return `live-sync ${read3.httpStatus} ${String(read3.body.status ?? read3.body.error ?? "unavailable")} ${numeric3(read3.body.activeConnections)} active ${optionalNumeric(commitToSend.p95)} commit-to-send p95 ${numeric3(performance.sendFailures)} send failures`;
|
|
8276
|
+
}
|
|
8277
|
+
function record6(value) {
|
|
8278
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8279
|
+
}
|
|
8280
|
+
function numeric3(value) {
|
|
8281
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
8282
|
+
}
|
|
8283
|
+
function optionalNumeric(value) {
|
|
8284
|
+
return typeof value === "number" && Number.isFinite(value) ? `${value} ms` : "\u2014";
|
|
8285
|
+
}
|
|
8286
|
+
function optionalAge(value) {
|
|
8287
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return "unknown";
|
|
8288
|
+
return `${Math.max(0, Math.round(value / 1e3))}s`;
|
|
8289
|
+
}
|
|
8290
|
+
|
|
8226
8291
|
// src/o11y-command.ts
|
|
8227
8292
|
async function o11yCommand(parsed, deps = {}) {
|
|
8228
8293
|
assertArgs(
|
|
@@ -8260,8 +8325,23 @@ async function o11yCommand(parsed, deps = {}) {
|
|
|
8260
8325
|
const base = `${cfg.platformUrl}/o11y/${encodeURIComponent(appId)}`;
|
|
8261
8326
|
const query = new URLSearchParams({ env, minutes: String(minutes) });
|
|
8262
8327
|
const headers = { authorization: `Bearer ${token}` };
|
|
8263
|
-
const
|
|
8328
|
+
const versionsQuery = new URLSearchParams({
|
|
8329
|
+
env,
|
|
8330
|
+
minutes: String(minutes),
|
|
8331
|
+
dimension: "version",
|
|
8332
|
+
metric: "requests"
|
|
8333
|
+
});
|
|
8334
|
+
const [
|
|
8335
|
+
application,
|
|
8336
|
+
applicationVersions,
|
|
8337
|
+
liveSync,
|
|
8338
|
+
canary,
|
|
8339
|
+
collector,
|
|
8340
|
+
provider,
|
|
8341
|
+
providerHistory
|
|
8342
|
+
] = await Promise.all([
|
|
8264
8343
|
read2(`${base}/metrics/red?${query}`, headers, doFetch),
|
|
8344
|
+
read2(`${base}/explore?${versionsQuery}`, headers, doFetch),
|
|
8265
8345
|
read2(
|
|
8266
8346
|
`${base}/live-sync/health?${query}`,
|
|
8267
8347
|
headers,
|
|
@@ -8285,11 +8365,12 @@ async function o11yCommand(parsed, deps = {}) {
|
|
|
8285
8365
|
providerHistory
|
|
8286
8366
|
});
|
|
8287
8367
|
const status = {
|
|
8288
|
-
schemaVersion:
|
|
8368
|
+
schemaVersion: 6,
|
|
8289
8369
|
scope: { appId, env, minutes },
|
|
8290
8370
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8291
8371
|
verdict,
|
|
8292
8372
|
application,
|
|
8373
|
+
applicationVersions,
|
|
8293
8374
|
liveSync,
|
|
8294
8375
|
canary,
|
|
8295
8376
|
collector,
|
|
@@ -8300,7 +8381,7 @@ async function o11yCommand(parsed, deps = {}) {
|
|
|
8300
8381
|
out.log(JSON.stringify(status, null, 2));
|
|
8301
8382
|
return;
|
|
8302
8383
|
}
|
|
8303
|
-
|
|
8384
|
+
printO11yStatus(status, out);
|
|
8304
8385
|
}
|
|
8305
8386
|
function statusMinutes(value) {
|
|
8306
8387
|
if (!Number.isSafeInteger(value) || value < 1 || value > 7 * 24 * 60) {
|
|
@@ -8322,65 +8403,6 @@ async function read2(url, headers, doFetch) {
|
|
|
8322
8403
|
}
|
|
8323
8404
|
return { httpStatus: response2.status, body };
|
|
8324
8405
|
}
|
|
8325
|
-
function printStatus2(status, out) {
|
|
8326
|
-
out.log(
|
|
8327
|
-
`o11y status ${status.scope.appId}/${status.scope.env} (${status.scope.minutes}m)`
|
|
8328
|
-
);
|
|
8329
|
-
const routes = Array.isArray(status.application.body.routes) ? status.application.body.routes.filter(record6) : [];
|
|
8330
|
-
const requests = routes.reduce(
|
|
8331
|
-
(total, row) => total + numeric3(row.requests),
|
|
8332
|
-
0
|
|
8333
|
-
);
|
|
8334
|
-
const errors = routes.reduce(
|
|
8335
|
-
(total, row) => total + numeric3(row.errors),
|
|
8336
|
-
0
|
|
8337
|
-
);
|
|
8338
|
-
out.log(
|
|
8339
|
-
`application ${status.application.httpStatus} ${requests} requests ${errors} errors`
|
|
8340
|
-
);
|
|
8341
|
-
out.log(
|
|
8342
|
-
liveSyncLine(status.liveSync)
|
|
8343
|
-
);
|
|
8344
|
-
const canaryDurations = record6(status.canary.body.durationsMs) ? status.canary.body.durationsMs : {};
|
|
8345
|
-
out.log(
|
|
8346
|
-
`canary ${status.canary.httpStatus} ${String(status.canary.body.status ?? status.canary.body.error ?? "unavailable")} ${optionalNumeric(canaryDurations.publishToVisibleMs)} publish-to-visible`
|
|
8347
|
-
);
|
|
8348
|
-
const collectorIngest = record6(status.collector.body.ingest) ? status.collector.body.ingest : {};
|
|
8349
|
-
const collectorStorage = record6(collectorIngest.storage) ? collectorIngest.storage : {};
|
|
8350
|
-
out.log(
|
|
8351
|
-
`collector ${status.collector.httpStatus} ${String(status.collector.body.status ?? status.collector.body.error ?? "unavailable")} ${numeric3(collectorStorage.affectedPoints)} affected points`
|
|
8352
|
-
);
|
|
8353
|
-
const providerMetrics = record6(status.provider.body.metrics) ? status.provider.body.metrics : {};
|
|
8354
|
-
out.log(
|
|
8355
|
-
`cloudflare ${status.provider.httpStatus} ${String(status.provider.body.status ?? status.provider.body.error ?? "unavailable")} ${numeric3(providerMetrics.requests)} invocations ${numeric3(providerMetrics.errors)} runtime errors`
|
|
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
|
-
);
|
|
8362
|
-
out.log(
|
|
8363
|
-
`verdict ${status.verdict.status} ${status.verdict.reasons.map((reason) => `${reason.source}:${reason.code}`).join(", ") || "all required signals healthy"}`
|
|
8364
|
-
);
|
|
8365
|
-
}
|
|
8366
|
-
function liveSyncLine(read3) {
|
|
8367
|
-
const performance = record6(read3.body.performance) ? read3.body.performance : {};
|
|
8368
|
-
const commitToSend = record6(performance.commitToSend) ? performance.commitToSend : {};
|
|
8369
|
-
return `live-sync ${read3.httpStatus} ${String(read3.body.status ?? read3.body.error ?? "unavailable")} ${numeric3(read3.body.activeConnections)} active ${optionalNumeric(commitToSend.p95)} commit-to-send p95 ${numeric3(performance.sendFailures)} send failures`;
|
|
8370
|
-
}
|
|
8371
|
-
function record6(value) {
|
|
8372
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8373
|
-
}
|
|
8374
|
-
function numeric3(value) {
|
|
8375
|
-
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
8376
|
-
}
|
|
8377
|
-
function optionalNumeric(value) {
|
|
8378
|
-
return typeof value === "number" && Number.isFinite(value) ? `${value} ms` : "\u2014";
|
|
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
|
-
}
|
|
8384
8406
|
|
|
8385
8407
|
// src/provision.ts
|
|
8386
8408
|
var import_apps5 = require("@odla-ai/apps");
|