@exotel-npm-dev/exotel-ai-assist 1.3.7 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -121,6 +121,8 @@ function MyCustomUI({ call_sid }: { call_sid: string }) {
121
121
 
122
122
  if (!isReady) return <p>Connecting…</p>;
123
123
 
124
+ if (streamState === "quota_exhausted") return <p>Your organisation's AI Assist quota is exhausted.</p>;
125
+ if (streamState === "agent_quota_exhausted") return <p>Your personal AI Assist call limit is reached.</p>;
124
126
  if (streamState === "throttled") return <p>AI Assist is at capacity — available on your next call.</p>;
125
127
  if (streamState === "disconnected") return <p>AI Assist disconnected.</p>;
126
128
  if (streamState === "connection_timeout") return <p>Connection timed out.</p>;
@@ -189,7 +191,7 @@ ctrl.on("suggestion", (s) => console.log("Suggestion:", s));
189
191
  ctrl.on("transcript", (t) => console.log("Transcript:", t));
190
192
  ctrl.on("streamState", (state) => {
191
193
  console.log("Stream state:", state);
192
- // state: "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout"
194
+ // Quota blocks are reported as "quota_exhausted" or "agent_quota_exhausted".
193
195
  });
194
196
  ctrl.on("error", (err) => console.error("Error:", err));
195
197
 
@@ -256,7 +258,7 @@ Extends `EventEmitter`.
256
258
  | `suggestion` | `Suggestion` | New AI suggestion (capped at last 50) |
257
259
  | `transcript` | `TranscriptLine[]` | Live transcript update |
258
260
  | `sentiment` | `Sentiment` | Sentiment label update |
259
- | `streamState` | `StreamState` | Server stream state change (`connected`, `throttled`, `pending`, `disconnected`, `connection_timeout`) |
261
+ | `streamState` | `StreamState` | Server stream state change, including tenant and per-agent quota exhaustion |
260
262
  | `onCallStart` | — | Connection opened |
261
263
  | `onCallEnd` | — | Connection closed |
262
264
  | `statusChange` | `ConnectionStatus` | WebSocket-level status transition (internal) |
@@ -270,7 +272,7 @@ Extends `EventEmitter`.
270
272
  | Field | Type | Description |
271
273
  | -------------------------- | ----------------------- | ---------------------------------------------------------------------------- |
272
274
  | `isReady` | `boolean` | `true` after connected + server ack. Multi-tab safe. `false` on disconnect |
273
- | `streamState` | `StreamState \| null` | Server stream state: `"connected"`, `"throttled"`, `"pending"`, `"disconnected"`, or `"connection_timeout"`. `null` until the first `stream_status` message |
275
+ | `streamState` | `StreamState \| null` | Server stream state, including `"quota_exhausted"` and `"agent_quota_exhausted"`. `null` until the first stream-state message |
274
276
  | `suggestions` | `Suggestion[]` | AI suggestions, oldest first, capped at 50 |
275
277
  | `transcripts` | `TranscriptLine[]` | Live transcript lines, ordered by start time |
276
278
  | `sentiment` | `Sentiment \| null` | Latest sentiment reading |
@@ -284,7 +286,14 @@ Extends `EventEmitter`.
284
286
  ### TypeScript Types
285
287
 
286
288
  ```ts
287
- type StreamState = "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout";
289
+ type StreamState =
290
+ | "connected"
291
+ | "throttled"
292
+ | "quota_exhausted"
293
+ | "agent_quota_exhausted"
294
+ | "pending"
295
+ | "disconnected"
296
+ | "connection_timeout";
288
297
 
289
298
  type ConnectionStatus = "idle" | "connecting" | "connected" | "disconnected" | "error";
290
299
 
@@ -331,7 +340,7 @@ wss://<wssBaseUrl>?[customParam1=value1&customParam2=value2&...]
331
340
  "type": "stream_status",
332
341
  "config": { /* bot config, populated on connected, null otherwise */ },
333
342
  "events": [ /* accumulated events since last message, usually [] */ ],
334
- "stream_state": "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout"
343
+ "stream_state": "connected" | "throttled" | "quota_exhausted" | "agent_quota_exhausted" | "pending" | "disconnected" | "connection_timeout"
335
344
  }
336
345
  ```
337
346
 
@@ -339,6 +348,8 @@ wss://<wssBaseUrl>?[customParam1=value1&customParam2=value2&...]
339
348
  | -------------------- | --------------------------------------------------------- |
340
349
  | `connected` | Stream is active — suggestions, transcript, and sentiment flow normally |
341
350
  | `throttled` | Capacity full — AI Assist cannot join this call; available on the next call |
351
+ | `quota_exhausted` | The organisation's AI Assist plan quota is exhausted |
352
+ | `agent_quota_exhausted` | The current agent's AI Assist call allowance is exhausted |
342
353
  | `pending` | Stream is pending — waiting for a definitive state |
343
354
  | `disconnected` | Stream ended or dropped |
344
355
  | `connection_timeout` | Connection timeout occurred |
@@ -1604,6 +1604,10 @@ class Utils {
1604
1604
  }
1605
1605
  Utils.MAX_EXTRA_QUERY_PARAMS = 3;
1606
1606
 
1607
+ const UNAVAILABLE_STREAM_STATES = new Set(["throttled", "quota_exhausted", "agent_quota_exhausted"]);
1608
+ function isUnavailableStreamState(state) {
1609
+ return state !== null && UNAVAILABLE_STREAM_STATES.has(state);
1610
+ }
1607
1611
  class ExotelAIAssistController extends EventEmitter {
1608
1612
  constructor(params) {
1609
1613
  super();
@@ -1637,7 +1641,7 @@ class ExotelAIAssistController extends EventEmitter {
1637
1641
  var _a;
1638
1642
  this._clearReconnectTimer();
1639
1643
  (_a = this.transport) === null || _a === void 0 ? void 0 : _a.disconnect();
1640
- if (this.readyFired && this._streamState !== "throttled") {
1644
+ if (this.readyFired && !isUnavailableStreamState(this._streamState)) {
1641
1645
  this.readyFired = false;
1642
1646
  this.emit("onReady", false);
1643
1647
  }
@@ -1719,8 +1723,8 @@ class ExotelAIAssistController extends EventEmitter {
1719
1723
  break;
1720
1724
  case "DISCONNECTED":
1721
1725
  if (this.connectionEstablished) {
1722
- const wasThrottled = this._streamState === "throttled";
1723
- if (this.readyFired && !wasThrottled) {
1726
+ const wasUnavailable = isUnavailableStreamState(this._streamState);
1727
+ if (this.readyFired && !wasUnavailable) {
1724
1728
  this.emit("onReady", false);
1725
1729
  }
1726
1730
  this.connectionEstablished = false;
@@ -1872,7 +1876,7 @@ class ExotelAIAssistController extends EventEmitter {
1872
1876
  _handleStreamStatus(state) {
1873
1877
  this._streamState = state;
1874
1878
  this.emit("streamState", state);
1875
- if (state === "connected" || state === "throttled") {
1879
+ if (state === "connected" || isUnavailableStreamState(state)) {
1876
1880
  this._fireReady();
1877
1881
  } else if (this.readyFired) {
1878
1882
  this.readyFired = false;
@@ -10,9 +10,11 @@ export interface UseExotelAIAssistReturn {
10
10
  /**
11
11
  * Server-reported stream state from `stream_status` messages.
12
12
  * `null` until the first `stream_status` is received.
13
- * - `"connected"` – stream is active and healthy
14
- * - `"throttled"` – capacity full; bot cannot join this call
15
- * - `"disconnected"` – stream ended or dropped
13
+ * - `"connected"` – stream is active and healthy
14
+ * - `"throttled"` – capacity full; bot cannot join this call
15
+ * - `"quota_exhausted"` – tenant plan quota is exhausted
16
+ * - `"agent_quota_exhausted"` – current agent's call quota is exhausted
17
+ * - `"disconnected"` – stream ended or dropped
16
18
  */
17
19
  streamState: StreamState | null;
18
20
  /** AI suggestions, oldest first, capped at 50. */
package/dist/index.js CHANGED
@@ -22105,6 +22105,10 @@ class Utils {
22105
22105
  }
22106
22106
  Utils.MAX_EXTRA_QUERY_PARAMS = 3;
22107
22107
 
22108
+ const UNAVAILABLE_STREAM_STATES$1 = new Set(["throttled", "quota_exhausted", "agent_quota_exhausted"]);
22109
+ function isUnavailableStreamState(state) {
22110
+ return state !== null && UNAVAILABLE_STREAM_STATES$1.has(state);
22111
+ }
22108
22112
  class ExotelAIAssistController extends EventEmitter {
22109
22113
  constructor(params) {
22110
22114
  super();
@@ -22138,7 +22142,7 @@ class ExotelAIAssistController extends EventEmitter {
22138
22142
  var _a;
22139
22143
  this._clearReconnectTimer();
22140
22144
  (_a = this.transport) === null || _a === void 0 ? void 0 : _a.disconnect();
22141
- if (this.readyFired && this._streamState !== "throttled") {
22145
+ if (this.readyFired && !isUnavailableStreamState(this._streamState)) {
22142
22146
  this.readyFired = false;
22143
22147
  this.emit("onReady", false);
22144
22148
  }
@@ -22220,8 +22224,8 @@ class ExotelAIAssistController extends EventEmitter {
22220
22224
  break;
22221
22225
  case "DISCONNECTED":
22222
22226
  if (this.connectionEstablished) {
22223
- const wasThrottled = this._streamState === "throttled";
22224
- if (this.readyFired && !wasThrottled) {
22227
+ const wasUnavailable = isUnavailableStreamState(this._streamState);
22228
+ if (this.readyFired && !wasUnavailable) {
22225
22229
  this.emit("onReady", false);
22226
22230
  }
22227
22231
  this.connectionEstablished = false;
@@ -22373,7 +22377,7 @@ class ExotelAIAssistController extends EventEmitter {
22373
22377
  _handleStreamStatus(state) {
22374
22378
  this._streamState = state;
22375
22379
  this.emit("streamState", state);
22376
- if (state === "connected" || state === "throttled") {
22380
+ if (state === "connected" || isUnavailableStreamState(state)) {
22377
22381
  this._fireReady();
22378
22382
  } else if (this.readyFired) {
22379
22383
  this.readyFired = false;
@@ -23236,6 +23240,7 @@ function TransferSummaryCard({
23236
23240
  });
23237
23241
  }
23238
23242
 
23243
+ const UNAVAILABLE_STREAM_STATES = new Set(["throttled", "quota_exhausted", "agent_quota_exhausted"]);
23239
23244
  function ExotelAIAssist(_a) {
23240
23245
  var {
23241
23246
  className,
@@ -23260,6 +23265,22 @@ function ExotelAIAssist(_a) {
23260
23265
  }, [isReady]);
23261
23266
  const connected = streamState === "connected";
23262
23267
  function renderProperEmptyContent() {
23268
+ if (streamState === "quota_exhausted") {
23269
+ return jsxRuntimeExports.jsx(EmptyState, {
23270
+ title: "AI Assist Unavailable",
23271
+ subtitle: "Contact your administrator to restore AI Assist.",
23272
+ showWarningBanner: true,
23273
+ warningBannerMessage: "Your organisation's AI Assist quota is exhausted. Ask your admin to renew the plan."
23274
+ });
23275
+ }
23276
+ if (streamState === "agent_quota_exhausted") {
23277
+ return jsxRuntimeExports.jsx(EmptyState, {
23278
+ title: "Your AI Assist limit is reached",
23279
+ subtitle: "Contact your administrator to raise your call allowance.",
23280
+ showWarningBanner: true,
23281
+ warningBannerMessage: "You've reached your personal AI Assist call limit."
23282
+ });
23283
+ }
23263
23284
  if (streamState === "throttled") {
23264
23285
  return jsxRuntimeExports.jsx(EmptyState, {
23265
23286
  title: "AI Assist Unavailable",
@@ -23296,7 +23317,7 @@ function ExotelAIAssist(_a) {
23296
23317
  botConfig: botConfig
23297
23318
  }), transferSummary ? jsxRuntimeExports.jsx(TransferSummaryCard, {
23298
23319
  data: transferSummary
23299
- }) : null, streamState !== "throttled" ? jsxRuntimeExports.jsxs(Root2$1, {
23320
+ }) : null, !streamState || !UNAVAILABLE_STREAM_STATES.has(streamState) ? jsxRuntimeExports.jsxs(Root2$1, {
23300
23321
  defaultValue: "suggestions",
23301
23322
  className: "oa-tabs",
23302
23323
  style: {
@@ -7391,6 +7391,10 @@ class Utils {
7391
7391
  }
7392
7392
  Utils.MAX_EXTRA_QUERY_PARAMS = 3;
7393
7393
 
7394
+ const UNAVAILABLE_STREAM_STATES$1 = new Set(["throttled", "quota_exhausted", "agent_quota_exhausted"]);
7395
+ function isUnavailableStreamState(state) {
7396
+ return state !== null && UNAVAILABLE_STREAM_STATES$1.has(state);
7397
+ }
7394
7398
  class ExotelAIAssistController extends EventEmitter {
7395
7399
  constructor(params) {
7396
7400
  super();
@@ -7424,7 +7428,7 @@ class ExotelAIAssistController extends EventEmitter {
7424
7428
  var _a;
7425
7429
  this._clearReconnectTimer();
7426
7430
  (_a = this.transport) === null || _a === void 0 ? void 0 : _a.disconnect();
7427
- if (this.readyFired && this._streamState !== "throttled") {
7431
+ if (this.readyFired && !isUnavailableStreamState(this._streamState)) {
7428
7432
  this.readyFired = false;
7429
7433
  this.emit("onReady", false);
7430
7434
  }
@@ -7506,8 +7510,8 @@ class ExotelAIAssistController extends EventEmitter {
7506
7510
  break;
7507
7511
  case "DISCONNECTED":
7508
7512
  if (this.connectionEstablished) {
7509
- const wasThrottled = this._streamState === "throttled";
7510
- if (this.readyFired && !wasThrottled) {
7513
+ const wasUnavailable = isUnavailableStreamState(this._streamState);
7514
+ if (this.readyFired && !wasUnavailable) {
7511
7515
  this.emit("onReady", false);
7512
7516
  }
7513
7517
  this.connectionEstablished = false;
@@ -7659,7 +7663,7 @@ class ExotelAIAssistController extends EventEmitter {
7659
7663
  _handleStreamStatus(state) {
7660
7664
  this._streamState = state;
7661
7665
  this.emit("streamState", state);
7662
- if (state === "connected" || state === "throttled") {
7666
+ if (state === "connected" || isUnavailableStreamState(state)) {
7663
7667
  this._fireReady();
7664
7668
  } else if (this.readyFired) {
7665
7669
  this.readyFired = false;
@@ -8522,6 +8526,7 @@ function TransferSummaryCard({
8522
8526
  });
8523
8527
  }
8524
8528
 
8529
+ const UNAVAILABLE_STREAM_STATES = new Set(["throttled", "quota_exhausted", "agent_quota_exhausted"]);
8525
8530
  function ExotelAIAssist(_a) {
8526
8531
  var {
8527
8532
  className,
@@ -8546,6 +8551,22 @@ function ExotelAIAssist(_a) {
8546
8551
  }, [isReady]);
8547
8552
  const connected = streamState === "connected";
8548
8553
  function renderProperEmptyContent() {
8554
+ if (streamState === "quota_exhausted") {
8555
+ return jsxRuntime.jsx(EmptyState, {
8556
+ title: "AI Assist Unavailable",
8557
+ subtitle: "Contact your administrator to restore AI Assist.",
8558
+ showWarningBanner: true,
8559
+ warningBannerMessage: "Your organisation's AI Assist quota is exhausted. Ask your admin to renew the plan."
8560
+ });
8561
+ }
8562
+ if (streamState === "agent_quota_exhausted") {
8563
+ return jsxRuntime.jsx(EmptyState, {
8564
+ title: "Your AI Assist limit is reached",
8565
+ subtitle: "Contact your administrator to raise your call allowance.",
8566
+ showWarningBanner: true,
8567
+ warningBannerMessage: "You've reached your personal AI Assist call limit."
8568
+ });
8569
+ }
8549
8570
  if (streamState === "throttled") {
8550
8571
  return jsxRuntime.jsx(EmptyState, {
8551
8572
  title: "AI Assist Unavailable",
@@ -8582,7 +8603,7 @@ function ExotelAIAssist(_a) {
8582
8603
  botConfig: botConfig
8583
8604
  }), transferSummary ? jsxRuntime.jsx(TransferSummaryCard, {
8584
8605
  data: transferSummary
8585
- }) : null, streamState !== "throttled" ? jsxRuntime.jsxs(Root2$1, {
8606
+ }) : null, !streamState || !UNAVAILABLE_STREAM_STATES.has(streamState) ? jsxRuntime.jsxs(Root2$1, {
8586
8607
  defaultValue: "suggestions",
8587
8608
  className: "oa-tabs",
8588
8609
  style: {
@@ -37,11 +37,13 @@ export interface Sentiment {
37
37
  export type ConnectionStatus = "idle" | "connecting" | "connected" | "disconnected" | "error";
38
38
  /**
39
39
  * Server-side stream state, received via `stream_status` messages.
40
- * - `connected` – stream is active and healthy
41
- * - `throttled` – capacity full; the bot cannot join this call
42
- * - `pending` – stream is pending
40
+ * - `connected` – stream is active and healthy
41
+ * - `throttled` – capacity full; the bot cannot join this call
42
+ * - `quota_exhausted` – the tenant's plan quota is exhausted
43
+ * - `agent_quota_exhausted` – the current agent's call quota is exhausted
44
+ * - `pending` – stream is pending
43
45
  */
44
- export type StreamState = "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout";
46
+ export type StreamState = "connected" | "throttled" | "quota_exhausted" | "agent_quota_exhausted" | "pending" | "disconnected" | "connection_timeout";
45
47
  /** Feature-flag config received from the AI Assist backend. */
46
48
  export interface BotConfig {
47
49
  sentiment: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exotel-npm-dev/exotel-ai-assist",
3
- "version": "1.3.7",
3
+ "version": "1.5.0",
4
4
  "description": "AI-powered real-time suggestions, transcript, and sentiment for agent calls",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -19,6 +19,12 @@ export interface ExotelAIAssistProps extends ExotelAIAssistParams {
19
19
  onReady?: (ready: boolean) => void;
20
20
  }
21
21
 
22
+ const UNAVAILABLE_STREAM_STATES = new Set([
23
+ "throttled",
24
+ "quota_exhausted",
25
+ "agent_quota_exhausted",
26
+ ]);
27
+
22
28
  export function ExotelAIAssist({ className, onReady, ...params }: ExotelAIAssistProps): JSX.Element {
23
29
  const {
24
30
  streamState,
@@ -41,6 +47,26 @@ export function ExotelAIAssist({ className, onReady, ...params }: ExotelAIAssist
41
47
  const connected = streamState === "connected";
42
48
 
43
49
  function renderProperEmptyContent(): JSX.Element | null {
50
+ if (streamState === "quota_exhausted") {
51
+ return (
52
+ <EmptyState
53
+ title="AI Assist Unavailable"
54
+ subtitle="Contact your administrator to restore AI Assist."
55
+ showWarningBanner={true}
56
+ warningBannerMessage="Your organisation's AI Assist quota is exhausted. Ask your admin to renew the plan."
57
+ />
58
+ );
59
+ }
60
+ if (streamState === "agent_quota_exhausted") {
61
+ return (
62
+ <EmptyState
63
+ title="Your AI Assist limit is reached"
64
+ subtitle="Contact your administrator to raise your call allowance."
65
+ showWarningBanner={true}
66
+ warningBannerMessage="You've reached your personal AI Assist call limit."
67
+ />
68
+ );
69
+ }
44
70
  if (streamState === "throttled") {
45
71
  return (
46
72
  <EmptyState
@@ -66,7 +92,7 @@ export function ExotelAIAssist({ className, onReady, ...params }: ExotelAIAssist
66
92
  <Header sentiment={sentiment} botConfig={botConfig} />
67
93
  {transferSummary ? <TransferSummaryCard data={transferSummary} /> : null}
68
94
 
69
- {streamState !== "throttled" ? (
95
+ {!streamState || !UNAVAILABLE_STREAM_STATES.has(streamState) ? (
70
96
  <Tabs.Root defaultValue="suggestions" className="oa-tabs" style={{ flex: 1, display: "flex", flexDirection: "column", minHeight: 0 }}>
71
97
  <Tabs.List className="oa-tabs-list">
72
98
  <Tabs.Trigger value="suggestions" className="oa-tabs-trigger">
@@ -17,6 +17,16 @@ import {
17
17
  import { ITransport, createTransport } from "../transport";
18
18
  import { Utils } from "../utils";
19
19
 
20
+ const UNAVAILABLE_STREAM_STATES: ReadonlySet<StreamState> = new Set([
21
+ "throttled",
22
+ "quota_exhausted",
23
+ "agent_quota_exhausted",
24
+ ]);
25
+
26
+ function isUnavailableStreamState(state: StreamState | null): boolean {
27
+ return state !== null && UNAVAILABLE_STREAM_STATES.has(state);
28
+ }
29
+
20
30
  export class ExotelAIAssistController extends EventEmitter<ControllerEvents> {
21
31
  private params: ExotelAIAssistParams;
22
32
  private transport: ITransport | null = null;
@@ -57,7 +67,7 @@ export class ExotelAIAssistController extends EventEmitter<ControllerEvents> {
57
67
  disconnect(): void {
58
68
  this._clearReconnectTimer();
59
69
  this.transport?.disconnect();
60
- if (this.readyFired && this._streamState !== "throttled") {
70
+ if (this.readyFired && !isUnavailableStreamState(this._streamState)) {
61
71
  this.readyFired = false;
62
72
  this.emit("onReady", false);
63
73
  }
@@ -145,8 +155,8 @@ export class ExotelAIAssistController extends EventEmitter<ControllerEvents> {
145
155
 
146
156
  case "DISCONNECTED":
147
157
  if (this.connectionEstablished) {
148
- const wasThrottled = this._streamState === "throttled";
149
- if (this.readyFired && !wasThrottled) {
158
+ const wasUnavailable = isUnavailableStreamState(this._streamState);
159
+ if (this.readyFired && !wasUnavailable) {
150
160
  this.emit("onReady", false);
151
161
  }
152
162
  this.connectionEstablished = false;
@@ -323,7 +333,7 @@ export class ExotelAIAssistController extends EventEmitter<ControllerEvents> {
323
333
  private _handleStreamStatus(state: StreamState): void {
324
334
  this._streamState = state;
325
335
  this.emit("streamState", state);
326
- if (state === "connected" || state === "throttled") {
336
+ if (state === "connected" || isUnavailableStreamState(state)) {
327
337
  this._fireReady();
328
338
  } else if (this.readyFired) {
329
339
  this.readyFired = false;
@@ -24,9 +24,11 @@ export interface UseExotelAIAssistReturn {
24
24
  /**
25
25
  * Server-reported stream state from `stream_status` messages.
26
26
  * `null` until the first `stream_status` is received.
27
- * - `"connected"` – stream is active and healthy
28
- * - `"throttled"` – capacity full; bot cannot join this call
29
- * - `"disconnected"` – stream ended or dropped
27
+ * - `"connected"` – stream is active and healthy
28
+ * - `"throttled"` – capacity full; bot cannot join this call
29
+ * - `"quota_exhausted"` – tenant plan quota is exhausted
30
+ * - `"agent_quota_exhausted"` – current agent's call quota is exhausted
31
+ * - `"disconnected"` – stream ended or dropped
30
32
  */
31
33
  streamState: StreamState | null;
32
34
  /** AI suggestions, oldest first, capped at 50. */
@@ -42,11 +42,20 @@ export type ConnectionStatus = "idle" | "connecting" | "connected" | "disconnect
42
42
 
43
43
  /**
44
44
  * Server-side stream state, received via `stream_status` messages.
45
- * - `connected` – stream is active and healthy
46
- * - `throttled` – capacity full; the bot cannot join this call
47
- * - `pending` – stream is pending
45
+ * - `connected` – stream is active and healthy
46
+ * - `throttled` – capacity full; the bot cannot join this call
47
+ * - `quota_exhausted` – the tenant's plan quota is exhausted
48
+ * - `agent_quota_exhausted` – the current agent's call quota is exhausted
49
+ * - `pending` – stream is pending
48
50
  */
49
- export type StreamState = "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout";
51
+ export type StreamState =
52
+ | "connected"
53
+ | "throttled"
54
+ | "quota_exhausted"
55
+ | "agent_quota_exhausted"
56
+ | "pending"
57
+ | "disconnected"
58
+ | "connection_timeout";
50
59
 
51
60
  // ---------------------------------------------------------------------------
52
61
  // Internal-only backend response types