diff --git a/runner/configuration/constants.ts b/runner/configuration/constants.ts index f74c5bf..f22ae3a 100644 --- a/runner/configuration/constants.ts +++ b/runner/configuration/constants.ts @@ -23,6 +23,15 @@ export const DEFAULT_SUMMARY_MODEL = 'gemini-2.5-flash-lite'; /** Name of the root folder where we store LLM-generated code for debugging */ export const LLM_OUTPUT_DIR = join(rootDir, 'llm-output'); +/** + * Path for WCS temporary directories. + * + * We want temporary workspaces to be nested inside the root project to + * better support symlinked node modules. E.g. Turbopack will otherwise + * fail if symlinked node modules are not reachable via parent directories. + */ +export const WCS_BASE_TMP_DIR = join(rootDir, 'tmp-workspaces'); + /** * Number of times we'll try to ask LLM to repair a build failure, * providing the build output and the code that causes the problem. diff --git a/runner/orchestration/file-system.ts b/runner/orchestration/file-system.ts index 74f48a3..eaad517 100644 --- a/runner/orchestration/file-system.ts +++ b/runner/orchestration/file-system.ts @@ -1,5 +1,4 @@ -import {tmpdir} from 'os'; -import {LLM_OUTPUT_DIR} from '../configuration/constants.js'; +import {LLM_OUTPUT_DIR, WCS_BASE_TMP_DIR} from '../configuration/constants.js'; import {Environment} from '../configuration/environment.js'; import { copyFolderExcept, @@ -25,6 +24,7 @@ const PENDING_INSTALLS = new Map>(); * @param env Environment that is currently being run. * @param rootPromptDef Definition of the root prompt. * @param progress Logger to use to log out the current progress. + * @param tmpdirBasePath Base path for temporary directories (like `/tmp`). * @param outputDirectory Custom output directory specified by the user. * @returns Temporary directory in which to build and a function used to clean in up. */ @@ -32,6 +32,7 @@ export async function setupProjectStructure( env: Environment, rootPromptDef: RootPromptDefinition, progress: ProgressLogger, + tmpdirBasePath: string = WCS_BASE_TMP_DIR, outputDirectory?: string, ) { let directory: string; @@ -48,7 +49,8 @@ export async function setupProjectStructure( cleanup = () => Promise.resolve(); } else { // When outputting to the temporary directory, make sure that the directory is unique. - directory = await mkdtemp(join(tmpdir(), `fw-${env.id}-build-${rootPromptDef.name}`)); + await mkdir(tmpdirBasePath, {recursive: true}); + directory = await mkdtemp(join(tmpdirBasePath, `fw-${env.id}-build-${rootPromptDef.name}`)); cleanup = async () => { try {