@iblai/data-layer 1.18.1 → 1.19.1
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/dist/index.d.ts +744 -3
- package/dist/index.esm.js +399 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +421 -0
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/features/analytics/types.d.ts +3 -0
- package/dist/src/features/user-llm-usage/__tests__/api-slice.test.d.ts +1 -0
- package/dist/src/features/user-llm-usage/__tests__/hooks.test.d.ts +1 -0
- package/dist/src/features/user-llm-usage/__tests__/utils.test.d.ts +1 -0
- package/dist/src/features/user-llm-usage/api-slice.d.ts +488 -0
- package/dist/src/features/user-llm-usage/constants.d.ts +25 -0
- package/dist/src/features/user-llm-usage/hooks.d.ts +43 -0
- package/dist/src/features/user-llm-usage/types.d.ts +150 -0
- package/dist/src/features/user-llm-usage/utils.d.ts +35 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -48424,6 +48424,396 @@ const USER_CHAT_HISTORY_REPORT_ACTIVE_STATES = [
|
|
|
48424
48424
|
'storing',
|
|
48425
48425
|
];
|
|
48426
48426
|
|
|
48427
|
+
const USER_LLM_USAGE_REDUCER_PATH = 'userLlmUsageApiSlice';
|
|
48428
|
+
const USER_LLM_USAGE_QUERY_KEYS = {
|
|
48429
|
+
GET_USER_LLM_USAGE: () => ['USER_LLM_USAGE'],
|
|
48430
|
+
};
|
|
48431
|
+
/** Upstream cap on `limit`. */
|
|
48432
|
+
const USER_LLM_USAGE_MAX_LIMIT = 1000;
|
|
48433
|
+
/**
|
|
48434
|
+
* The same llm-usage endpoint the admin analytics use, always scoped to one
|
|
48435
|
+
* `username`. The path builder is the admin one, so array params (`measures`)
|
|
48436
|
+
* serialize identically — comma-joined — and empty values are dropped the
|
|
48437
|
+
* same way.
|
|
48438
|
+
*/
|
|
48439
|
+
const USER_LLM_USAGE_ENDPOINTS = {
|
|
48440
|
+
GET_USER_LLM_USAGE: {
|
|
48441
|
+
service: exports.SERVICES.DM,
|
|
48442
|
+
path: ({ resource, ...rest }) => NON_AI_ANALYTICS_ENDPOINTS.GET_LLM_USAGE.path(resource, rest),
|
|
48443
|
+
},
|
|
48444
|
+
};
|
|
48445
|
+
/**
|
|
48446
|
+
* User-safe fallbacks per error kind. None of them echo the backend's detail,
|
|
48447
|
+
* so a 403 or 404 never tells the viewer whether another user or tenant exists.
|
|
48448
|
+
*/
|
|
48449
|
+
const USER_LLM_USAGE_ERROR_MESSAGES = {
|
|
48450
|
+
forbidden: 'Usage data is not available for this account.',
|
|
48451
|
+
not_found: 'Usage data is not available for this account.',
|
|
48452
|
+
unauthorized: 'Your session has expired. Sign in again to see your usage.',
|
|
48453
|
+
unavailable: 'Usage data is temporarily unavailable. Please try again later.',
|
|
48454
|
+
invalid_params: 'This usage request is not supported.',
|
|
48455
|
+
unknown: 'Something went wrong while loading your usage.',
|
|
48456
|
+
};
|
|
48457
|
+
|
|
48458
|
+
const RESOURCES = ['metrics', 'traces', 'observations'];
|
|
48459
|
+
/** Params the backend refuses on the observations resource. */
|
|
48460
|
+
const NOT_ON_OBSERVATIONS = ['session_id', 'mentor_unique_id'];
|
|
48461
|
+
const isSet = (value) => value !== undefined && value !== null && value !== '';
|
|
48462
|
+
/**
|
|
48463
|
+
* Runtime twin of the param types, for params assembled dynamically where the
|
|
48464
|
+
* compiler cannot see them. Runs before every request, so an invalid
|
|
48465
|
+
* combination never leaves the browser.
|
|
48466
|
+
*/
|
|
48467
|
+
function validateUserLlmUsageParams(params) {
|
|
48468
|
+
if (!params || typeof params !== 'object') {
|
|
48469
|
+
return { ok: false, reason: 'params must be an object' };
|
|
48470
|
+
}
|
|
48471
|
+
const p = params;
|
|
48472
|
+
if (!RESOURCES.includes(p.resource)) {
|
|
48473
|
+
return { ok: false, reason: `unknown resource "${String(p.resource)}"` };
|
|
48474
|
+
}
|
|
48475
|
+
if (typeof p.platform_key !== 'string' || p.platform_key.trim() === '') {
|
|
48476
|
+
return { ok: false, reason: 'platform_key is required' };
|
|
48477
|
+
}
|
|
48478
|
+
if (typeof p.username !== 'string' || p.username.trim() === '') {
|
|
48479
|
+
// Without it the backend falls back to the caller's own scope, which for
|
|
48480
|
+
// an admin is every user on the platform.
|
|
48481
|
+
return { ok: false, reason: 'username is required' };
|
|
48482
|
+
}
|
|
48483
|
+
if (p.resource === 'observations') {
|
|
48484
|
+
const offending = NOT_ON_OBSERVATIONS.find((key) => isSet(p[key]));
|
|
48485
|
+
if (offending) {
|
|
48486
|
+
return { ok: false, reason: `${offending} is not allowed on observations` };
|
|
48487
|
+
}
|
|
48488
|
+
}
|
|
48489
|
+
const hasDates = isSet(p.start_date) || isSet(p.end_date);
|
|
48490
|
+
if (p.date_filter === 'custom') {
|
|
48491
|
+
if (!isSet(p.start_date) || !isSet(p.end_date)) {
|
|
48492
|
+
return { ok: false, reason: 'a custom range needs both start_date and end_date' };
|
|
48493
|
+
}
|
|
48494
|
+
}
|
|
48495
|
+
else if (hasDates) {
|
|
48496
|
+
return { ok: false, reason: 'start_date/end_date require date_filter "custom"' };
|
|
48497
|
+
}
|
|
48498
|
+
if (isSet(p.limit)) {
|
|
48499
|
+
const limit = Number(p.limit);
|
|
48500
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > USER_LLM_USAGE_MAX_LIMIT) {
|
|
48501
|
+
return { ok: false, reason: `limit must be between 1 and ${USER_LLM_USAGE_MAX_LIMIT}` };
|
|
48502
|
+
}
|
|
48503
|
+
}
|
|
48504
|
+
return { ok: true, params: params };
|
|
48505
|
+
}
|
|
48506
|
+
const errorFor = (kind, status) => ({
|
|
48507
|
+
kind,
|
|
48508
|
+
...(status !== undefined && { status }),
|
|
48509
|
+
message: USER_LLM_USAGE_ERROR_MESSAGES[kind],
|
|
48510
|
+
});
|
|
48511
|
+
/**
|
|
48512
|
+
* Maps whatever a usage query failed with onto a typed, user-safe error.
|
|
48513
|
+
* The backend's own `detail`/`error` text is never carried over.
|
|
48514
|
+
*
|
|
48515
|
+
* A 401 is reported as `unauthorized` for completeness, but it has already
|
|
48516
|
+
* gone through the app's registered auth handler (token refresh, then the
|
|
48517
|
+
* host's 401 handler) inside the base query before it gets here.
|
|
48518
|
+
*/
|
|
48519
|
+
function normalizeUserLlmUsageError(error) {
|
|
48520
|
+
if (error === undefined || error === null)
|
|
48521
|
+
return null;
|
|
48522
|
+
if (typeof error !== 'object')
|
|
48523
|
+
return errorFor('unknown');
|
|
48524
|
+
const { status, data } = error;
|
|
48525
|
+
if (status === 'CUSTOM_ERROR') {
|
|
48526
|
+
const kind = data === null || data === void 0 ? void 0 : data.kind;
|
|
48527
|
+
return errorFor(kind === 'invalid_params' ? 'invalid_params' : 'unknown', status);
|
|
48528
|
+
}
|
|
48529
|
+
if (status === 'FETCH_ERROR' || status === 'TIMEOUT_ERROR') {
|
|
48530
|
+
return errorFor('unavailable', status);
|
|
48531
|
+
}
|
|
48532
|
+
if (typeof status === 'number') {
|
|
48533
|
+
if (status === 401)
|
|
48534
|
+
return errorFor('unauthorized', status);
|
|
48535
|
+
if (status === 403)
|
|
48536
|
+
return errorFor('forbidden', status);
|
|
48537
|
+
if (status === 404)
|
|
48538
|
+
return errorFor('not_found', status);
|
|
48539
|
+
if (status === 502 || status === 503 || status === 504)
|
|
48540
|
+
return errorFor('unavailable', status);
|
|
48541
|
+
return errorFor('unknown', status);
|
|
48542
|
+
}
|
|
48543
|
+
return errorFor('unknown');
|
|
48544
|
+
}
|
|
48545
|
+
/**
|
|
48546
|
+
* Wraps the raw response so `data` is always a list. Single-item lookups
|
|
48547
|
+
* (`trace_id`, `observation_id`) come back as one object without `meta`.
|
|
48548
|
+
*/
|
|
48549
|
+
function toUserLlmUsageEnvelope(raw, resource) {
|
|
48550
|
+
const body = (raw && typeof raw === 'object' ? raw : {});
|
|
48551
|
+
const data = Array.isArray(body.data)
|
|
48552
|
+
? body.data
|
|
48553
|
+
: body.data && typeof body.data === 'object'
|
|
48554
|
+
? [body.data]
|
|
48555
|
+
: [];
|
|
48556
|
+
const envelope = { resource, data };
|
|
48557
|
+
if (resource !== 'metrics' && body.meta) {
|
|
48558
|
+
envelope.meta = body.meta;
|
|
48559
|
+
}
|
|
48560
|
+
return envelope;
|
|
48561
|
+
}
|
|
48562
|
+
/**
|
|
48563
|
+
* Empty-state rule shared by every usage hook: paginated resources trust
|
|
48564
|
+
* `meta.totalItems`; metrics (and unpaginated lookups) fall back to the rows.
|
|
48565
|
+
*/
|
|
48566
|
+
function isUserLlmUsageEmpty(envelope) {
|
|
48567
|
+
if (!envelope)
|
|
48568
|
+
return false;
|
|
48569
|
+
if (envelope.meta && typeof envelope.meta.totalItems === 'number') {
|
|
48570
|
+
return envelope.meta.totalItems === 0;
|
|
48571
|
+
}
|
|
48572
|
+
return envelope.data.length === 0;
|
|
48573
|
+
}
|
|
48574
|
+
/** Reads a numeric measure (`sum_totalCost`, `avg_latency`, …) off a metrics row. */
|
|
48575
|
+
function readMeasure(row, key) {
|
|
48576
|
+
const value = row === null || row === void 0 ? void 0 : row[key];
|
|
48577
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
48578
|
+
return value;
|
|
48579
|
+
if (typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value))) {
|
|
48580
|
+
return Number(value);
|
|
48581
|
+
}
|
|
48582
|
+
return 0;
|
|
48583
|
+
}
|
|
48584
|
+
|
|
48585
|
+
/**
|
|
48586
|
+
* One request through the app's standard base query (auth header, token
|
|
48587
|
+
* refresh, registered 401 handler). `iblFetchBaseQuery` throws on HTTP
|
|
48588
|
+
* errors, and a thrown error would reach RTK as a SerializedError with the
|
|
48589
|
+
* status stripped; catching it here keeps `{ status, data }` intact so the
|
|
48590
|
+
* view can tell a 403 from a 404.
|
|
48591
|
+
*/
|
|
48592
|
+
async function fetchUserLlmUsage(params, api, extraOptions) {
|
|
48593
|
+
const check = validateUserLlmUsageParams(params);
|
|
48594
|
+
if (!check.ok) {
|
|
48595
|
+
return {
|
|
48596
|
+
error: {
|
|
48597
|
+
status: 'CUSTOM_ERROR',
|
|
48598
|
+
error: check.reason,
|
|
48599
|
+
data: { kind: 'invalid_params', error: check.reason },
|
|
48600
|
+
},
|
|
48601
|
+
};
|
|
48602
|
+
}
|
|
48603
|
+
try {
|
|
48604
|
+
const result = await iblFetchBaseQuery({
|
|
48605
|
+
url: USER_LLM_USAGE_ENDPOINTS.GET_USER_LLM_USAGE.path(check.params),
|
|
48606
|
+
service: USER_LLM_USAGE_ENDPOINTS.GET_USER_LLM_USAGE.service,
|
|
48607
|
+
}, api, extraOptions);
|
|
48608
|
+
if ('error' in result && result.error) {
|
|
48609
|
+
return { error: result.error };
|
|
48610
|
+
}
|
|
48611
|
+
return { data: toUserLlmUsageEnvelope(result.data, params.resource) };
|
|
48612
|
+
}
|
|
48613
|
+
catch (error) {
|
|
48614
|
+
return { error: error };
|
|
48615
|
+
}
|
|
48616
|
+
}
|
|
48617
|
+
/**
|
|
48618
|
+
* Per-user llm-usage queries. Registered in the mentor and skills stores.
|
|
48619
|
+
* Cache entries are keyed on the full param object, so `platform_key`,
|
|
48620
|
+
* `username`, `resource` and every filter take part in the key.
|
|
48621
|
+
*/
|
|
48622
|
+
const userLlmUsageApiSlice = react.createApi({
|
|
48623
|
+
reducerPath: USER_LLM_USAGE_REDUCER_PATH,
|
|
48624
|
+
baseQuery: iblFakeBaseQuery,
|
|
48625
|
+
tagTypes: [...USER_LLM_USAGE_QUERY_KEYS.GET_USER_LLM_USAGE()],
|
|
48626
|
+
endpoints: (builder) => ({
|
|
48627
|
+
getUserLlmUsageMetrics: builder.query({
|
|
48628
|
+
queryFn: (params, api, extraOptions) => fetchUserLlmUsage(params, api, extraOptions),
|
|
48629
|
+
providesTags: USER_LLM_USAGE_QUERY_KEYS.GET_USER_LLM_USAGE(),
|
|
48630
|
+
}),
|
|
48631
|
+
getUserLlmUsageTraces: builder.query({
|
|
48632
|
+
queryFn: (params, api, extraOptions) => fetchUserLlmUsage(params, api, extraOptions),
|
|
48633
|
+
providesTags: USER_LLM_USAGE_QUERY_KEYS.GET_USER_LLM_USAGE(),
|
|
48634
|
+
}),
|
|
48635
|
+
getUserLlmUsageObservations: builder.query({
|
|
48636
|
+
queryFn: (params, api, extraOptions) => fetchUserLlmUsage(params, api, extraOptions),
|
|
48637
|
+
providesTags: USER_LLM_USAGE_QUERY_KEYS.GET_USER_LLM_USAGE(),
|
|
48638
|
+
}),
|
|
48639
|
+
}),
|
|
48640
|
+
});
|
|
48641
|
+
const { useGetUserLlmUsageMetricsQuery, useGetUserLlmUsageTracesQuery, useGetUserLlmUsageObservationsQuery, } = userLlmUsageApiSlice;
|
|
48642
|
+
|
|
48643
|
+
/** A query needs a platform key and a user; without either it stays idle. */
|
|
48644
|
+
const shouldSkip = (params, options) => !!(options === null || options === void 0 ? void 0 : options.skip) || !params || !params.platform_key || !params.username;
|
|
48645
|
+
function useDerivedState(query, isIdle) {
|
|
48646
|
+
const { data, error, isLoading, isFetching, refetch } = query;
|
|
48647
|
+
return react$1.useMemo(() => {
|
|
48648
|
+
var _a;
|
|
48649
|
+
const normalized = isIdle ? null : normalizeUserLlmUsageError(error);
|
|
48650
|
+
return {
|
|
48651
|
+
rows: (_a = data === null || data === void 0 ? void 0 : data.data) !== null && _a !== void 0 ? _a : [],
|
|
48652
|
+
meta: data === null || data === void 0 ? void 0 : data.meta,
|
|
48653
|
+
// Only a successful load can be empty: an error or a pending first load
|
|
48654
|
+
// is not "no usage".
|
|
48655
|
+
isEmpty: !isIdle && !normalized && !isLoading && isUserLlmUsageEmpty(data),
|
|
48656
|
+
isIdle,
|
|
48657
|
+
isLoading: !isIdle && isLoading,
|
|
48658
|
+
isFetching: !isIdle && isFetching,
|
|
48659
|
+
error: normalized,
|
|
48660
|
+
refetch: () => {
|
|
48661
|
+
if (!isIdle)
|
|
48662
|
+
refetch();
|
|
48663
|
+
},
|
|
48664
|
+
};
|
|
48665
|
+
}, [data, error, isLoading, isFetching, refetch, isIdle]);
|
|
48666
|
+
}
|
|
48667
|
+
/** Any metrics query. Idle until `platform_key` and `username` are set. */
|
|
48668
|
+
function useUserLlmUsageMetrics(params, options) {
|
|
48669
|
+
const skip = shouldSkip(params, options);
|
|
48670
|
+
const query$1 = useGetUserLlmUsageMetricsQuery(skip || !params ? query.skipToken : params);
|
|
48671
|
+
return useDerivedState(query$1, skip);
|
|
48672
|
+
}
|
|
48673
|
+
/** Any traces query. Idle until `platform_key` and `username` are set. */
|
|
48674
|
+
function useUserLlmUsageTraces(params, options) {
|
|
48675
|
+
const skip = shouldSkip(params, options);
|
|
48676
|
+
const query$1 = useGetUserLlmUsageTracesQuery(skip || !params ? query.skipToken : params);
|
|
48677
|
+
return useDerivedState(query$1, skip);
|
|
48678
|
+
}
|
|
48679
|
+
/** Any observations query. Idle until `platform_key` and `username` are set. */
|
|
48680
|
+
function useUserLlmUsageObservations(params, options) {
|
|
48681
|
+
const skip = shouldSkip(params, options);
|
|
48682
|
+
const query$1 = useGetUserLlmUsageObservationsQuery(skip || !params ? query.skipToken : params);
|
|
48683
|
+
return useDerivedState(query$1, skip);
|
|
48684
|
+
}
|
|
48685
|
+
/**
|
|
48686
|
+
* `{ platformKey, username, ...range }` → the wire params, or null while
|
|
48687
|
+
* either identifier is still missing.
|
|
48688
|
+
*/
|
|
48689
|
+
function scopeToParams(scope) {
|
|
48690
|
+
const { platformKey, username, ...range } = scope;
|
|
48691
|
+
if (!platformKey || !username)
|
|
48692
|
+
return null;
|
|
48693
|
+
return {
|
|
48694
|
+
platform_key: platformKey,
|
|
48695
|
+
username,
|
|
48696
|
+
...range,
|
|
48697
|
+
};
|
|
48698
|
+
}
|
|
48699
|
+
// ---------------------------------------------------------------------------
|
|
48700
|
+
// Thin wrappers — one per view need. Each is the parameterized hook
|
|
48701
|
+
// above with the resource and measures filled in, plus a parsed view of the
|
|
48702
|
+
// rows so components never read `sum_totalCost`-style keys themselves.
|
|
48703
|
+
// ---------------------------------------------------------------------------
|
|
48704
|
+
/** Headline totals for the user: `measures=total_cost,total_tokens,count`, summed. */
|
|
48705
|
+
function useUserLlmUsageSummary(scope, options) {
|
|
48706
|
+
const base = scopeToParams(scope);
|
|
48707
|
+
const state = useUserLlmUsageMetrics(base && {
|
|
48708
|
+
...base,
|
|
48709
|
+
resource: 'metrics',
|
|
48710
|
+
measures: ['total_cost', 'total_tokens', 'count'],
|
|
48711
|
+
aggregation: 'sum',
|
|
48712
|
+
}, options);
|
|
48713
|
+
return react$1.useMemo(() => {
|
|
48714
|
+
const row = state.rows[0];
|
|
48715
|
+
const summary = row
|
|
48716
|
+
? {
|
|
48717
|
+
totalCost: readMeasure(row, 'sum_totalCost'),
|
|
48718
|
+
totalTokens: readMeasure(row, 'sum_totalTokens'),
|
|
48719
|
+
count: readMeasure(row, 'sum_count'),
|
|
48720
|
+
}
|
|
48721
|
+
: null;
|
|
48722
|
+
// The totals query always answers with one row; a row of zeros is still
|
|
48723
|
+
// "no usage in this range".
|
|
48724
|
+
const isEmpty = state.isEmpty || (!!summary && summary.count === 0 && summary.totalCost === 0);
|
|
48725
|
+
return { ...state, isEmpty, summary };
|
|
48726
|
+
}, [state]);
|
|
48727
|
+
}
|
|
48728
|
+
/** The user's spend per time bucket (`granularity=day` unless told otherwise). */
|
|
48729
|
+
function useUserLlmSpendOverTime(scope, options) {
|
|
48730
|
+
const { granularity = 'day', ...rest } = scope;
|
|
48731
|
+
const base = scopeToParams(rest);
|
|
48732
|
+
const state = useUserLlmUsageMetrics(base && {
|
|
48733
|
+
...base,
|
|
48734
|
+
resource: 'metrics',
|
|
48735
|
+
measures: ['total_cost'],
|
|
48736
|
+
aggregation: 'sum',
|
|
48737
|
+
granularity,
|
|
48738
|
+
}, options);
|
|
48739
|
+
return react$1.useMemo(() => {
|
|
48740
|
+
const points = state.rows
|
|
48741
|
+
.filter((row) => typeof row.time_dimension === 'string' && row.time_dimension)
|
|
48742
|
+
.map((row) => ({
|
|
48743
|
+
date: String(row.time_dimension).slice(0, 10),
|
|
48744
|
+
totalCost: readMeasure(row, 'sum_totalCost'),
|
|
48745
|
+
}))
|
|
48746
|
+
.sort((a, b) => a.date.localeCompare(b.date));
|
|
48747
|
+
return { ...state, points };
|
|
48748
|
+
}, [state]);
|
|
48749
|
+
}
|
|
48750
|
+
/** The user's spend and call count per model, most expensive first. */
|
|
48751
|
+
function useUserLlmCostByModel(scope, options) {
|
|
48752
|
+
const { limit, ...rest } = scope;
|
|
48753
|
+
const base = scopeToParams(rest);
|
|
48754
|
+
const state = useUserLlmUsageMetrics(base && {
|
|
48755
|
+
...base,
|
|
48756
|
+
resource: 'metrics',
|
|
48757
|
+
measures: ['total_cost', 'count'],
|
|
48758
|
+
aggregation: 'sum',
|
|
48759
|
+
group_by: 'model',
|
|
48760
|
+
order_by: 'total_cost',
|
|
48761
|
+
direction: 'desc',
|
|
48762
|
+
...(limit !== undefined && { limit }),
|
|
48763
|
+
}, options);
|
|
48764
|
+
return react$1.useMemo(() => {
|
|
48765
|
+
const models = state.rows
|
|
48766
|
+
.map((row) => ({
|
|
48767
|
+
model: typeof row.providedModelName === 'string' ? row.providedModelName : '',
|
|
48768
|
+
totalCost: readMeasure(row, 'sum_totalCost'),
|
|
48769
|
+
count: readMeasure(row, 'sum_count'),
|
|
48770
|
+
}))
|
|
48771
|
+
.sort((a, b) => b.totalCost - a.totalCost);
|
|
48772
|
+
return { ...state, models };
|
|
48773
|
+
}, [state]);
|
|
48774
|
+
}
|
|
48775
|
+
/** The user's spend and call count per service (the trace name: chat, memory, …). */
|
|
48776
|
+
function useUserLlmCostByService(scope, options) {
|
|
48777
|
+
const base = scopeToParams(scope);
|
|
48778
|
+
const state = useUserLlmUsageMetrics(base && {
|
|
48779
|
+
...base,
|
|
48780
|
+
resource: 'metrics',
|
|
48781
|
+
measures: ['total_cost', 'count'],
|
|
48782
|
+
aggregation: 'sum',
|
|
48783
|
+
group_by: 'type',
|
|
48784
|
+
}, options);
|
|
48785
|
+
return react$1.useMemo(() => {
|
|
48786
|
+
const services = state.rows
|
|
48787
|
+
.map((row) => ({
|
|
48788
|
+
service: typeof row.traceName === 'string' ? row.traceName : '',
|
|
48789
|
+
totalCost: readMeasure(row, 'sum_totalCost'),
|
|
48790
|
+
count: readMeasure(row, 'sum_count'),
|
|
48791
|
+
}))
|
|
48792
|
+
.sort((a, b) => b.totalCost - a.totalCost);
|
|
48793
|
+
return { ...state, services };
|
|
48794
|
+
}, [state]);
|
|
48795
|
+
}
|
|
48796
|
+
const USER_LLM_RECENT_ACTIVITY_PAGE_SIZE = 10;
|
|
48797
|
+
/** The user's traces, newest first, one page at a time. */
|
|
48798
|
+
function useUserLlmRecentActivity(scope, options) {
|
|
48799
|
+
const { page = 1, limit = USER_LLM_RECENT_ACTIVITY_PAGE_SIZE, ...rest } = scope;
|
|
48800
|
+
const base = scopeToParams(rest);
|
|
48801
|
+
return useUserLlmUsageTraces(base && {
|
|
48802
|
+
...base,
|
|
48803
|
+
resource: 'traces',
|
|
48804
|
+
order_by: 'timestamp',
|
|
48805
|
+
direction: 'desc',
|
|
48806
|
+
page,
|
|
48807
|
+
limit,
|
|
48808
|
+
}, options);
|
|
48809
|
+
}
|
|
48810
|
+
/** The steps (observations) inside one trace. Idle until a trace is picked. */
|
|
48811
|
+
function useUserLlmTraceObservations(scope, options) {
|
|
48812
|
+
const { traceId, limit = 50, ...rest } = scope;
|
|
48813
|
+
const base = scopeToParams(rest);
|
|
48814
|
+
return useUserLlmUsageObservations(base && traceId ? { ...base, resource: 'observations', trace_id: traceId, limit } : null, options);
|
|
48815
|
+
}
|
|
48816
|
+
|
|
48427
48817
|
const mentorReducer = {
|
|
48428
48818
|
[mentorApiSlice.reducerPath]: mentorApiSlice.reducer,
|
|
48429
48819
|
[tenantApiSlice.reducerPath]: tenantApiSlice.reducer,
|
|
@@ -48486,6 +48876,7 @@ const mentorReducer = {
|
|
|
48486
48876
|
[gradingApiSlice.reducerPath]: gradingApiSlice.reducer,
|
|
48487
48877
|
[spendCapsApiSlice.reducerPath]: spendCapsApiSlice.reducer,
|
|
48488
48878
|
[userChatHistoryApiSlice.reducerPath]: userChatHistoryApiSlice.reducer,
|
|
48879
|
+
[userLlmUsageApiSlice.reducerPath]: userLlmUsageApiSlice.reducer,
|
|
48489
48880
|
};
|
|
48490
48881
|
const mentorMiddleware = [
|
|
48491
48882
|
mentorApiSlice.middleware,
|
|
@@ -48549,6 +48940,7 @@ const mentorMiddleware = [
|
|
|
48549
48940
|
gradingApiSlice.middleware,
|
|
48550
48941
|
spendCapsApiSlice.middleware,
|
|
48551
48942
|
userChatHistoryApiSlice.middleware,
|
|
48943
|
+
userLlmUsageApiSlice.middleware,
|
|
48552
48944
|
];
|
|
48553
48945
|
|
|
48554
48946
|
const skillsReducer = {
|
|
@@ -48595,6 +48987,8 @@ const skillsReducer = {
|
|
|
48595
48987
|
[chatPrivacyApiSlice.reducerPath]: chatPrivacyApiSlice.reducer,
|
|
48596
48988
|
[agentSkillsApiSlice.reducerPath]: agentSkillsApiSlice.reducer,
|
|
48597
48989
|
[userChatHistoryApiSlice.reducerPath]: userChatHistoryApiSlice.reducer,
|
|
48990
|
+
[chatApiSlice.reducerPath]: chatApiSlice.reducer,
|
|
48991
|
+
[userLlmUsageApiSlice.reducerPath]: userLlmUsageApiSlice.reducer,
|
|
48598
48992
|
};
|
|
48599
48993
|
const skillsMiddleware = [
|
|
48600
48994
|
perLearnerApiSlice.middleware,
|
|
@@ -48640,6 +49034,8 @@ const skillsMiddleware = [
|
|
|
48640
49034
|
chatPrivacyApiSlice.middleware,
|
|
48641
49035
|
agentSkillsApiSlice.middleware,
|
|
48642
49036
|
userChatHistoryApiSlice.middleware,
|
|
49037
|
+
chatApiSlice.middleware,
|
|
49038
|
+
userLlmUsageApiSlice.middleware,
|
|
48643
49039
|
];
|
|
48644
49040
|
|
|
48645
49041
|
const initializeDataLayer = (dmUrl, lmsUrl, legacyLmsUrl, storageService, httpErrorHandler = {}, studioUrl, refreshAuthToken) => {
|
|
@@ -48751,6 +49147,12 @@ exports.USER_CHAT_HISTORY_ENDPOINTS = USER_CHAT_HISTORY_ENDPOINTS;
|
|
|
48751
49147
|
exports.USER_CHAT_HISTORY_QUERY_KEYS = USER_CHAT_HISTORY_QUERY_KEYS;
|
|
48752
49148
|
exports.USER_CHAT_HISTORY_REDUCER_PATH = USER_CHAT_HISTORY_REDUCER_PATH;
|
|
48753
49149
|
exports.USER_CHAT_HISTORY_REPORT_ACTIVE_STATES = USER_CHAT_HISTORY_REPORT_ACTIVE_STATES;
|
|
49150
|
+
exports.USER_LLM_RECENT_ACTIVITY_PAGE_SIZE = USER_LLM_RECENT_ACTIVITY_PAGE_SIZE;
|
|
49151
|
+
exports.USER_LLM_USAGE_ENDPOINTS = USER_LLM_USAGE_ENDPOINTS;
|
|
49152
|
+
exports.USER_LLM_USAGE_ERROR_MESSAGES = USER_LLM_USAGE_ERROR_MESSAGES;
|
|
49153
|
+
exports.USER_LLM_USAGE_MAX_LIMIT = USER_LLM_USAGE_MAX_LIMIT;
|
|
49154
|
+
exports.USER_LLM_USAGE_QUERY_KEYS = USER_LLM_USAGE_QUERY_KEYS;
|
|
49155
|
+
exports.USER_LLM_USAGE_REDUCER_PATH = USER_LLM_USAGE_REDUCER_PATH;
|
|
48754
49156
|
exports.USER_PROGRESS_DATA_POINTS = USER_PROGRESS_DATA_POINTS;
|
|
48755
49157
|
exports.USER_PROGRESS_SUMMARY_TYPE = USER_PROGRESS_SUMMARY_TYPE;
|
|
48756
49158
|
exports.WATCHED_GROUPS_ENDPOINTS = WATCHED_GROUPS_ENDPOINTS;
|
|
@@ -48804,6 +49206,7 @@ exports.evalTotalPages = evalTotalPages;
|
|
|
48804
49206
|
exports.evaluationsApiSlice = evaluationsApiSlice;
|
|
48805
49207
|
exports.fakeBaseQueryWithLogging = fakeBaseQueryWithLogging;
|
|
48806
49208
|
exports.featureTags = featureTags;
|
|
49209
|
+
exports.fetchUserLlmUsage = fetchUserLlmUsage;
|
|
48807
49210
|
exports.filterCourseUserRoles = filterCourseUserRoles;
|
|
48808
49211
|
exports.filterGlobalUserRoles = filterGlobalUserRoles;
|
|
48809
49212
|
exports.filterOrgUserRoles = filterOrgUserRoles;
|
|
@@ -48818,6 +49221,7 @@ exports.isBaseAgentMentor = isBaseAgentMentor;
|
|
|
48818
49221
|
exports.isPoliciesResponse = isPoliciesResponse;
|
|
48819
49222
|
exports.isPrivacyBlockedError = isPrivacyBlockedError;
|
|
48820
49223
|
exports.isSpendCapExceededErrorBody = isSpendCapExceededErrorBody;
|
|
49224
|
+
exports.isUserLlmUsageEmpty = isUserLlmUsageEmpty;
|
|
48821
49225
|
exports.llmsApiSlice = llmsApiSlice;
|
|
48822
49226
|
exports.mcpApiSlice = mcpApiSlice;
|
|
48823
49227
|
exports.memoryApiSlice = memoryApiSlice;
|
|
@@ -48830,6 +49234,7 @@ exports.mentorReducer = mentorReducer;
|
|
|
48830
49234
|
exports.moderationLogsApiReducer = moderationLogsApiReducer;
|
|
48831
49235
|
exports.moderationLogsApiSlice = moderationLogsApiSlice;
|
|
48832
49236
|
exports.monetizationApiSlice = monetizationApiSlice;
|
|
49237
|
+
exports.normalizeUserLlmUsageError = normalizeUserLlmUsageError;
|
|
48833
49238
|
exports.notificationsApiSlice = notificationsApiSlice;
|
|
48834
49239
|
exports.notificationsCustomApiSlice = notificationsCustomApiSlice;
|
|
48835
49240
|
exports.perLearnerApiSlice = perLearnerApiSlice;
|
|
@@ -48839,6 +49244,7 @@ exports.platformApiSlice = platformApiSlice;
|
|
|
48839
49244
|
exports.platformCustomApiSlice = platformCustomApiSlice;
|
|
48840
49245
|
exports.projectsApiSlice = projectsApiSlice;
|
|
48841
49246
|
exports.promptsApiSlice = promptsApiSlice;
|
|
49247
|
+
exports.readMeasure = readMeasure;
|
|
48842
49248
|
exports.reportsApiSlice = reportsApiSlice;
|
|
48843
49249
|
exports.resolveEffectiveAgentSkills = resolveEffectiveAgentSkills;
|
|
48844
49250
|
exports.retirementApiSlice = retirementApiSlice;
|
|
@@ -48854,6 +49260,7 @@ exports.supportTicketsApiSlice = supportTicketsApiSlice;
|
|
|
48854
49260
|
exports.tenantApiReducer = tenantApiReducer;
|
|
48855
49261
|
exports.tenantApiSlice = tenantApiSlice;
|
|
48856
49262
|
exports.tenantLogoApiSlice = tenantLogoApiSlice;
|
|
49263
|
+
exports.toUserLlmUsageEnvelope = toUserLlmUsageEnvelope;
|
|
48857
49264
|
exports.toolsApiSlice = toolsApiSlice;
|
|
48858
49265
|
exports.trainingDocumentsApiSlice = trainingDocumentsApiSlice;
|
|
48859
49266
|
exports.unwrapApiTokenList = unwrapApiTokenList;
|
|
@@ -49271,6 +49678,9 @@ exports.useGetUserEnrolledProgramsQuery = useGetUserEnrolledProgramsQuery;
|
|
|
49271
49678
|
exports.useGetUserExperienceQuery = useGetUserExperienceQuery;
|
|
49272
49679
|
exports.useGetUserInstitutionsQuery = useGetUserInstitutionsQuery;
|
|
49273
49680
|
exports.useGetUserInvitationsQuery = useGetUserInvitationsQuery;
|
|
49681
|
+
exports.useGetUserLlmUsageMetricsQuery = useGetUserLlmUsageMetricsQuery;
|
|
49682
|
+
exports.useGetUserLlmUsageObservationsQuery = useGetUserLlmUsageObservationsQuery;
|
|
49683
|
+
exports.useGetUserLlmUsageTracesQuery = useGetUserLlmUsageTracesQuery;
|
|
49274
49684
|
exports.useGetUserMemorySettingsQuery = useGetUserMemorySettingsQuery;
|
|
49275
49685
|
exports.useGetUserMetadataEdxQuery = useGetUserMetadataEdxQuery;
|
|
49276
49686
|
exports.useGetUserMetadataQuery = useGetUserMetadataQuery;
|
|
@@ -49682,12 +50092,23 @@ exports.useUploadStudioScormPackageMutation = useUploadStudioScormPackageMutatio
|
|
|
49682
50092
|
exports.useUpsertAgentSpendCapMutation = useUpsertAgentSpendCapMutation;
|
|
49683
50093
|
exports.useUpsertTenantSpendCapMutation = useUpsertTenantSpendCapMutation;
|
|
49684
50094
|
exports.useUpsertUserSpendCapMutation = useUpsertUserSpendCapMutation;
|
|
50095
|
+
exports.useUserLlmCostByModel = useUserLlmCostByModel;
|
|
50096
|
+
exports.useUserLlmCostByService = useUserLlmCostByService;
|
|
50097
|
+
exports.useUserLlmRecentActivity = useUserLlmRecentActivity;
|
|
50098
|
+
exports.useUserLlmSpendOverTime = useUserLlmSpendOverTime;
|
|
50099
|
+
exports.useUserLlmTraceObservations = useUserLlmTraceObservations;
|
|
50100
|
+
exports.useUserLlmUsageMetrics = useUserLlmUsageMetrics;
|
|
50101
|
+
exports.useUserLlmUsageObservations = useUserLlmUsageObservations;
|
|
50102
|
+
exports.useUserLlmUsageSummary = useUserLlmUsageSummary;
|
|
50103
|
+
exports.useUserLlmUsageTraces = useUserLlmUsageTraces;
|
|
49685
50104
|
exports.useUsersGradesPassedQuery = useUsersGradesPassedQuery;
|
|
49686
50105
|
exports.useValidateWorkflowMutation = useValidateWorkflowMutation;
|
|
49687
50106
|
exports.useWithdrawApplicationMutation = useWithdrawApplicationMutation;
|
|
49688
50107
|
exports.userApiSlice = userApiSlice;
|
|
49689
50108
|
exports.userChatHistoryApiSlice = userChatHistoryApiSlice;
|
|
49690
50109
|
exports.userInvitationsApiSlice = userInvitationsApiSlice;
|
|
50110
|
+
exports.userLlmUsageApiSlice = userLlmUsageApiSlice;
|
|
50111
|
+
exports.validateUserLlmUsageParams = validateUserLlmUsageParams;
|
|
49691
50112
|
exports.watchedGroupsApiSlice = watchedGroupsApiSlice;
|
|
49692
50113
|
exports.workflowsApiSlice = workflowsApiSlice;
|
|
49693
50114
|
//# sourceMappingURL=index.js.map
|