@vosjs/cli 0.11.1 → 0.13.0

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.
@@ -3351,9 +3351,30 @@ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "
3351
3351
  import { join as join8 } from "path";
3352
3352
 
3353
3353
  // src/plugin/recordingCap.ts
3354
- import { formatDurationCap, planLimits } from "@vosjs/shared/limits";
3354
+ var HOSTED_RECORDING_CAP_SECONDS = 30 * 60;
3355
+ function parseHostedCap(body) {
3356
+ const limits = body && typeof body === "object" ? body.limits : void 0;
3357
+ const cap = limits?.recordingMaxSeconds;
3358
+ return typeof cap === "number" && Number.isInteger(cap) && cap > 0 ? cap : null;
3359
+ }
3360
+ async function hostedRecordingCap(origin, key, fetchImpl = fetch) {
3361
+ const ctl = new AbortController();
3362
+ const timer = setTimeout(() => ctl.abort(), 2e3);
3363
+ try {
3364
+ const res = await fetchImpl(`${origin.replace(/\/+$/, "")}/api/limits`, {
3365
+ signal: ctl.signal,
3366
+ ...key ? { headers: { authorization: `Bearer ${key}` } } : {}
3367
+ });
3368
+ if (!res.ok) return null;
3369
+ return parseHostedCap(await res.json());
3370
+ } catch {
3371
+ return null;
3372
+ } finally {
3373
+ clearTimeout(timer);
3374
+ }
3375
+ }
3355
3376
  function defaultMaxDurationSeconds() {
3356
- return planLimits().recordingMaxSeconds;
3377
+ return HOSTED_RECORDING_CAP_SECONDS;
3357
3378
  }
3358
3379
  function capReached(elapsedMs, capSeconds) {
3359
3380
  return elapsedMs >= capSeconds * 1e3;
@@ -3361,6 +3382,14 @@ function capReached(elapsedMs, capSeconds) {
3361
3382
  function clampWait(waitMs, elapsedMs, capSeconds) {
3362
3383
  return Math.max(0, Math.min(waitMs, capSeconds * 1e3 - elapsedMs));
3363
3384
  }
3385
+ function formatDurationCap(seconds) {
3386
+ if (seconds < 60) return `${seconds} s`;
3387
+ const m = Math.round(seconds / 60);
3388
+ if (m < 60) return `${m} min`;
3389
+ const h = Math.floor(m / 60);
3390
+ const rest = m % 60;
3391
+ return rest ? `${h} h ${rest} min` : `${h} h`;
3392
+ }
3364
3393
  function cappedLine(capSeconds) {
3365
3394
  return `stopped at ${formatDurationCap(capSeconds)} (--max-duration ${capSeconds}); the remaining steps did not run`;
3366
3395
  }
@@ -6648,10 +6677,25 @@ async function loadActions(file) {
6648
6677
  ${errors.join("\n ")}`);
6649
6678
  return raw;
6650
6679
  }
6651
- function maxDurationFlag(flags) {
6652
- const v = numFlag(flags, "max-duration", defaultMaxDurationSeconds());
6653
- if (!(v > 0)) throw new UsageError("--max-duration expects seconds above 0");
6654
- return v;
6680
+ async function maxDuration(flags, r) {
6681
+ if (hasFlag(flags, "max-duration")) {
6682
+ const v = numFlag(flags, "max-duration", defaultMaxDurationSeconds());
6683
+ if (!(v > 0)) throw new UsageError("--max-duration expects seconds above 0");
6684
+ return v;
6685
+ }
6686
+ const origin = platformOrigin({
6687
+ origin: strFlag(flags, "origin"),
6688
+ api: strFlag(flags, "api")
6689
+ });
6690
+ const live = await hostedRecordingCap(
6691
+ origin,
6692
+ resolveCredential(strFlag(flags, "key"))
6693
+ );
6694
+ if (live) return live;
6695
+ r.log(
6696
+ `note: could not read the hosted cap from ${origin}/api/limits; recording up to the built-in ${formatDurationCap(defaultMaxDurationSeconds())}`
6697
+ );
6698
+ return defaultMaxDurationSeconds();
6655
6699
  }
6656
6700
  function strictReason(rec) {
6657
6701
  const parts = [`${rec.skipped.length} skipped step(s)`];
@@ -6684,6 +6728,7 @@ async function cmdRecord(argv) {
6684
6728
  throw new UsageError('no URL \u2014 set "url" in the actions file or pass --url');
6685
6729
  const outDir = resolve6(strFlag(flags, "out") ?? "take");
6686
6730
  const backdrop = await takeBackdrop(flags, r);
6731
+ const maxDurationSeconds = await maxDuration(flags, r);
6687
6732
  if (existsSync10(join14(outDir, "meta.json"))) {
6688
6733
  const { prevDoc, kept } = await prepareReRecord(outDir);
6689
6734
  r.log(
@@ -6697,7 +6742,7 @@ async function cmdRecord(argv) {
6697
6742
  r.log("recording\u2026");
6698
6743
  r.event({ event: "phase", phase: "record" });
6699
6744
  const rec = await recordTake(browser, url, actions, paths, r.log, {
6700
- maxDurationSeconds: maxDurationFlag(flags)
6745
+ maxDurationSeconds
6701
6746
  });
6702
6747
  r.event({ event: "phase", phase: "encode" });
6703
6748
  r.log("encoding\u2026");
@@ -6766,6 +6811,7 @@ async function cmdCreate2(argv) {
6766
6811
  throw new UsageError("--parallel expects an integer between 1 and 16");
6767
6812
  }
6768
6813
  const backdrop = await takeBackdrop(flags, r);
6814
+ const maxDurationSeconds = await maxDuration(flags, r);
6769
6815
  if (existsSync10(join14(outDir, "meta.json"))) {
6770
6816
  const { prevDoc, kept } = await prepareReRecord(outDir);
6771
6817
  r.log(
@@ -6779,7 +6825,7 @@ async function cmdCreate2(argv) {
6779
6825
  r.log("recording\u2026");
6780
6826
  r.event({ event: "phase", phase: "record" });
6781
6827
  const rec = await recordTake(browser, url, actions, paths, r.log, {
6782
- maxDurationSeconds: maxDurationFlag(flags)
6828
+ maxDurationSeconds
6783
6829
  });
6784
6830
  r.event({ event: "phase", phase: "encode" });
6785
6831
  r.log("encoding\u2026");
@@ -7245,12 +7291,12 @@ async function cmdDigest(argv) {
7245
7291
  sourceDuration: d.take.sourceDuration,
7246
7292
  outputDuration: d.take.outputDuration,
7247
7293
  hasCursor: d.take.hasCursor,
7248
- tokensEstimateClaude: d.images.tokensEstimateClaude,
7294
+ tokensEstimate: d.images.tokensEstimate,
7249
7295
  bytes: result.bytes
7250
7296
  },
7251
7297
  `Wrote ${result.file} \u2014 ${d.moments.length} moments (${Object.entries(
7252
7298
  kinds
7253
- ).map(([k, n]) => `${n} ${k}`).join(", ")}), ${d.images.full} frames + ${d.images.crop} crops` + (d.images.sheet ? `, sheet.png` : "") + ` \u2014 ~${d.images.tokensEstimateClaude} image tokens to read them all` + (d.take.hasCursor ? "" : "\n no cursor track: moments are head/tail/scenes only \u2014 pace by activity, zoom only where the ask names a place") + `
7299
+ ).map(([k, n]) => `${n} ${k}`).join(", ")}), ${d.images.full} frames + ${d.images.crop} crops` + (d.images.sheet ? `, sheet.png` : "") + ` \u2014 ~${d.images.tokensEstimate} image tokens to read them all` + (d.take.hasCursor ? "" : "\n no cursor track: moments are head/tail/scenes only \u2014 pace by activity, zoom only where the ask names a place") + `
7254
7300
  Read digest.json, then the sheet, then a crop only where you must decide.`
7255
7301
  );
7256
7302
  return EXIT_OK;
@@ -7565,4 +7611,4 @@ export {
7565
7611
  convertAgentBrowser,
7566
7612
  run
7567
7613
  };
7568
- //# sourceMappingURL=chunk-3W3XD6HL.js.map
7614
+ //# sourceMappingURL=chunk-6TFKMNSG.js.map