diff --git a/docs/ai.md b/docs/ai.md index d106b0f25..248b54825 100644 --- a/docs/ai.md +++ b/docs/ai.md @@ -4,7 +4,7 @@ # AI Logic -Firebase AI Logic gives you access to the latest generative AI models from Google: the Gemini models and Imagen models. +Firebase AI Logic gives you access to the latest generative AI models from Google: the Gemini models, including the Gemini image models. [Learn more](https://firebase.google.com/docs/ai-logic) diff --git a/docs/version-21-upgrade.md b/docs/version-21-upgrade.md index f163129c0..253b28ea4 100644 --- a/docs/version-21-upgrade.md +++ b/docs/version-21-upgrade.md @@ -32,10 +32,28 @@ The Vertex AI module has been renamed to Firebase AI Logic. The `@angular/fire/v **`getVertexAI` is not a plain rename.** `getAI` already existed alongside it, and a plain `getAI()` call talks to the Gemini Developer API backend, not to Vertex AI. The equivalent of `getVertexAI()` is `getAI(app, { backend: new VertexAIBackend() })`, which is what the migration writes, so your app keeps calling the Vertex AI backend it was configured, enabled, and billed for. A `location` option moves into the `VertexAIBackend` constructor. -`ng update @angular/fire` rewrites these imports and identifiers for you and logs every `getVertexAI` call it rewrites. Code it cannot rewrite safely (for example when the options are not a literal `{ location }` object or that literal references other rewritten symbols, when the function itself is handed around as a value, when a local declaration in the file reuses an imported symbol's name, or when the file already binds `getAI` or `VertexAIBackend` from a source other than AI Logic) is left in place with a warning. The import path itself still moves to the new entry point, so the leftover code fails to compile there, and nothing changes backends silently. A file where a named `getVertexAI` import has any use that cannot be rewritten keeps every use of its named `getVertexAI` imports in place (namespace-style `ns.getVertexAI(...)` calls are judged per call), and each skipped call is logged. `export * from '@angular/fire/vertexai'` is also left alone (rewriting it would silently rename your re-exported public symbols), so replace it with named re-exports by hand. `VertexAIOptions` was removed rather than renamed (the new `AIOptions` takes a `backend` instead of a `location`), so imports of it are left and warned about. Migrate those sites using the table above. `getGenerativeModel` and `getImagenModel` keep their names. +`ng update @angular/fire` rewrites these imports and identifiers for you and logs every `getVertexAI` call it rewrites. `getGenerativeModel` keeps its name. Imports straight from the Firebase SDK (`firebase/vertexai`, gone in SDK 12) are rewritten to `firebase/ai` under the same rules. The rewrite parses your sources with the `typescript` package (an optional peer dependency of `@angular/fire`). Every Angular workspace already has it, but if the migration warns that it could not be resolved, install `typescript` and re-run. See [ai.md](./ai.md) for current usage. +### What the migration will not rewrite + +Code the migration cannot rewrite safely is left in place with a warning. The import path itself still moves to the new entry point, so the leftover code fails to compile there. Nothing changes backends silently. It plays safe like this in four situations: + +- **Options it cannot read:** when the `getVertexAI` call's options are not a literal `{ location }` object, or that literal references other symbols the migration is also rewriting. +- **The function used as a value:** when `getVertexAI` is stored or passed around rather than called directly. +- **Name collisions:** when a local declaration in the file reuses an imported symbol's name, or the file already gets `getAI` or `VertexAIBackend` from a source other than AI Logic. +- **Wildcard re-exports:** when a file has `export * from '@angular/fire/vertexai'`, that line stays as written, because rewriting it would silently rename your re-exported public symbols. Replace it with named re-exports by hand. + +A file where a named `getVertexAI` import is used in a way that cannot be rewritten keeps every use of its named `getVertexAI` imports in place (namespace-style `ns.getVertexAI(...)` calls are judged per call), and each skipped call is logged. + +### Removed symbols + +Two symbols were removed rather than renamed. The migration leaves their imports in place, which breaks loudly, and warns with guidance: + +- `VertexAIOptions`: the new `AIOptions` takes a `backend` instead of a `location`, so rebuild the options by hand using the table above. +- `getImagenModel`: Firebase shut the Imagen models down in August 2026 and removed the API in firebase 12.18 (`@firebase/ai` 2.15), so move image generation to the Gemini image models through [`getGenerativeModel`](https://firebase.google.com/docs/ai-logic/generate-images-gemini). + ## Other notes - **Angular 21 is required.** AngularFire 21 peers `@angular/* ^21.0.0` and does not support Angular 22 (a future AngularFire 22 will). diff --git a/src/ai/firebase.ts b/src/ai/firebase.ts index 9ca7d8e6a..55d66b595 100644 --- a/src/ai/firebase.ts +++ b/src/ai/firebase.ts @@ -4,13 +4,11 @@ import { ɵzoneWrap } from '@angular/fire'; import { getAI as _getAI, getGenerativeModel as _getGenerativeModel, - getImagenModel as _getImagenModel, getLiveGenerativeModel as _getLiveGenerativeModel, startAudioConversation as _startAudioConversation } from 'firebase/ai'; export const getAI = ɵzoneWrap(_getAI, true); export const getGenerativeModel = ɵzoneWrap(_getGenerativeModel, true); -export const getImagenModel = ɵzoneWrap(_getImagenModel, true); export const getLiveGenerativeModel = ɵzoneWrap(_getLiveGenerativeModel, true); export const startAudioConversation = ɵzoneWrap(_startAudioConversation, true); diff --git a/src/schematics/update/v21/vertexai-to-ai.jasmine.ts b/src/schematics/update/v21/vertexai-to-ai.jasmine.ts index ca89596f1..6501e42c6 100644 --- a/src/schematics/update/v21/vertexai-to-ai.jasmine.ts +++ b/src/schematics/update/v21/vertexai-to-ai.jasmine.ts @@ -746,6 +746,24 @@ describe('rewriteVertexAIToAI', () => { expect(warn.calls.mostRecent().args[0]).toContain('no longer exists in the new entry point'); }); + it('leaves getImagenModel in place and warns that the Imagen API is gone', () => { + const { context: spiedContext, warn } = contextWithLogSpies(); + const source = [ + `import { getVertexAI, getImagenModel } from '@angular/fire/vertexai';`, + `export const a = getVertexAI();`, + `export const model = getImagenModel(a, { model: 'imagen-3.0-generate-002' });`, + ].join('\n'); + const tree = treeWith({ 'src/app/foo.ts': source }); + + rewriteVertexAIToAI(tree, spiedContext, typescript); + + const out = tree.readText('src/app/foo.ts'); + expect(out).toContain(`import { getAI, VertexAIBackend, getImagenModel } from '@angular/fire/ai';`); + expect(out).toContain(`getImagenModel(a, { model: 'imagen-3.0-generate-002' });`); + expect(warn).toHaveBeenCalledTimes(1); + expect(warn.calls.mostRecent().args[0]).toContain('Imagen models were shut down'); + }); + it('reuses an existing VertexAIBackend import instead of adding a second one', () => { const source = [ `import { VertexAIBackend } from '@angular/fire/ai';`, diff --git a/src/schematics/update/v21/vertexai-to-ai/tables.ts b/src/schematics/update/v21/vertexai-to-ai/tables.ts index 7e125e52e..2a6729b72 100644 --- a/src/schematics/update/v21/vertexai-to-ai/tables.ts +++ b/src/schematics/update/v21/vertexai-to-ai/tables.ts @@ -30,6 +30,7 @@ export const SYMBOL_RENAMES: Record = { // replacement, so the import keeps its name (breaking loudly) and the log explains why. export const REMOVED_SYMBOL_GUIDANCE: Record = { VertexAIOptions: 'the new AIOptions takes a backend instead of a location, rebuild the options by hand', + getImagenModel: 'the Imagen models were shut down in August 2026 and firebase 12.18 removed the API, move image generation to the Gemini image models through getGenerativeModel', }; export const GET_VERTEX_AI = 'getVertexAI'; diff --git a/tools/build.ts b/tools/build.ts index c0943f381..a2a704bcf 100644 --- a/tools/build.ts +++ b/tools/build.ts @@ -114,7 +114,13 @@ ${exportedZoneWrappedFns} await writeFile(filePath, fileOutput); }; return Promise.all([ - reexport('ai', 'firebase', 'firebase/ai', tsKeys()), + reexport('ai', 'firebase', 'firebase/ai', tsKeys(), { + // Removed in @firebase/ai 2.15.0 (firebase 12.18.0), which the ^12.4.0 range + // resolves for fresh installs. A named import here would make consumer builds + // fail on that version, so only re-export it through the star export, which + // tracks whichever firebase is installed. + getImagenModel: null, + }), reexport('analytics', 'firebase', 'firebase/analytics', tsKeys(), { isSupported: { blockUntilFirst: false }, logEvent: { blockUntilFirst: false, logLevel: LogLevel.VERBOSE },