Skip to content

fix(llm_agent): add duck typing fallback for BaseLlm in bundled environments#35

Closed
Alex980102 wants to merge 1 commit intogoogle:mainfrom
Alex980102:fix/bundling-instanceof-basellm
Closed

fix(llm_agent): add duck typing fallback for BaseLlm in bundled environments#35
Alex980102 wants to merge 1 commit intogoogle:mainfrom
Alex980102:fix/bundling-instanceof-basellm

Conversation

@Alex980102
Copy link

@Alex980102 Alex980102 commented Dec 22, 2025

Summary

This PR fixes an issue where custom BaseLlm subclasses fail to be recognized in bundled environments.

Fixes #36

Problem

When packages are bundled (e.g., with adk-devtools, webpack, esbuild), the BaseLlm class identity differs between the bundled code and external packages. This causes instanceof BaseLlm to return false for valid subclasses, resulting in:

Error: No model found for {agent_name}

Solution

Add a duck typing fallback in canonicalModel getter that checks for required BaseLlm properties when instanceof fails.

Testing

  • Build passes
  • All 150 tests pass

Related

@google-cla
Copy link

google-cla bot commented Dec 22, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@Alex980102 Alex980102 force-pushed the fix/bundling-instanceof-basellm branch from 3574f3c to 0468123 Compare December 22, 2025 02:19
…onments

When packages are bundled (e.g., with esbuild, webpack), the BaseLlm class
identity may differ between the bundled code and external packages, causing
instanceof to fail. This duck-type check ensures compatibility.
@Alex980102 Alex980102 force-pushed the fix/bundling-instanceof-basellm branch from 0468123 to 4213492 Compare December 22, 2025 02:37
Alex980102 added a commit to pailat/adk-llm-bridge that referenced this pull request Dec 22, 2025
- Move LLMRegistry.register() pattern to Quick Start (stable)
- Add 'Known Issue' section explaining instanceof bundling problem
- Link to upstream PR google/adk-js#35
- Mark AIGateway() direct usage with workaround reference
- Examples already use the stable pattern
Alex980102 added a commit to pailat/adk-llm-bridge that referenced this pull request Dec 22, 2025
- Move LLMRegistry.register() pattern to Quick Start (stable)
- Add 'Known Issue' section explaining instanceof bundling problem
- Link to upstream PR google/adk-js#35
- Mark AIGateway() direct usage with workaround reference
- Examples already use the stable pattern
Comment on lines 781 to +790
if (this.model instanceof BaseLlm) {
return this.model;
}
// Duck typing fallback for bundled environments where instanceof fails.
if (this.model && typeof this.model === 'object' &&
'model' in this.model &&
'generateContentAsync' in this.model &&
typeof (this.model as BaseLlm).generateContentAsync === 'function') {
return this.model as BaseLlm;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I was thinking of another a bit more robust approach here using the symbols.

in the BaseLlm:

const BASE_MODEL_SYMBOL = Symbol('baseModel');

export function isBaseLlm(obj: unknown): obj is BaseLlm {
  return typeof obj === 'object' && obj !== null && BASE_MODEL_SYMBOL in obj && obj[BASE_MODEL_SYMBOL] === true;
}

/**
 * The BaseLLM class.
 */
export abstract class BaseLlm {
  readonly [BASE_MODEL_SYMBOL] = true;
  // ...
}

Then use the isBaseLlm function here:

Suggested change
if (this.model instanceof BaseLlm) {
return this.model;
}
// Duck typing fallback for bundled environments where instanceof fails.
if (this.model && typeof this.model === 'object' &&
'model' in this.model &&
'generateContentAsync' in this.model &&
typeof (this.model as BaseLlm).generateContentAsync === 'function') {
return this.model as BaseLlm;
}
if (isBaseLlm(this.model)) {
return this.model;
}

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the feedback, @kalenkevich! I see the Symbol approach with isBaseLlm() is already implemented in main. Should I close this PR since the fix is already in place?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hello, sorry forgot to mention it here.

Yes please, close the PR. Thanks for your issue.

@Alex980102 Alex980102 closed this Dec 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Custom BaseLlm subclasses fail with "No model found" in bundled environments

2 participants