summaryrefslogtreecommitdiff
path: root/packages/cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src')
-rw-r--r--packages/cli/src/utils/sandbox.ts114
1 files changed, 110 insertions, 4 deletions
diff --git a/packages/cli/src/utils/sandbox.ts b/packages/cli/src/utils/sandbox.ts
index 740b75d1..7b734e89 100644
--- a/packages/cli/src/utils/sandbox.ts
+++ b/packages/cli/src/utils/sandbox.ts
@@ -303,11 +303,13 @@ export async function start_sandbox(sandbox: string) {
}
// stop if image is missing
- if (!execSync(`${sandbox} images -q ${image}`).toString().trim()) {
+ if (!(await ensureSandboxImageIsPresent(sandbox, image))) {
const remedy = gcPath.includes('gemini-code/packages/')
- ? 'Try `scripts/build_sandbox.sh` under gemini-code repo.'
- : 'Please notify [email protected].';
- console.error(`ERROR: ${image} is missing. ${remedy}`);
+ ? 'Try running `BUILD_SANDBOX=1 gemini` or `scripts/build_sandbox.sh` under the gemini-code repo to build it locally, or check the image name and your network connection.'
+ : 'Please check the image name, your network connection, or notify [email protected] if the issue persists.';
+ console.error(
+ `ERROR: Sandbox image '${image}' is missing or could not be pulled. ${remedy}`,
+ );
process.exit(1);
}
@@ -483,3 +485,107 @@ export async function start_sandbox(sandbox: string) {
child.on('close', resolve);
});
}
+
+// Helper functions to ensure sandbox image is present
+async function imageExists(sandbox: string, image: string): Promise<boolean> {
+ return new Promise((resolve) => {
+ const args = ['images', '-q', image];
+ const checkProcess = spawn(sandbox, args);
+
+ let stdoutData = '';
+ if (checkProcess.stdout) {
+ checkProcess.stdout.on('data', (data) => {
+ stdoutData += data.toString();
+ });
+ }
+
+ checkProcess.on('error', (err) => {
+ console.warn(
+ `Failed to start '${sandbox}' command for image check: ${err.message}`,
+ );
+ resolve(false);
+ });
+
+ checkProcess.on('close', (code) => {
+ // Non-zero code might indicate docker daemon not running, etc.
+ // The primary success indicator is non-empty stdoutData.
+ if (code !== 0) {
+ // console.warn(`'${sandbox} images -q ${image}' exited with code ${code}.`);
+ }
+ resolve(stdoutData.trim() !== '');
+ });
+ });
+}
+
+async function pullImage(sandbox: string, image: string): Promise<boolean> {
+ console.info(`Attempting to pull image ${image} using ${sandbox}...`);
+ return new Promise((resolve) => {
+ const args = ['pull', image];
+ const pullProcess = spawn(sandbox, args, { stdio: 'pipe' });
+
+ let stderrData = '';
+ if (pullProcess.stdout) {
+ pullProcess.stdout.on('data', (data) => {
+ console.info(data.toString().trim()); // Show pull progress
+ });
+ }
+ if (pullProcess.stderr) {
+ pullProcess.stderr.on('data', (data) => {
+ stderrData += data.toString();
+ console.error(data.toString().trim()); // Show pull errors/info from the command itself
+ });
+ }
+
+ pullProcess.on('error', (err) => {
+ console.warn(
+ `Failed to start '${sandbox} pull ${image}' command: ${err.message}`,
+ );
+ resolve(false);
+ });
+
+ pullProcess.on('close', (code) => {
+ if (code === 0) {
+ console.info(`Successfully pulled image ${image}.`);
+ resolve(true);
+ } else {
+ console.warn(
+ `Failed to pull image ${image}. '${sandbox} pull ${image}' exited with code ${code}.`,
+ );
+ if (stderrData.trim()) {
+ // Details already printed by the stderr listener above
+ }
+ resolve(false);
+ }
+ });
+ });
+}
+
+async function ensureSandboxImageIsPresent(
+ sandbox: string,
+ image: string,
+): Promise<boolean> {
+ console.info(`Checking for sandbox image: ${image}`);
+ if (await imageExists(sandbox, image)) {
+ console.info(`Sandbox image ${image} found locally.`);
+ return true;
+ }
+
+ console.info(`Sandbox image ${image} not found locally.`);
+ if (await pullImage(sandbox, image)) {
+ // After attempting to pull, check again to be certain
+ if (await imageExists(sandbox, image)) {
+ console.info(`Sandbox image ${image} is now available after pulling.`);
+ return true;
+ } else {
+ console.warn(
+ `Sandbox image ${image} still not found after a pull attempt. This might indicate an issue with the image name or registry, or the pull command reported success but failed to make the image available.`,
+ );
+ return false;
+ }
+ }
+
+ console.error(
+ `Failed to obtain sandbox image ${image} after check and pull attempt.`,
+ );
+ return false; // Pull command failed or image still not present
+}