@odla-ai/cli 0.35.0 → 0.35.3

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/dist/bin.js CHANGED
@@ -174,7 +174,7 @@ function absoluteEntryPath(entryPath) {
174
174
 
175
175
  // src/bin.ts
176
176
  var argv = process.argv.slice(2);
177
- requireCurrentCliForProvision(argv).then(() => requireCoherentProvisionRuntime(argv)).then(async () => (await import("./cli-Z5NSTS75.js")).runCli()).catch((err) => {
177
+ requireCurrentCliForProvision(argv).then(() => requireCoherentProvisionRuntime(argv)).then(async () => (await import("./cli-ZBNA7J4T.js")).runCli()).catch((err) => {
178
178
  console.error(redactSecrets(`odla-ai: ${err instanceof Error ? err.message : String(err)}`));
179
179
  process.exitCode = exitCodeFor(err);
180
180
  });
@@ -149,6 +149,29 @@ function handshakeWaitMs(waitSeconds, interactive = process4.stdout.isTTY === tr
149
149
  return interactive ? void 0 : 9e4;
150
150
  }
151
151
 
152
+ // src/cached-credential.ts
153
+ import { rmSync as rmSync2 } from "fs";
154
+ var noted = null;
155
+ function noteCachedCredential(tokenFile) {
156
+ noted = tokenFile;
157
+ }
158
+ function isCredentialRejection(error) {
159
+ const message2 = error instanceof Error ? error.message : String(error ?? "");
160
+ return /\((401|403)\)\s*$/.test(message2.trim());
161
+ }
162
+ function explainRejectedCredential(error) {
163
+ const tokenFile = noted;
164
+ if (!tokenFile || !isCredentialRejection(error)) return null;
165
+ noted = null;
166
+ rmSync2(tokenFile, { force: true });
167
+ return [
168
+ "auth: the cached credential was rejected by odla, so it was revoked before its cached expiry.",
169
+ " The usual cause is a newer sign-in for this project: collecting a handshake retires the",
170
+ " principal's other credentials, so a second terminal or worktree supersedes this one.",
171
+ ` Discarded ${tokenFile}; re-run this command to request a fresh approval.`
172
+ ].join("\n");
173
+ }
174
+
152
175
  // src/local.ts
153
176
  import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
154
177
  import { dirname as dirname2, isAbsolute, relative, resolve } from "path";
@@ -294,6 +317,7 @@ async function getDeveloperToken(cfg, options, doFetch, out, grantRequest = {})
294
317
  }
295
318
  if (cached?.token && cached.platform === audience && (cached.expiresAt ?? 0) > Date.now() + 6e4 && cachedGrantCovers(cached, grantIntent)) {
296
319
  out.error(`auth: using cached developer token (${displayPath(cfg.local.tokenFile, cfg.rootDir)})`);
320
+ noteCachedCredential(cfg.local.tokenFile);
297
321
  return cached.token;
298
322
  }
299
323
  } else {
@@ -13279,6 +13303,29 @@ function recordInvocation(parsed) {
13279
13303
  }
13280
13304
  }
13281
13305
 
13306
+ // src/advisory-output.ts
13307
+ import { formatAdvisory, parseAdvisories } from "@odla-ai/apps";
13308
+ function advisoryCollectingFetch(inner, sink) {
13309
+ return (async (input, init) => {
13310
+ const response2 = await inner(input, init);
13311
+ try {
13312
+ sink.push(...parseAdvisories(response2));
13313
+ } catch {
13314
+ }
13315
+ return response2;
13316
+ });
13317
+ }
13318
+ function renderAdvisories(out, advisories, env = process.env) {
13319
+ if (env.ODLA_NO_ADVISORIES) return;
13320
+ const seen = /* @__PURE__ */ new Set();
13321
+ for (const advisory of advisories) {
13322
+ const key = `${advisory.code}:${advisory.message}`;
13323
+ if (seen.has(key)) continue;
13324
+ seen.add(key);
13325
+ out.error(formatAdvisory(advisory));
13326
+ }
13327
+ }
13328
+
13282
13329
  // src/runbook-actions.ts
13283
13330
  import { readFileSync as readFileSync9 } from "fs";
13284
13331
  var PLATFORM_SCOPE = "$platform";
@@ -13309,9 +13356,20 @@ async function bySlug(ctx, slug) {
13309
13356
  "GET",
13310
13357
  `/runbook?app=${encodeURIComponent(ctx.appId)}&slug=${encodeURIComponent(slug)}&limit=1`
13311
13358
  );
13312
- const found = page2.records[0];
13313
- if (!found) throw new Error(`no runbook "${slug}" in ${ctx.appId}`);
13314
- return found;
13359
+ const filtered = page2.records.find((record11) => record11.slug === slug);
13360
+ if (filtered) return filtered;
13361
+ const limit = 100;
13362
+ for (let offset = 0; ; offset += limit) {
13363
+ const fallback = await call(
13364
+ ctx,
13365
+ "GET",
13366
+ `/runbook?app=${encodeURIComponent(ctx.appId)}&limit=${limit}&offset=${offset}`
13367
+ );
13368
+ const found = fallback.records.find((record11) => record11.slug === slug);
13369
+ if (found) return found;
13370
+ if (!fallback.records.length || offset + fallback.records.length >= fallback.total) break;
13371
+ }
13372
+ throw new Error(`no runbook "${slug}" in ${ctx.appId}`);
13315
13373
  }
13316
13374
  function readBody(file, inline) {
13317
13375
  if (inline !== void 0) return inline;
@@ -13396,7 +13454,7 @@ async function runbookRevert(ctx, slug, version) {
13396
13454
  ctx,
13397
13455
  "POST",
13398
13456
  `/runbook/${encodeURIComponent(runbook.id)}/revert`,
13399
- { version }
13457
+ { version, expectedVersion: runbook.version }
13400
13458
  );
13401
13459
  if (ctx.json) return ctx.out.log(JSON.stringify(result, null, 2));
13402
13460
  ctx.out.log(`${slug} reverted to v${version}, now v${result.record?.version ?? runbook.version + 1}`);
@@ -13885,7 +13943,7 @@ async function runbookComment(ctx, slug, body) {
13885
13943
 
13886
13944
  // src/runbook-editor.ts
13887
13945
  import { spawnSync } from "child_process";
13888
- import { mkdtempSync, readFileSync as readFileSync12, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
13946
+ import { mkdtempSync, readFileSync as readFileSync12, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
13889
13947
  import { tmpdir as tmpdir4 } from "os";
13890
13948
  import { join as join15 } from "path";
13891
13949
  import process15 from "process";
@@ -13922,7 +13980,7 @@ function editText(initial, slug, deps = {}) {
13922
13980
  const edited = readFileSync12(file, "utf8");
13923
13981
  return edited === initial ? null : edited;
13924
13982
  } finally {
13925
- rmSync2(dir, { recursive: true, force: true });
13983
+ rmSync3(dir, { recursive: true, force: true });
13926
13984
  }
13927
13985
  }
13928
13986
  var defaultRunOrInjected = (deps) => deps.run ?? defaultRun;
@@ -14810,6 +14868,23 @@ async function securityStatus(parsed, dependencies) {
14810
14868
 
14811
14869
  // src/cli.ts
14812
14870
  async function runCli(argv = process.argv.slice(2), dependencies = {}) {
14871
+ const out = redactingOutput(dependencies.stdout ?? console);
14872
+ const advisories = [];
14873
+ const withAdvisoryReader = {
14874
+ ...dependencies,
14875
+ fetch: advisoryCollectingFetch(dependencies.fetch ?? fetch, advisories)
14876
+ };
14877
+ try {
14878
+ return await dispatchCli(argv, withAdvisoryReader);
14879
+ } catch (error) {
14880
+ const explanation = explainRejectedCredential(error);
14881
+ if (explanation) out.error(explanation);
14882
+ throw error;
14883
+ } finally {
14884
+ renderAdvisories(out, advisories);
14885
+ }
14886
+ }
14887
+ async function dispatchCli(argv, dependencies) {
14813
14888
  const runtime = {
14814
14889
  ...dependencies,
14815
14890
  stdout: redactingOutput(dependencies.stdout ?? console)
@@ -15034,4 +15109,4 @@ export {
15034
15109
  isTerminalHostedSecurityStatus,
15035
15110
  runCli
15036
15111
  };
15037
- //# sourceMappingURL=chunk-EG23MPUC.js.map
15112
+ //# sourceMappingURL=chunk-PYR73XBD.js.map