trajectories-sh 1.18.0 → 1.18.1
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.
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getApiUrl,
|
|
3
|
+
getAuthHeader
|
|
4
|
+
} from "./chunk-Q2ZEN43L.js";
|
|
5
|
+
|
|
6
|
+
// src/quota.ts
|
|
7
|
+
async function fetchOrgUsage() {
|
|
8
|
+
const auth = await getAuthHeader();
|
|
9
|
+
if (!auth) return null;
|
|
10
|
+
try {
|
|
11
|
+
const resp = await fetch(`${getApiUrl()}/api/cli/usage`, {
|
|
12
|
+
headers: { Authorization: auth },
|
|
13
|
+
signal: AbortSignal.timeout(1e4)
|
|
14
|
+
});
|
|
15
|
+
if (!resp.ok) return null;
|
|
16
|
+
return await resp.json();
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function planUpgradeLabel(plan) {
|
|
22
|
+
return plan === "free" ? "Team" : "Premiere";
|
|
23
|
+
}
|
|
24
|
+
async function preflightQuota(check) {
|
|
25
|
+
const usage = await fetchOrgUsage();
|
|
26
|
+
if (!usage) return;
|
|
27
|
+
if (usage.plan === "premiere") return;
|
|
28
|
+
const plan = planUpgradeLabel(usage.plan);
|
|
29
|
+
if (check.kind === "trajectory") {
|
|
30
|
+
if (usage.trajectory_count >= usage.trajectory_limit) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Trajectory limit reached (${usage.trajectory_count.toLocaleString()}/${usage.trajectory_limit.toLocaleString()}). Upgrade to ${plan} for more: https://trajectories.sh/pricing`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const projected = usage.storage_bytes_used + check.projectedAddedBytes;
|
|
36
|
+
if (projected > usage.storage_limit_bytes) {
|
|
37
|
+
const usedGB = (usage.storage_bytes_used / 1024 ** 3).toFixed(1);
|
|
38
|
+
const uploadGB = (check.projectedAddedBytes / 1024 ** 3).toFixed(1);
|
|
39
|
+
const limitGB = (usage.storage_limit_bytes / 1024 ** 3).toFixed(0);
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Storage limit would be exceeded (${usedGB} GB used + ${uploadGB} GB upload > ${limitGB} GB limit). Upgrade to ${plan} for more: https://trajectories.sh/pricing`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (usage.task_count + check.newTaskCount > usage.task_limit) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Task limit reached (${usage.task_count.toLocaleString()}/${usage.task_limit.toLocaleString()}). Upgrade to ${plan} for more: https://trajectories.sh/pricing`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
preflightQuota
|
|
55
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -95,7 +95,7 @@ async function uploadTrajectoryAction(directory, opts) {
|
|
|
95
95
|
Uploading trajectory ${directory} \u2192 ${chalk.cyan(slug)}
|
|
96
96
|
`));
|
|
97
97
|
try {
|
|
98
|
-
const { uploadJob } = await import("./upload-
|
|
98
|
+
const { uploadJob } = await import("./upload-JHU236SW.js");
|
|
99
99
|
const result = await uploadJob(directory, {
|
|
100
100
|
slug,
|
|
101
101
|
name: opts.name
|
|
@@ -141,7 +141,7 @@ async function uploadTaskAction(directory, opts) {
|
|
|
141
141
|
Uploading task ${directory} \u2192 ${chalk.cyan(name)}
|
|
142
142
|
`));
|
|
143
143
|
try {
|
|
144
|
-
const { pushTask } = await import("./push-task-
|
|
144
|
+
const { pushTask } = await import("./push-task-OZTAROKW.js");
|
|
145
145
|
const result = await pushTask(directory, {
|
|
146
146
|
name: opts.name,
|
|
147
147
|
visibility: opts.visibility
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
preflightQuota
|
|
3
|
+
} from "./chunk-2ELJH3IV.js";
|
|
1
4
|
import {
|
|
2
5
|
getApiUrl,
|
|
3
6
|
getAuthHeader
|
|
@@ -116,18 +119,9 @@ async function pushTask(dir, opts) {
|
|
|
116
119
|
"No task content found. A task needs at least an instruction.md, Dockerfile, or test file."
|
|
117
120
|
);
|
|
118
121
|
}
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
const usageResp = await fetch(`${apiUrl}/api/cli/usage`, {
|
|
122
|
-
headers: { Authorization: auth },
|
|
123
|
-
signal: AbortSignal.timeout(1e4)
|
|
124
|
-
});
|
|
125
|
-
if (usageResp.ok) {
|
|
126
|
-
const usage = await usageResp.json();
|
|
127
|
-
}
|
|
128
|
-
} catch {
|
|
129
|
-
}
|
|
122
|
+
await preflightQuota({ kind: "task", newTaskCount: 1 });
|
|
130
123
|
console.log(" Uploading...");
|
|
124
|
+
const apiUrl = getApiUrl();
|
|
131
125
|
const resp = await fetch(`${apiUrl}/api/cli/push-task`, {
|
|
132
126
|
method: "POST",
|
|
133
127
|
headers: {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
preflightQuota
|
|
3
|
+
} from "./chunk-2ELJH3IV.js";
|
|
1
4
|
import {
|
|
2
5
|
getApiUrl,
|
|
3
6
|
getAuthHeader
|
|
@@ -10,7 +13,7 @@ import { tmpdir } from "os";
|
|
|
10
13
|
import { randomBytes, createHash } from "crypto";
|
|
11
14
|
var SKIP = /* @__PURE__ */ new Set(["__pycache__", ".DS_Store", ".git", "node_modules"]);
|
|
12
15
|
var MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
13
|
-
var CONCURRENCY = Number(process.env.TRAJECTORIES_CLI_CONCURRENCY ?? "
|
|
16
|
+
var CONCURRENCY = Number(process.env.TRAJECTORIES_CLI_CONCURRENCY ?? "256");
|
|
14
17
|
var BATCH_SIZE = Number(process.env.TRAJECTORIES_CLI_BATCH_SIZE ?? "500");
|
|
15
18
|
var WEBP_CONCURRENCY = Number(process.env.TRAJECTORIES_CLI_WEBP_CONCURRENCY ?? "4");
|
|
16
19
|
var HASH_CONCURRENCY = Number(process.env.TRAJECTORIES_CLI_HASH_CONCURRENCY ?? "16");
|
|
@@ -328,40 +331,11 @@ ${samples}${more}
|
|
|
328
331
|
`
|
|
329
332
|
);
|
|
330
333
|
}
|
|
334
|
+
await preflightQuota({ kind: "trajectory", projectedAddedBytes: totalSize });
|
|
331
335
|
process.stdout.write(` Hashing...\r`);
|
|
332
336
|
const t0 = Date.now();
|
|
333
337
|
const contentHash = await computeContentHash(files);
|
|
334
338
|
console.log(` Hash: ${contentHash.slice(0, 16)}... (${((Date.now() - t0) / 1e3).toFixed(1)}s)`);
|
|
335
|
-
try {
|
|
336
|
-
const auth = await getAuthHeader();
|
|
337
|
-
const usageResp = await fetch(`${getApiUrl()}/api/cli/usage`, {
|
|
338
|
-
headers: auth ? { Authorization: auth } : {},
|
|
339
|
-
signal: AbortSignal.timeout(1e4)
|
|
340
|
-
});
|
|
341
|
-
if (usageResp.status === 200) {
|
|
342
|
-
const usage = await usageResp.json();
|
|
343
|
-
if (usage.plan !== "premiere") {
|
|
344
|
-
if (usage.trajectory_count >= usage.trajectory_limit) {
|
|
345
|
-
const plan = usage.plan === "free" ? "Team" : "Premiere";
|
|
346
|
-
throw new Error(
|
|
347
|
-
`Trajectory limit reached (${usage.trajectory_count.toLocaleString()}/${usage.trajectory_limit.toLocaleString()}). Upgrade to ${plan} for more: https://trajectories.sh/pricing`
|
|
348
|
-
);
|
|
349
|
-
}
|
|
350
|
-
const projectedStorage = usage.storage_bytes_used + totalSize;
|
|
351
|
-
if (projectedStorage > usage.storage_limit_bytes) {
|
|
352
|
-
const usedGB = (usage.storage_bytes_used / 1024 ** 3).toFixed(1);
|
|
353
|
-
const uploadGB = (totalSize / 1024 ** 3).toFixed(1);
|
|
354
|
-
const limitGB = (usage.storage_limit_bytes / 1024 ** 3).toFixed(0);
|
|
355
|
-
const plan = usage.plan === "free" ? "Team" : "Premiere";
|
|
356
|
-
throw new Error(
|
|
357
|
-
`Storage limit would be exceeded (${usedGB} GB used + ${uploadGB} GB upload > ${limitGB} GB limit). Upgrade to ${plan} for more: https://trajectories.sh/pricing`
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
} catch (e) {
|
|
363
|
-
if (e.message?.includes("limit")) throw e;
|
|
364
|
-
}
|
|
365
339
|
const initResp = await apiPost("/api/cli/push/init", { slug, name, visibility, estimated_bytes: totalSize, content_hash: contentHash });
|
|
366
340
|
if (!initResp.ok) {
|
|
367
341
|
throw new Error(`Init failed: ${await initResp.text()}`);
|
|
@@ -514,7 +488,7 @@ async function fetchSignedUrlsForBatch(jobId, paths) {
|
|
|
514
488
|
async function uploadOneFileWithError(file, signedUrl) {
|
|
515
489
|
const data = readFileSync(file.absPath);
|
|
516
490
|
let lastError = "unknown error";
|
|
517
|
-
for (let attempt = 0; attempt <
|
|
491
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
518
492
|
try {
|
|
519
493
|
const resp = await fetch(signedUrl, {
|
|
520
494
|
method: "PUT",
|
|
@@ -529,10 +503,14 @@ async function uploadOneFileWithError(file, signedUrl) {
|
|
|
529
503
|
if (body) lastError += ` \u2014 ${body.slice(0, 150).replace(/\s+/g, " ")}`;
|
|
530
504
|
} catch {
|
|
531
505
|
}
|
|
506
|
+
if (resp.status === 503 || resp.status === 429) {
|
|
507
|
+
await sleep(2e3 * (attempt + 1));
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
532
510
|
} catch (e) {
|
|
533
511
|
lastError = `fetch error: ${e?.name ?? "Error"} ${e?.message ?? e}`;
|
|
534
512
|
}
|
|
535
|
-
if (attempt <
|
|
513
|
+
if (attempt < 4) await sleep(1e3 * (attempt + 1));
|
|
536
514
|
}
|
|
537
515
|
return { ok: false, error: lastError };
|
|
538
516
|
}
|