🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@runinfra/cli

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@runinfra/cli - npm Package Compare versions

Comparing version
0.2.3
to
0.2.4
+927
dist/doctor.js
import { constants as fsConstants } from "node:fs";
import { access, lstat, readFile, readdir, stat } from "node:fs/promises";
import { homedir } from "node:os";
import { dirname, isAbsolute, posix as posixPath, resolve as resolvePath, win32 as winPath, } from "node:path";
import { credentialsExpired, parseCredentials, } from "./credentials.js";
import { judgeFreeSpace, readFreeBytes } from "./disk.js";
import { endpointsFor, resolveApiBase, } from "./endpoints.js";
import { EXIT_CODES, isCliError, } from "./errors.js";
import { headResource, requestJson, } from "./http.js";
import { credentialLocation } from "./paths.js";
import { formatBytes } from "./progress.js";
import { redactToPrefix } from "./redact.js";
import { compareVersions, detectInstallChannel, latestVersionSeen, upgradeCommandFor, } from "./update-notice.js";
import { CLI_VERSION, isSupportedNodeVersion, MINIMUM_NODE_MAJOR, } from "./version.js";
const SCHEMA_VERSION = 1;
const DEFAULT_NETWORK_TIMEOUT_MS = 5_000;
const DEFAULT_LOCAL_TIMEOUT_MS = 5_000;
const DEFAULT_COMMAND_TIMEOUT_MS = 12_000;
const MAX_RESPONSE_BYTES = 64 * 1024;
const LARGE_PULL_BYTES = 41 * 1024 * 1024 * 1024;
const HUGGING_FACE_ORIGIN = "https://huggingface.co";
const AUTH_PROBE_SLUG = "__runinfra_doctor__";
const MAX_REPORTED_PART_NAMES = 20;
const CHECK_TITLES = {
"runtime.node": "Node runtime",
"install.channel": "Install channel",
"install.version": "CLI version",
"auth.credential": "Stored credential",
"auth.server": "Server credential",
"network.api": "RunInfra API",
"network.huggingface": "Hugging Face",
"env.hf_token": "HF_TOKEN",
"storage.writable": "Target writable",
"storage.free_space": "Free space",
"storage.stale_parts": "Interrupted pulls",
};
const GROUPS = [
{ title: "Runtime", ids: ["runtime.node"] },
{ title: "Install", ids: ["install.channel", "install.version"] },
{ title: "Authentication", ids: ["auth.credential", "auth.server"] },
{ title: "Network", ids: ["network.api", "network.huggingface"] },
{ title: "Environment", ids: ["env.hf_token"] },
{
title: "Storage",
ids: ["storage.writable", "storage.free_space", "storage.stale_parts"],
},
];
export async function doctor(input, overrides = {}) {
const dependencies = resolveDependencies(overrides);
const target = resolveTarget(input.options.out, dependencies.cwd);
const targetName = targetLabel(input.options.out);
const configuredBase = resolveApiBase(input.env);
const installChannel = detectInstallChannel({
env: input.env,
versions: dependencies.versions,
});
let interrupted = input.signal.aborted;
let commandTimedOut = false;
const commandController = new AbortController();
const interrupt = () => {
interrupted = true;
commandController.abort();
};
if (input.signal.aborted) {
commandController.abort();
}
else {
input.signal.addEventListener("abort", interrupt, { once: true });
}
const commandTimer = setTimeout(() => {
commandTimedOut = true;
commandController.abort();
}, dependencies.commandTimeoutMs);
const guarded = (values) => runGuardedCheck({
...values,
parentSignal: commandController.signal,
parentWasInterrupted: () => interrupted,
});
try {
const runtimePromise = guarded({
id: "runtime.node",
title: CHECK_TITLES["runtime.node"] ?? "Node runtime",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "unsupported_runtime",
timeoutStatus: "fail",
timeoutRemedy: "Run doctor again with a responsive local runtime.",
run: async () => runtimeCheck(input.nodeVersion),
});
const channelPromise = guarded({
id: "install.channel",
title: CHECK_TITLES["install.channel"] ?? "Install channel",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "unsupported_runtime",
timeoutStatus: "fail",
timeoutRemedy: "Reinstall the CLI through npm, PyPI, or the standalone installer.",
run: async () => installChannelCheck(installChannel),
});
const credentialPromise = guarded({
id: "auth.credential",
title: CHECK_TITLES["auth.credential"] ?? "Stored credential",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "storage_unwritable",
timeoutStatus: "fail",
timeoutRemedy: "Check the credentials directory and run doctor again.",
run: async () => credentialCheck(await dependencies.readCredentialState(credentialLocation({
platform: input.platform,
env: input.env,
homeDir: dependencies.homeDir,
})), dependencies.now()),
});
const authServerPromise = guarded({
id: "auth.server",
title: CHECK_TITLES["auth.server"] ?? "Server credential",
timeoutMs: dependencies.networkTimeoutMs,
defaultFailureCode: "server_error",
timeoutStatus: "warn",
timeoutRemedy: "Check the connection or corporate proxy, then run doctor again. Use --offline on an air-gapped machine.",
run: async (signal) => authServerCheck(input, dependencies, signal),
});
const apiPromise = guarded({
id: "network.api",
title: CHECK_TITLES["network.api"] ?? "RunInfra API",
timeoutMs: dependencies.networkTimeoutMs,
defaultFailureCode: "network",
timeoutStatus: "fail",
timeoutRemedy: "Check the connection and proxy settings, then run doctor again.",
run: async (signal) => apiNetworkCheck(input.options.offline, configuredBase, dependencies, signal),
});
const huggingFacePromise = guarded({
id: "network.huggingface",
title: CHECK_TITLES["network.huggingface"] ?? "Hugging Face",
timeoutMs: dependencies.networkTimeoutMs,
defaultFailureCode: "network",
timeoutStatus: "warn",
timeoutRemedy: "Check whether the proxy permits huggingface.co. Weights-carrying packages do not require it.",
run: async (signal) => huggingFaceNetworkCheck(input.options.offline, dependencies, signal),
});
const hfTokenPromise = guarded({
id: "env.hf_token",
title: CHECK_TITLES["env.hf_token"] ?? "HF_TOKEN",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "usage",
timeoutStatus: "fail",
timeoutRemedy: "Run doctor again from a responsive shell.",
run: async () => hfTokenCheck(input.env),
});
const writablePromise = guarded({
id: "storage.writable",
title: CHECK_TITLES["storage.writable"] ?? "Target writable",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "storage_unwritable",
timeoutStatus: "fail",
timeoutRemedy: "Check the target filesystem, or pass --out to another directory.",
run: async () => writableCheck(await dependencies.inspectWritable(target), targetName),
});
const freeSpacePromise = guarded({
id: "storage.free_space",
title: CHECK_TITLES["storage.free_space"] ?? "Free space",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "disk_space",
timeoutStatus: "fail",
timeoutRemedy: "Check the target volume manually, or pass --out to another volume.",
run: async () => {
const probePath = await nearestExistingDirectory(target);
return freeSpaceCheck(await dependencies.readFreeBytes(probePath), targetName);
},
});
const stalePartsPromise = guarded({
id: "storage.stale_parts",
title: CHECK_TITLES["storage.stale_parts"] ?? "Interrupted pulls",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "storage_unwritable",
timeoutStatus: "fail",
timeoutRemedy: "Check the target directory and run doctor again.",
run: async (signal) => stalePartsCheck(await dependencies.findStaleParts(target, signal), input.options.out, input.platform),
});
const [runtime, channel, credential, authServer, api, huggingFace, hfToken, writable, freeSpace, staleParts,] = await Promise.all([
runtimePromise,
channelPromise,
credentialPromise,
authServerPromise,
apiPromise,
huggingFacePromise,
hfTokenPromise,
writablePromise,
freeSpacePromise,
stalePartsPromise,
]);
const version = await guarded({
id: "install.version",
title: CHECK_TITLES["install.version"] ?? "CLI version",
timeoutMs: dependencies.localTimeoutMs,
defaultFailureCode: "server_error",
timeoutStatus: "fail",
timeoutRemedy: "Run doctor again.",
run: async () => installVersionCheck(input.options.offline, installChannel, input.platform, dependencies.latestVersion()),
});
const internalChecks = [
runtime,
channel,
version,
credential,
authServer,
api,
huggingFace,
hfToken,
writable,
freeSpace,
staleParts,
];
const checks = internalChecks.map((entry) => entry.check);
const report = {
schemaVersion: SCHEMA_VERSION,
cliVersion: CLI_VERSION,
generatedAt: generatedAt(dependencies.now),
summary: summarize(checks),
checks,
};
if (input.options.json) {
input.output.result(JSON.stringify(report));
}
else {
renderHuman(input.output, report);
}
const firstFailure = internalChecks.find((entry) => entry.check.status === "fail");
if (firstFailure !== undefined && firstFailure.failureCode !== null) {
return EXIT_CODES[firstFailure.failureCode];
}
if (commandTimedOut)
return EXIT_CODES.network;
return 0;
}
finally {
clearTimeout(commandTimer);
input.signal.removeEventListener("abort", interrupt);
}
}
function resolveDependencies(overrides) {
return {
now: overrides.now ?? Date.now,
versions: overrides.versions ?? process.versions,
homeDir: overrides.homeDir ?? safeHomeDirectory(),
cwd: overrides.cwd ?? safeWorkingDirectory(),
networkTimeoutMs: overrides.networkTimeoutMs ?? DEFAULT_NETWORK_TIMEOUT_MS,
localTimeoutMs: overrides.localTimeoutMs ?? DEFAULT_LOCAL_TIMEOUT_MS,
commandTimeoutMs: overrides.commandTimeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS,
readCredentialState: overrides.readCredentialState ?? readCredentialStateFromDisk,
inspectWritable: overrides.inspectWritable ?? inspectWritableOnDisk,
findStaleParts: overrides.findStaleParts ?? findStalePartsOnDisk,
readFreeBytes: overrides.readFreeBytes ?? readFreeBytes,
requestJson: overrides.requestJson ?? requestJson,
headResource: overrides.headResource ?? headResource,
latestVersion: overrides.latestVersion ?? latestVersionSeen,
};
}
async function runGuardedCheck(input) {
return await new Promise((resolve) => {
let settled = false;
const controller = new AbortController();
const finish = (value) => {
if (settled)
return;
settled = true;
clearTimeout(timer);
input.parentSignal.removeEventListener("abort", parentAbort);
resolve(value);
};
const parentAbort = () => {
controller.abort();
if (input.parentWasInterrupted()) {
finish(failure(input.id, input.title, "Check was interrupted.", "Run doctor again.", "interrupted"));
return;
}
finish(failure(input.id, input.title, "Check exceeded the doctor command ceiling.", "Run doctor again. If it repeats, include this report in the support ticket.", input.defaultFailureCode));
};
const timer = setTimeout(() => {
controller.abort();
const detail = `Check timed out after ${input.timeoutMs}ms.`;
if (input.timeoutStatus === "warn") {
finish(warning(input.id, input.title, detail, input.timeoutRemedy));
}
else {
finish(failure(input.id, input.title, detail, input.timeoutRemedy, input.defaultFailureCode));
}
}, input.timeoutMs);
if (input.parentSignal.aborted) {
parentAbort();
return;
}
input.parentSignal.addEventListener("abort", parentAbort, { once: true });
void Promise.resolve()
.then(async () => input.run(controller.signal))
.then(finish, (error) => {
finish(failure(input.id, input.title, `Check failed with ${errorKind(error)}.`, "Run doctor again. If it repeats, include this report in the support ticket.", input.defaultFailureCode));
});
});
}
function runtimeCheck(nodeVersion) {
if (isSupportedNodeVersion(nodeVersion)) {
return okay("runtime.node", CHECK_TITLES["runtime.node"] ?? "Node runtime", `Node ${safeInline(nodeVersion)} meets the required major version ${MINIMUM_NODE_MAJOR}.`);
}
return failure("runtime.node", CHECK_TITLES["runtime.node"] ?? "Node runtime", `Node ${safeInline(nodeVersion)} is below the required major version ${MINIMUM_NODE_MAJOR}.`, `Run this CLI with Node ${MINIMUM_NODE_MAJOR} or newer, or reinstall the standalone or PyPI package.`, "unsupported_runtime");
}
function installChannelCheck(channel) {
const title = CHECK_TITLES["install.channel"] ?? "Install channel";
switch (channel) {
case "npm":
return okay("install.channel", title, "Installed through npm.");
case "pypi":
return okay("install.channel", title, "Installed through a PyPI wheel.");
case "standalone":
return okay("install.channel", title, "Running as a standalone binary.");
case "unknown":
return warning("install.channel", title, "The install channel could not be inferred honestly.", "When upgrading, use the same npm, PyPI, or standalone channel that installed this copy.");
}
}
function installVersionCheck(offline, channel, platform, latest) {
const title = CHECK_TITLES["install.version"] ?? "CLI version";
if (offline) {
return skipped("install.version", title, `Running ${CLI_VERSION}; newer-version comparison was skipped offline.`);
}
if (latest === null) {
return warning("install.version", title, `Running ${CLI_VERSION}; no valid latest-version header was observed.`, "Run doctor again when the RunInfra API is reachable.");
}
if (compareVersions(latest, CLI_VERSION) === 1) {
const command = upgradeCommandFor(channel, platform);
return warning("install.version", title, `Running ${CLI_VERSION}; RunInfra advertised ${safeInline(latest)}.`, command === null
? "Reinstall with the same channel that installed this copy."
: command);
}
return okay("install.version", title, `Running ${CLI_VERSION}; the server advertised ${safeInline(latest)}.`);
}
function credentialCheck(state, nowMs) {
const title = CHECK_TITLES["auth.credential"] ?? "Stored credential";
if (state.kind === "missing") {
return failure("auth.credential", title, "No credential is stored on this machine.", "Run `runinfra login` to connect this terminal.", "not_authenticated");
}
if (state.kind === "invalid") {
return failure("auth.credential", title, "The stored credential file is unreadable or malformed.", "Move or delete the credential file yourself, then run `runinfra login`.", "not_authenticated");
}
const credential = state.credentials;
const visible = redactToPrefix(credential.apiKey, credential.keyPrefix);
if (credentialsExpired(credential, nowMs)) {
return failure("auth.credential", title, `Credential ${visible} expired at ${safeInline(credential.expiresAt)}.`, "Run `runinfra login` to connect this terminal again.", "auth_expired");
}
return okay("auth.credential", title, `Credential ${visible} expires at ${safeInline(credential.expiresAt)}.`);
}
async function authServerCheck(input, dependencies, signal) {
const title = CHECK_TITLES["auth.server"] ?? "Server credential";
if (input.options.offline) {
return skipped("auth.server", title, "Server credential validation was skipped offline.");
}
const state = await dependencies.readCredentialState(credentialLocation({
platform: input.platform,
env: input.env,
homeDir: dependencies.homeDir,
}));
if (state.kind !== "present") {
return skipped("auth.server", title, "No valid local credential was available to send.");
}
const storedBase = resolveApiBase({
RUNINFRA_API_BASE: state.credentials.apiBase,
});
if (!storedBase.ok) {
return failure("auth.server", title, "The credential records an invalid API origin.", "Run `runinfra login` to replace the stored credential.", "not_authenticated");
}
let response;
try {
response = await dependencies.requestJson({
method: "GET",
url: endpointsFor(storedBase.base).download(AUTH_PROBE_SLUG),
captureCliVersionHeader: true,
headers: { authorization: `Bearer ${state.credentials.apiKey}` },
idleTimeoutMs: dependencies.networkTimeoutMs,
maxRedirects: 0,
maxBodyBytes: MAX_RESPONSE_BYTES,
signal,
});
}
catch (error) {
if (isCliError(error)) {
return warning("auth.server", title, safeCliErrorMessage(error.message), (error.hint === null ? null : safeCliErrorMessage(error.hint)) ??
"Check the connection or proxy settings, then run doctor again.");
}
throw error;
}
const code = failureCode(response.body);
if (code === "not_found" && response.status === 404) {
return okay("auth.server", title, "The server accepted the stored credential.");
}
if (code === "not_found") {
return warning("auth.server", title, `The diagnostic refusal used code not_found with unexpected HTTP ${response.status}.`, "Run doctor again. If it repeats, include this report and HTTP status in the support ticket.");
}
switch (code) {
case "key_expired":
return failure("auth.server", title, "The server rejected the credential because it expired.", "Run `runinfra login` to connect this terminal again.", "auth_expired");
case "key_revoked":
return failure("auth.server", title, "The server rejected the credential because it was revoked in Settings.", "Run `runinfra login` to connect this terminal again.", "not_authenticated");
case "workspace_access_revoked":
return failure("auth.server", title, "The credential is live, but your account no longer has access to its workspace.", "Ask a workspace admin to re-invite you, then run `runinfra login` again.", "not_entitled");
case "invalid_key":
case "missing_credentials":
return failure("auth.server", title, "The server did not accept the stored credential.", "Run `runinfra login` to connect this terminal again.", "not_authenticated");
case "rate_limited":
return warning("auth.server", title, "The server rate-limited the credential check, so validity is unknown.", "Wait a minute, then run doctor once more.");
case "auth_unavailable":
return warning("auth.server", title, "The server could not validate credentials right now.", "Run doctor again in a few minutes.");
default:
break;
}
if (response.status === 401) {
return failure("auth.server", title, "The server rejected the credential without a specific refusal code.", "Run `runinfra login` to connect this terminal again.", "not_authenticated");
}
if (response.status === 403) {
return failure("auth.server", title, "The server accepted the identity but refused package-download access.", "Ask a workspace admin to restore download permission, then run doctor again.", "not_entitled");
}
return warning("auth.server", title, `The server answered HTTP ${response.status}, but not with the diagnostic contract.`, "Run doctor again. If it repeats, include this report and HTTP status in the support ticket.");
}
async function apiNetworkCheck(offline, configuredBase, dependencies, signal) {
const title = CHECK_TITLES["network.api"] ?? "RunInfra API";
if (offline) {
return skipped("network.api", title, "RunInfra API reachability was skipped offline.");
}
if (!configuredBase.ok) {
return failure("network.api", title, "RUNINFRA_API_BASE is not a safe HTTP or HTTPS origin.", "Set RUNINFRA_API_BASE to an HTTPS origin without a query or fragment.", "usage");
}
let response;
try {
response = await dependencies.requestJson({
method: "GET",
url: endpointsFor(configuredBase.base).download(AUTH_PROBE_SLUG),
captureCliVersionHeader: true,
idleTimeoutMs: dependencies.networkTimeoutMs,
maxRedirects: 0,
maxBodyBytes: MAX_RESPONSE_BYTES,
signal,
});
}
catch (error) {
if (isCliError(error)) {
return failure("network.api", title, safeCliErrorMessage(error.message), (error.hint === null ? null : safeCliErrorMessage(error.hint)) ??
"Check the connection or proxy settings, then run doctor again.", error.code === "server_error" ? "server_error" : "network");
}
throw error;
}
if (response.status >= 500) {
return failure("network.api", title, `The API origin answered HTTP ${response.status}.`, "Run doctor again shortly. If it repeats, check RunInfra status or contact support.", "server_error");
}
if (response.status === 429) {
return warning("network.api", title, "The API origin is reachable but rate-limited this request.", "Wait a minute, then run doctor once more.");
}
return okay("network.api", title, `The API origin is reachable and answered HTTP ${response.status}.`);
}
async function huggingFaceNetworkCheck(offline, dependencies, signal) {
const title = CHECK_TITLES["network.huggingface"] ?? "Hugging Face";
if (offline) {
return skipped("network.huggingface", title, "Hugging Face reachability was skipped offline.");
}
let response;
try {
response = await dependencies.headResource(HUGGING_FACE_ORIGIN, {
idleTimeoutMs: dependencies.networkTimeoutMs,
signal,
});
}
catch (error) {
if (isCliError(error)) {
return warning("network.huggingface", title, safeCliErrorMessage(error.message), "Check whether the proxy permits huggingface.co. Weights-carrying packages do not require it.");
}
throw error;
}
if (response.status >= 500) {
return warning("network.huggingface", title, `huggingface.co answered HTTP ${response.status}.`, "Try again later. Weights-carrying packages do not require Hugging Face.");
}
if (response.status === 429) {
return warning("network.huggingface", title, "huggingface.co is reachable but rate-limited the check.", "Wait before pulling a recipe package. Weights-carrying packages do not require Hugging Face.");
}
if (response.status === 407) {
return warning("network.huggingface", title, "The proxy requires authentication before it will reach huggingface.co.", "Configure credentials for the corporate proxy, or use a weights-carrying package.");
}
if (response.status >= 400) {
return warning("network.huggingface", title, `huggingface.co answered HTTP ${response.status}, so recipe-package access is uncertain.`, "Check whether the proxy or network policy permits huggingface.co. Weights-carrying packages do not require it.");
}
return okay("network.huggingface", title, `huggingface.co is reachable and answered HTTP ${response.status}.`);
}
function hfTokenCheck(env) {
const title = CHECK_TITLES["env.hf_token"] ?? "HF_TOKEN";
if (env.HF_TOKEN?.trim()) {
return okay("env.hf_token", title, "HF_TOKEN is set. Its value was not read into the report.");
}
return warning("env.hf_token", title, "HF_TOKEN is not set. Public and weights-carrying packages can still work.", "Set HF_TOKEN only when a recipe package uses a gated Hugging Face repository.");
}
function writableCheck(inspection, targetName) {
const title = CHECK_TITLES["storage.writable"] ?? "Target writable";
if (inspection.kind === "writable") {
if (!inspection.targetExists) {
return warning("storage.writable", title, `${targetName} does not exist yet. Its nearest existing parent passes the operating system's write-permission check, but the target itself could not be verified without creating it.`, "Create the target directory yourself, then run doctor again to verify it directly.");
}
return okay("storage.writable", title, `${targetName} passes the operating system's write-permission check. No probe file was created.`);
}
if (inspection.kind === "not_directory") {
return failure("storage.writable", title, `${targetName} is not a directory.`, "Pass --out to a directory.", "storage_unwritable");
}
return failure("storage.writable", title, `${targetName} failed the write-permission check (${safeInline(inspection.errorKind)}).`, "Check ownership and permissions, or pass --out to another directory.", "storage_unwritable");
}
function freeSpaceCheck(freeBytes, targetName) {
const title = CHECK_TITLES["storage.free_space"] ?? "Free space";
if (freeBytes === null) {
return warning("storage.free_space", title, `Free space on the volume for ${targetName} could not be measured.`, "Check the target volume manually before pulling a large kit or weights.");
}
if (freeBytes === 0) {
return failure("storage.free_space", title, `The volume for ${targetName} reports 0 B free.`, "Free space, or pass --out to another volume.", "disk_space");
}
const verdict = judgeFreeSpace(freeBytes, LARGE_PULL_BYTES);
if (!verdict.ok) {
return warning("storage.free_space", title, `${formatBytes(freeBytes)} is free. That is below the large-pull heuristic of ${formatBytes(verdict.requiredBytes)} for a 41 GB transfer plus headroom.`, "Free more space, or pass --out to a larger volume before pulling a large package.");
}
return okay("storage.free_space", title, `${formatBytes(freeBytes)} is free, above the 41 GB large-pull heuristic plus headroom.`);
}
function stalePartsCheck(parts, out, platform) {
const title = CHECK_TITLES["storage.stale_parts"] ?? "Interrupted pulls";
if (parts.length === 0) {
return okay("storage.stale_parts", title, "No kit partials, resume records, or interrupted resume temporaries were found.");
}
const totalBytes = parts.reduce((total, part) => {
const size = Number.isFinite(part.sizeBytes) && part.sizeBytes > 0
? part.sizeBytes
: 0;
return Number.isSafeInteger(total + size) ? total + size : total;
}, 0);
const shown = parts.slice(0, MAX_REPORTED_PART_NAMES);
const names = shown.map((part) => safeReportedName(part.name));
const omitted = parts.length - shown.length;
const suffix = omitted > 0 ? `, plus ${omitted} more` : "";
const command = cleanupCommand(shown.map((part) => part.name), out, platform);
const cleanup = command === null
? "Review the named files and remove them manually only if you do not want to resume."
: `If you do not want to resume, remove the listed files yourself: ${command}`;
return warning("storage.stale_parts", title, `Found ${parts.length} interrupted partial or resume-state file(s), ${formatBytes(totalBytes)} logical size: ${names.join(", ")}${suffix}. Preallocated .part length can exceed bytes actually downloaded.`, `Run the same pull command to resume. ${cleanup}`);
}
function okay(id, title, detail) {
return {
check: { id, title, status: "ok", detail, remedy: null },
failureCode: null,
};
}
function warning(id, title, detail, remedy) {
return {
check: { id, title, status: "warn", detail, remedy },
failureCode: null,
};
}
function failure(id, title, detail, remedy, code) {
return {
check: { id, title, status: "fail", detail, remedy },
failureCode: code,
};
}
function skipped(id, title, detail) {
return {
check: { id, title, status: "skip", detail, remedy: null },
failureCode: null,
};
}
function summarize(checks) {
const summary = { ok: 0, warn: 0, fail: 0, skipped: 0 };
for (const check of checks) {
switch (check.status) {
case "ok":
summary.ok += 1;
break;
case "warn":
summary.warn += 1;
break;
case "fail":
summary.fail += 1;
break;
case "skip":
summary.skipped += 1;
break;
}
}
return summary;
}
function renderHuman(output, report) {
output.info(`RunInfra doctor ${report.cliVersion}`);
output.info(`Generated ${report.generatedAt}`);
output.info("");
const byId = new Map(report.checks.map((check) => [check.id, check]));
const titleWidth = Math.max(...report.checks.map((check) => check.title.length));
for (const group of GROUPS) {
output.info(group.title);
for (const id of group.ids) {
const check = byId.get(id);
if (check === undefined)
continue;
output.info(` ${marker(check.status).padEnd(6)} ${check.title.padEnd(titleWidth)} ${check.detail}`);
if ((check.status === "warn" || check.status === "fail") &&
check.remedy !== null) {
output.detail(`Remedy: ${check.remedy}`);
}
}
output.info("");
}
output.info(`Summary: ${report.summary.ok} ok, ${report.summary.warn} warning(s), ${report.summary.fail} failed, ${report.summary.skipped} skipped.`);
}
function marker(status) {
switch (status) {
case "ok":
return "[OK]";
case "warn":
return "[WARN]";
case "fail":
return "[FAIL]";
case "skip":
return "[SKIP]";
}
}
async function readCredentialStateFromDisk(location) {
let raw;
try {
raw = await readFile(location.file, "utf8");
}
catch (error) {
if (error.code === "ENOENT") {
return { kind: "missing" };
}
throw error;
}
const credentials = parseCredentials(raw);
return credentials === null
? { kind: "invalid" }
: { kind: "present", credentials };
}
async function inspectWritableOnDisk(target) {
let candidate = target;
let targetExists = true;
for (let depth = 0; depth < 64; depth += 1) {
try {
const stats = await stat(candidate);
if (!stats.isDirectory())
return { kind: "not_directory" };
await access(candidate, fsConstants.W_OK);
return { kind: "writable", targetExists };
}
catch (error) {
const code = error.code;
if (code === "ENOENT") {
targetExists = false;
const parent = dirname(candidate);
if (parent === candidate) {
return { kind: "unwritable", errorKind: "ENOENT" };
}
candidate = parent;
continue;
}
return { kind: "unwritable", errorKind: errorKind(error) };
}
}
return { kind: "unwritable", errorKind: "path_depth" };
}
async function nearestExistingDirectory(target) {
let candidate = target;
for (let depth = 0; depth < 64; depth += 1) {
try {
const stats = await stat(candidate);
return stats.isDirectory() ? candidate : dirname(candidate);
}
catch (error) {
if (error.code !== "ENOENT")
throw error;
const parent = dirname(candidate);
if (parent === candidate)
return candidate;
candidate = parent;
}
}
return target;
}
async function findStalePartsOnDisk(target, signal) {
if (signal.aborted)
return [];
const rootEntries = await entriesOrNull(target);
if (rootEntries === null)
return [];
const parts = [];
await collectKitParts(target, "", rootEntries, parts, signal);
if (signal.aborted)
return parts;
await collectWeightState(target, "", rootEntries, parts, signal);
let scannedEntries = 0;
for (const entry of rootEntries) {
scannedEntries += 1;
if (scannedEntries % 256 === 0)
await yieldToEventLoop();
if (signal.aborted)
break;
if (!entry.isDirectory())
continue;
if (entry.name === ".runinfra-weights-parts")
continue;
const childPath = resolvePath(target, entry.name);
const childEntries = await entriesOrNull(childPath);
if (childEntries === null)
continue;
await collectWeightState(childPath, entry.name, childEntries, parts, signal);
}
if (signal.aborted)
return parts;
parts.sort((a, b) => a.name.localeCompare(b.name));
return parts;
}
async function entriesOrNull(directory) {
try {
return await readdirWithTypes(directory);
}
catch (error) {
const code = error.code;
if (code === "ENOENT" || code === "ENOTDIR")
return null;
throw error;
}
}
async function readdirWithTypes(directory) {
return await readdir(directory, { withFileTypes: true });
}
async function collectKitParts(directory, prefix, entries, output, signal) {
let scannedEntries = 0;
for (const entry of entries) {
scannedEntries += 1;
if (scannedEntries % 256 === 0)
await yieldToEventLoop();
if (signal.aborted)
return;
if (!entry.isFile())
continue;
if (!entry.name.endsWith(".part") &&
!entry.name.endsWith(".part.json") &&
!entry.name.endsWith(".part.json.tmp")) {
continue;
}
const size = await logicalFileSize(resolvePath(directory, entry.name));
if (size === null)
continue;
output.push({ name: relativeName(prefix, entry.name), sizeBytes: size });
}
}
async function collectWeightState(directory, prefix, entries, output, signal) {
if (signal.aborted)
return;
const resumes = [];
let partsDirectory;
let scannedEntries = 0;
for (const entry of entries) {
scannedEntries += 1;
if (scannedEntries % 256 === 0)
await yieldToEventLoop();
if (signal.aborted)
return;
if (entry.isFile() &&
(entry.name === ".runinfra-weights.json" ||
entry.name === ".runinfra-weights.json.tmp")) {
resumes.push(entry);
}
else if (entry.isDirectory() &&
entry.name === ".runinfra-weights-parts") {
partsDirectory = entry;
}
}
for (const resume of resumes) {
if (signal.aborted)
return;
const size = await logicalFileSize(resolvePath(directory, resume.name));
if (size !== null) {
output.push({
name: relativeName(prefix, resume.name),
sizeBytes: size,
});
}
}
if (partsDirectory === undefined)
return;
const partsPath = resolvePath(directory, partsDirectory.name);
if (signal.aborted)
return;
const partEntries = await entriesOrNull(partsPath);
if (partEntries === null)
return;
const partsPrefix = relativeName(prefix, partsDirectory.name);
await collectKitParts(partsPath, partsPrefix, partEntries, output, signal);
}
async function yieldToEventLoop() {
await new Promise((resolve) => setImmediate(resolve));
}
async function logicalFileSize(path) {
try {
const stats = await lstat(path);
if (!stats.isFile())
return null;
return Number.isSafeInteger(stats.size) && stats.size >= 0 ? stats.size : 0;
}
catch (error) {
if (error.code === "ENOENT")
return null;
throw error;
}
}
function relativeName(prefix, name) {
return prefix.length === 0 ? name : `${prefix.replace(/\\/gu, "/")}/${name}`;
}
function resolveTarget(out, cwd) {
if (out === null)
return resolvePath(cwd);
return isAbsolute(out) ? resolvePath(out) : resolvePath(cwd, out);
}
function targetLabel(out) {
return out === null
? "the current directory"
: `the target ${safeReportedName(out)}`;
}
function generatedAt(now) {
let nowMs;
try {
nowMs = now();
}
catch {
nowMs = Date.now();
}
if (!Number.isFinite(nowMs))
nowMs = Date.now();
const date = new Date(nowMs);
return Number.isFinite(date.getTime())
? date.toISOString()
: new Date().toISOString();
}
function safeHomeDirectory() {
try {
return homedir();
}
catch {
return ".";
}
}
function safeWorkingDirectory() {
try {
return process.cwd();
}
catch {
return ".";
}
}
function failureCode(body) {
if (!isRecord(body) || body.ok !== false || typeof body.code !== "string") {
return null;
}
return body.code;
}
function isRecord(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function errorKind(error) {
if (error instanceof Error) {
const name = safeToken(error.name || "Error");
const code = safeToken(String(error.code ?? ""));
return code.length > 0 ? `${name} (${code})` : name;
}
return safeToken(typeof error || "unknown");
}
function safeCliErrorMessage(message) {
const withoutQueries = message.replace(/https?:\/\/[^\s?#]+[?#][^\s]*/giu, (url) => {
const query = url.search(/[?#]/u);
return `${url.slice(0, query)}?[query removed]`;
});
const withoutSecrets = withoutQueries.replace(/\b(?:rp_|hf_)[A-Za-z0-9_-]{8,}\b/gu, "[secret removed]");
return safeInline(withoutSecrets, 240);
}
function safeInline(value, maxLength = 160) {
return value
.replace(/[\u0000-\u001f\u007f]+/gu, " ")
.replace(/\s+/gu, " ")
.trim()
.slice(0, maxLength);
}
function safeToken(value) {
return value.replace(/[^A-Za-z0-9_.-]+/gu, "_").slice(0, 48) || "unknown";
}
function safeReportedName(name) {
const noQuery = name.includes("?")
? `${name.slice(0, name.indexOf("?"))}?[query removed]`
: name;
const withoutSecrets = noQuery.replace(/\b(?:rp_|hf_)[A-Za-z0-9_-]{8,}\b/gu, "[secret-shaped name removed]");
return safeInline(withoutSecrets, 160);
}
function cleanupCommand(names, out, platform) {
if (names.length === 0 || names.length > MAX_REPORTED_PART_NAMES)
return null;
if (names.some((name) => !isSafeCleanupName(name)))
return null;
if (out !== null && !isSafeCleanupBase(out))
return null;
const path = platform === "win32" ? winPath : posixPath;
const base = out ?? ".";
const paths = names.map((name) => path.join(base, ...name.split("/")));
if (platform === "win32") {
return `Remove-Item -LiteralPath ${paths
.map((item) => `'${item.replace(/'/gu, "''")}'`)
.join(",")}`;
}
return `rm -- ${paths.map(shellQuote).join(" ")}`;
}
function isSafeCleanupName(name) {
return (name.length > 0 &&
name.length <= 240 &&
!name.startsWith("/") &&
!name.includes("..") &&
!/(?:rp_|hf_)[A-Za-z0-9_-]{8,}/u.test(name) &&
/^[A-Za-z0-9._/ -]+$/u.test(name));
}
function isSafeCleanupBase(value) {
return (value.length > 0 &&
value.length <= 240 &&
!/[?\u0000-\u001f\u007f]/u.test(value) &&
!/(?:rp_|hf_)[A-Za-z0-9_-]{8,}/u.test(value));
}
function shellQuote(value) {
return `'${value.replace(/'/gu, "'\\''")}'`;
}
+13
-0

@@ -9,4 +9,17 @@ #!/usr/bin/env node

import { fileURLToPath } from "node:url";
import { run } from "../dist/main.js";
// An installed npm entry resolves inside node_modules. The same file invoked
// directly from a checkout does not, so it remains honestly unknown. PyPI
// supplies its own marker, while Bun identifies the standalone executable.
const entryPath = fileURLToPath(import.meta.url).replaceAll("\\", "/");
if (
!process.versions.bun &&
!process.env.RUNINFRA_DIST_CHANNEL &&
/\/node_modules\/@runinfra\/cli\//u.test(entryPath)
) {
process.env.RUNINFRA_DIST_CHANNEL = "npm";
}
// Ctrl-C must stop the transfer, not kill the process mid-write: the

@@ -13,0 +26,0 @@ // download engine watches this signal, finishes the write it is on, records

+25
-3

@@ -1,2 +0,2 @@

export const COMMANDS = ["login", "logout", "whoami", "pull"];
export const COMMANDS = ["login", "logout", "whoami", "doctor", "pull"];
export const MIN_CONCURRENCY = 1;

@@ -13,2 +13,4 @@ export const MAX_CONCURRENCY = 16;

weights: false,
json: false,
offline: false,
};

@@ -84,4 +86,7 @@ }

case "-o": {
if (command !== "pull") {
return { ok: false, message: `--out applies to \`runinfra pull\` only.` };
if (command !== "pull" && command !== "doctor") {
return {
ok: false,
message: `--out applies to \`runinfra pull\` or \`runinfra doctor\` only.`,
};
}

@@ -130,2 +135,19 @@ const value = takeValue();

}
case "--json": {
if (command !== "doctor") {
return { ok: false, message: `--json applies to \`runinfra doctor\` only.` };
}
args.json = true;
break;
}
case "--offline": {
if (command !== "doctor") {
return {
ok: false,
message: `--offline applies to \`runinfra doctor\` only.`,
};
}
args.offline = true;
break;
}
default:

@@ -132,0 +154,0 @@ return {

@@ -97,2 +97,3 @@ import { CliError, describeError } from "./errors.js";

url: input.endpoints.loopbackInit,
captureCliVersionHeader: true,
json: {

@@ -125,2 +126,3 @@ codeChallenge: input.codeChallenge,

url: input.endpoints.token,
captureCliVersionHeader: true,
json: {

@@ -138,2 +140,3 @@ code: input.code,

url: input.endpoints.deviceInit,
captureCliVersionHeader: true,
json: {

@@ -180,2 +183,3 @@ codeChallenge: input.codeChallenge,

url: input.endpoints.revoke,
captureCliVersionHeader: true,
headers: { authorization: `Bearer ${input.apiKey}` },

@@ -245,2 +249,3 @@ json: {},

url: input.endpoints.devicePoll,
captureCliVersionHeader: true,
json: { deviceCode: input.deviceCode },

@@ -247,0 +252,0 @@ });

@@ -9,2 +9,3 @@ import { headResource, streamRange } from "./http.js";

url: endpoints.download(slug),
captureCliVersionHeader: true,
headers: { authorization: `Bearer ${apiKey}` },

@@ -11,0 +12,0 @@ ...(signal ? { signal } : {}),

@@ -23,2 +23,4 @@ import { API_BASE_ENV } from "./endpoints.js";

" and when that access expires.",
" doctor Diagnose runtime, install, credential, network,",
" environment, and target-storage problems.",
" pull <slug> Download a package this workspace owns. Resumable:",

@@ -33,2 +35,16 @@ " run the same command again to continue. Add --weights",

"",
"DOCTOR OPTIONS",
" --json Write one versioned JSON document to stdout and",
" suppress human narration.",
" --offline Skip every network check, including the authenticated",
" credential check. No request is made.",
" --out DIR Diagnose the directory a later pull will use.",
" Defaults to the current directory.",
"",
"With a valid stored key, doctor makes one authenticated request to validate it.",
"With no readable stored key, that check is skipped and no key is sent.",
"That request updates server-side last-used bookkeeping and consumes one",
"download-route IP rate-limit token. It does not download or presign a file.",
"Doctor never writes, deletes, repairs, or refreshes local state.",
"",
"PULL OPTIONS",

@@ -52,3 +68,3 @@ " --out DIR Where to write the file. Defaults to the current",

" 3 not signed in, denied, expired, or refused by a gated source",
" 4 the workspace does not own it",
" 4 workspace access was removed, or the workspace does not own it",
" 5 network, server, or rate-limit failure, including an origin that will",

@@ -63,2 +79,4 @@ " not serve ranges",

"could not be made. The warning carries that, not the exit code.",
"doctor exits 0 when no check failed. Warnings and skipped checks are not",
"failures. A failed check uses the existing code for its failure family.",
"",

@@ -65,0 +83,0 @@ "Access can also be revoked at any time from Settings, API keys on runinfra.ai.",

+16
-8

@@ -10,3 +10,3 @@ import { request as httpRequest } from "node:http";

const DEFAULT_MAX_REDIRECTS = 5;
function normalizeHeaders(message) {
function normalizeHeaders(message, responseUrl, trustedCliVersionUrl) {
const out = {};

@@ -18,3 +18,11 @@ for (const [name, value] of Object.entries(message.headers)) {

}
recordLatest(out[CLI_LATEST_VERSION_HEADER]);
if (trustedCliVersionUrl !== null) {
try {
if (new URL(responseUrl).origin === new URL(trustedCliVersionUrl).origin) {
recordLatest(out[CLI_LATEST_VERSION_HEADER]);
}
}
catch {
}
}
return out;

@@ -115,3 +123,3 @@ }

}
redirectHeaders.push(normalizeHeaders(message));
redirectHeaders.push(normalizeHeaders(message, currentUrl, options.captureCliVersionHeader === true ? options.url : null));
message.resume();

@@ -159,3 +167,3 @@ let next;

const { message, finalUrl } = await dispatch(options);
const headers = normalizeHeaders(message);
const headers = normalizeHeaders(message, finalUrl, options.captureCliVersionHeader === true ? options.url : null);
const body = await bufferBody(message, finalUrl, options.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES);

@@ -185,3 +193,3 @@ return {

export async function headResource(url, options = {}) {
const { message } = await dispatch({
const { message, finalUrl } = await dispatch({
method: "HEAD",

@@ -198,3 +206,3 @@ url,

status: message.statusCode ?? 0,
headers: normalizeHeaders(message),
headers: normalizeHeaders(message, finalUrl, null),
};

@@ -260,3 +268,3 @@ }

const status = message.statusCode ?? 0;
const headers = normalizeHeaders(message);
const headers = normalizeHeaders(message, finalUrl, null);
if (request.validateResponse) {

@@ -318,3 +326,3 @@ try {

const status = message.statusCode ?? 0;
const headers = normalizeHeaders(message);
const headers = normalizeHeaders(message, finalUrl, null);
if (request.validateResponse) {

@@ -321,0 +329,0 @@ try {

import { parseArgs } from "./args.js";
import { createContext } from "./context.js";
import { doctor } from "./doctor.js";
import { describeError, exitCodeFor, CliError } from "./errors.js";

@@ -19,7 +20,8 @@ import { helpText } from "./help.js";

}
if (parsed.args.command === "help") {
const command = parsed.args.command;
if (command === "help") {
output.result(helpText());
return 0;
}
if (parsed.args.command === "version") {
if (command === "version") {
output.result(`${CLI_NAME} ${CLI_VERSION}`);

@@ -29,2 +31,17 @@ return 0;

const nodeVersion = options.nodeVersion ?? process.versions.node;
const signal = options.signal ?? neverAborted();
if (command === "doctor") {
return await doctor({
output,
env: options.env ?? process.env,
platform: options.platform ?? process.platform,
nodeVersion,
signal,
options: {
json: parsed.args.json,
offline: parsed.args.offline,
out: parsed.args.out,
},
}, options.doctorDeps);
}
if (!isSupportedNodeVersion(nodeVersion)) {

@@ -34,3 +51,2 @@ output.error(`Node ${MINIMUM_NODE_MAJOR} or newer is required, found ${nodeVersion}.`);

}
const signal = options.signal ?? neverAborted();
try {

@@ -43,3 +59,3 @@ const context = createContext({

let exitCode;
switch (parsed.args.command) {
switch (command) {
case "login":

@@ -46,0 +62,0 @@ exitCode = await login(context, { device: parsed.args.device });

@@ -9,1 +9,13 @@ export function redact(secret) {

}
export function redactToPrefix(secret, prefix) {
const value = secret.trim();
const visible = prefix.trim();
if (visible.length === 0 ||
visible.length > 12 ||
!/^[A-Za-z0-9_-]+$/u.test(visible) ||
!value.startsWith(visible) ||
value.length - visible.length < 8) {
return "********";
}
return `${visible}...`;
}

@@ -84,2 +84,34 @@ import { chmod, mkdir, open, readFile, rename, rm, writeFile, } from "node:fs/promises";

}
export function latestVersionSeen() {
return latestSeen;
}
export function detectInstallChannel(input) {
const declared = input.env.RUNINFRA_DIST_CHANNEL?.trim();
if (declared === PYPI_CHANNEL)
return "pypi";
if (declared === "npm")
return "npm";
if (declared === "standalone")
return "standalone";
if (declared !== undefined && declared.length > 0)
return "unknown";
if (input.versions.bun !== undefined)
return "standalone";
if (input.versions.node !== undefined && input.nodeFallback === "npm") {
return "npm";
}
return "unknown";
}
export function upgradeCommandFor(channel, platform) {
switch (channel) {
case "pypi":
return "pip install --upgrade runinfra-cli";
case "standalone":
return platform === "win32" ? WINDOWS_INSTALLER : POSIX_INSTALLER;
case "npm":
return "npm install -g @runinfra/cli@latest";
case "unknown":
return null;
}
}
export function __resetLatestForTest() {

@@ -141,10 +173,11 @@ latestSeen = null;

function updateMessage(latest, env, platform, versions) {
if (env.RUNINFRA_DIST_CHANNEL === PYPI_CHANNEL) {
return `RunInfra CLI ${latest} is available. Upgrade: pip install --upgrade runinfra-cli`;
const channel = detectInstallChannel({ env, versions, nodeFallback: "npm" });
const command = upgradeCommandFor(channel, platform);
if (channel === "standalone" && command !== null) {
return `RunInfra CLI ${latest} is available. Re-run the RunInfra standalone installer: ${command}`;
}
if (versions.bun !== undefined) {
const installer = platform === "win32" ? WINDOWS_INSTALLER : POSIX_INSTALLER;
return `RunInfra CLI ${latest} is available. Re-run the RunInfra standalone installer: ${installer}`;
if (command !== null) {
return `RunInfra CLI ${latest} is available. Upgrade: ${command}`;
}
return `RunInfra CLI ${latest} is available. Upgrade: npm install -g @runinfra/cli@latest`;
return `RunInfra CLI ${latest} is available. Reinstall it with the same channel that installed this copy.`;
}

@@ -151,0 +184,0 @@ async function persistState(file, temp, state, platform) {

export const CLI_NAME = "runinfra";
export const CLI_PACKAGE = "@runinfra/cli";
export const CLI_VERSION = "0.2.3";
export const CLI_VERSION = "0.2.4";
export const CLI_CLIENT_ID = "runinfra-cli";

@@ -5,0 +5,0 @@ export const MINIMUM_NODE_MAJOR = 20;

{
"name": "@runinfra/cli",
"version": "0.2.3",
"version": "0.2.4",
"description": "RunInfra CLI: browser-approved sign-in and resumable downloads for optimized model packages",

@@ -5,0 +5,0 @@ "license": "SEE LICENSE IN LICENSE",

@@ -170,3 +170,4 @@ # @runinfra/cli

- **It never prints the key.** `whoami` and `logout` show a redacted form
(`rp_k...8fq2`). No other code path renders it.
(`rp_k...8fq2`). `doctor` shows only the server-issued visible prefix and no
suffix. No code path renders the full key.
- **The key it holds cannot spend money.** CLI keys carry `purpose = 'cli'`.

@@ -176,2 +177,6 @@ The inference gateway refuses every purpose that is not `customer`, so a

exactly one door: downloading a package your workspace already owns.
- **It sends no telemetry.** `doctor` is a report the user chooses to run and
paste. It writes nothing to local disk and transmits no report. When a valid
local credential is present, its one authenticated request only asks whether
that credential still works.

@@ -188,5 +193,43 @@ ---

| `runinfra whoami` | Shows what this machine has stored, and when its access expires. |
| `runinfra doctor [--json] [--offline] [--out DIR]` | Diagnoses this runtime, credential, network access, environment, and pull target without repairing or deleting anything. |
---
## `runinfra doctor`
```console
$ runinfra doctor --out /data/models
```
Human mode writes an aligned report to stderr and nothing to stdout. `--json`
writes exactly one versioned JSON document to stdout and suppresses narration,
so an agent can parse and branch on the result without scraping terminal text.
Doctor never writes, deletes, repairs, refreshes, or rotates local state. It
does not remove partial downloads. When it finds resumable `.part` files or
recipe-weight resume records, it names them, reports their logical size, and
shows a command the user may choose to run after deciding not to resume.
Without `--offline`, doctor makes exactly one authenticated request when a valid
local credential is available, to answer whether it is valid, expired, revoked,
or belongs to a workspace the user can no longer access. With no readable local
credential, that check is skipped and no authenticated request is made. The
request uses an intentionally invalid catalog slug: authentication runs first,
then slug validation stops the request before entitlement lookup or presigning.
It updates the key's server-side `lastUsedAt` bookkeeping and consumes one token
from the catalog download IP rate limit. It does not download anything and does
not change state the user can observe or would need preserved for a bug report.
`--offline` skips that request and every other network check. The JSON entries
for `install.version`, `auth.server`, `network.api`, and
`network.huggingface` then have status `skip`.
Warnings do not make the command fail. A missing `HF_TOKEN`, an unreachable
Hugging Face origin, low space under the documented large-pull heuristic, and
an auth-server timeout are warnings because none proves the requested package
cannot work. A typed credential rejection is a failure. The first failed check
in stable report order selects its exit code from the table below.
---
## `runinfra login`

@@ -610,3 +653,3 @@

| 3 | Not signed in, denied, expired, revoked, or refused by a gated Hugging Face source | After fixing authentication or source access |
| 4 | The workspace does not own the package, or its files are not published yet | No |
| 4 | Workspace access was removed, the workspace does not own the package, or its files are not published yet | No |
| 5 | Network, server, or rate-limit failure, including an origin that advertises byte ranges and then will not serve them | Yes |

@@ -624,2 +667,7 @@ | 6 | Integrity failure: checksum mismatch, wrong pinned revision, a 206 that did not describe the requested range, or the artifact changed mid-download | Start over |

`runinfra doctor` is `0` whenever no check has status `fail`. Warnings and
skipped checks remain machine-visible in the report but do not turn information
into an error. If checks fail, the first failure in the stable check order uses
the existing code for that failure family.
Two of these rows were wrong until they were measured against what the client

@@ -676,2 +724,9 @@ actually does, and both errors pointed a script at the wrong recovery. An

Doctor uses the existing download route for its single authenticated
credential check, with the intentionally invalid slug `__runinfra_doctor__`.
The route authenticates before validating the slug, so a valid credential gets
the ordinary `not_found` envelope without entitlement lookup or a presigned
URL. The route's IP limiter runs before key validation, so every online doctor
run consumes one limiter token even when the credential is rejected.
### Refusal envelope

@@ -678,0 +733,0 @@