trajectories-sh 1.18.2 → 1.18.4

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
@@ -98,7 +98,7 @@ async function uploadTrajectoryAction(pathArg, opts) {
98
98
  );
99
99
  }
100
100
  if (isZip) {
101
- const { uploadZip } = await import("./upload-3CRW3BJ6.js");
101
+ const { uploadZip } = await import("./upload-XTPRJGN4.js");
102
102
  const slug2 = opts.slug ?? pathArg.replace(/\.zip$/i, "").replace(/\/+$/, "").split("/").pop();
103
103
  console.log(chalk.bold(`
104
104
  Uploading ZIP ${pathArg} \u2192 ${chalk.cyan(slug2)}
@@ -127,7 +127,7 @@ async function uploadTrajectoryAction(pathArg, opts) {
127
127
  Uploading trajectory ${pathArg} \u2192 ${chalk.cyan(slug)}
128
128
  `));
129
129
  try {
130
- const { uploadJob } = await import("./upload-3CRW3BJ6.js");
130
+ const { uploadJob } = await import("./upload-XTPRJGN4.js");
131
131
  const result = await uploadJob(pathArg, {
132
132
  slug,
133
133
  name: opts.name
@@ -51,46 +51,59 @@ async function apiPost(path, body, timeout = 3e5) {
51
51
  });
52
52
  }
53
53
  async function uploadZip(zipPath, opts) {
54
- const { readFileSync: readFileSync2, statSync: statSync2 } = await import("fs");
55
- const { getApiUrl: _getApiUrl, getAuthHeader: _getAuthHeader } = await import("./config-4XJRECIW.js");
56
- const auth = await _getAuthHeader();
57
- if (!auth) throw new Error("Not authenticated. Run: trajectories auth login");
58
- const fileStat = statSync2(zipPath);
54
+ const { execSync } = await import("child_process");
55
+ const { mkdtempSync, existsSync, readdirSync: readdirSync2, statSync: _statSync } = await import("fs");
56
+ const { join: _join } = await import("path");
57
+ const { tmpdir: _tmpdir } = await import("os");
58
+ const fileStat = _statSync(zipPath);
59
59
  const sizeMB = (fileStat.size / (1024 * 1024)).toFixed(1);
60
60
  console.log(` ZIP size: ${sizeMB} MB`);
61
- console.log(" Uploading to server (server-side extraction)...");
62
- const fileData = readFileSync2(zipPath);
63
- const formData = new FormData();
64
- formData.append("file", new Blob([fileData]), zipPath.split("/").pop() ?? "upload.zip");
65
- if (opts.slug) formData.append("slug", opts.slug);
66
- if (opts.name) formData.append("name", opts.name);
67
- formData.append("visibility", "unlisted");
68
- const apiUrl = _getApiUrl();
69
- const resp = await fetch(`${apiUrl}/api/cli/push/zip`, {
70
- method: "POST",
71
- headers: { Authorization: auth },
72
- body: formData,
73
- signal: AbortSignal.timeout(36e5)
61
+ console.log(" Extracting ZIP...");
62
+ const tmpDir = mkdtempSync(_join(_tmpdir(), "traj-zip-"));
63
+ execSync(`unzip -q -o ${JSON.stringify(zipPath)} -d ${JSON.stringify(tmpDir)}`, {
64
+ stdio: "pipe",
65
+ timeout: 3e5
74
66
  });
75
- if (!resp.ok) {
76
- let detail;
77
- try {
78
- const body = await resp.json();
79
- detail = body.detail || JSON.stringify(body);
80
- } catch {
81
- detail = await resp.text();
67
+ const topEntries = readdirSync2(tmpDir, { withFileTypes: true });
68
+ const jobDirs = [];
69
+ if (existsSync(_join(tmpDir, "config.json")) && existsSync(_join(tmpDir, "result.json"))) {
70
+ jobDirs.push({ path: tmpDir, name: opts.name || opts.slug || "job" });
71
+ } else {
72
+ for (const entry of topEntries) {
73
+ if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name === "__MACOSX") continue;
74
+ const jobPath = _join(tmpDir, entry.name);
75
+ if (existsSync(_join(jobPath, "config.json")) && existsSync(_join(jobPath, "result.json"))) {
76
+ jobDirs.push({ path: jobPath, name: opts.name || entry.name });
77
+ }
82
78
  }
83
- throw new Error(`ZIP upload failed (${resp.status}): ${detail}`);
84
79
  }
85
- const result = await resp.json();
86
- const siteUrl = apiUrl.includes("localhost") ? "http://localhost:3000" : apiUrl.replace("api.", "").replace(/\/$/, "");
87
- return result.jobs.map((j) => ({
88
- jobId: j.job_id,
89
- slug: j.slug,
90
- nTrials: j.n_trials,
91
- meanReward: j.mean_reward ?? void 0,
92
- viewerUrl: `${siteUrl}/t/${j.job_id}`
93
- }));
80
+ if (jobDirs.length === 0) {
81
+ throw new Error("No Harbor job directories found in the ZIP. Each job must contain config.json and result.json.");
82
+ }
83
+ console.log(` Found ${jobDirs.length} job(s) in ZIP`);
84
+ const results = [];
85
+ for (let i = 0; i < jobDirs.length; i++) {
86
+ const jobDir = jobDirs[i];
87
+ const jobSlug = opts.slug ? jobDirs.length > 1 ? `${opts.slug}-${i + 1}` : opts.slug : jobDir.path.split("/").pop();
88
+ console.log(`
89
+ Job ${i + 1}/${jobDirs.length}: ${jobDir.name} \u2192 ${jobSlug}`);
90
+ const result = await uploadJob(jobDir.path, {
91
+ slug: jobSlug,
92
+ name: jobDir.name
93
+ });
94
+ results.push({
95
+ jobId: result.jobId,
96
+ slug: result.slug,
97
+ nTrials: result.nTrials,
98
+ meanReward: result.meanReward,
99
+ viewerUrl: result.viewerUrl
100
+ });
101
+ }
102
+ try {
103
+ execSync(`rm -rf ${JSON.stringify(tmpDir)}`, { stdio: "pipe" });
104
+ } catch {
105
+ }
106
+ return results;
94
107
  }
95
108
  async function convertToWebP(dir) {
96
109
  const { files } = collectFiles(dir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trajectories-sh",
3
- "version": "1.18.2",
3
+ "version": "1.18.4",
4
4
  "description": "CLI for uploading trajectory jobs to trajectories.sh",
5
5
  "type": "module",
6
6
  "bin": {