@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.
@@ -0,0 +1,150 @@
1
+ import type { DateFilter, LlmUsageAggregation, LlmUsageGranularity, LlmUsageGroupBy, LlmUsageMeasure, LlmUsageMetricsRow, LlmUsageObservation, LlmUsagePaginationMeta, LlmUsageTrace } from '../analytics/types';
2
+ export type UserLlmUsageResource = 'metrics' | 'traces' | 'observations';
3
+ /**
4
+ * Services the platform emits traces for. Deployments emit others too
5
+ * (`rag`, `memory_context`, `guided_prompt_generation`, …), so any string is
6
+ * accepted while the known names still autocomplete.
7
+ */
8
+ export type UserLlmUsageTraceName = 'chat' | 'call' | 'memory' | 'grading' | 'moderation' | 'embeddings' | (string & {});
9
+ export type UserLlmUsageDirection = 'asc' | 'desc';
10
+ /** Every range the endpoint knows except `custom`, which needs its own dates. */
11
+ export type UserLlmUsagePresetDateFilter = Exclude<DateFilter, 'custom'>;
12
+ /**
13
+ * Omitting `date_filter` means **today** upstream. `start_date`/`end_date`
14
+ * only exist alongside `date_filter: 'custom'`, and then both are required.
15
+ */
16
+ export type UserLlmUsageDateRange = {
17
+ date_filter?: UserLlmUsagePresetDateFilter;
18
+ start_date?: never;
19
+ end_date?: never;
20
+ } | {
21
+ date_filter: 'custom';
22
+ start_date: string;
23
+ end_date: string;
24
+ };
25
+ interface UserLlmUsageCommonParams {
26
+ /** Always sent; the backend validates it against the caller's tenancy. */
27
+ platform_key: string;
28
+ /**
29
+ * The user whose usage this is — the profile being viewed, not necessarily
30
+ * the caller. Required, so a request can never silently widen to the
31
+ * caller's own scope (which for an admin is the whole platform).
32
+ */
33
+ username: string;
34
+ trace_name?: UserLlmUsageTraceName;
35
+ llm_model?: string;
36
+ /** Upstream maximum is {@link USER_LLM_USAGE_MAX_LIMIT}. */
37
+ limit?: number;
38
+ }
39
+ export type UserLlmUsageMetricsParams = UserLlmUsageCommonParams & UserLlmUsageDateRange & {
40
+ resource: 'metrics';
41
+ /** Serialized as a comma-separated list. Upstream default: `total_cost`. */
42
+ measures?: LlmUsageMeasure[];
43
+ aggregation?: LlmUsageAggregation;
44
+ group_by?: LlmUsageGroupBy;
45
+ /** Turns the result into a time series bucketed by this unit. */
46
+ granularity?: LlmUsageGranularity;
47
+ session_id?: string;
48
+ mentor_unique_id?: string;
49
+ order_by?: LlmUsageMeasure;
50
+ direction?: UserLlmUsageDirection;
51
+ };
52
+ export type UserLlmUsageTracesParams = UserLlmUsageCommonParams & UserLlmUsageDateRange & {
53
+ resource: 'traces';
54
+ session_id?: string;
55
+ mentor_unique_id?: string;
56
+ order_by?: 'timestamp' | 'name' | 'session_id';
57
+ direction?: UserLlmUsageDirection;
58
+ page?: number;
59
+ /** Single-trace lookup; an id the caller cannot see answers 404. */
60
+ trace_id?: string;
61
+ };
62
+ export type UserLlmUsageObservationsParams = UserLlmUsageCommonParams & UserLlmUsageDateRange & {
63
+ resource: 'observations';
64
+ trace_id?: string;
65
+ observation_id?: string;
66
+ page?: number;
67
+ /** Not accepted on observations upstream (400) — scope with `trace_id`. */
68
+ session_id?: never;
69
+ /** Not accepted on observations upstream (403/400) — scope with `trace_id`. */
70
+ mentor_unique_id?: never;
71
+ };
72
+ /** Self-view request params, discriminated by `resource`. No `username`. */
73
+ export type UserLlmUsageParams = UserLlmUsageMetricsParams | UserLlmUsageTracesParams | UserLlmUsageObservationsParams;
74
+ /** Observation rows also carry flattened token counts next to `usage`. */
75
+ export type UserLlmUsageObservation = LlmUsageObservation & {
76
+ promptTokens?: number;
77
+ completionTokens?: number;
78
+ totalTokens?: number;
79
+ costDetails?: {
80
+ total?: number;
81
+ [key: string]: number | undefined;
82
+ };
83
+ };
84
+ /**
85
+ * The response envelope, with `data` always a list — single-item lookups
86
+ * (`trace_id` on traces, `observation_id` on observations) are wrapped. `meta`
87
+ * is only sent for paginated list pages of traces and observations.
88
+ */
89
+ export interface UserLlmUsageEnvelope<R extends UserLlmUsageResource, Row> {
90
+ resource: R;
91
+ data: Row[];
92
+ meta?: R extends 'metrics' ? never : LlmUsagePaginationMeta;
93
+ }
94
+ export type UserLlmUsageMetricsResponse = UserLlmUsageEnvelope<'metrics', LlmUsageMetricsRow>;
95
+ export type UserLlmUsageTracesResponse = UserLlmUsageEnvelope<'traces', LlmUsageTrace>;
96
+ export type UserLlmUsageObservationsResponse = UserLlmUsageEnvelope<'observations', UserLlmUsageObservation>;
97
+ /**
98
+ * What the UI branches on. `forbidden` and `not_found` deliberately carry the
99
+ * same kind of neutral message whatever the backend said, so the view never
100
+ * reveals whether another user or tenant exists.
101
+ */
102
+ export type UserLlmUsageErrorKind = 'forbidden' | 'not_found' | 'unauthorized' | 'unavailable' | 'invalid_params' | 'unknown';
103
+ export interface UserLlmUsageError {
104
+ kind: UserLlmUsageErrorKind;
105
+ /** HTTP status (or RTK's string status) when there was a response. */
106
+ status?: number | string;
107
+ /** A user-safe English fallback; UIs should prefer their own copy per `kind`. */
108
+ message: string;
109
+ }
110
+ /** Derived state every usage hook returns. */
111
+ export interface UserLlmUsageQueryState<Row> {
112
+ rows: Row[];
113
+ meta?: LlmUsagePaginationMeta;
114
+ /** True once loaded with nothing to show (`meta.totalItems === 0` or no rows). */
115
+ isEmpty: boolean;
116
+ /** True while the platform key or username is missing, so nothing was requested. */
117
+ isIdle: boolean;
118
+ isLoading: boolean;
119
+ isFetching: boolean;
120
+ error: UserLlmUsageError | null;
121
+ refetch: () => void;
122
+ }
123
+ /** Shared by the thin wrapper hooks: whose usage, on which tenant and window. */
124
+ export type UserLlmUsageScope = {
125
+ /** The current platform; hooks stay idle while it is empty. */
126
+ platformKey: string | null | undefined;
127
+ /** The profile being viewed; hooks stay idle while it is empty. */
128
+ username: string | null | undefined;
129
+ } & UserLlmUsageDateRange;
130
+ export interface UserLlmUsageSummary {
131
+ totalCost: number;
132
+ totalTokens: number;
133
+ count: number;
134
+ }
135
+ export interface UserLlmSpendPoint {
136
+ /** Bucket start as `YYYY-MM-DD`. */
137
+ date: string;
138
+ totalCost: number;
139
+ }
140
+ export interface UserLlmCostByModelRow {
141
+ model: string;
142
+ totalCost: number;
143
+ count: number;
144
+ }
145
+ export interface UserLlmCostByServiceRow {
146
+ service: string;
147
+ totalCost: number;
148
+ count: number;
149
+ }
150
+ export {};
@@ -0,0 +1,35 @@
1
+ import type { UserLlmUsageEnvelope, UserLlmUsageError, UserLlmUsageParams, UserLlmUsageResource } from './types';
2
+ export type UserLlmUsageValidation = {
3
+ ok: true;
4
+ params: UserLlmUsageParams;
5
+ } | {
6
+ ok: false;
7
+ reason: string;
8
+ };
9
+ /**
10
+ * Runtime twin of the param types, for params assembled dynamically where the
11
+ * compiler cannot see them. Runs before every request, so an invalid
12
+ * combination never leaves the browser.
13
+ */
14
+ export declare function validateUserLlmUsageParams(params: unknown): UserLlmUsageValidation;
15
+ /**
16
+ * Maps whatever a usage query failed with onto a typed, user-safe error.
17
+ * The backend's own `detail`/`error` text is never carried over.
18
+ *
19
+ * A 401 is reported as `unauthorized` for completeness, but it has already
20
+ * gone through the app's registered auth handler (token refresh, then the
21
+ * host's 401 handler) inside the base query before it gets here.
22
+ */
23
+ export declare function normalizeUserLlmUsageError(error: unknown): UserLlmUsageError | null;
24
+ /**
25
+ * Wraps the raw response so `data` is always a list. Single-item lookups
26
+ * (`trace_id`, `observation_id`) come back as one object without `meta`.
27
+ */
28
+ export declare function toUserLlmUsageEnvelope<R extends UserLlmUsageResource, Row>(raw: unknown, resource: R): UserLlmUsageEnvelope<R, Row>;
29
+ /**
30
+ * Empty-state rule shared by every usage hook: paginated resources trust
31
+ * `meta.totalItems`; metrics (and unpaginated lookups) fall back to the rows.
32
+ */
33
+ export declare function isUserLlmUsageEmpty(envelope: Pick<UserLlmUsageEnvelope<UserLlmUsageResource, unknown>, 'data' | 'meta'> | undefined): boolean;
34
+ /** Reads a numeric measure (`sum_totalCost`, `avg_latency`, …) off a metrics row. */
35
+ export declare function readMeasure(row: Record<string, unknown> | undefined, key: string): number;
@@ -139,6 +139,11 @@ export * from './features/watched-groups/types';
139
139
  export * from './features/user-chat-history/api-slice';
140
140
  export * from './features/user-chat-history/constants';
141
141
  export * from './features/user-chat-history/types';
142
+ export * from './features/user-llm-usage/api-slice';
143
+ export * from './features/user-llm-usage/constants';
144
+ export * from './features/user-llm-usage/types';
145
+ export * from './features/user-llm-usage/utils';
146
+ export * from './features/user-llm-usage/hooks';
142
147
  export * from './reducers';
143
148
  export * from './utils';
144
149
  export type { CustomQueryArgs } from './features/utils';