Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ tests/**/package-lock.json
coverage/
.env
go.sum
dev/.cache/
112 changes: 109 additions & 3 deletions dev/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@
* SPDX-License-Identifier: Apache-2.0
*/
import esbuild from 'esbuild';
import {cp, writeFile} from 'node:fs/promises';
import {execSync} from 'node:child_process';
import {createWriteStream, existsSync, unlink} from 'node:fs';
import {mkdir, readFile, rm, writeFile} from 'node:fs/promises';
import * as https from 'node:https';
import * as path from 'node:path';
import {fileURLToPath} from 'node:url';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import {shimPlugin} from 'esbuild-shim-plugin';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const ADK_WEB_VERSION = 'v1.0.0';
const cacheDir = path.join(__dirname, '.cache');
const zipCachePath = path.join(cacheDir, `adk-web-${ADK_WEB_VERSION}.zip`);

const licenseHeaderText = `/**
* @license
* Copyright 2026 Google LLC
Expand All @@ -26,6 +38,101 @@ const commonOptions = {
sourcemap: false,
};

function downloadFile(url, dest) {
return new Promise((resolve, reject) => {
const request = https.get(url, (response) => {
if (
response.statusCode &&
response.statusCode >= 300 &&
response.statusCode < 400 &&
response.headers.location
) {
// Follow redirect
downloadFile(response.headers.location, dest)
.then(resolve)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call response.resume() before recursing/returning here to ensure the redirected response stream is fully consumed and socket resources are released.

.catch(reject);
return;
}

if (response.statusCode !== 200) {
reject(
new Error(
`Failed to get '${url}' (status code: ${response.statusCode})`,
),
);
return;
}

const file = createWriteStream(dest);
response.pipe(file);
file.on('finish', () => {
file.close();
resolve(undefined);
});
file.on('error', (err) => {
unlink(dest, () => reject(err));
});
});

request.on('error', (err) => {
unlink(dest, () => reject(err));
});
});
}

function unzipFile(zipPath, destDir) {
if (process.platform === 'win32') {
execSync(
`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`,
);
} else {
execSync(`unzip -o "${zipPath}" -d "${destDir}"`);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since adm-zip was recently added to the core workspace dependencies, we can use it here as a platform-independent JS library for unzipping, instead of spawning child processes for unzip (which might be missing on minimal Linux environments) or powershell (which can have execution policies block it):

import AdmZip from 'adm-zip';

function unzipFile(zipPath, destDir) {
  const zip = new AdmZip(zipPath);
  zip.extractAllTo(destDir, true);
}

Make sure to add adm-zip to the dev package dependencies/devDependencies too.

}

async function ensureBrowserAssets() {
const browserOutputDir = path.join(__dirname, 'dist/browser');
const versionFile = path.join(browserOutputDir, '.version');

let needPopulate = false;

if (!existsSync(browserOutputDir)) {
needPopulate = true;
} else {
try {
const version = (await readFile(versionFile, 'utf8')).trim();
if (version !== ADK_WEB_VERSION) needPopulate = true;
} catch {
needPopulate = true;
}
}

if (needPopulate) {
if (!existsSync(zipCachePath)) {
console.log(
`[ADK Build] ADK Web zip not cached. Fetching ${ADK_WEB_VERSION} from GitHub...`,
);
if (!existsSync(cacheDir)) {
await mkdir(cacheDir, {recursive: true});
}
const url = `https://github.com/google/adk-web/releases/download/${ADK_WEB_VERSION}/adk-web-browser.zip`;
await downloadFile(url, zipCachePath);
console.log(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To prevent corrupt cache files if the download gets interrupted mid-way (which would skip downloads and fail during unzipping on subsequent runs), consider downloading to a temporary file (e.g. zipCachePath + '.tmp') and renaming it to zipCachePath only after completion.

`[ADK Build] Downloaded and cached ADK Web ${ADK_WEB_VERSION}.`,
);
}

console.log(`[ADK Build] Extracting ADK Web assets to dist/browser...`);
if (existsSync(browserOutputDir)) {
await rm(browserOutputDir, {recursive: true, force: true});
}
await mkdir(browserOutputDir, {recursive: true});
unzipFile(zipCachePath, browserOutputDir);
await writeFile(versionFile, ADK_WEB_VERSION, 'utf8');
console.log(`[ADK Build] ADK Web assets successfully populated.`);
}
}

/**
* Builds the ADK devtools library.
*/
Expand All @@ -52,8 +159,7 @@ async function main() {

// Run file operations sequentially to avoid race conditions
await writeFile('./dist/cjs/package.json', '{"type": "commonjs"}');
await cp('./src/browser', './dist/esm/browser', {recursive: true});
await cp('./src/browser', './dist/cjs/browser', {recursive: true});
await ensureBrowserAssets();
}

main().catch((err) => {
Expand Down
17 changes: 0 additions & 17 deletions dev/src/browser/adk_favicon.svg

This file was deleted.

9 changes: 0 additions & 9 deletions dev/src/browser/assets/ADK-512-color.svg

This file was deleted.

52 changes: 0 additions & 52 deletions dev/src/browser/assets/audio-processor.js

This file was deleted.

3 changes: 0 additions & 3 deletions dev/src/browser/assets/config/runtime-config.json

This file was deleted.

17 changes: 0 additions & 17 deletions dev/src/browser/chunk-EQDQRRRY.js

This file was deleted.

Loading
Loading