trajectories-sh 1.12.0 → 1.14.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.
package/dist/cli.js CHANGED
@@ -76,12 +76,20 @@ async function uploadTrajectoryAction(directory, opts) {
76
76
  console.error(chalk.red(" \u2717 Not authenticated. Run: trajectories auth login"));
77
77
  process.exit(1);
78
78
  }
79
+ if (opts.visibility === "public") {
80
+ console.error(
81
+ chalk.red(
82
+ " \u2717 --visibility public is not allowed from the CLI.\n Upload as 'unlisted' or 'private', then flip visibility to public\n from the trajectory page on trajectories.sh."
83
+ )
84
+ );
85
+ process.exit(1);
86
+ }
79
87
  const slug = opts.slug ?? directory.replace(/\/+$/, "").split("/").pop();
80
88
  console.log(chalk.bold(`
81
89
  Uploading trajectory ${directory} \u2192 ${chalk.cyan(slug)}
82
90
  `));
83
91
  try {
84
- const { uploadJob } = await import("./upload-CDNIKYW3.js");
92
+ const { uploadJob } = await import("./upload-DKXZOGUF.js");
85
93
  const result = await uploadJob(directory, {
86
94
  slug,
87
95
  name: opts.name,
@@ -222,7 +230,11 @@ async function deleteTrajectoryAction(url, opts) {
222
230
  }
223
231
  }
224
232
  var upload = program.command("upload").description("Upload trajectories or tasks");
225
- upload.command("trajectory <directory>").description("Upload a trajectory job directory").option("-s, --slug <slug>", "URL slug (default: directory name)").option("-n, --name <name>", "Display name (default: slug)").option("-v, --visibility <vis>", "public, unlisted, or private", "private").action(uploadTrajectoryAction);
233
+ upload.command("trajectory <directory>").description("Upload a trajectory job directory").option("-s, --slug <slug>", "URL slug (default: directory name)").option("-n, --name <name>", "Display name (default: slug)").option(
234
+ "-v, --visibility <vis>",
235
+ "unlisted or private (use the UI to flip a trajectory to public after upload)",
236
+ "private"
237
+ ).action(uploadTrajectoryAction);
226
238
  upload.command("task <directory>").description("Upload a benchmark task directory").option("-n, --name <name>", "Task name (default: directory name)").option("-v, --visibility <vis>", "public or private", "public").action(uploadTaskAction);
227
239
  var download = program.command("download").description("Download trajectories");
228
240
  download.command("trajectory <url>").description("Download a trajectory job from trajectories.sh").option("-o, --output <dir>", "Output directory (default: slug name)").action(downloadTrajectoryAction);
@@ -403,14 +403,15 @@ async function uploadDirect(jobId, files) {
403
403
  const pending = /* @__PURE__ */ new Set();
404
404
  for (let bi = 0; bi < batches.length; bi++) {
405
405
  const batch = batches[bi];
406
- const urlMap = await nextUrlsPromise;
406
+ const { urlMap, errors: urlErrors } = await nextUrlsPromise;
407
407
  nextUrlsPromise = bi + 1 < batches.length ? fetchSignedUrlsForBatch(jobId, batches[bi + 1].map((f) => f.relPath)) : null;
408
408
  for (const file of batch) {
409
409
  if (!urlMap.has(file.relPath)) {
410
410
  failedFiles.push(file.relPath);
411
+ const serverError = urlErrors.get(file.relPath);
411
412
  failureReasons.push({
412
413
  path: file.relPath,
413
- reason: "no signed URL from server after retries"
414
+ reason: serverError ? `signed-url error: ${truncate(serverError, 140)}` : "no signed URL from server after retries"
414
415
  });
415
416
  bar.tick(0);
416
417
  continue;
@@ -438,21 +439,31 @@ async function uploadDirect(jobId, files) {
438
439
  bar.done();
439
440
  if (failedFiles.length > 0) {
440
441
  const byReason = /* @__PURE__ */ new Map();
441
- for (const { reason } of failureReasons) {
442
- byReason.set(reason, (byReason.get(reason) ?? 0) + 1);
442
+ for (const { reason, path } of failureReasons) {
443
+ const existing = byReason.get(reason);
444
+ if (existing) {
445
+ existing.count++;
446
+ } else {
447
+ byReason.set(reason, { count: 1, samplePath: path });
448
+ }
443
449
  }
444
- const reasonLines = [...byReason.entries()].sort((a, b) => b[1] - a[1]).map(([reason, count]) => ` ${count}\xD7 ${reason}`).join("\n");
445
- const samplePath = failedFiles[0];
450
+ const reasonLines = [...byReason.entries()].sort((a, b) => b[1].count - a[1].count).map(([reason, { count, samplePath }]) => ` ${count}\xD7 ${reason}
451
+ e.g. ${samplePath}`).join("\n");
446
452
  throw new Error(
447
- `Upload incomplete: ${failedFiles.length}/${files.length} file(s) failed. First failed file: ${samplePath}.
453
+ `Upload incomplete: ${failedFiles.length}/${files.length} file(s) failed.
448
454
  Failure breakdown:
449
455
  ${reasonLines}
450
- Retry the upload or check your network connection.`
456
+
457
+ If these look like 409 / "already exists" errors, the previous upload
458
+ attempt left stale files at the same storage path. Retry the upload \u2014
459
+ the server now heals those on the next push_init. Otherwise retry
460
+ after a minute or check https://status.supabase.com.`
451
461
  );
452
462
  }
453
463
  }
454
464
  async function fetchSignedUrlsForBatch(jobId, paths) {
455
465
  const urlMap = /* @__PURE__ */ new Map();
466
+ const errors = /* @__PURE__ */ new Map();
456
467
  let pending = paths.slice();
457
468
  const attempts = 4;
458
469
  for (let attempt = 0; attempt < attempts && pending.length > 0; attempt++) {
@@ -471,13 +482,15 @@ async function fetchSignedUrlsForBatch(jobId, paths) {
471
482
  for (const u of urls) {
472
483
  if (u.signed_url) {
473
484
  urlMap.set(u.path, u.signed_url);
485
+ errors.delete(u.path);
474
486
  } else {
487
+ if (u.error) errors.set(u.path, u.error);
475
488
  stillPending.push(u.path);
476
489
  }
477
490
  }
478
491
  pending = stillPending;
479
492
  }
480
- return urlMap;
493
+ return { urlMap, errors };
481
494
  }
482
495
  async function uploadOneFileWithError(file, signedUrl) {
483
496
  const data = readFileSync(file.absPath);
@@ -507,6 +520,9 @@ async function uploadOneFileWithError(file, signedUrl) {
507
520
  function sleep(ms) {
508
521
  return new Promise((r) => setTimeout(r, ms));
509
522
  }
523
+ function truncate(s, n) {
524
+ return s.length > n ? s.slice(0, n - 1) + "\u2026" : s;
525
+ }
510
526
  export {
511
527
  collectFiles,
512
528
  uploadJob
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trajectories-sh",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "description": "CLI for uploading trajectory jobs to trajectories.sh",
5
5
  "type": "module",
6
6
  "bin": {