Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c616128
feat(vertexai): Add support for `AbortSignal`
dlarocque Mar 31, 2025
54589ad
Run formatter
dlarocque May 12, 2025
b4ae062
Merge branch 'main' into dl/abort-signal
dlarocque May 22, 2025
a82a809
Fix docs
dlarocque May 22, 2025
f690611
Update changeset to use `@firebase/ai`
dlarocque May 22, 2025
821e580
remove ghost changeset
dlarocque May 22, 2025
15239fb
update example in docs
dlarocque May 22, 2025
0096b9a
Docs review
dlarocque May 27, 2025
931972d
Merge branch 'main' into dl/abort-signal
dlarocque May 27, 2025
3a5ce74
Merge branch 'main' into dl/abort-signal
dlarocque Jun 23, 2025
62552a2
do not log abort errors during chat message stream
dlarocque Nov 4, 2025
d4d62a2
Merge branch 'main' into dl/abort-signal
dlarocque Nov 4, 2025
9f31324
remove old vertex ai docs
dlarocque Nov 4, 2025
1633e80
clean up and add tests
dlarocque Nov 4, 2025
a5b0848
revert launch json change
dlarocque Nov 4, 2025
5ab789f
Merge branch 'main' into dl/abort-signal
dlarocque Nov 12, 2025
472b40c
revert chrome adapter change
dlarocque Nov 12, 2025
dbb11a9
fix external signal listener leak
dlarocque Nov 14, 2025
3557b15
fix sendMessageStream abort signal tests
dlarocque Nov 14, 2025
4a3af45
format and fix generative-model tests
dlarocque Nov 14, 2025
b016952
remove console log in tests
dlarocque Nov 14, 2025
40ce3c5
fix imagen test request options assertion
dlarocque Nov 14, 2025
bf1b031
throw AbortError if timeout is invoked on request
dlarocque Nov 19, 2025
49461e1
assert chatSessionStream throws the request error
dlarocque Nov 19, 2025
8b3baac
format and docs
dlarocque Nov 19, 2025
2988c61
fix lint err
dlarocque Nov 19, 2025
2cbd4c4
fix issue where externalSignal event listener is cleared during stream
dlarocque Nov 19, 2025
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
6 changes: 6 additions & 0 deletions .changeset/long-keys-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'firebase': minor
'@firebase/ai': minor
---

Add support for `AbortSignal`, allowing requests to be aborted.
19 changes: 12 additions & 7 deletions common/api-review/ai.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ export class ChatSession {
params?: StartChatParams | undefined;
// (undocumented)
requestOptions?: RequestOptions | undefined;
sendMessage(request: string | Array<string | Part>): Promise<GenerateContentResult>;
sendMessageStream(request: string | Array<string | Part>): Promise<GenerateContentStreamResult>;
sendMessage(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
sendMessageStream(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
}

// @beta
Expand Down Expand Up @@ -539,9 +539,9 @@ export interface GenerativeContentBlob {
export class GenerativeModel extends AIModel {
// Warning: (ae-incompatible-release-tags) The symbol "__constructor" is marked as @public, but its signature references "ChromeAdapter" which is marked as @beta
constructor(ai: AI, modelParams: ModelParams, requestOptions?: RequestOptions, chromeAdapter?: ChromeAdapter | undefined);
countTokens(request: CountTokensRequest | string | Array<string | Part>): Promise<CountTokensResponse>;
generateContent(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentResult>;
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentStreamResult>;
countTokens(request: CountTokensRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<CountTokensResponse>;
generateContent(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
// (undocumented)
generationConfig: GenerationConfig;
// (undocumented)
Expand Down Expand Up @@ -784,9 +784,9 @@ export interface ImagenInlineImage {
// @public
export class ImagenModel extends AIModel {
constructor(ai: AI, modelParams: ImagenModelParams, requestOptions?: RequestOptions | undefined);
generateImages(prompt: string): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
// @internal
generateImagesGCS(prompt: string, gcsURI: string): Promise<ImagenGenerationResponse<ImagenGCSImage>>;
generateImagesGCS(prompt: string, gcsURI: string, singleRequestOptions?: SingleRequestOptions): Promise<ImagenGenerationResponse<ImagenGCSImage>>;
generationConfig?: ImagenGenerationConfig;
// (undocumented)
requestOptions?: RequestOptions | undefined;
Expand Down Expand Up @@ -1294,6 +1294,11 @@ export interface Segment {
text: string;
}

// @public
export interface SingleRequestOptions extends RequestOptions {
signal?: AbortSignal;
}

// @beta
export interface SpeechConfig {
voiceConfig?: VoiceConfig;
Expand Down
2 changes: 2 additions & 0 deletions docs-devsite/_toc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ toc:
path: /docs/reference/js/ai.searchentrypoint.md
- title: Segment
path: /docs/reference/js/ai.segment.md
- title: SingleRequestOptions
path: /docs/reference/js/ai.singlerequestoptions.md
- title: SpeechConfig
path: /docs/reference/js/ai.speechconfig.md
- title: StartAudioConversationOptions
Expand Down
10 changes: 6 additions & 4 deletions docs-devsite/ai.chatsession.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export declare class ChatSession
| Method | Modifiers | Description |
| --- | --- | --- |
| [getHistory()](./ai.chatsession.md#chatsessiongethistory) | | Gets the chat history so far. Blocked prompts are not added to history. Neither blocked candidates nor the prompts that generated them are added to history. |
| [sendMessage(request)](./ai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) |
| [sendMessageStream(request)](./ai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. |
| [sendMessage(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessage) | | Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.generatecontentresult.md#generatecontentresult_interface) |
| [sendMessageStream(request, singleRequestOptions)](./ai.chatsession.md#chatsessionsendmessagestream) | | Sends a chat message and receives the response as a [GenerateContentStreamResult](./ai.generatecontentstreamresult.md#generatecontentstreamresult_interface) containing an iterable stream and a response promise. |

## ChatSession.(constructor)

Expand Down Expand Up @@ -104,14 +104,15 @@ Sends a chat message and receives a non-streaming [GenerateContentResult](./ai.g
<b>Signature:</b>

```typescript
sendMessage(request: string | Array<string | Part>): Promise<GenerateContentResult>;
sendMessage(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
```

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| request | string \| Array&lt;string \| [Part](./ai.md#part)<!-- -->&gt; | |
| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | |

<b>Returns:</b>

Expand All @@ -124,14 +125,15 @@ Sends a chat message and receives the response as a [GenerateContentStreamResult
<b>Signature:</b>

```typescript
sendMessageStream(request: string | Array<string | Part>): Promise<GenerateContentStreamResult>;
sendMessageStream(request: string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
```

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| request | string \| Array&lt;string \| [Part](./ai.md#part)<!-- -->&gt; | |
| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | |

<b>Returns:</b>

Expand Down
15 changes: 9 additions & 6 deletions docs-devsite/ai.generativemodel.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ export declare class GenerativeModel extends AIModel

| Method | Modifiers | Description |
| --- | --- | --- |
| [countTokens(request)](./ai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. |
| [generateContent(request)](./ai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->. |
| [generateContentStream(request)](./ai.generativemodel.md#generativemodelgeneratecontentstream) | | Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. |
| [countTokens(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelcounttokens) | | Counts the tokens in the provided request. |
| [generateContent(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelgeneratecontent) | | Makes a single non-streaming call to the model and returns an object containing a single [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface)<!-- -->. |
| [generateContentStream(request, singleRequestOptions)](./ai.generativemodel.md#generativemodelgeneratecontentstream) | | Makes a single streaming call to the model and returns an object containing an iterable stream that iterates over all chunks in the streaming response as well as a promise that returns the final aggregated response. |
| [startChat(startChatParams)](./ai.generativemodel.md#generativemodelstartchat) | | Gets a new [ChatSession](./ai.chatsession.md#chatsession_class) instance which can be used for multi-turn chats. |

## GenerativeModel.(constructor)
Expand Down Expand Up @@ -119,14 +119,15 @@ Counts the tokens in the provided request.
<b>Signature:</b>

```typescript
countTokens(request: CountTokensRequest | string | Array<string | Part>): Promise<CountTokensResponse>;
countTokens(request: CountTokensRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<CountTokensResponse>;
```

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| request | [CountTokensRequest](./ai.counttokensrequest.md#counttokensrequest_interface) \| string \| Array&lt;string \| [Part](./ai.md#part)<!-- -->&gt; | |
| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | |

<b>Returns:</b>

Expand All @@ -139,14 +140,15 @@ Makes a single non-streaming call to the model and returns an object containing
<b>Signature:</b>

```typescript
generateContent(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentResult>;
generateContent(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentResult>;
```

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| request | [GenerateContentRequest](./ai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array&lt;string \| [Part](./ai.md#part)<!-- -->&gt; | |
| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | |

<b>Returns:</b>

Expand All @@ -159,14 +161,15 @@ Makes a single streaming call to the model and returns an object containing an i
<b>Signature:</b>

```typescript
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>): Promise<GenerateContentStreamResult>;
generateContentStream(request: GenerateContentRequest | string | Array<string | Part>, singleRequestOptions?: SingleRequestOptions): Promise<GenerateContentStreamResult>;
```

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| request | [GenerateContentRequest](./ai.generatecontentrequest.md#generatecontentrequest_interface) \| string \| Array&lt;string \| [Part](./ai.md#part)<!-- -->&gt; | |
| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | |

<b>Returns:</b>

Expand Down
5 changes: 3 additions & 2 deletions docs-devsite/ai.imagenmodel.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export declare class ImagenModel extends AIModel

| Method | Modifiers | Description |
| --- | --- | --- |
| [generateImages(prompt)](./ai.imagenmodel.md#imagenmodelgenerateimages) | | Generates images using the Imagen model and returns them as base64-encoded strings. |
| [generateImages(prompt, singleRequestOptions)](./ai.imagenmodel.md#imagenmodelgenerateimages) | | Generates images using the Imagen model and returns them as base64-encoded strings. |

## ImagenModel.(constructor)

Expand Down Expand Up @@ -100,14 +100,15 @@ If the prompt was not blocked, but one or more of the generated images were filt
<b>Signature:</b>

```typescript
generateImages(prompt: string): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
generateImages(prompt: string, singleRequestOptions?: SingleRequestOptions): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
```

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| prompt | string | A text prompt describing the image(s) to generate. |
| singleRequestOptions | [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | |

<b>Returns:</b>

Expand Down
1 change: 1 addition & 0 deletions docs-devsite/ai.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ The Firebase AI Web SDK.
| [SchemaShared](./ai.schemashared.md#schemashared_interface) | Basic [Schema](./ai.schema.md#schema_class) properties shared across several Schema-related types. |
| [SearchEntrypoint](./ai.searchentrypoint.md#searchentrypoint_interface) | Google search entry point. |
| [Segment](./ai.segment.md#segment_interface) | Represents a specific segment within a [Content](./ai.content.md#content_interface) object, often used to pinpoint the exact location of text or data that grounding information refers to. |
| [SingleRequestOptions](./ai.singlerequestoptions.md#singlerequestoptions_interface) | Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like <code>timeout</code> and <code>baseUrl</code>) with request-specific controls like cancellation via <code>AbortSignal</code>.<!-- -->Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (for example, [GenerativeModel](./ai.generativemodel.md#generativemodel_class)<!-- -->). |
| [SpeechConfig](./ai.speechconfig.md#speechconfig_interface) | <b><i>(Public Preview)</i></b> Configures speech synthesis. |
| [StartAudioConversationOptions](./ai.startaudioconversationoptions.md#startaudioconversationoptions_interface) | <b><i>(Public Preview)</i></b> Options for [startAudioConversation()](./ai.md#startaudioconversation_01c8e7f)<!-- -->. |
| [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat)<!-- -->. |
Expand Down
61 changes: 61 additions & 0 deletions docs-devsite/ai.singlerequestoptions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
Project: /docs/reference/js/_project.yaml
Book: /docs/reference/_book.yaml
page_type: reference

{% comment %}
DO NOT EDIT THIS FILE!
This is generated by the JS SDK team, and any local changes will be
overwritten. Changes should be made in the source code at
https://github.com/firebase/firebase-js-sdk
{% endcomment %}

# SingleRequestOptions interface
Options that can be provided per-request. Extends the base [RequestOptions](./ai.requestoptions.md#requestoptions_interface) (like `timeout` and `baseUrl`<!-- -->) with request-specific controls like cancellation via `AbortSignal`<!-- -->.

Options specified here will override any default [RequestOptions](./ai.requestoptions.md#requestoptions_interface) configured on a model (for example, [GenerativeModel](./ai.generativemodel.md#generativemodel_class)<!-- -->).

<b>Signature:</b>

```typescript
export interface SingleRequestOptions extends RequestOptions
```
<b>Extends:</b> [RequestOptions](./ai.requestoptions.md#requestoptions_interface)

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [signal](./ai.singlerequestoptions.md#singlerequestoptionssignal) | AbortSignal | An <code>AbortSignal</code> instance that allows cancelling ongoing requests (like <code>generateContent</code> or <code>generateImages</code>).<!-- -->If provided, calling <code>abort()</code> on the corresponding <code>AbortController</code> will attempt to cancel the underlying HTTP request. An <code>AbortError</code> will be thrown if cancellation is successful.<!-- -->Note that this will not cancel the request in the backend, so any applicable billing charges will still be applied despite cancellation. |

## SingleRequestOptions.signal

An `AbortSignal` instance that allows cancelling ongoing requests (like `generateContent` or `generateImages`<!-- -->).

If provided, calling `abort()` on the corresponding `AbortController` will attempt to cancel the underlying HTTP request. An `AbortError` will be thrown if cancellation is successful.

Note that this will not cancel the request in the backend, so any applicable billing charges will still be applied despite cancellation.

<b>Signature:</b>

```typescript
signal?: AbortSignal;
```

### Example


```javascript
const controller = new AbortController();
const model = getGenerativeModel({
// ...
});
model.generateContent(
"Write a story about a magic backpack.",
{ signal: controller.signal }
);

// To cancel request:
controller.abort();

```

2 changes: 1 addition & 1 deletion packages/ai/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const PACKAGE_VERSION = version;

export const LANGUAGE_TAG = 'gl-js';

export const DEFAULT_FETCH_TIMEOUT_MS = 180 * 1000;
export const DEFAULT_FETCH_TIMEOUT_MS = 180 * 1000; // TODO: Extend default timeout to accommodate for longer generation requests with pro models.

/**
* Defines the name of the default in-cloud model to use for hybrid inference.
Expand Down
Loading
Loading