SPB Git

spb/autoscholar

Public
3.9 KB · 114 lines typescript
1import { execFileSync } from "node:child_process";2import { readFileSync } from "node:fs";3import { createRequire } from "node:module";4import { arch, cpus, hostname, platform, release, totalmem, userInfo } from "node:os";5import type { NodeMetadata } from "@autoscholar/schemas";6import { WORKER_PROTOCOL_VERSION } from "@autoscholar/schemas";78const require = createRequire(import.meta.url);910function tryExec(cmd: string, args: string[]): string | undefined {11  try {12    return execFileSync(cmd, args, {13      encoding: "utf8",14      timeout: 8000,15      stdio: ["ignore", "pipe", "ignore"],16    }).trim();17  } catch {18    return undefined;19  }20}2122export function sdkVersion(): string {23  for (const p of [24    new URL("../node_modules/@anthropic-ai/claude-agent-sdk/package.json", import.meta.url),25    new URL("../../../node_modules/@anthropic-ai/claude-agent-sdk/package.json", import.meta.url),26  ]) {27    try {28      return (JSON.parse(readFileSync(p, "utf8")) as { version: string }).version;29    } catch {30      /* try next */31    }32  }33  try {34    const entry = require.resolve("@anthropic-ai/claude-agent-sdk");35    const m = entry.match(/claude-agent-sdk@(\d+\.\d+\.\d+)/);36    if (m) return m[1]!;37  } catch {38    /* unknown */39  }40  return "unknown";41}4243export function workerVersion(): string {44  try {45    return (46      JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")) as { version: string }47    ).version;48  } catch {49    return "0.0.0";50  }51}5253export function machineId(): string {54  const ioreg = tryExec("/usr/sbin/ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"]);55  const m = ioreg?.match(/"IOPlatformUUID" = "([^"]+)"/);56  return m?.[1] ?? `${hostname()}-${arch()}`;57}5859export function collectNodeMetadata(opts: { simulated: boolean; profiles: string[] }): NodeMetadata {60  const tools: Record<string, string> = {};61  const probe = (name: string, cmd: string, args: string[]) => {62    const v = tryExec(cmd, args);63    if (v) tools[name] = v.split("\n")[0]!.slice(0, 80);64  };65  probe("node", "node", ["--version"]);66  probe("python3", "/opt/homebrew/bin/python3", ["--version"]);67  probe("uv", "/opt/homebrew/bin/uv", ["--version"]);68  probe("tectonic", process.env.TECTONIC_BIN ?? "/opt/homebrew/bin/tectonic", ["--version"]);69  probe("pdftoppm", "/opt/homebrew/bin/pdftoppm", ["-v"]);70  probe("git", "git", ["--version"]);71  probe("R", "/opt/homebrew/bin/Rscript", ["--version"]);72  probe("julia", "/opt/homebrew/bin/julia", ["--version"]);73  tools["claude-agent-sdk"] = sdkVersion();74  const sandboxAvailable =75    platform() === "darwin"76      ? !!tryExec("/usr/bin/sandbox-exec", ["-n", "no-network", "/usr/bin/true"]) ||77        tryExec("/bin/ls", ["/usr/bin/sandbox-exec"]) === "/usr/bin/sandbox-exec"78      : false;79  return {80    machineId: machineId(),81    hostname: hostname(),82    platform: platform(),83    arch: arch(),84    cpuCores: cpus().length,85    memoryBytes: totalmem(),86    osVersion: tryExec("/usr/bin/sw_vers", ["-productVersion"]) ?? release(),87    workerVersion: workerVersion(),88    protocolVersion: WORKER_PROTOCOL_VERSION,89    sdkVersion: sdkVersion(),90    tools,91    profiles: opts.profiles,92    user: userInfo().username,93    sandboxAvailable: opts.simulated ? false : sandboxAvailable,94    ...(opts.simulated ? { simulated: true } : {}),95  } as NodeMetadata;96}9798export function loadAverage(): { load1: number; memFreeBytes: number; diskFreeBytes: number } {99  const load1 = (() => {100    try {101      const { loadavg } = require("node:os") as typeof import("node:os");102      return loadavg()[0] ?? 0;103    } catch {104      return 0;105    }106  })();107  const { freemem } = require("node:os") as typeof import("node:os");108  let diskFreeBytes = 0;109  const df = tryExec("/bin/df", ["-k", process.env.WORKER_ROOT ?? "/"]);110  const line = df?.split("\n")[1];111  if (line) diskFreeBytes = Number(line.split(/\s+/)[3] ?? 0) * 1024;112  return { load1, memFreeBytes: freemem(), diskFreeBytes };113}114
Files · ef05f6361435a2ce0794692497d0c9123d722bef
Menu

Theme