Build agent images asynchronously instead of blocking the host

Replace the execSync docker build in buildAgentGroupImage with an awaited
promisified exec so the single-threaded host stays responsive during the
image build (up to 15 minutes) that a package-install approval or
`ncl groups restart --rebuild` triggers. Timeout, buffered stdio, and
non-zero-exit error propagation are preserved; both callers already await.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
gavrielc
2026-07-04 16:04:56 +03:00
parent aecad864e6
commit e3b2ffce36
+9 -3
View File
@@ -3,9 +3,10 @@
* Spawns agent containers with session folder + agent group folder mounts.
* The container runs the v2 agent-runner which polls the session DB.
*/
import { ChildProcess, execSync, spawn } from 'child_process';
import { ChildProcess, exec, spawn } from 'child_process';
import fs from 'fs';
import path from 'path';
import { promisify } from 'util';
import { OneCLI } from '@onecli-sh/sdk';
@@ -510,6 +511,8 @@ async function buildContainerArgs(
return args;
}
const execAsync = promisify(exec);
/** Build a per-agent-group Docker image with custom packages. */
export async function buildAgentGroupImage(agentGroupId: string): Promise<void> {
const agentGroup = getAgentGroup(agentGroupId);
@@ -545,9 +548,12 @@ export async function buildAgentGroupImage(agentGroupId: string): Promise<void>
const tmpDockerfile = path.join(DATA_DIR, `Dockerfile.${agentGroupId}`);
fs.writeFileSync(tmpDockerfile, dockerfile);
try {
execSync(`${CONTAINER_RUNTIME_BIN} build -t ${imageTag} -f ${tmpDockerfile} .`, {
// Awaited async exec so the single-threaded host stays responsive during
// the build (can take minutes) instead of blocking on execSync. exec buffers
// stdout/stderr (matching the old stdio: 'pipe') and rejects on a non-zero
// exit, so error propagation is unchanged.
await execAsync(`${CONTAINER_RUNTIME_BIN} build -t ${imageTag} -f ${tmpDockerfile} .`, {
cwd: DATA_DIR,
stdio: 'pipe',
timeout: 900_000,
});
} finally {