Part of #607.
Describe the bug
dist/web/models/apigee_llm.js contains invalid JavaScript. Any browser bundler that reaches it fails to parse:
✘ [ERROR] Unexpected "super"
node_modules/@google/adk/dist/web/models/apigee_llm.js:141:25:
141 │ yield* __yieldStar(super.generateContentAsync(llmRequest, s...
╵ ~~~~~
This is unavoidable for every browser consumer: LlmAgent → models/registry.js → apigee_llm.js. Importing LlmAgent, or anything from the web barrel, pulls it in.
It is also not fixable by consumer configuration, unlike the other defects in #607. It is a syntax error; no bundler flag makes a parser accept it. The only consumer-side options are patch-package or aliasing the module to a stub.
Root cause
core/src/models/apigee_llm.ts:142-149:
override async *generateContentAsync(
...
): AsyncGenerator<LlmResponse, void> {
...
yield* super.generateContentAsync(llmRequest, stream, abortSignal);
}
That source is perfectly valid. The problem is the browser build target in core/build.js:9-12:
const platformBuildTargets = {
'node': ['node10.4'],
'browser': ['chrome58', 'firefox57', 'safari11'], // <-- here
};
Native async generators require Chrome 63 / Safari 12. Because the target names Chrome 58 and Safari 11, esbuild downlevels the method into an __asyncGenerator closure — and super is not valid inside that closure. esbuild emits the broken output without complaint at build time; the failure surfaces later, in the consumer's bundler.
To Reproduce
Minimal, self-contained — reproduces both the break and the fix:
// repro.ts
class Base {
async *gen(): AsyncGenerator<number, void> { yield 1; }
}
export class Child extends Base {
override async *gen(): AsyncGenerator<number, void> {
yield* super.gen();
}
}
# Step 1: build the way ADK builds its web output
npx esbuild repro.ts --target=chrome58 --format=esm --outfile=out58.js
npx esbuild repro.ts --target=chrome63 --format=esm --outfile=out63.js
grep -c __yieldStar out58.js # 1 -> downlevelled, contains `super` in a closure
grep -c __yieldStar out63.js # 0 -> native async generator
# Step 2: consume it, the way an app bundles @google/adk
echo "import {Child} from './out58.js'; console.log(Child);" > c58.js
echo "import {Child} from './out63.js'; console.log(Child);" > c63.js
npx esbuild c58.js --bundle --platform=browser --outfile=/dev/null
# ✘ [ERROR] Unexpected "super"
npx esbuild c63.js --bundle --platform=browser --outfile=/dev/null
# ⚡ Done — bundles cleanly
I verified each of chrome58, safari11, chrome63, safari12 individually: the first two downlevel and break, the second two are native and fine.
Expected behavior
dist/web/** should be parseable by standard bundlers.
Proposed fix
core/build.js:9-12 — raise the browser targets to the first versions with native async generator support:
const platformBuildTargets = {
'node': ['node10.4'],
- 'browser': ['chrome58', 'firefox57', 'safari11'],
+ // Async generators are native from Chrome 63 / Safari 12. Targeting older
+ // versions makes esbuild downlevel them into a closure, which emits invalid
+ // `super` references (see models/apigee_llm.ts) that consumers cannot parse.
+ 'browser': ['chrome63', 'firefox57', 'safari12'],
};
Chrome 58 (2017) and Safari 11 (2017) are well below any plausible support floor for this library — the built-in AI APIs ADK's web build is most useful with require Chrome 138+.
An alternative fix is to refactor apigee_llm.ts to avoid super inside the generator (e.g. assign const parent = super.generateContentAsync.bind(this) outside, or call AsyncGenerator delegation via a helper). That works too, but only papers over the target problem — any future super inside an async generator reintroduces it. I'd suggest doing the target bump regardless, and the refactor only if the old targets must be kept.
Suggested regression test
npx esbuild dist/web/index_web.js --bundle --platform=browser --outfile=/dev/null
Fails today, passes after the change. core/test has no browser-bundle test currently.
Environment
@google/adk main @ 8944bfb, core v1.5.0 (also reproduced on published 1.4.0)
- esbuild 0.25.x, Node 22
Part of #607.
Describe the bug
dist/web/models/apigee_llm.jscontains invalid JavaScript. Any browser bundler that reaches it fails to parse:This is unavoidable for every browser consumer:
LlmAgent→models/registry.js→apigee_llm.js. ImportingLlmAgent, or anything from the web barrel, pulls it in.It is also not fixable by consumer configuration, unlike the other defects in #607. It is a syntax error; no bundler flag makes a parser accept it. The only consumer-side options are
patch-packageor aliasing the module to a stub.Root cause
core/src/models/apigee_llm.ts:142-149:That source is perfectly valid. The problem is the browser build target in
core/build.js:9-12:Native async generators require Chrome 63 / Safari 12. Because the target names Chrome 58 and Safari 11, esbuild downlevels the method into an
__asyncGeneratorclosure — andsuperis not valid inside that closure. esbuild emits the broken output without complaint at build time; the failure surfaces later, in the consumer's bundler.To Reproduce
Minimal, self-contained — reproduces both the break and the fix:
I verified each of
chrome58,safari11,chrome63,safari12individually: the first two downlevel and break, the second two are native and fine.Expected behavior
dist/web/**should be parseable by standard bundlers.Proposed fix
core/build.js:9-12— raise the browser targets to the first versions with native async generator support:const platformBuildTargets = { 'node': ['node10.4'], - 'browser': ['chrome58', 'firefox57', 'safari11'], + // Async generators are native from Chrome 63 / Safari 12. Targeting older + // versions makes esbuild downlevel them into a closure, which emits invalid + // `super` references (see models/apigee_llm.ts) that consumers cannot parse. + 'browser': ['chrome63', 'firefox57', 'safari12'], };Chrome 58 (2017) and Safari 11 (2017) are well below any plausible support floor for this library — the built-in AI APIs ADK's web build is most useful with require Chrome 138+.
An alternative fix is to refactor
apigee_llm.tsto avoidsuperinside the generator (e.g. assignconst parent = super.generateContentAsync.bind(this)outside, or callAsyncGeneratordelegation via a helper). That works too, but only papers over the target problem — any futuresuperinside an async generator reintroduces it. I'd suggest doing the target bump regardless, and the refactor only if the old targets must be kept.Suggested regression test
Fails today, passes after the change.
core/testhas no browser-bundle test currently.Environment
@google/adkmain@8944bfb,corev1.5.0 (also reproduced on published 1.4.0)