@epam/ai-dial-chat-hooks 1.2.10 → 1.2.12

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.
@@ -33,10 +33,13 @@ export declare const decodeDeploymentId: (id: string) => string;
33
33
  export declare const normalizeDeploymentId: (id: string) => string;
34
34
  /**
35
35
  * Finds a deployment matching `idOrReference` by `id` first, falling back to
36
- * `reference` when no `id` matches. DIAL Core sometimes addresses a
37
- * deployment by `reference` in places that store a deployment id (e.g. a
38
- * conversation's or message's `model.id`), so lookups against the fetched
39
- * deployments list must accept either value.
36
+ * `reference` when no `id` matches, and finally to an `id` match that ignores
37
+ * percent-encoding. DIAL Core sometimes addresses a deployment by `reference`
38
+ * in places that store a deployment id (e.g. a conversation's or message's
39
+ * `model.id`), and a conversation created by a Custom Viewer (a DIAL Loop
40
+ * agent) may store the raw, human-readable application id while the listing
41
+ * returns it encoded ([#9275](https://github.com/epam/ai-dial-chat/issues/9275)), so lookups against the fetched deployments
42
+ * list must accept any of these forms.
40
43
  */
41
44
  export declare const findDeploymentByIdOrReference: (deployments: DeploymentItemDto[], idOrReference: string | null | undefined) => DeploymentItemDto | undefined;
42
45
  //# sourceMappingURL=deployment-id.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deployment-id.d.ts","sourceRoot":"","sources":["../../src/catalog/deployment-id.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEvE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,KAAG,MAIlC,CAAC;AAEf;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,KAAG,MAUlC,CAAC;AAEf;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,GAAI,IAAI,MAAM,KAAG,MACP,CAAC;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,GACxC,aAAa,iBAAiB,EAAE,EAChC,eAAe,MAAM,GAAG,IAAI,GAAG,SAAS,KACvC,iBAAiB,GAAG,SAMtB,CAAC"}
1
+ {"version":3,"file":"deployment-id.d.ts","sourceRoot":"","sources":["../../src/catalog/deployment-id.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEvE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,KAAG,MAIlC,CAAC;AAEf;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAAI,IAAI,MAAM,KAAG,MAUlC,CAAC;AAEf;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,GAAI,IAAI,MAAM,KAAG,MACP,CAAC;AAE7C;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,GACxC,aAAa,iBAAiB,EAAE,EAChC,eAAe,MAAM,GAAG,IAAI,GAAG,SAAS,KACvC,iBAAiB,GAAG,SAUtB,CAAC"}
@@ -6,7 +6,11 @@ var e = (e) => e.split("/").map((e) => encodeURIComponent(e)).join("/"), t = (e)
6
6
  return e;
7
7
  }
8
8
  }).join("/"), n = (n) => e(t(n)), r = (e, t) => {
9
- if (t) return e.find((e) => e.id === t) ?? e.find((e) => e.reference === t);
9
+ if (!t) return;
10
+ let r = e.find((e) => e.id === t) ?? e.find((e) => e.reference === t);
11
+ if (r) return r;
12
+ let i = n(t);
13
+ return e.find((e) => n(e.id) === i);
10
14
  };
11
15
  //#endregion
12
16
  export { t as decodeDeploymentId, e as encodeDeploymentId, r as findDeploymentByIdOrReference, n as normalizeDeploymentId };
@@ -1,6 +1,7 @@
1
1
  import { CatalogItemLimits, UsageLimitProgressRow } from '@epam/ai-dial-catalog';
2
- import { DeploymentLimitsResponseDto, LimitStatsDto } from '@epam/ai-dial-chat-api-client';
2
+ import { LimitStatsDto } from '@epam/ai-dial-chat-api-client';
3
3
  import { FormatResetTime } from '../usage/map-usage-data-to-dashboard';
4
+ import { UsageLimitsSources } from '../usage/useDeploymentUsageLimits/useDeploymentUsageLimits';
4
5
  /** Labels and formatter callbacks for the conversation-input limits mapping utility. */
5
6
  export interface ConversationInputLimitsLabels {
6
7
  /** Heading of the group listing the selected deployment's token limits. */
@@ -23,6 +24,6 @@ export interface ConversationInputLimitsLabels {
23
24
  }) => string;
24
25
  }
25
26
  export declare const buildResetFields: (stats: LimitStatsDto, formatResetTime: FormatResetTime | undefined) => Pick<UsageLimitProgressRow, "resetLabel" | "resetIsoValue" | "resetAriaLabel">;
26
- /** Maps a deployment's day, week, and month token limits and the caller's cost budget to display-ready rows, or `undefined` when none qualify. */
27
- export declare const mapDeploymentLimitsToInput: (dto: DeploymentLimitsResponseDto | undefined, labels: ConversationInputLimitsLabels, formatResetTime?: FormatResetTime) => CatalogItemLimits | undefined;
27
+ /** Maps the deployment's day, week, and month token limits (from `sources.deployment`) and the account cost budget (from `sources.account`) to display-ready rows, or `undefined` when none qualify. */
28
+ export declare const mapDeploymentLimitsToInput: (sources: UsageLimitsSources, labels: ConversationInputLimitsLabels, formatResetTime?: FormatResetTime) => CatalogItemLimits | undefined;
28
29
  //# sourceMappingURL=map-deployment-limits-to-input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"map-deployment-limits-to-input.d.ts","sourceRoot":"","sources":["../../src/catalog/map-deployment-limits-to-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EAEtB,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,2BAA2B,EAC3B,aAAa,EACd,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAE5E,wFAAwF;AACxF,MAAM,WAAW,6BAA6B;IAC5C,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1D,wDAAwD;IACxD,uBAAuB,EAAE,CAAC,MAAM,EAAE;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,MAAM,CAAC;CACd;AA+FD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,aAAa,EACpB,iBAAiB,eAAe,GAAG,SAAS,KAC3C,IAAI,CACL,qBAAqB,EACrB,YAAY,GAAG,eAAe,GAAG,gBAAgB,CAYlD,CAAC;AAuGF,kJAAkJ;AAClJ,eAAO,MAAM,0BAA0B,GACrC,KAAK,2BAA2B,GAAG,SAAS,EAC5C,QAAQ,6BAA6B,EACrC,kBAAkB,eAAe,KAChC,iBAAiB,GAAG,SAyCtB,CAAC"}
1
+ {"version":3,"file":"map-deployment-limits-to-input.d.ts","sourceRoot":"","sources":["../../src/catalog/map-deployment-limits-to-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EAEtB,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAEV,aAAa,EACd,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAC;AAErG,wFAAwF;AACxF,MAAM,WAAW,6BAA6B;IAC5C,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1D,wDAAwD;IACxD,uBAAuB,EAAE,CAAC,MAAM,EAAE;QAChC,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,KAAK,MAAM,CAAC;CACd;AAgGD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,aAAa,EACpB,iBAAiB,eAAe,GAAG,SAAS,KAC3C,IAAI,CACL,qBAAqB,EACrB,YAAY,GAAG,eAAe,GAAG,gBAAgB,CAYlD,CAAC;AA4GF,wMAAwM;AACxM,eAAO,MAAM,0BAA0B,GACrC,SAAS,kBAAkB,EAC3B,QAAQ,6BAA6B,EACrC,kBAAkB,eAAe,KAChC,iBAAiB,GAAG,SAqCtB,CAAC"}
@@ -61,7 +61,7 @@ var n = [
61
61
  return r >= 1 ? t.LimitReached : r >= a && e !== t.LimitReached ? t.RunningLow : e;
62
62
  }, void 0), _ = (e, t, n, r, i, a, o) => {
63
63
  let s = t.flatMap((t) => {
64
- let n = e[t.key];
64
+ let n = e?.[t.key];
65
65
  return !u(n) || !h(n) ? [] : (o.push(n), [p(n, r[t.labelField], r, i, a)]);
66
66
  });
67
67
  return s.length > 0 ? {
@@ -69,11 +69,10 @@ var n = [
69
69
  rows: s
70
70
  } : void 0;
71
71
  }, v = (t, i, a) => {
72
- if (t == null) return;
73
- let o = [], u = [_(t, n, i.tokenGroup, i, {
72
+ let o = [], u = [_(t.deployment, n, i.tokenGroup, i, {
74
73
  format: (e) => s.format(l(e)),
75
74
  formatFull: (e) => c.format(e)
76
- }, a, o), _(t, r, i.costGroup, i, {
75
+ }, a, o), _(t.account, r, i.costGroup, i, {
77
76
  format: e,
78
77
  formatFull: e
79
78
  }, a, o)].filter((e) => e != null);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@epam/ai-dial-chat-hooks",
3
3
  "description": "Framework-level React hooks extracted from AI DIAL Chat for building custom chat interfaces",
4
- "version": "1.2.10",
4
+ "version": "1.2.12",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "main": "./index.js",
@@ -116,8 +116,8 @@
116
116
  }
117
117
  },
118
118
  "dependencies": {
119
- "@epam/ai-dial-chat-api-client": "1.2.10",
120
- "dompurify": "3.4.16",
119
+ "@epam/ai-dial-chat-api-client": "1.2.12",
120
+ "dompurify": "3.4.17",
121
121
  "fflate": "^0.8.3",
122
122
  "lru-cache": "^10.4.3",
123
123
  "mime-types": "^3.0.2",
@@ -125,22 +125,22 @@
125
125
  },
126
126
  "peerDependencies": {
127
127
  "react": "^19.2.8",
128
- "@epam/ai-dial-attachment-canvas": "1.2.10",
129
- "@epam/ai-dial-attachment-input": "1.2.10",
130
- "@epam/ai-dial-catalog": "1.2.10",
131
- "@epam/ai-dial-chat-overlay": "1.2.10",
132
- "@epam/ai-dial-chat-shared": "1.2.10",
133
- "@epam/ai-dial-conversation-input": "1.2.10",
134
- "@epam/ai-dial-mcp-apps": "1.2.10",
135
- "@epam/ai-dial-publish-panel": "1.2.10",
136
- "@epam/ai-dial-quotations": "1.2.10",
128
+ "@epam/ai-dial-attachment-canvas": "1.2.12",
129
+ "@epam/ai-dial-attachment-input": "1.2.12",
130
+ "@epam/ai-dial-catalog": "1.2.12",
131
+ "@epam/ai-dial-chat-overlay": "1.2.12",
132
+ "@epam/ai-dial-chat-shared": "1.2.12",
133
+ "@epam/ai-dial-conversation-input": "1.2.12",
134
+ "@epam/ai-dial-mcp-apps": "1.2.12",
135
+ "@epam/ai-dial-publish-panel": "1.2.12",
136
+ "@epam/ai-dial-quotations": "1.2.12",
137
137
  "@epam/ai-dial-react-file-manager": "^0.3.5",
138
- "@epam/ai-dial-scheduled-tasks": "1.2.10",
139
- "@epam/ai-dial-share": "1.2.10",
140
- "@epam/ai-dial-skill-editor": "1.2.10",
141
- "@epam/ai-dial-source-panel": "1.2.10",
138
+ "@epam/ai-dial-scheduled-tasks": "1.2.12",
139
+ "@epam/ai-dial-share": "1.2.12",
140
+ "@epam/ai-dial-skill-editor": "1.2.12",
141
+ "@epam/ai-dial-source-panel": "1.2.12",
142
142
  "@epam/ai-dial-ui-kit": "^0.15.4",
143
- "@epam/ai-dial-usage-dashboard": "1.2.10",
143
+ "@epam/ai-dial-usage-dashboard": "1.2.12",
144
144
  "@modelcontextprotocol/sdk": "^1.32.1",
145
145
  "@epam/pdf-highlighter-kit": "^0.0.19",
146
146
  "@mcp-ui/client": "^7.1.1"
@@ -1,6 +1,6 @@
1
- import { DeploymentLimitsResponseDto } from '@epam/ai-dial-chat-api-client';
2
1
  import { UsageLimitBannerSeverity } from '@epam/ai-dial-conversation-input';
3
2
  import { UsagePeriod } from './usage-period';
3
+ import { UsageLimitsSources } from './useDeploymentUsageLimits/useDeploymentUsageLimits';
4
4
  /** The day/week/month usage stat the composer banner reports on, and how close it is to its limit. */
5
5
  export interface UsageBannerSource {
6
6
  /** Calendar period of the stat. */
@@ -15,9 +15,10 @@ export interface UsageBannerSource {
15
15
  /** `true` when `total` is a real cap: finite, positive, and below DIAL Core's unlimited sentinel. */
16
16
  export declare const isCappedStat: (total: number) => boolean;
17
17
  /**
18
- * Returns the capped day/week/month token or cost stat with the highest
19
- * used/total ratio, classified against `thresholdPercent`, or `undefined` when
20
- * no stat is capped or the worst one is below the threshold.
18
+ * Returns the capped day/week/month token stat of `sources.deployment` or cost
19
+ * stat of `sources.account` with the highest used/total ratio, classified
20
+ * against `thresholdPercent`, or `undefined` when no stat is capped or the
21
+ * worst one is below the threshold.
21
22
  */
22
- export declare const selectUsageBannerSource: (dto: DeploymentLimitsResponseDto | undefined, thresholdPercent: number) => UsageBannerSource | undefined;
23
+ export declare const selectUsageBannerSource: (sources: UsageLimitsSources, thresholdPercent: number) => UsageBannerSource | undefined;
23
24
  //# sourceMappingURL=usage-banner-source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usage-banner-source.d.ts","sourceRoot":"","sources":["../../src/usage/usage-banner-source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAE5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,sGAAsG;AACtG,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,uDAAuD;IACvD,QAAQ,EAAE,wBAAwB,CAAC;IACnC,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAQD,qGAAqG;AACrG,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,OAC4B,CAAC;AA8B1E;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,2BAA2B,GAAG,SAAS,EAC5C,kBAAkB,MAAM,KACvB,iBAAiB,GAAG,SAoCtB,CAAC"}
1
+ {"version":3,"file":"usage-banner-source.d.ts","sourceRoot":"","sources":["../../src/usage/usage-banner-source.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AAE9F,sGAAsG;AACtG,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,MAAM,EAAE,WAAW,CAAC;IACpB,uDAAuD;IACvD,QAAQ,EAAE,wBAAwB,CAAC;IACnC,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAQD,qGAAqG;AACrG,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,OAC4B,CAAC;AAsC1E;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,kBAAkB,EAC3B,kBAAkB,MAAM,KACvB,iBAAiB,GAAG,SAsCtB,CAAC"}
@@ -2,22 +2,46 @@ import { UsagePeriod as e } from "./usage-period.js";
2
2
  import { UsageLimitBannerSeverity as t } from "@epam/ai-dial-conversation-input";
3
3
  //#region src/usage/usage-banner-source.ts
4
4
  var n = 2 ** 53 - 1, r = (e) => Number.isFinite(e) && e > 0 && e < n, i = [
5
- ["monthTokenStats", e.Month],
6
- ["monthCostStats", e.Month],
7
- ["weekTokenStats", e.Week],
8
- ["weekCostStats", e.Week],
9
- ["dayTokenStats", e.Day],
10
- ["dayCostStats", e.Day]
5
+ [
6
+ "deployment",
7
+ "monthTokenStats",
8
+ e.Month
9
+ ],
10
+ [
11
+ "account",
12
+ "monthCostStats",
13
+ e.Month
14
+ ],
15
+ [
16
+ "deployment",
17
+ "weekTokenStats",
18
+ e.Week
19
+ ],
20
+ [
21
+ "account",
22
+ "weekCostStats",
23
+ e.Week
24
+ ],
25
+ [
26
+ "deployment",
27
+ "dayTokenStats",
28
+ e.Day
29
+ ],
30
+ [
31
+ "account",
32
+ "dayCostStats",
33
+ e.Day
34
+ ]
11
35
  ], a = (e, n) => {
12
36
  let a;
13
- for (let [t, n] of i) {
14
- let i = e?.[t];
37
+ for (let [t, n, o] of i) {
38
+ let i = e[t]?.[n];
15
39
  if (i == null || !r(i.total)) continue;
16
- let o = Math.max(i.used, 0) / i.total;
17
- (a == null || o > a.ratio) && (a = {
40
+ let s = Math.max(i.used, 0) / i.total;
41
+ (a == null || s > a.ratio) && (a = {
18
42
  stat: i,
19
- period: n,
20
- ratio: o
43
+ period: o,
44
+ ratio: s
21
45
  });
22
46
  }
23
47
  if (a == null) return;
@@ -1,32 +1,56 @@
1
- import { DeploymentLimitsResponseDto } from '@epam/ai-dial-chat-api-client';
2
- /** Host-configured call that fetches the limits of one deployment. */
3
- export type GetDeploymentLimits = (deploymentId: string) => Promise<DeploymentLimitsResponseDto>;
1
+ import { DeploymentLimitsResponseDto, UserLimitStatsResponseDto } from '@epam/ai-dial-chat-api-client';
2
+ /** The caller's account-wide cost budget and spend: the top level of a user-usage response. */
3
+ export type AccountUsage = Pick<UserLimitStatsResponseDto, 'dayCostStats' | 'weekCostStats' | 'monthCostStats'>;
4
+ /**
5
+ * What the usage dial and the usage banner are mapped from. Each field has a
6
+ * single scope, so a deployment's figures are never read as the account's or
7
+ * the other way round.
8
+ */
9
+ export interface UsageLimitsSources {
10
+ /** The selected deployment's own stats (its deployment-usage response). Only its token stats are read. */
11
+ deployment: DeploymentLimitsResponseDto | undefined;
12
+ /** The caller's account budget and spend. Only its cost stats are read. */
13
+ account: AccountUsage | undefined;
14
+ }
15
+ /** Host-configured calls that fetch the two usage sources. */
16
+ export interface UsageLimitsApi {
17
+ /** Fetches one deployment's own usage, every stat scoped to that deployment. */
18
+ getDeploymentUsage: (deploymentId: string) => Promise<DeploymentLimitsResponseDto>;
19
+ /** Fetches the caller's account usage; only its top-level cost stats are read. */
20
+ getAccountUsage: () => Promise<AccountUsage>;
21
+ }
4
22
  /** Return shape of {@link useDeploymentUsageLimits}. */
5
23
  export interface UseDeploymentUsageLimitsResult {
6
- /** Raw limits response for the selected deployment, or `undefined` before the first success. */
7
- limitsDto: DeploymentLimitsResponseDto | undefined;
8
- /** `true` while a fetch is in flight. */
24
+ /** The last successfully fetched value of each source. */
25
+ sources: UsageLimitsSources;
26
+ /** `true` until both calls of the current fetch have settled. */
9
27
  isLoading: boolean;
10
- /** `true` after the most recent fetch rejected. */
28
+ /** `true` after either call of the most recent fetch rejected. */
11
29
  hasError: boolean;
12
- /** Re-fetches the current deployment when no request is in flight. */
30
+ /** Re-fetches both sources when no request is in flight. */
13
31
  refresh: () => void;
14
32
  }
15
33
  /**
16
- * Fetches the selected deployment's usage limits via the provided
17
- * `getDeploymentLimits` function. The hook accepts the fetch function as a
18
- * parameter so the caller supplies an already-configured API client — the hook
19
- * never constructs or imports one itself. The function's identity is not a
20
- * re-fetch trigger; only `deploymentId` and `refresh()` are.
34
+ * Fetches the selected deployment's own usage and the caller's account usage
35
+ * through the provided `api`. The hook accepts the calls as a parameter so the
36
+ * caller supplies an already-configured API client; the hook never constructs
37
+ * or imports one itself. The identity of `api` is not a re-fetch trigger; only
38
+ * `deploymentId` and `refresh()` are.
39
+ *
40
+ * Two sources rather than one deployment-limits response: there, the cost
41
+ * stats add an application's aggregated callee cost to the account spend that
42
+ * already contains it, so an agent's spend would be counted twice.
21
43
  *
22
- * A monotonic request ID prevents a slower response for a previous deployment
23
- * from replacing the current value. Refresh failures preserve the last known
24
- * response so the open popover can surface a non-blocking error.
44
+ * Both calls share one monotonic request ID, so a slower response for a
45
+ * previous deployment never replaces the current value. Each source keeps its
46
+ * last known value when its own call fails, so the open popover can surface a
47
+ * non-blocking error while the other source still renders. The account source
48
+ * survives a deployment change, since it does not depend on the selection.
25
49
  *
26
- * The raw response is returned rather than a mapped display model: mapping
50
+ * The raw responses are returned rather than a mapped display model: mapping
27
51
  * needs the caller's translated labels and locale-bound reset formatter, and
28
52
  * holding the mapped value in state here would leave it stale after a language
29
53
  * change until the next fetch.
30
54
  */
31
- export declare const useDeploymentUsageLimits: (deploymentId: string | undefined, getDeploymentLimits: GetDeploymentLimits) => UseDeploymentUsageLimitsResult;
55
+ export declare const useDeploymentUsageLimits: (deploymentId: string | undefined, api: UsageLimitsApi) => UseDeploymentUsageLimitsResult;
32
56
  //# sourceMappingURL=useDeploymentUsageLimits.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDeploymentUsageLimits.d.ts","sourceRoot":"","sources":["../../../src/usage/useDeploymentUsageLimits/useDeploymentUsageLimits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAGjF,sEAAsE;AACtE,MAAM,MAAM,mBAAmB,GAAG,CAChC,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC,2BAA2B,CAAC,CAAC;AAE1C,wDAAwD;AACxD,MAAM,WAAW,8BAA8B;IAC7C,gGAAgG;IAChG,SAAS,EAAE,2BAA2B,GAAG,SAAS,CAAC;IACnD,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,mDAAmD;IACnD,QAAQ,EAAE,OAAO,CAAC;IAClB,sEAAsE;IACtE,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,GAAG,SAAS,EAChC,qBAAqB,mBAAmB,KACvC,8BAgEF,CAAC"}
1
+ {"version":3,"file":"useDeploymentUsageLimits.d.ts","sourceRoot":"","sources":["../../../src/usage/useDeploymentUsageLimits/useDeploymentUsageLimits.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,yBAAyB,EAC1B,MAAM,+BAA+B,CAAC;AAGvC,+FAA+F;AAC/F,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,yBAAyB,EACzB,cAAc,GAAG,eAAe,GAAG,gBAAgB,CACpD,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,0GAA0G;IAC1G,UAAU,EAAE,2BAA2B,GAAG,SAAS,CAAC;IACpD,2EAA2E;IAC3E,OAAO,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC;AAED,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,gFAAgF;IAChF,kBAAkB,EAAE,CAClB,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAC1C,kFAAkF;IAClF,eAAe,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;CAC9C;AAED,wDAAwD;AACxD,MAAM,WAAW,8BAA8B;IAC7C,0DAA0D;IAC1D,OAAO,EAAE,kBAAkB,CAAC;IAC5B,iEAAiE;IACjE,SAAS,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,QAAQ,EAAE,OAAO,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,GAAG,SAAS,EAChC,KAAK,cAAc,KAClB,8BA6EF,CAAC"}
@@ -1,39 +1,34 @@
1
- import { useCallback as e, useEffect as t, useRef as n, useState as r } from "react";
1
+ import { useCallback as e, useEffect as t, useMemo as n, useRef as r, useState as i } from "react";
2
2
  //#region src/usage/useDeploymentUsageLimits/useDeploymentUsageLimits.ts
3
- var i = (i, a) => {
4
- let [o, s] = r(), [c, l] = r(!1), [u, d] = r(!1), [f, p] = r(0), m = n(0), h = n(!1), g = n(void 0), _ = n(a);
5
- _.current = a;
6
- let v = e(() => {
7
- h.current || p((e) => e + 1);
3
+ var a = (a, o) => {
4
+ let [s, c] = i(), [l, u] = i(), [d, f] = i(!1), [p, m] = i(!1), [h, g] = i(0), _ = r(0), v = r(!1), y = r(void 0), b = r(o);
5
+ b.current = o;
6
+ let x = e(() => {
7
+ v.current || g((e) => e + 1);
8
8
  }, []);
9
9
  return t(() => {
10
- let e = g.current !== i;
11
- if (g.current = i, !i) {
12
- m.current += 1, s(void 0), l(!1), d(!1), h.current = !1;
10
+ let e = y.current !== a;
11
+ if (y.current = a, !a) {
12
+ _.current += 1, c(void 0), f(!1), m(!1), v.current = !1;
13
13
  return;
14
14
  }
15
- e && s(void 0);
16
- let t = ++m.current, n = !1;
17
- return l(!0), d(!1), h.current = !0, (async () => {
18
- try {
19
- let e = await _.current(i);
20
- if (n || t !== m.current) return;
21
- s(e);
22
- } catch {
23
- if (n || t !== m.current) return;
24
- d(!0);
25
- } finally {
26
- !n && t === m.current && (l(!1), h.current = !1);
27
- }
15
+ e && c(void 0);
16
+ let t = ++_.current, n = !1, r = () => !n && t === _.current;
17
+ return f(!0), m(!1), v.current = !0, (async () => {
18
+ let [e, t] = await Promise.allSettled([b.current.getDeploymentUsage(a), b.current.getAccountUsage()]);
19
+ r() && (e.status === "fulfilled" && c(e.value), t.status === "fulfilled" && u(t.value), m(e.status === "rejected" || t.status === "rejected"), f(!1), v.current = !1);
28
20
  })(), () => {
29
21
  n = !0;
30
22
  };
31
- }, [i, f]), {
32
- limitsDto: o,
33
- isLoading: c,
34
- hasError: u,
35
- refresh: v
23
+ }, [a, h]), {
24
+ sources: n(() => ({
25
+ deployment: s,
26
+ account: l
27
+ }), [s, l]),
28
+ isLoading: d,
29
+ hasError: p,
30
+ refresh: x
36
31
  };
37
32
  };
38
33
  //#endregion
39
- export { i as useDeploymentUsageLimits };
34
+ export { a as useDeploymentUsageLimits };
@@ -1,6 +1,6 @@
1
1
  import { UsageLimitBannerViewProps } from '@epam/ai-dial-conversation-input';
2
2
  import { TranslateFn } from '../usage-reset-time';
3
- import { GetDeploymentLimits } from '../useDeploymentUsageLimits/useDeploymentUsageLimits';
3
+ import { UsageLimitsApi } from '../useDeploymentUsageLimits/useDeploymentUsageLimits';
4
4
  /**
5
5
  * i18n key strings the consuming app's translation bundle must define for
6
6
  * `useUsageLimitBanner` to produce translated strings, in addition to
@@ -29,8 +29,10 @@ export interface UseUsageLimitBannerOptions {
29
29
  deploymentId: string | undefined;
30
30
  /** Whether the selected deployment is currently generating a response. Defaults to `false`. */
31
31
  isGenerationInProgress?: boolean;
32
- /** Host-configured call that fetches one deployment's limits. */
33
- getDeploymentLimits: GetDeploymentLimits;
32
+ /** Host-configured call that fetches one deployment's own usage. */
33
+ getDeploymentUsage: UsageLimitsApi['getDeploymentUsage'];
34
+ /** Host-configured call that fetches the caller's account usage. */
35
+ getAccountUsage: UsageLimitsApi['getAccountUsage'];
34
36
  /** Used percentage at or above which a not-yet-exhausted limit raises a warning. */
35
37
  warningThresholdPercent: number;
36
38
  /** Active UI locale, used to format the reset time. */
@@ -47,10 +49,10 @@ export interface UseUsageLimitBannerResult {
47
49
  }
48
50
  /**
49
51
  * Everything the composer usage banner needs except its rendering: fetches the
50
- * selected deployment's limits, refreshes them after each generation, picks
51
- * the limit worth reporting, formats its sentences, and tracks tab-lifetime
52
- * dismissal. Spread `banner` onto `UsageLimitBannerView` from
53
- * `@epam/ai-dial-conversation-input`.
52
+ * selected deployment's own usage and the account usage, refreshes both after
53
+ * each generation, picks the limit worth reporting, formats its sentences, and
54
+ * tracks tab-lifetime dismissal. Spread `banner` onto `UsageLimitBannerView`
55
+ * from `@epam/ai-dial-conversation-input`.
54
56
  */
55
- export declare const useUsageLimitBanner: ({ deploymentId, isGenerationInProgress, getDeploymentLimits, warningThresholdPercent, activeLocale, t, }: UseUsageLimitBannerOptions) => UseUsageLimitBannerResult;
57
+ export declare const useUsageLimitBanner: ({ deploymentId, isGenerationInProgress, getDeploymentUsage, getAccountUsage, warningThresholdPercent, activeLocale, t, }: UseUsageLimitBannerOptions) => UseUsageLimitBannerResult;
56
58
  //# sourceMappingURL=useUsageLimitBanner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useUsageLimitBanner.d.ts","sourceRoot":"","sources":["../../../src/usage/useUsageLimitBanner/useUsageLimitBanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,kCAAkC,CAAC;AAI1C,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,sDAAsD,CAAC;AAI9D;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;IACjC,0EAA0E;;IAE1E,2EAA2E;;IAE3E,4EAA4E;;IAE5E,0EAA0E;;IAE1E,2EAA2E;;IAE3E,4EAA4E;;IAE5E,2CAA2C;;CAEnC,CAAC;AAkBX,6CAA6C;AAC7C,MAAM,WAAW,0BAA0B;IACzC,+CAA+C;IAC/C,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,+FAA+F;IAC/F,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iEAAiE;IACjE,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,oFAAoF;IACpF,uBAAuB,EAAE,MAAM,CAAC;IAChC,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,CAAC,EAAE,WAAW,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,yBAAyB,EACzB,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,gBAAgB,CAClE,CAAC;AAEF,mDAAmD;AACnD,MAAM,WAAW,yBAAyB;IACxC,wIAAwI;IACxI,MAAM,EAAE,qBAAqB,GAAG,SAAS,CAAC;CAC3C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAAI,0GAOjC,0BAA0B,KAAG,yBAiE/B,CAAC"}
1
+ {"version":3,"file":"useUsageLimitBanner.d.ts","sourceRoot":"","sources":["../../../src/usage/useUsageLimitBanner/useUsageLimitBanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,kCAAkC,CAAC;AAI1C,OAAO,EAAE,KAAK,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,sDAAsD,CAAC;AAI9D;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;IACjC,0EAA0E;;IAE1E,2EAA2E;;IAE3E,4EAA4E;;IAE5E,0EAA0E;;IAE1E,2EAA2E;;IAE3E,4EAA4E;;IAE5E,2CAA2C;;CAEnC,CAAC;AAkBX,6CAA6C;AAC7C,MAAM,WAAW,0BAA0B;IACzC,+CAA+C;IAC/C,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,+FAA+F;IAC/F,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,oEAAoE;IACpE,kBAAkB,EAAE,cAAc,CAAC,oBAAoB,CAAC,CAAC;IACzD,oEAAoE;IACpE,eAAe,EAAE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IACnD,oFAAoF;IACpF,uBAAuB,EAAE,MAAM,CAAC;IAChC,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,CAAC,EAAE,WAAW,CAAC;CAChB;AAED,gEAAgE;AAChE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,yBAAyB,EACzB,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,gBAAgB,CAClE,CAAC;AAEF,mDAAmD;AACnD,MAAM,WAAW,yBAAyB;IACxC,wIAAwI;IACxI,MAAM,EAAE,qBAAqB,GAAG,SAAS,CAAC;CAC3C;AAED;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAAI,0HAQjC,0BAA0B,KAAG,yBAqE/B,CAAC"}
@@ -26,41 +26,44 @@ var l = {
26
26
  [e.Week]: l.reachedWeek,
27
27
  [e.Month]: l.reachedMonth
28
28
  }
29
- }, d = ({ deploymentId: e, isGenerationInProgress: c = !1, getDeploymentLimits: d, warningThresholdPercent: f, activeLocale: p, t: m }) => {
30
- let { limitsDto: h, isLoading: g, refresh: _ } = r(e, d), { isDismissed: v, dismiss: y } = a();
29
+ }, d = ({ deploymentId: e, isGenerationInProgress: c = !1, getDeploymentUsage: d, getAccountUsage: f, warningThresholdPercent: p, activeLocale: m, t: h }) => {
30
+ let g = s(() => ({
31
+ getDeploymentUsage: d,
32
+ getAccountUsage: f
33
+ }), [d, f]), { sources: _, isLoading: v, refresh: y } = r(e, g), { isDismissed: b, dismiss: x } = a();
31
34
  i({
32
35
  isGenerationInProgress: c,
33
- isLoading: g,
34
- refresh: _
36
+ isLoading: v,
37
+ refresh: y
35
38
  });
36
- let b = s(() => t(h, f), [h, f]), x = s(() => {
37
- if (b != null && e) return {
38
- dismissalKey: `${e}:${b.period}:${b.severity}`,
39
- limitText: m(u[b.severity][b.period], { percent: b.usedPercent }),
40
- reset: n(b.resetsAt, b.period, p, m)
39
+ let S = s(() => t(_, p), [_, p]), C = s(() => {
40
+ if (S != null && e) return {
41
+ dismissalKey: `${e}:${S.period}:${S.severity}`,
42
+ limitText: h(u[S.severity][S.period], { percent: S.usedPercent }),
43
+ reset: n(S.resetsAt, S.period, m, h)
41
44
  };
42
45
  }, [
43
- b,
46
+ S,
44
47
  e,
45
- p,
46
- m
47
- ]), S = x?.dismissalKey, C = o(() => {
48
- S != null && y(S);
49
- }, [y, S]), w = m(l.closeLabel);
48
+ m,
49
+ h
50
+ ]), w = C?.dismissalKey, T = o(() => {
51
+ w != null && x(w);
52
+ }, [x, w]), E = h(l.closeLabel);
50
53
  return { banner: s(() => {
51
- if (!(b == null || x == null || v(x.dismissalKey))) return {
52
- severity: b.severity,
53
- limitText: x.limitText,
54
- reset: x.reset,
55
- onClose: C,
56
- closeAriaLabel: w
54
+ if (!(S == null || C == null || b(C.dismissalKey))) return {
55
+ severity: S.severity,
56
+ limitText: C.limitText,
57
+ reset: C.reset,
58
+ onClose: T,
59
+ closeAriaLabel: E
57
60
  };
58
61
  }, [
59
- b,
60
- x,
61
- v,
62
+ S,
62
63
  C,
63
- w
64
+ b,
65
+ T,
66
+ E
64
67
  ]) };
65
68
  };
66
69
  //#endregion