@iblai/data-layer 1.18.1 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +741 -3
- package/dist/index.esm.js +397 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +419 -0
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- 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,7 @@ const skillsReducer = {
|
|
|
48595
48987
|
[chatPrivacyApiSlice.reducerPath]: chatPrivacyApiSlice.reducer,
|
|
48596
48988
|
[agentSkillsApiSlice.reducerPath]: agentSkillsApiSlice.reducer,
|
|
48597
48989
|
[userChatHistoryApiSlice.reducerPath]: userChatHistoryApiSlice.reducer,
|
|
48990
|
+
[userLlmUsageApiSlice.reducerPath]: userLlmUsageApiSlice.reducer,
|
|
48598
48991
|
};
|
|
48599
48992
|
const skillsMiddleware = [
|
|
48600
48993
|
perLearnerApiSlice.middleware,
|
|
@@ -48640,6 +49033,7 @@ const skillsMiddleware = [
|
|
|
48640
49033
|
chatPrivacyApiSlice.middleware,
|
|
48641
49034
|
agentSkillsApiSlice.middleware,
|
|
48642
49035
|
userChatHistoryApiSlice.middleware,
|
|
49036
|
+
userLlmUsageApiSlice.middleware,
|
|
48643
49037
|
];
|
|
48644
49038
|
|
|
48645
49039
|
const initializeDataLayer = (dmUrl, lmsUrl, legacyLmsUrl, storageService, httpErrorHandler = {}, studioUrl, refreshAuthToken) => {
|
|
@@ -48751,6 +49145,12 @@ exports.USER_CHAT_HISTORY_ENDPOINTS = USER_CHAT_HISTORY_ENDPOINTS;
|
|
|
48751
49145
|
exports.USER_CHAT_HISTORY_QUERY_KEYS = USER_CHAT_HISTORY_QUERY_KEYS;
|
|
48752
49146
|
exports.USER_CHAT_HISTORY_REDUCER_PATH = USER_CHAT_HISTORY_REDUCER_PATH;
|
|
48753
49147
|
exports.USER_CHAT_HISTORY_REPORT_ACTIVE_STATES = USER_CHAT_HISTORY_REPORT_ACTIVE_STATES;
|
|
49148
|
+
exports.USER_LLM_RECENT_ACTIVITY_PAGE_SIZE = USER_LLM_RECENT_ACTIVITY_PAGE_SIZE;
|
|
49149
|
+
exports.USER_LLM_USAGE_ENDPOINTS = USER_LLM_USAGE_ENDPOINTS;
|
|
49150
|
+
exports.USER_LLM_USAGE_ERROR_MESSAGES = USER_LLM_USAGE_ERROR_MESSAGES;
|
|
49151
|
+
exports.USER_LLM_USAGE_MAX_LIMIT = USER_LLM_USAGE_MAX_LIMIT;
|
|
49152
|
+
exports.USER_LLM_USAGE_QUERY_KEYS = USER_LLM_USAGE_QUERY_KEYS;
|
|
49153
|
+
exports.USER_LLM_USAGE_REDUCER_PATH = USER_LLM_USAGE_REDUCER_PATH;
|
|
48754
49154
|
exports.USER_PROGRESS_DATA_POINTS = USER_PROGRESS_DATA_POINTS;
|
|
48755
49155
|
exports.USER_PROGRESS_SUMMARY_TYPE = USER_PROGRESS_SUMMARY_TYPE;
|
|
48756
49156
|
exports.WATCHED_GROUPS_ENDPOINTS = WATCHED_GROUPS_ENDPOINTS;
|
|
@@ -48804,6 +49204,7 @@ exports.evalTotalPages = evalTotalPages;
|
|
|
48804
49204
|
exports.evaluationsApiSlice = evaluationsApiSlice;
|
|
48805
49205
|
exports.fakeBaseQueryWithLogging = fakeBaseQueryWithLogging;
|
|
48806
49206
|
exports.featureTags = featureTags;
|
|
49207
|
+
exports.fetchUserLlmUsage = fetchUserLlmUsage;
|
|
48807
49208
|
exports.filterCourseUserRoles = filterCourseUserRoles;
|
|
48808
49209
|
exports.filterGlobalUserRoles = filterGlobalUserRoles;
|
|
48809
49210
|
exports.filterOrgUserRoles = filterOrgUserRoles;
|
|
@@ -48818,6 +49219,7 @@ exports.isBaseAgentMentor = isBaseAgentMentor;
|
|
|
48818
49219
|
exports.isPoliciesResponse = isPoliciesResponse;
|
|
48819
49220
|
exports.isPrivacyBlockedError = isPrivacyBlockedError;
|
|
48820
49221
|
exports.isSpendCapExceededErrorBody = isSpendCapExceededErrorBody;
|
|
49222
|
+
exports.isUserLlmUsageEmpty = isUserLlmUsageEmpty;
|
|
48821
49223
|
exports.llmsApiSlice = llmsApiSlice;
|
|
48822
49224
|
exports.mcpApiSlice = mcpApiSlice;
|
|
48823
49225
|
exports.memoryApiSlice = memoryApiSlice;
|
|
@@ -48830,6 +49232,7 @@ exports.mentorReducer = mentorReducer;
|
|
|
48830
49232
|
exports.moderationLogsApiReducer = moderationLogsApiReducer;
|
|
48831
49233
|
exports.moderationLogsApiSlice = moderationLogsApiSlice;
|
|
48832
49234
|
exports.monetizationApiSlice = monetizationApiSlice;
|
|
49235
|
+
exports.normalizeUserLlmUsageError = normalizeUserLlmUsageError;
|
|
48833
49236
|
exports.notificationsApiSlice = notificationsApiSlice;
|
|
48834
49237
|
exports.notificationsCustomApiSlice = notificationsCustomApiSlice;
|
|
48835
49238
|
exports.perLearnerApiSlice = perLearnerApiSlice;
|
|
@@ -48839,6 +49242,7 @@ exports.platformApiSlice = platformApiSlice;
|
|
|
48839
49242
|
exports.platformCustomApiSlice = platformCustomApiSlice;
|
|
48840
49243
|
exports.projectsApiSlice = projectsApiSlice;
|
|
48841
49244
|
exports.promptsApiSlice = promptsApiSlice;
|
|
49245
|
+
exports.readMeasure = readMeasure;
|
|
48842
49246
|
exports.reportsApiSlice = reportsApiSlice;
|
|
48843
49247
|
exports.resolveEffectiveAgentSkills = resolveEffectiveAgentSkills;
|
|
48844
49248
|
exports.retirementApiSlice = retirementApiSlice;
|
|
@@ -48854,6 +49258,7 @@ exports.supportTicketsApiSlice = supportTicketsApiSlice;
|
|
|
48854
49258
|
exports.tenantApiReducer = tenantApiReducer;
|
|
48855
49259
|
exports.tenantApiSlice = tenantApiSlice;
|
|
48856
49260
|
exports.tenantLogoApiSlice = tenantLogoApiSlice;
|
|
49261
|
+
exports.toUserLlmUsageEnvelope = toUserLlmUsageEnvelope;
|
|
48857
49262
|
exports.toolsApiSlice = toolsApiSlice;
|
|
48858
49263
|
exports.trainingDocumentsApiSlice = trainingDocumentsApiSlice;
|
|
48859
49264
|
exports.unwrapApiTokenList = unwrapApiTokenList;
|
|
@@ -49271,6 +49676,9 @@ exports.useGetUserEnrolledProgramsQuery = useGetUserEnrolledProgramsQuery;
|
|
|
49271
49676
|
exports.useGetUserExperienceQuery = useGetUserExperienceQuery;
|
|
49272
49677
|
exports.useGetUserInstitutionsQuery = useGetUserInstitutionsQuery;
|
|
49273
49678
|
exports.useGetUserInvitationsQuery = useGetUserInvitationsQuery;
|
|
49679
|
+
exports.useGetUserLlmUsageMetricsQuery = useGetUserLlmUsageMetricsQuery;
|
|
49680
|
+
exports.useGetUserLlmUsageObservationsQuery = useGetUserLlmUsageObservationsQuery;
|
|
49681
|
+
exports.useGetUserLlmUsageTracesQuery = useGetUserLlmUsageTracesQuery;
|
|
49274
49682
|
exports.useGetUserMemorySettingsQuery = useGetUserMemorySettingsQuery;
|
|
49275
49683
|
exports.useGetUserMetadataEdxQuery = useGetUserMetadataEdxQuery;
|
|
49276
49684
|
exports.useGetUserMetadataQuery = useGetUserMetadataQuery;
|
|
@@ -49682,12 +50090,23 @@ exports.useUploadStudioScormPackageMutation = useUploadStudioScormPackageMutatio
|
|
|
49682
50090
|
exports.useUpsertAgentSpendCapMutation = useUpsertAgentSpendCapMutation;
|
|
49683
50091
|
exports.useUpsertTenantSpendCapMutation = useUpsertTenantSpendCapMutation;
|
|
49684
50092
|
exports.useUpsertUserSpendCapMutation = useUpsertUserSpendCapMutation;
|
|
50093
|
+
exports.useUserLlmCostByModel = useUserLlmCostByModel;
|
|
50094
|
+
exports.useUserLlmCostByService = useUserLlmCostByService;
|
|
50095
|
+
exports.useUserLlmRecentActivity = useUserLlmRecentActivity;
|
|
50096
|
+
exports.useUserLlmSpendOverTime = useUserLlmSpendOverTime;
|
|
50097
|
+
exports.useUserLlmTraceObservations = useUserLlmTraceObservations;
|
|
50098
|
+
exports.useUserLlmUsageMetrics = useUserLlmUsageMetrics;
|
|
50099
|
+
exports.useUserLlmUsageObservations = useUserLlmUsageObservations;
|
|
50100
|
+
exports.useUserLlmUsageSummary = useUserLlmUsageSummary;
|
|
50101
|
+
exports.useUserLlmUsageTraces = useUserLlmUsageTraces;
|
|
49685
50102
|
exports.useUsersGradesPassedQuery = useUsersGradesPassedQuery;
|
|
49686
50103
|
exports.useValidateWorkflowMutation = useValidateWorkflowMutation;
|
|
49687
50104
|
exports.useWithdrawApplicationMutation = useWithdrawApplicationMutation;
|
|
49688
50105
|
exports.userApiSlice = userApiSlice;
|
|
49689
50106
|
exports.userChatHistoryApiSlice = userChatHistoryApiSlice;
|
|
49690
50107
|
exports.userInvitationsApiSlice = userInvitationsApiSlice;
|
|
50108
|
+
exports.userLlmUsageApiSlice = userLlmUsageApiSlice;
|
|
50109
|
+
exports.validateUserLlmUsageParams = validateUserLlmUsageParams;
|
|
49691
50110
|
exports.watchedGroupsApiSlice = watchedGroupsApiSlice;
|
|
49692
50111
|
exports.workflowsApiSlice = workflowsApiSlice;
|
|
49693
50112
|
//# sourceMappingURL=index.js.map
|