diff --git a/container/entrypoint.sh b/container/entrypoint.sh index 623d6a76ef3..2d627abe908 100755 --- a/container/entrypoint.sh +++ b/container/entrypoint.sh @@ -7,6 +7,13 @@ set -e # Cap JS heap to prevent OOM export NODE_OPTIONS="--max-old-space-size=2048" +# Cap Go heap for tsgo (TypeScript native compiler) — Go doesn't auto-detect +# container memory limits, so without this tsgo allocates unbounded memory and hangs. +# Set to 75% of available RAM, leaving headroom for OS + other processes. +# See: https://github.com/microsoft/typescript-go/issues/2125 +TOTAL_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}') +export GOMEMLIMIT=$(( TOTAL_KB * 3 / 4 / 1024 ))MiB + # Configure git with GitHub token if [ -n "$GITHUB_TOKEN" ]; then gh auth setup-git 2>/dev/null || true diff --git a/src/backends/local-backend.ts b/src/backends/local-backend.ts index 1d5d36ddce9..3bbed9a5586 100644 --- a/src/backends/local-backend.ts +++ b/src/backends/local-backend.ts @@ -12,6 +12,7 @@ import path from 'path'; import { CONTAINER_IMAGE, CONTAINER_MAX_OUTPUT_SIZE, + CONTAINER_MEMORY, CONTAINER_STARTUP_TIMEOUT, CONTAINER_TIMEOUT, DATA_DIR, @@ -231,7 +232,7 @@ function buildVolumeMounts( } function buildContainerArgs(mounts: VolumeMount[], containerName: string): string[] { - const args: string[] = ['run', '-i', '--rm', '--name', containerName]; + const args: string[] = ['run', '-i', '--rm', '--memory', CONTAINER_MEMORY, '--name', containerName]; for (const mount of mounts) { if (mount.readonly) { diff --git a/src/config.ts b/src/config.ts index 4846557b6f9..fc68ef98090 100644 --- a/src/config.ts +++ b/src/config.ts @@ -29,6 +29,7 @@ export const MAIN_GROUP_FOLDER = 'main'; export const CONTAINER_IMAGE = process.env.CONTAINER_IMAGE || 'nanoclaw-agent:latest'; +export const CONTAINER_MEMORY = process.env.CONTAINER_MEMORY || '4G'; export const CONTAINER_TIMEOUT = parseInt( process.env.CONTAINER_TIMEOUT || '1800000', 10,