@epam/ai-dial-chat-hooks 1.3.0-dev.51 → 1.3.0-dev.55
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/catalog/useCatalogEditNavigation/useCatalogEditNavigation.d.ts.map +1 -1
- package/catalog/useCatalogEditNavigation/useCatalogEditNavigation.js +82 -82
- package/entry-points/usage-limits.d.ts +8 -0
- package/entry-points/usage-limits.d.ts.map +1 -0
- package/index.d.ts +7 -0
- package/index.d.ts.map +1 -1
- package/index.js +124 -117
- package/package.json +24 -15
- package/shared/application-schema.d.ts +2 -0
- package/shared/application-schema.d.ts.map +1 -1
- package/shared/application-schema.js +2 -2
- package/usage/map-usage-data-to-dashboard.d.ts +1 -16
- package/usage/map-usage-data-to-dashboard.d.ts.map +1 -1
- package/usage/usage-banner-source.d.ts +23 -0
- package/usage/usage-banner-source.d.ts.map +1 -0
- package/usage/usage-banner-source.js +36 -0
- package/usage/usage-period.d.ts +7 -0
- package/usage/usage-period.d.ts.map +1 -0
- package/usage/usage-period.js +6 -0
- package/usage/usage-reset-time.d.ts +69 -0
- package/usage/usage-reset-time.d.ts.map +1 -0
- package/usage/usage-reset-time.js +72 -0
- package/usage/useDeploymentUsageLimits/useDeploymentUsageLimits.d.ts +32 -0
- package/usage/useDeploymentUsageLimits/useDeploymentUsageLimits.d.ts.map +1 -0
- package/usage/useDeploymentUsageLimits/useDeploymentUsageLimits.js +39 -0
- package/usage/useRefreshUsageAfterGeneration/useRefreshUsageAfterGeneration.d.ts +16 -0
- package/usage/useRefreshUsageAfterGeneration/useRefreshUsageAfterGeneration.d.ts.map +1 -0
- package/usage/useRefreshUsageAfterGeneration/useRefreshUsageAfterGeneration.js +14 -0
- package/usage/useUsageLimitBanner/useUsageLimitBanner.d.ts +56 -0
- package/usage/useUsageLimitBanner/useUsageLimitBanner.d.ts.map +1 -0
- package/usage/useUsageLimitBanner/useUsageLimitBanner.js +67 -0
- package/usage/useUsageLimitBannerDismissal/useUsageLimitBannerDismissal.d.ts +14 -0
- package/usage/useUsageLimitBannerDismissal/useUsageLimitBannerDismissal.d.ts.map +1 -0
- package/usage/useUsageLimitBannerDismissal/useUsageLimitBannerDismissal.js +19 -0
- package/usage-limits.d.ts +2 -0
- package/usage-limits.js +8 -0
- package/utils.js +10 -10
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { UsagePeriod } from './usage-period';
|
|
2
|
+
/**
|
|
3
|
+
* i18n key strings the consuming app's translation bundle must define for the
|
|
4
|
+
* reset-time formatters to produce translated strings. The values are the
|
|
5
|
+
* default key paths used by AI DIAL Chat.
|
|
6
|
+
*/
|
|
7
|
+
export declare const USAGE_RESET_I18N_KEYS: {
|
|
8
|
+
/** Visible label for a full reset time. Receives `{ dateTime: string }`. */
|
|
9
|
+
readonly resetsAtLabel: "usage.resetsAtLabel";
|
|
10
|
+
/** Spoken label for a full reset time. Receives `{ dateTime: string }`. */
|
|
11
|
+
readonly resetsAtAriaLabel: "usage.resetsAtAriaLabel";
|
|
12
|
+
/** Short daily reset sentence. Receives `{ time: string }`. */
|
|
13
|
+
readonly resetsAtTime: "conversationInput.usageBanner.resetsAtTime";
|
|
14
|
+
/** Short weekly/monthly reset sentence. Receives `{ date: string }`. */
|
|
15
|
+
readonly resetsOnDate: "conversationInput.usageBanner.resetsOnDate";
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A DIAL Core `resetsAt` instant, normalized into the preformatted strings the
|
|
19
|
+
* usage dashboard renders. Every `Date` and `Intl` call for reset times lives
|
|
20
|
+
* in this module: the display components receive only these strings
|
|
21
|
+
* and never sees a raw timestamp, a locale, or a timezone.
|
|
22
|
+
*/
|
|
23
|
+
export interface ResetTimeDisplay {
|
|
24
|
+
/** Exclusive end of the period, as an epoch ms value, for boundary scheduling. */
|
|
25
|
+
resetsAtMs: number;
|
|
26
|
+
/** Machine-readable instant for a `<time dateTime>` attribute, e.g. '2026-09-16T00:00:00Z'. */
|
|
27
|
+
isoValue: string;
|
|
28
|
+
/** Visible label, e.g. 'Resets 16 Sept 2026, 03:00 GMT+3'. */
|
|
29
|
+
label: string;
|
|
30
|
+
/** Accessible expansion naming the timezone in full, e.g. 'Usage resets Sep 16, 2026 at 2:00 AM Central European Summer Time'. */
|
|
31
|
+
ariaLabel: string;
|
|
32
|
+
}
|
|
33
|
+
/** A translate function compatible with i18next's `TFunction`. */
|
|
34
|
+
export type TranslateFn = (key: string, options?: Record<string, unknown>) => string;
|
|
35
|
+
/**
|
|
36
|
+
* Formats DIAL Core's `resetsAt` for display in the viewer's locale and
|
|
37
|
+
* timezone, always stating the zone so a UTC boundary shown in local time is
|
|
38
|
+
* never ambiguous.
|
|
39
|
+
*
|
|
40
|
+
* Returns `undefined` on every failure path — an absent, empty, or
|
|
41
|
+
* unparseable value, or an `Intl` implementation that throws (embedded and
|
|
42
|
+
* restricted runtimes expose incomplete ones, which is why the resolution is
|
|
43
|
+
* wrapped, matching `getBrowserTimezone` in `@epam/ai-dial-chat-hooks`). A
|
|
44
|
+
* reset time is decoration on a usage figure and never a gate on it, so the
|
|
45
|
+
* caller renders the rest of the card unchanged when this returns nothing.
|
|
46
|
+
*
|
|
47
|
+
* The boundary is never derived from the browser's own calendar — no local
|
|
48
|
+
* midnight, no start-of-week, no arithmetic on `new Date()`.
|
|
49
|
+
*/
|
|
50
|
+
export declare const formatUsageResetTime: (resetsAt: string | undefined, activeLocale: string, t: TranslateFn) => ResetTimeDisplay | undefined;
|
|
51
|
+
/** A `resetsAt` instant as the one-sentence reset notice the composer usage banner renders. */
|
|
52
|
+
export interface ShortResetTimeDisplay {
|
|
53
|
+
/** Machine-readable instant for a `<time dateTime>` attribute, e.g. '2026-10-13T00:00:00Z'. */
|
|
54
|
+
isoValue: string;
|
|
55
|
+
/** Visible sentence, e.g. 'Resets at 3:00 AM GMT+3.' or 'Resets on Oct 19.'. */
|
|
56
|
+
label: string;
|
|
57
|
+
/** Accessible expansion with the full date, time and zone name, from `formatUsageResetTime`. */
|
|
58
|
+
ariaLabel: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Formats DIAL Core's `resetsAt` as the banner's reset sentence: a time with
|
|
62
|
+
* its zone offset for a daily period, a short date (with the year only when it
|
|
63
|
+
* is not the current one) for a weekly or monthly period.
|
|
64
|
+
*
|
|
65
|
+
* Returns `undefined` on the same failure paths as `formatUsageResetTime`,
|
|
66
|
+
* whose spoken form it reuses, so the caller renders the period sentence alone.
|
|
67
|
+
*/
|
|
68
|
+
export declare const formatUsageResetShort: (resetsAt: string | undefined, period: UsagePeriod, activeLocale: string, t: TranslateFn) => ShortResetTimeDisplay | undefined;
|
|
69
|
+
//# sourceMappingURL=usage-reset-time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-reset-time.d.ts","sourceRoot":"","sources":["../../src/usage/usage-reset-time.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;IAChC,4EAA4E;;IAE5E,2EAA2E;;IAE3E,+DAA+D;;IAE/D,wEAAwE;;CAEhE,CAAC;AAEX;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,kIAAkI;IAClI,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,CACxB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,MAAM,CAAC;AAEZ;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAU,MAAM,GAAG,SAAS,EAC5B,cAAc,MAAM,EACpB,GAAG,WAAW,KACb,gBAAgB,GAAG,SA+DrB,CAAC;AAEF,+FAA+F;AAC/F,MAAM,WAAW,qBAAqB;IACpC,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAChC,UAAU,MAAM,GAAG,SAAS,EAC5B,QAAQ,WAAW,EACnB,cAAc,MAAM,EACpB,GAAG,WAAW,KACb,qBAAqB,GAAG,SAiD1B,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { UsagePeriod as e } from "./usage-period.js";
|
|
2
|
+
//#region src/usage/usage-reset-time.ts
|
|
3
|
+
var t = {
|
|
4
|
+
resetsAtLabel: "usage.resetsAtLabel",
|
|
5
|
+
resetsAtAriaLabel: "usage.resetsAtAriaLabel",
|
|
6
|
+
resetsAtTime: "conversationInput.usageBanner.resetsAtTime",
|
|
7
|
+
resetsOnDate: "conversationInput.usageBanner.resetsOnDate"
|
|
8
|
+
}, n = (e, n, r) => {
|
|
9
|
+
if (!e) return;
|
|
10
|
+
let i = Date.parse(e);
|
|
11
|
+
if (!Number.isNaN(i)) try {
|
|
12
|
+
let a = Intl.DateTimeFormat().resolvedOptions().timeZone, o = new Date(i), s = a ? { timeZone: a } : {}, c = {
|
|
13
|
+
year: "numeric",
|
|
14
|
+
month: "short",
|
|
15
|
+
day: "numeric",
|
|
16
|
+
hour: "numeric",
|
|
17
|
+
minute: "2-digit"
|
|
18
|
+
}, l = new Intl.DateTimeFormat(n, {
|
|
19
|
+
...c,
|
|
20
|
+
timeZoneName: "shortOffset",
|
|
21
|
+
...s
|
|
22
|
+
}).format(o), u = new Intl.DateTimeFormat(n, {
|
|
23
|
+
...c,
|
|
24
|
+
timeZoneName: "long",
|
|
25
|
+
...s
|
|
26
|
+
}).format(o);
|
|
27
|
+
return {
|
|
28
|
+
resetsAtMs: i,
|
|
29
|
+
isoValue: e,
|
|
30
|
+
label: r(t.resetsAtLabel, { dateTime: l }),
|
|
31
|
+
ariaLabel: r(t.resetsAtAriaLabel, { dateTime: u })
|
|
32
|
+
};
|
|
33
|
+
} catch {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}, r = (r, i, a, o) => {
|
|
37
|
+
let s = n(r, a, o);
|
|
38
|
+
if (s != null) try {
|
|
39
|
+
let n = Intl.DateTimeFormat().resolvedOptions().timeZone, r = n ? { timeZone: n } : {}, c = new Date(s.resetsAtMs);
|
|
40
|
+
if (i === e.Day) {
|
|
41
|
+
let e = new Intl.DateTimeFormat(a, {
|
|
42
|
+
hour: "numeric",
|
|
43
|
+
minute: "2-digit",
|
|
44
|
+
timeZoneName: "shortOffset",
|
|
45
|
+
...r
|
|
46
|
+
}).format(c);
|
|
47
|
+
return {
|
|
48
|
+
isoValue: s.isoValue,
|
|
49
|
+
label: o(t.resetsAtTime, { time: e }),
|
|
50
|
+
ariaLabel: s.ariaLabel
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
let l = new Intl.DateTimeFormat("en-US", {
|
|
54
|
+
year: "numeric",
|
|
55
|
+
...r
|
|
56
|
+
}), u = l.format(c) !== l.format(/* @__PURE__ */ new Date()), d = new Intl.DateTimeFormat(a, {
|
|
57
|
+
month: "short",
|
|
58
|
+
day: "numeric",
|
|
59
|
+
...u ? { year: "numeric" } : {},
|
|
60
|
+
...r
|
|
61
|
+
}).format(c);
|
|
62
|
+
return {
|
|
63
|
+
isoValue: s.isoValue,
|
|
64
|
+
label: o(t.resetsOnDate, { date: d }),
|
|
65
|
+
ariaLabel: s.ariaLabel
|
|
66
|
+
};
|
|
67
|
+
} catch {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { t as USAGE_RESET_I18N_KEYS, r as formatUsageResetShort, n as formatUsageResetTime };
|
|
@@ -0,0 +1,32 @@
|
|
|
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>;
|
|
4
|
+
/** Return shape of {@link useDeploymentUsageLimits}. */
|
|
5
|
+
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. */
|
|
9
|
+
isLoading: boolean;
|
|
10
|
+
/** `true` after the most recent fetch rejected. */
|
|
11
|
+
hasError: boolean;
|
|
12
|
+
/** Re-fetches the current deployment when no request is in flight. */
|
|
13
|
+
refresh: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
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.
|
|
21
|
+
*
|
|
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.
|
|
25
|
+
*
|
|
26
|
+
* The raw response is returned rather than a mapped display model: mapping
|
|
27
|
+
* needs the caller's translated labels and locale-bound reset formatter, and
|
|
28
|
+
* holding the mapped value in state here would leave it stale after a language
|
|
29
|
+
* change until the next fetch.
|
|
30
|
+
*/
|
|
31
|
+
export declare const useDeploymentUsageLimits: (deploymentId: string | undefined, getDeploymentLimits: GetDeploymentLimits) => UseDeploymentUsageLimitsResult;
|
|
32
|
+
//# sourceMappingURL=useDeploymentUsageLimits.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback as e, useEffect as t, useRef as n, useState as r } from "react";
|
|
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);
|
|
8
|
+
}, []);
|
|
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;
|
|
13
|
+
return;
|
|
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
|
+
}
|
|
28
|
+
})(), () => {
|
|
29
|
+
n = !0;
|
|
30
|
+
};
|
|
31
|
+
}, [i, f]), {
|
|
32
|
+
limitsDto: o,
|
|
33
|
+
isLoading: c,
|
|
34
|
+
hasError: u,
|
|
35
|
+
refresh: v
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { i as useDeploymentUsageLimits };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface UseRefreshUsageAfterGenerationOptions {
|
|
2
|
+
/** Whether the selected deployment is currently generating a response. */
|
|
3
|
+
isGenerationInProgress: boolean;
|
|
4
|
+
/** `true` while the usage fetch is in flight; a pending refresh waits for it. */
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
/** Re-fetches the usage limits. */
|
|
7
|
+
refresh: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Refreshes usage limits once after a response finishes streaming
|
|
11
|
+
* (`isGenerationInProgress` `true` → `false`), deferring the refresh while a
|
|
12
|
+
* fetch is still in flight. Shared by the usage dial and the usage banner so
|
|
13
|
+
* the two cannot drift.
|
|
14
|
+
*/
|
|
15
|
+
export declare const useRefreshUsageAfterGeneration: ({ isGenerationInProgress, isLoading, refresh, }: UseRefreshUsageAfterGenerationOptions) => void;
|
|
16
|
+
//# sourceMappingURL=useRefreshUsageAfterGeneration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRefreshUsageAfterGeneration.d.ts","sourceRoot":"","sources":["../../../src/usage/useRefreshUsageAfterGeneration/useRefreshUsageAfterGeneration.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,qCAAqC;IACpD,0EAA0E;IAC1E,sBAAsB,EAAE,OAAO,CAAC;IAChC,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,mCAAmC;IACnC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GAAI,iDAI5C,qCAAqC,KAAG,IAe1C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect as e, useRef as t } from "react";
|
|
2
|
+
//#region src/usage/useRefreshUsageAfterGeneration/useRefreshUsageAfterGeneration.ts
|
|
3
|
+
var n = ({ isGenerationInProgress: n, isLoading: r, refresh: i }) => {
|
|
4
|
+
let a = t(n), o = t(!1);
|
|
5
|
+
e(() => {
|
|
6
|
+
a.current && !n && (o.current = !0), a.current = n, o.current && !r && (o.current = !1, i());
|
|
7
|
+
}, [
|
|
8
|
+
n,
|
|
9
|
+
r,
|
|
10
|
+
i
|
|
11
|
+
]);
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { n as useRefreshUsageAfterGeneration };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { UsageLimitBannerViewProps } from '@epam/ai-dial-conversation-input';
|
|
2
|
+
import { TranslateFn } from '../usage-reset-time';
|
|
3
|
+
import { GetDeploymentLimits } from '../useDeploymentUsageLimits/useDeploymentUsageLimits';
|
|
4
|
+
/**
|
|
5
|
+
* i18n key strings the consuming app's translation bundle must define for
|
|
6
|
+
* `useUsageLimitBanner` to produce translated strings, in addition to
|
|
7
|
+
* `USAGE_RESET_I18N_KEYS`. The values are the default key paths used by AI
|
|
8
|
+
* DIAL Chat.
|
|
9
|
+
*/
|
|
10
|
+
export declare const USAGE_BANNER_I18N_KEYS: {
|
|
11
|
+
/** Warning sentence for a daily limit. Receives `{ percent: number }`. */
|
|
12
|
+
readonly warningDay: "conversationInput.usageBanner.warningDay";
|
|
13
|
+
/** Warning sentence for a weekly limit. Receives `{ percent: number }`. */
|
|
14
|
+
readonly warningWeek: "conversationInput.usageBanner.warningWeek";
|
|
15
|
+
/** Warning sentence for a monthly limit. Receives `{ percent: number }`. */
|
|
16
|
+
readonly warningMonth: "conversationInput.usageBanner.warningMonth";
|
|
17
|
+
/** Reached sentence for a daily limit. Receives `{ percent: number }`. */
|
|
18
|
+
readonly reachedDay: "conversationInput.usageBanner.reachedDay";
|
|
19
|
+
/** Reached sentence for a weekly limit. Receives `{ percent: number }`. */
|
|
20
|
+
readonly reachedWeek: "conversationInput.usageBanner.reachedWeek";
|
|
21
|
+
/** Reached sentence for a monthly limit. Receives `{ percent: number }`. */
|
|
22
|
+
readonly reachedMonth: "conversationInput.usageBanner.reachedMonth";
|
|
23
|
+
/** Accessible name of the close button. */
|
|
24
|
+
readonly closeLabel: "conversationInput.usageBanner.closeLabel";
|
|
25
|
+
};
|
|
26
|
+
/** Inputs of {@link useUsageLimitBanner}. */
|
|
27
|
+
export interface UseUsageLimitBannerOptions {
|
|
28
|
+
/** ID of the currently selected deployment. */
|
|
29
|
+
deploymentId: string | undefined;
|
|
30
|
+
/** Whether the selected deployment is currently generating a response. Defaults to `false`. */
|
|
31
|
+
isGenerationInProgress?: boolean;
|
|
32
|
+
/** Host-configured call that fetches one deployment's limits. */
|
|
33
|
+
getDeploymentLimits: GetDeploymentLimits;
|
|
34
|
+
/** Used percentage at or above which a not-yet-exhausted limit raises a warning. */
|
|
35
|
+
warningThresholdPercent: number;
|
|
36
|
+
/** Active UI locale, used to format the reset time. */
|
|
37
|
+
activeLocale: string;
|
|
38
|
+
/** Translate function compatible with i18next's `TFunction`. */
|
|
39
|
+
t: TranslateFn;
|
|
40
|
+
}
|
|
41
|
+
/** The part of `UsageLimitBannerViewProps` the hook decides. */
|
|
42
|
+
export type UsageLimitBannerState = Pick<UsageLimitBannerViewProps, 'severity' | 'limitText' | 'reset' | 'onClose' | 'closeAriaLabel'>;
|
|
43
|
+
/** Return shape of {@link useUsageLimitBanner}. */
|
|
44
|
+
export interface UseUsageLimitBannerResult {
|
|
45
|
+
/** Props for `UsageLimitBannerView`, or `undefined` when no banner should render (no deployment, below the threshold, or dismissed). */
|
|
46
|
+
banner: UsageLimitBannerState | undefined;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 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`.
|
|
54
|
+
*/
|
|
55
|
+
export declare const useUsageLimitBanner: ({ deploymentId, isGenerationInProgress, getDeploymentLimits, warningThresholdPercent, activeLocale, t, }: UseUsageLimitBannerOptions) => UseUsageLimitBannerResult;
|
|
56
|
+
//# sourceMappingURL=useUsageLimitBanner.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { UsagePeriod as e } from "../usage-period.js";
|
|
2
|
+
import { selectUsageBannerSource as t } from "../usage-banner-source.js";
|
|
3
|
+
import { formatUsageResetShort as n } from "../usage-reset-time.js";
|
|
4
|
+
import { useDeploymentUsageLimits as r } from "../useDeploymentUsageLimits/useDeploymentUsageLimits.js";
|
|
5
|
+
import { useRefreshUsageAfterGeneration as i } from "../useRefreshUsageAfterGeneration/useRefreshUsageAfterGeneration.js";
|
|
6
|
+
import { useUsageLimitBannerDismissal as a } from "../useUsageLimitBannerDismissal/useUsageLimitBannerDismissal.js";
|
|
7
|
+
import { useCallback as o, useMemo as s } from "react";
|
|
8
|
+
import { UsageLimitBannerSeverity as c } from "@epam/ai-dial-conversation-input";
|
|
9
|
+
//#region src/usage/useUsageLimitBanner/useUsageLimitBanner.ts
|
|
10
|
+
var l = {
|
|
11
|
+
warningDay: "conversationInput.usageBanner.warningDay",
|
|
12
|
+
warningWeek: "conversationInput.usageBanner.warningWeek",
|
|
13
|
+
warningMonth: "conversationInput.usageBanner.warningMonth",
|
|
14
|
+
reachedDay: "conversationInput.usageBanner.reachedDay",
|
|
15
|
+
reachedWeek: "conversationInput.usageBanner.reachedWeek",
|
|
16
|
+
reachedMonth: "conversationInput.usageBanner.reachedMonth",
|
|
17
|
+
closeLabel: "conversationInput.usageBanner.closeLabel"
|
|
18
|
+
}, u = {
|
|
19
|
+
[c.Warning]: {
|
|
20
|
+
[e.Day]: l.warningDay,
|
|
21
|
+
[e.Week]: l.warningWeek,
|
|
22
|
+
[e.Month]: l.warningMonth
|
|
23
|
+
},
|
|
24
|
+
[c.Reached]: {
|
|
25
|
+
[e.Day]: l.reachedDay,
|
|
26
|
+
[e.Week]: l.reachedWeek,
|
|
27
|
+
[e.Month]: l.reachedMonth
|
|
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();
|
|
31
|
+
i({
|
|
32
|
+
isGenerationInProgress: c,
|
|
33
|
+
isLoading: g,
|
|
34
|
+
refresh: _
|
|
35
|
+
});
|
|
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)
|
|
41
|
+
};
|
|
42
|
+
}, [
|
|
43
|
+
b,
|
|
44
|
+
e,
|
|
45
|
+
p,
|
|
46
|
+
m
|
|
47
|
+
]), S = x?.dismissalKey, C = o(() => {
|
|
48
|
+
S != null && y(S);
|
|
49
|
+
}, [y, S]), w = m(l.closeLabel);
|
|
50
|
+
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
|
|
57
|
+
};
|
|
58
|
+
}, [
|
|
59
|
+
b,
|
|
60
|
+
x,
|
|
61
|
+
v,
|
|
62
|
+
C,
|
|
63
|
+
w
|
|
64
|
+
]) };
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
export { l as USAGE_BANNER_I18N_KEYS, d as useUsageLimitBanner };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface UseUsageLimitBannerDismissalResult {
|
|
2
|
+
/** `true` when the banner was dismissed for `key` in this tab. */
|
|
3
|
+
isDismissed: (key: string) => boolean;
|
|
4
|
+
/** Records a dismissal for `key`, hiding every banner that shows it. */
|
|
5
|
+
dismiss: (key: string) => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Tab-lifetime, in-memory record of dismissed usage-banner keys
|
|
9
|
+
* (`${deploymentId}:${period}:${severity}`), shared by every composer.
|
|
10
|
+
*/
|
|
11
|
+
export declare const useUsageLimitBannerDismissal: () => UseUsageLimitBannerDismissalResult;
|
|
12
|
+
/** Clears every recorded dismissal. Test isolation only. */
|
|
13
|
+
export declare const resetUsageLimitBannerDismissals: () => void;
|
|
14
|
+
//# sourceMappingURL=useUsageLimitBannerDismissal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUsageLimitBannerDismissal.d.ts","sourceRoot":"","sources":["../../../src/usage/useUsageLimitBannerDismissal/useUsageLimitBannerDismissal.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,kCAAkC;IACjD,kEAAkE;IAClE,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,wEAAwE;IACxE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,QACnC,kCAWH,CAAC;AAEJ,4DAA4D;AAC5D,eAAO,MAAM,+BAA+B,QAAO,IAElD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useCallback as e, useSyncExternalStore as t } from "react";
|
|
2
|
+
//#region src/usage/useUsageLimitBannerDismissal/useUsageLimitBannerDismissal.ts
|
|
3
|
+
var n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = (e) => {
|
|
4
|
+
n = e, r.forEach((e) => e());
|
|
5
|
+
}, a = (e) => (r.add(e), () => {
|
|
6
|
+
r.delete(e);
|
|
7
|
+
}), o = () => n, s = () => {
|
|
8
|
+
let r = t(a, o, o);
|
|
9
|
+
return {
|
|
10
|
+
isDismissed: e((e) => r.has(e), [r]),
|
|
11
|
+
dismiss: e((e) => {
|
|
12
|
+
n.has(e) || i(new Set([...n, e]));
|
|
13
|
+
}, [])
|
|
14
|
+
};
|
|
15
|
+
}, c = () => {
|
|
16
|
+
i(/* @__PURE__ */ new Set());
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { c as resetUsageLimitBannerDismissals, s as useUsageLimitBannerDismissal };
|
package/usage-limits.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { UsagePeriod as e } from "./usage/usage-period.js";
|
|
2
|
+
import { isCappedStat as t, selectUsageBannerSource as n } from "./usage/usage-banner-source.js";
|
|
3
|
+
import { USAGE_RESET_I18N_KEYS as r, formatUsageResetShort as i, formatUsageResetTime as a } from "./usage/usage-reset-time.js";
|
|
4
|
+
import { useDeploymentUsageLimits as o } from "./usage/useDeploymentUsageLimits/useDeploymentUsageLimits.js";
|
|
5
|
+
import { useRefreshUsageAfterGeneration as s } from "./usage/useRefreshUsageAfterGeneration/useRefreshUsageAfterGeneration.js";
|
|
6
|
+
import { resetUsageLimitBannerDismissals as c, useUsageLimitBannerDismissal as l } from "./usage/useUsageLimitBannerDismissal/useUsageLimitBannerDismissal.js";
|
|
7
|
+
import { USAGE_BANNER_I18N_KEYS as u, useUsageLimitBanner as d } from "./usage/useUsageLimitBanner/useUsageLimitBanner.js";
|
|
8
|
+
export { u as USAGE_BANNER_I18N_KEYS, r as USAGE_RESET_I18N_KEYS, e as UsagePeriod, i as formatUsageResetShort, a as formatUsageResetTime, t as isCappedStat, c as resetUsageLimitBannerDismissals, n as selectUsageBannerSource, o as useDeploymentUsageLimits, s as useRefreshUsageAfterGeneration, d as useUsageLimitBanner, l as useUsageLimitBannerDismissal };
|
package/utils.js
CHANGED
|
@@ -5,13 +5,13 @@ import { includesIgnoreCase as o, safeDecodeURI as s, safeDecodeURIComponent as
|
|
|
5
5
|
import { appendLocaleCode as d, buildAdditionalLocaleOptions as f, composeLocalePayload as p, decomposeLocalizedFields as m, resolveLocalizedText as h, toBaseLocale as g } from "./shared/locale.js";
|
|
6
6
|
import { formatCalendarDate as _, padTwoDigits as v } from "./shared/formatting.js";
|
|
7
7
|
import { PromptSource as y, parsePromptResourceUrl as b } from "./prompt/prompt-resource.js";
|
|
8
|
-
import { getRunnerSchemas as x, isCustomAppSchema as S,
|
|
9
|
-
import { buildPromptExportEnvelope as
|
|
10
|
-
import { PROMPT_CONTENT_MAX_LENGTH as
|
|
11
|
-
import { usePromptsState as
|
|
12
|
-
import { apSchedulerDayToJsDay as
|
|
13
|
-
import { getBrowserTimezone as
|
|
14
|
-
import { isValidAbsoluteUrl as
|
|
15
|
-
import { buildExternalServiceScopeId as
|
|
16
|
-
import { useUsageData as
|
|
17
|
-
export {
|
|
8
|
+
import { getRunnerSchemas as x, isCustomAppSchema as S, isMindMapSchema as C, isQuickAppSchema as w } from "./shared/application-schema.js";
|
|
9
|
+
import { buildPromptExportEnvelope as T, buildPromptExportFileName as E, serializePromptExport as D } from "./prompt/export-prompt.js";
|
|
10
|
+
import { PROMPT_CONTENT_MAX_LENGTH as O, PROMPT_COUNTER_ANNOUNCE_THRESHOLD as k, PROMPT_DESCRIPTION_MAX_LENGTH as A, PROMPT_NAME_MAX_LENGTH as j, PromptFieldError as M, buildPromptPath as N, getRemainingCharacters as P, validatePromptContent as F, validatePromptDescription as I, validatePromptName as L } from "./prompt/prompt.js";
|
|
11
|
+
import { usePromptsState as R } from "./prompt/usePromptsState/usePromptsState.js";
|
|
12
|
+
import { apSchedulerDayToJsDay as z, jsDayToApSchedulerDay as B } from "./shared/cron-weekday.js";
|
|
13
|
+
import { getBrowserTimezone as V } from "./shared/browser-timezone.js";
|
|
14
|
+
import { isValidAbsoluteUrl as H, isValidFeaturesData as U, parseFeaturesData as W } from "./shared/custom-apps.js";
|
|
15
|
+
import { buildExternalServiceScopeId as G, getExternalServiceFallbackName as K, parseExternalServiceUrl as q } from "./shared/external-services.js";
|
|
16
|
+
import { useUsageData as J } from "./usage/useUsageData/useUsageData.js";
|
|
17
|
+
export { O as PROMPT_CONTENT_MAX_LENGTH, k as PROMPT_COUNTER_ANNOUNCE_THRESHOLD, A as PROMPT_DESCRIPTION_MAX_LENGTH, j as PROMPT_NAME_MAX_LENGTH, M as PromptFieldError, y as PromptSource, z as apSchedulerDayToJsDay, d as appendLocaleCode, f as buildAdditionalLocaleOptions, G as buildExternalServiceScopeId, T as buildPromptExportEnvelope, E as buildPromptExportFileName, N as buildPromptPath, p as composeLocalePayload, i as createCsrfMiddleware, a as createUnauthorizedMiddleware, m as decomposeLocalizedFields, _ as formatCalendarDate, e as getApiErrorDetails, t as getApiErrorMessage, n as getApiErrorStatus, V as getBrowserTimezone, K as getExternalServiceFallbackName, P as getRemainingCharacters, x as getRunnerSchemas, o as includesIgnoreCase, r as isConversationNotFoundError, S as isCustomAppSchema, C as isMindMapSchema, w as isQuickAppSchema, H as isValidAbsoluteUrl, U as isValidFeaturesData, B as jsDayToApSchedulerDay, v as padTwoDigits, q as parseExternalServiceUrl, W as parseFeaturesData, b as parsePromptResourceUrl, h as resolveLocalizedText, s as safeDecodeURI, c as safeDecodeURIComponent, D as serializePromptExport, l as stripSurroundingSlashes, u as stripTrailingSlashes, g as toBaseLocale, R as usePromptsState, J as useUsageData, F as validatePromptContent, I as validatePromptDescription, L as validatePromptName };
|