@runinfra/cli 0.1.0 → 0.1.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.
- package/dist/endpoints.js +1 -1
- package/dist/http.js +22 -1
- package/dist/pull.js +19 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/endpoints.js
CHANGED
|
@@ -29,7 +29,7 @@ export function resolveApiBase(env) {
|
|
|
29
29
|
const base = `${url.origin}${url.pathname}`.replace(/\/+$/u, "");
|
|
30
30
|
return { ok: true, base };
|
|
31
31
|
}
|
|
32
|
-
function isLoopbackHostname(hostname) {
|
|
32
|
+
export function isLoopbackHostname(hostname) {
|
|
33
33
|
return (hostname === "localhost" ||
|
|
34
34
|
hostname === "127.0.0.1" ||
|
|
35
35
|
hostname === "[::1]" ||
|
package/dist/http.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { request as httpRequest } from "node:http";
|
|
2
2
|
import { request as httpsRequest } from "node:https";
|
|
3
|
+
import { isLoopbackHostname } from "./endpoints.js";
|
|
3
4
|
import { CliError } from "./errors.js";
|
|
4
5
|
import { userAgent } from "./version.js";
|
|
5
6
|
export const DEFAULT_IDLE_TIMEOUT_MS = 30_000;
|
|
@@ -24,11 +25,28 @@ function networkError(url, cause) {
|
|
|
24
25
|
}
|
|
25
26
|
return new CliError("network", `Could not reach ${host}: ${detail}`, "Check your connection or proxy settings, then run the command again.");
|
|
26
27
|
}
|
|
28
|
+
const CREDENTIAL_HEADERS = new Set([
|
|
29
|
+
"authorization",
|
|
30
|
+
"cookie",
|
|
31
|
+
"proxy-authorization",
|
|
32
|
+
]);
|
|
33
|
+
function headersForHop(requested, origin, originalOrigin) {
|
|
34
|
+
if (!requested || origin === originalOrigin)
|
|
35
|
+
return { ...(requested ?? {}) };
|
|
36
|
+
const carried = {};
|
|
37
|
+
for (const [name, value] of Object.entries(requested)) {
|
|
38
|
+
if (CREDENTIAL_HEADERS.has(name.toLowerCase()))
|
|
39
|
+
continue;
|
|
40
|
+
carried[name] = value;
|
|
41
|
+
}
|
|
42
|
+
return carried;
|
|
43
|
+
}
|
|
27
44
|
async function dispatch(options) {
|
|
28
45
|
const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
|
|
29
46
|
let currentUrl = options.url;
|
|
30
47
|
let method = options.method;
|
|
31
48
|
let body = options.json === undefined ? null : Buffer.from(JSON.stringify(options.json), "utf8");
|
|
49
|
+
const originalOrigin = new URL(options.url).origin;
|
|
32
50
|
for (let hop = 0; hop <= maxRedirects; hop += 1) {
|
|
33
51
|
const parsed = new URL(currentUrl);
|
|
34
52
|
const secure = parsed.protocol === "https:";
|
|
@@ -36,7 +54,7 @@ async function dispatch(options) {
|
|
|
36
54
|
const headers = {
|
|
37
55
|
accept: "application/json",
|
|
38
56
|
"user-agent": userAgent(),
|
|
39
|
-
...(options.headers
|
|
57
|
+
...headersForHop(options.headers, parsed.origin, originalOrigin),
|
|
40
58
|
};
|
|
41
59
|
if (body) {
|
|
42
60
|
headers["content-type"] = "application/json";
|
|
@@ -74,6 +92,9 @@ async function dispatch(options) {
|
|
|
74
92
|
if (parsed.protocol === "https:" && next.protocol !== "https:") {
|
|
75
93
|
throw new CliError("network", `${parsed.host} redirected to an insecure URL (${next.protocol}//${next.host}).`, "This is not something the CLI can safely follow. Report it to support.");
|
|
76
94
|
}
|
|
95
|
+
if (next.protocol === "http:" && !isLoopbackHostname(next.hostname)) {
|
|
96
|
+
throw new CliError("network", `${parsed.host} redirected to a plaintext URL off this machine (${next.protocol}//${next.host}).`, "This is not something the CLI can safely follow. Report it to support.");
|
|
97
|
+
}
|
|
77
98
|
if (status === 303 || ((status === 301 || status === 302) && method !== "HEAD")) {
|
|
78
99
|
method = "GET";
|
|
79
100
|
body = null;
|
package/dist/pull.js
CHANGED
|
@@ -37,7 +37,25 @@ export async function pull(context, options, signal) {
|
|
|
37
37
|
const existing = await statOrNull(finalPath);
|
|
38
38
|
if (existing !== null) {
|
|
39
39
|
if (existing.size === artifact.sizeBytes) {
|
|
40
|
-
|
|
40
|
+
if (lease.checksumSha256) {
|
|
41
|
+
let lastTickMs = 0;
|
|
42
|
+
const actual = await sha256File(finalPath, (hashed) => {
|
|
43
|
+
const nowMs = Date.now();
|
|
44
|
+
if (nowMs - lastTickMs < 500)
|
|
45
|
+
return;
|
|
46
|
+
lastTickMs = nowMs;
|
|
47
|
+
const percent = artifact.sizeBytes > 0 ? (hashed / artifact.sizeBytes) * 100 : 0;
|
|
48
|
+
output.status(` Checking the file already here ${percent.toFixed(1)}%`);
|
|
49
|
+
}, signal);
|
|
50
|
+
output.endStatus();
|
|
51
|
+
if (judgeChecksum(lease.checksumSha256, actual) === "mismatch") {
|
|
52
|
+
throw new CliError("checksum_mismatch", `${finalPath} is the published size but does not match the published checksum.`, "Move or delete that file, then run the same command again to download it fresh.");
|
|
53
|
+
}
|
|
54
|
+
output.info(`${fileName} is already downloaded, and its checksum matches.`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
output.info(`${fileName} is already downloaded. UNVERIFIED: this package publishes no checksum.`);
|
|
58
|
+
}
|
|
41
59
|
output.result(finalPath);
|
|
42
60
|
return 0;
|
|
43
61
|
}
|
package/dist/version.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const CLI_NAME = "runinfra";
|
|
2
2
|
export const CLI_PACKAGE = "@runinfra/cli";
|
|
3
|
-
export const CLI_VERSION = "0.1.
|
|
3
|
+
export const CLI_VERSION = "0.1.1";
|
|
4
4
|
export const CLI_CLIENT_ID = "runinfra-cli";
|
|
5
5
|
export const MINIMUM_NODE_MAJOR = 20;
|
|
6
6
|
export function isSupportedNodeVersion(version) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runinfra/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "RunInfra CLI: browser-approved sign-in and resumable downloads for optimized model packages",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
-
"homepage": "https://runinfra.ai/
|
|
6
|
+
"homepage": "https://runinfra.ai/catalog",
|
|
7
7
|
"bugs": {
|
|
8
8
|
"url": "https://runinfra.ai/contact"
|
|
9
9
|
},
|