Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/lib/agent-onboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
import fs from "fs";
import os from "os";
import path from "path";
import { spawnSync } from "child_process";

import { ROOT, run, shellQuote } from "./runner";
import { loadAgent, resolveAgentName, type AgentDefinition } from "./agent-defs";
import { getProviderSelectionConfig } from "./inference-config";
import * as onboardSession from "./onboard-session";
import { sleepSeconds } from "./wait";

export interface OnboardContext {
step: (current: number, total: number, message: string) => void;
Expand Down Expand Up @@ -100,7 +100,7 @@ export function getAgentPermissivePolicyPath(agent: AgentDefinition): string | n
}

function sleep(seconds: number): void {
spawnSync("sleep", [String(seconds)]);
sleepSeconds(seconds);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/lib/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ export async function executeDeploy(opts: DeployExecutionOptions): Promise<void>
return fail([` Timed out waiting for Brev instance readiness for ${name}`], error, exit);
}
stdoutWrite(".");
spawnSync("sleep", ["3"]);
sleepSeconds(3);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

// ── SSH trust-on-first-use (TOFU) ──────────────────────────────
Expand Down Expand Up @@ -371,7 +371,7 @@ export async function executeDeploy(opts: DeployExecutionOptions): Promise<void>
);
}
stdoutWrite(".");
spawnSync("sleep", ["3"]);
sleepSeconds(3);
}

const sshOpts = buildSshOpts(knownHostsFile, shellQuote);
Expand Down
4 changes: 3 additions & 1 deletion src/lib/nim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { run, runCapture } = require("./runner");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { sleepSeconds } = require("./wait");
// eslint-disable-next-line @typescript-eslint/no-require-imports
const nimImages = require("../../bin/lib/nim-images.json");

import { VLLM_PORT } from "./ports";
Expand Down Expand Up @@ -231,7 +233,7 @@ export function waitForNimHealth(port = VLLM_PORT, timeout = 300): boolean {
/* ignored */
}
// eslint-disable-next-line @typescript-eslint/no-require-imports
require("child_process").spawnSync("sleep", [String(intervalSec)]);
sleepSeconds(intervalSec);
}
console.error(` NIM did not become healthy within ${timeout}s.`);
return false;
Expand Down
3 changes: 3 additions & 0 deletions src/lib/onboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ const {
// Shared constant so getSuggestedPolicyPresets() and setupPoliciesWithSelection()
// stay in sync.
const LOCAL_INFERENCE_PROVIDERS = ["ollama-local", "vllm-local"];
const {
sleepSeconds,
} = require("./wait");
Comment thread
ksapru marked this conversation as resolved.
const { inferContainerRuntime, isWsl, shouldPatchCoredns } = require("./platform");
const { resolveOpenshell } = require("./resolve-openshell");
const {
Expand Down
23 changes: 23 additions & 0 deletions src/lib/wait.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

/**
* Synchronous waiting primitives for CLI commands.
*/

/**
* Synchronously sleep for the given number of milliseconds.
* Uses Atomics.wait to block without pegging the CPU.
*/
export function sleepMs(ms: number): void {
if (ms <= 0) return;
const buffer = new Int32Array(new SharedArrayBuffer(4));
Atomics.wait(buffer, 0, 0, ms);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* Synchronously sleep for the given number of seconds.
*/
export function sleepSeconds(seconds: number): void {
sleepMs(seconds * 1000);
}
3 changes: 2 additions & 1 deletion src/nemoclaw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const sandboxVersion = require("./lib/sandbox-version");
const sandboxState = require("./lib/sandbox-state");
const { ensureOllamaAuthProxy } = require("./lib/onboard");
const skillInstall = require("./lib/skill-install");
const { sleepSeconds } = require("./lib/wait");

// ── Global commands ──────────────────────────────────────────────

Expand Down Expand Up @@ -316,7 +317,7 @@ function checkAndRecoverSandboxProcesses(sandboxName, { quiet = false } = {}) {
const recovered = recoverSandboxProcesses(sandboxName);
if (recovered) {
// Wait for gateway to bind its HTTP port before declaring success
spawnSync("sleep", ["3"]);
sleepSeconds(3);
if (isSandboxGatewayRunning(sandboxName) !== true) {
// Gateway process started but HTTP endpoint never came up
if (!quiet) {
Expand Down
38 changes: 38 additions & 0 deletions test/wait.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

import assert from "node:assert";
import { describe, expect, it } from "vitest";
import { sleepMs, sleepSeconds } from "../src/lib/wait.ts";

describe("wait utility", () => {
it("sleepMs blocks for approximately the requested time", () => {
const start = Date.now();
sleepMs(100);
const end = Date.now();
const duration = end - start;

// Allow for some jitter, but should be at least 100ms and not excessively more.
assert.ok(duration >= 100, `duration ${duration}ms < 100ms`);
assert.ok(duration < 200, `duration ${duration}ms > 200ms`);
});

it("sleepSeconds blocks for approximately the requested time", () => {
const start = Date.now();
sleepSeconds(0.1);
const end = Date.now();
const duration = end - start;

assert.ok(duration >= 100, `duration ${duration}ms < 100ms`);
assert.ok(duration < 200, `duration ${duration}ms > 200ms`);
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.

it("returns immediately for zero or negative time", () => {
const start = Date.now();
sleepMs(0);
sleepMs(-50);
const end = Date.now();
const duration = end - start;
assert.ok(duration < 50, `duration ${duration}ms > 50ms`);
});
});