@odla-ai/cli 0.46.4 → 0.46.6

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
@@ -172,7 +172,7 @@ function absoluteEntryPath(entryPath) {
172
172
 
173
173
  // src/bin.ts
174
174
  var argv = process.argv.slice(2);
175
- requireCurrentCliForProvision(argv).then(() => requireCoherentProvisionRuntime(argv)).then(async () => (await import("./cli-UTMLBANX.js")).runCli()).catch((err) => {
175
+ requireCurrentCliForProvision(argv).then(() => requireCoherentProvisionRuntime(argv)).then(async () => (await import("./cli-IAA6SOCV.js")).runCli()).catch((err) => {
176
176
  console.error(redactSecrets(`odla-ai: ${err instanceof Error ? err.message : String(err)}`));
177
177
  process.exitCode = exitCodeFor(err);
178
178
  });
@@ -1194,7 +1194,7 @@ var COMMAND_SURFACE = {
1194
1194
  audit: {},
1195
1195
  credential: { set: {} }
1196
1196
  },
1197
- spend: { show: {}, reset: {} }
1197
+ spend: { show: {}, set: {}, reset: {} }
1198
1198
  },
1199
1199
  app: {
1200
1200
  archive: {},
@@ -1342,11 +1342,16 @@ function surfacePaths(node = COMMAND_SURFACE, prefix = []) {
1342
1342
  }
1343
1343
 
1344
1344
  // src/admin-spend.ts
1345
- async function call(ctx, method, scope) {
1346
- const url = `${ctx.platformUrl.replace(/\/$/, "")}/registry/platform/spend?scope=${encodeURIComponent(scope)}`;
1345
+ async function call(ctx, method, scope, payload) {
1346
+ const base = `${ctx.platformUrl.replace(/\/$/, "")}/registry/platform/spend`;
1347
+ const url = scope === "default" ? `${base}/default` : `${base}?scope=${encodeURIComponent(scope)}`;
1347
1348
  const response2 = await ctx.doFetch(url, {
1348
1349
  method,
1349
- headers: { authorization: `Bearer ${ctx.token}` }
1350
+ headers: {
1351
+ authorization: `Bearer ${ctx.token}`,
1352
+ ...payload === void 0 ? {} : { "content-type": "application/json" }
1353
+ },
1354
+ ...payload === void 0 ? {} : { body: JSON.stringify(payload) }
1350
1355
  });
1351
1356
  const body = await response2.json().catch(() => ({}));
1352
1357
  if (!response2.ok) {
@@ -1390,14 +1395,36 @@ async function spendReset(ctx, scope) {
1390
1395
  async function adminSpend(parsed, ctx) {
1391
1396
  const action2 = parsed.positionals[2];
1392
1397
  const scope = parsed.positionals[3] ?? stringOpt(parsed.options.scope);
1393
- if (action2 !== "show" && action2 !== "reset") rejectWord(["admin", "spend"], action2);
1398
+ if (action2 !== "show" && action2 !== "reset" && action2 !== "set") rejectWord(["admin", "spend"], action2);
1394
1399
  if (!scope) {
1395
1400
  throw new Error(
1396
- `"admin spend ${action2}" needs a scope, e.g. odla-ai admin spend ${action2} app:my-app:<incarnation>`
1401
+ `"admin spend ${action2}" needs a scope, e.g. odla-ai admin spend ${action2} app:my-app:<incarnation> (or "default" for the fleet-wide fallback)`
1397
1402
  );
1398
1403
  }
1404
+ if (action2 === "set") return adminSpendSet(ctx, parsed, scope);
1399
1405
  return action2 === "show" ? spendShow(ctx, scope) : spendReset(ctx, scope);
1400
1406
  }
1407
+ async function adminSpendSet(ctx, parsed, scope) {
1408
+ const daily = stringOpt(parsed.options.daily);
1409
+ const none = parsed.options.none === true;
1410
+ if (none === (daily !== void 0)) {
1411
+ throw new Error("admin spend set needs exactly one of --daily <usd> or --none");
1412
+ }
1413
+ const dailyCapUsd = none ? null : Number(daily);
1414
+ if (dailyCapUsd !== null && (!Number.isFinite(dailyCapUsd) || dailyCapUsd < 0)) {
1415
+ throw new Error("--daily takes a non-negative dollar amount, for example --daily 25");
1416
+ }
1417
+ const result = await call(ctx, "PUT", scope, { dailyCapUsd });
1418
+ if (ctx.json) {
1419
+ ctx.out.log(JSON.stringify(result, null, 2));
1420
+ return;
1421
+ }
1422
+ ctx.out.log(`${result.scope ?? scope}: ${result.message}`);
1423
+ if (typeof result.spentUsd === "number") ctx.out.log(` spent today ${money(result.spentUsd)}`);
1424
+ if (result.alreadyOverCap) {
1425
+ ctx.out.log(" today's spend already exceeds this cap \u2014 the next call will latch it.");
1426
+ }
1427
+ }
1401
1428
 
1402
1429
  // src/operator-context.ts
1403
1430
  import { existsSync as existsSync5 } from "fs";
@@ -2195,7 +2222,7 @@ async function adminCommand(parsed, deps = {}) {
2195
2222
  rejectWord(["admin", "ai", "credential"], parsed.positionals[3]);
2196
2223
  }
2197
2224
  if (area === "spend") {
2198
- assertArgs(parsed, JSON_OPTIONS, 4);
2225
+ assertArgs(parsed, [...JSON_OPTIONS, "daily", "none", "scope"], 4);
2199
2226
  const context2 = await resolveOperatorContext(parsed, { allowMissingConfig: true });
2200
2227
  const out = deps.stdout ?? console;
2201
2228
  const doFetch = deps.fetch ?? fetch;
@@ -11035,6 +11062,7 @@ Usage:
11035
11062
  odla-ai admin ai usage [--context <name>] [--app-id <id>] [--env <env>] [--run-id <id>] [--limit <1-500>] [--json]
11036
11063
  odla-ai admin ai audit [--context <name>] [--limit <1-200>] [--json]
11037
11064
  odla-ai admin spend show <app:<id>:<incarnation>> [--context <name>] [--json]
11065
+ odla-ai admin spend set <app:<id>:<incarnation>> (--daily <usd>|--none) [--context <name>] [--json]
11038
11066
  odla-ai admin spend reset <app:<id>:<incarnation>> [--context <name>] [--json]
11039
11067
  odla-ai security github connect [--repo owner/name] [--env dev] [continue in Studio; human session required]
11040
11068
  odla-ai security github disconnect --source <id> [--env dev] [continue in Studio; human session required]
@@ -16183,4 +16211,4 @@ export {
16183
16211
  isTerminalHostedSecurityStatus,
16184
16212
  runCli
16185
16213
  };
16186
- //# sourceMappingURL=chunk-PCEGBCLZ.js.map
16214
+ //# sourceMappingURL=chunk-AVUBGTWE.js.map