@agentmark-ai/api-types 0.1.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.
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export { createVerifiedAppId, isTenantContext } from './tenant-context';
3
+ export type { TenantContext } from './tenant-context';
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.isTenantContext = exports.createVerifiedAppId = void 0;
18
+ __exportStar(require("./types"), exports);
19
+ var tenant_context_1 = require("./tenant-context");
20
+ Object.defineProperty(exports, "createVerifiedAppId", { enumerable: true, get: function () { return tenant_context_1.createVerifiedAppId; } });
21
+ Object.defineProperty(exports, "isTenantContext", { enumerable: true, get: function () { return tenant_context_1.isTenantContext; } });
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Tenant Context Types
3
+ * Feature: 007-analytics-architecture-evaluation
4
+ *
5
+ * Provides type-safe tenant context for multi-tenant data access.
6
+ * Uses branded types to ensure appId can only come from verification.
7
+ *
8
+ * NOTE: The verifyAppAccess() function is NOT included here because it
9
+ * depends on `server-only` and Supabase. It remains in the dashboard app.
10
+ * This module exports only the types and type guard.
11
+ */
12
+ import type { VerifiedAppId } from './types';
13
+ /**
14
+ * Immutable tenant context created after verification.
15
+ *
16
+ * All analytics data access methods require this context,
17
+ * ensuring tenant isolation is enforced at the type level.
18
+ */
19
+ export interface TenantContext {
20
+ /** User ID from authentication */
21
+ readonly userId: string;
22
+ /** Tenant ID from JWT app_metadata */
23
+ readonly tenantId: string;
24
+ /** Verified app ID - guaranteed to belong to tenantId */
25
+ readonly appId: VerifiedAppId;
26
+ /** Data retention window in days (-1 = unlimited) */
27
+ readonly dataRetentionDays: number;
28
+ }
29
+ /**
30
+ * Creates a VerifiedAppId from a string that has been verified externally
31
+ * (e.g., by Unkey API key validation or Supabase RLS).
32
+ *
33
+ * Performs a runtime check that the value is a non-empty string.
34
+ * This is the sanctioned way to create a VerifiedAppId in the gateway,
35
+ * where verification happens via API key middleware rather than verifyAppAccess().
36
+ *
37
+ * @throws {Error} if the value is empty or not a string
38
+ */
39
+ export declare function createVerifiedAppId(appId: string): VerifiedAppId;
40
+ /**
41
+ * Type guard to check if a value is a valid TenantContext.
42
+ *
43
+ * Useful for runtime validation in edge cases.
44
+ */
45
+ export declare function isTenantContext(value: unknown): value is TenantContext;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ /**
3
+ * Tenant Context Types
4
+ * Feature: 007-analytics-architecture-evaluation
5
+ *
6
+ * Provides type-safe tenant context for multi-tenant data access.
7
+ * Uses branded types to ensure appId can only come from verification.
8
+ *
9
+ * NOTE: The verifyAppAccess() function is NOT included here because it
10
+ * depends on `server-only` and Supabase. It remains in the dashboard app.
11
+ * This module exports only the types and type guard.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.createVerifiedAppId = createVerifiedAppId;
15
+ exports.isTenantContext = isTenantContext;
16
+ // ============================================================================
17
+ // Factory Functions
18
+ // ============================================================================
19
+ /**
20
+ * Creates a VerifiedAppId from a string that has been verified externally
21
+ * (e.g., by Unkey API key validation or Supabase RLS).
22
+ *
23
+ * Performs a runtime check that the value is a non-empty string.
24
+ * This is the sanctioned way to create a VerifiedAppId in the gateway,
25
+ * where verification happens via API key middleware rather than verifyAppAccess().
26
+ *
27
+ * @throws {Error} if the value is empty or not a string
28
+ */
29
+ function createVerifiedAppId(appId) {
30
+ if (typeof appId !== 'string' || appId.length === 0) {
31
+ throw new Error('createVerifiedAppId: appId must be a non-empty string');
32
+ }
33
+ return appId;
34
+ }
35
+ // ============================================================================
36
+ // Type Guards and Utilities
37
+ // ============================================================================
38
+ /**
39
+ * Type guard to check if a value is a valid TenantContext.
40
+ *
41
+ * Useful for runtime validation in edge cases.
42
+ */
43
+ function isTenantContext(value) {
44
+ if (typeof value !== 'object' || value === null) {
45
+ return false;
46
+ }
47
+ const obj = value;
48
+ return (typeof obj.userId === 'string' &&
49
+ typeof obj.tenantId === 'string' &&
50
+ typeof obj.appId === 'string' &&
51
+ typeof obj.dataRetentionDays === 'number' &&
52
+ obj.userId.length > 0 &&
53
+ obj.tenantId.length > 0 &&
54
+ obj.appId.length > 0);
55
+ }
@@ -0,0 +1,847 @@
1
+ /**
2
+ * Analytics Service Types
3
+ * Feature: 007-analytics-architecture-evaluation
4
+ *
5
+ * These types define the contract for the analytics service layer,
6
+ * including API request/response shapes and internal data structures.
7
+ */
8
+ declare const __brand: unique symbol;
9
+ export type VerifiedAppId = string & {
10
+ readonly [__brand]: 'VerifiedAppId';
11
+ };
12
+ import type { TenantContext } from './tenant-context';
13
+ /**
14
+ * Date range for analytics queries.
15
+ * Supports preset ranges or custom date selection.
16
+ *
17
+ * App-internal camelCase shape — distinct from api-schemas's wire-format
18
+ * `DateRangeParamsSchema` (snake_case `start_date` / `end_date`, both
19
+ * optional). Kept here because no Zod schema describes this exact shape.
20
+ */
21
+ export interface DateRange {
22
+ start: string;
23
+ end: string;
24
+ }
25
+ /**
26
+ * Preset date range values for quick selection.
27
+ *
28
+ * App-internal narrower union — api-schemas's `DateRangePreset` adds
29
+ * a `'yesterday'` value not used by this surface. Kept local to avoid
30
+ * loosening consumer expectations.
31
+ */
32
+ export type DateRangePreset = 'today' | '7d' | '30d' | '90d' | 'custom';
33
+ /**
34
+ * Standard pagination parameters.
35
+ *
36
+ * Sourced from api-schemas's `PaginationParamsSchema` (z.infer<>) —
37
+ * both packages agree on `{ limit: number; offset: number }`, so the
38
+ * canonical shape lives in api-schemas and this file re-exports it
39
+ * to stay in lockstep with the wire contract.
40
+ */
41
+ import type { PaginationParams as _PaginationParams } from '@agentmark-ai/api-schemas';
42
+ export type PaginationParams = _PaginationParams;
43
+ /**
44
+ * Summary metrics for the dashboard header.
45
+ * Aggregated from dashboard_hourly_mv materialized view.
46
+ */
47
+ export interface MetricsSummary {
48
+ totalRequests: number;
49
+ successCount: number;
50
+ errorCount: number;
51
+ totalCost: number;
52
+ totalTokens: number;
53
+ inputTokens: number;
54
+ outputTokens: number;
55
+ avgLatencyMs: number;
56
+ uniqueUsers: number;
57
+ }
58
+ /**
59
+ * Time series data point for dashboard charts.
60
+ * Hourly granularity from dashboard_hourly_mv.
61
+ */
62
+ export interface TimeSeriesPoint {
63
+ date: string;
64
+ hour: number;
65
+ requests: number;
66
+ successes: number;
67
+ errors: number;
68
+ cost: number;
69
+ tokens: number;
70
+ inputTokens: number;
71
+ outputTokens: number;
72
+ avgLatencyMs: number;
73
+ uniqueUsers: number;
74
+ }
75
+ /**
76
+ * Complete metrics response including summary and time series.
77
+ */
78
+ export interface MetricsResponse {
79
+ summary: MetricsSummary;
80
+ timeSeries: TimeSeriesPoint[];
81
+ }
82
+ /**
83
+ * Statistics for a single model.
84
+ * Aggregated from model_stats_mv materialized view.
85
+ */
86
+ export interface ModelStats {
87
+ model: string;
88
+ requests: number;
89
+ cost: number;
90
+ tokens: number;
91
+ inputTokens: number;
92
+ outputTokens: number;
93
+ avgLatencyMs: number;
94
+ successRate: number;
95
+ }
96
+ /**
97
+ * Response for top models query.
98
+ */
99
+ export interface ModelStatsResponse {
100
+ models: ModelStats[];
101
+ }
102
+ /**
103
+ * A single ranking item for dimension-grouped queries.
104
+ * Used by getRankingData to return data grouped by any dimension
105
+ * (model, user_id, metadata fields).
106
+ */
107
+ export interface RankingDataItem {
108
+ dimensionValue: string;
109
+ requests: number;
110
+ cost: number;
111
+ tokens: number;
112
+ inputTokens: number;
113
+ outputTokens: number;
114
+ avgLatencyMs: number;
115
+ successRate: number;
116
+ }
117
+ /**
118
+ * Response for dimension-grouped ranking queries.
119
+ */
120
+ export interface RankingDataResponse {
121
+ items: RankingDataItem[];
122
+ }
123
+ /**
124
+ * V1 saved filter config — search-only. Retained for backward compat.
125
+ */
126
+ export interface SavedFilterConfigV1 {
127
+ search?: string;
128
+ searchField?: string;
129
+ }
130
+ /**
131
+ * V2 saved filter config — supports all filter dimensions.
132
+ */
133
+ export interface SavedFilterConfig {
134
+ version: 2;
135
+ filters?: AnalyticsFilter[];
136
+ userId?: string;
137
+ dateRange?: {
138
+ preset?: string;
139
+ start?: string;
140
+ end?: string;
141
+ };
142
+ sortBy?: {
143
+ field: string;
144
+ order: 'asc' | 'desc';
145
+ };
146
+ }
147
+ /**
148
+ * Type guard for v2 saved filter configs.
149
+ */
150
+ export declare function isFilterConfigV2(config: SavedFilterConfigV1 | SavedFilterConfig | SavedViewConfig): config is SavedFilterConfig;
151
+ /**
152
+ * Display mode for the requests page.
153
+ */
154
+ export type RequestsDisplayMode = 'list' | 'aggregate';
155
+ /**
156
+ * V3 saved view config — supports display mode, groupBy, and column visibility.
157
+ * Used by the Requests page saved views system.
158
+ */
159
+ export interface SavedViewConfig {
160
+ version: 3;
161
+ displayMode: RequestsDisplayMode;
162
+ groupBy?: string;
163
+ filters?: AnalyticsFilter[];
164
+ dateRange?: {
165
+ preset?: string;
166
+ start?: string;
167
+ end?: string;
168
+ };
169
+ sortBy?: {
170
+ field: string;
171
+ order: 'asc' | 'desc';
172
+ };
173
+ columns?: Array<{
174
+ field: string;
175
+ visible: boolean;
176
+ }>;
177
+ }
178
+ /**
179
+ * Type guard for v3 saved view configs.
180
+ */
181
+ export declare function isViewConfigV3(config: SavedFilterConfigV1 | SavedFilterConfig | SavedViewConfig): config is SavedViewConfig;
182
+ /**
183
+ * A single row in the aggregate requests table.
184
+ * Groups requests by a dimension (model, user_id, metadata key).
185
+ */
186
+ export interface AggregateRequestsRow {
187
+ dimensionValue: string;
188
+ requests: number;
189
+ cost: number;
190
+ tokens: number;
191
+ inputTokens: number;
192
+ outputTokens: number;
193
+ avgLatencyMs: number;
194
+ successRate: number;
195
+ }
196
+ /**
197
+ * Paginated response for aggregate requests.
198
+ */
199
+ export interface AggregateRequestsResponse {
200
+ items: AggregateRequestsRow[];
201
+ total: number;
202
+ limit: number;
203
+ offset: number;
204
+ }
205
+ /**
206
+ * Parameters for aggregate requests query.
207
+ */
208
+ export interface AggregateRequestsParams extends PaginationParams {
209
+ dimension: string;
210
+ sortField?: string;
211
+ sortOrder?: 'asc' | 'desc';
212
+ filters?: AnalyticsFilter[];
213
+ startDate?: string;
214
+ endDate?: string;
215
+ }
216
+ /**
217
+ * Parameters for listing traces.
218
+ */
219
+ export interface TracesParams extends PaginationParams {
220
+ model?: string;
221
+ userId?: string;
222
+ status?: 'OK' | 'ERROR';
223
+ startDate?: string;
224
+ endDate?: string;
225
+ datasetRunId?: string;
226
+ sessionId?: string;
227
+ name?: string;
228
+ tags?: string[];
229
+ commitSha?: string;
230
+ filters?: AnalyticsFilter[];
231
+ sortBy?: string;
232
+ sortOrder?: 'asc' | 'desc';
233
+ }
234
+ /**
235
+ * Summary of a trace for list views.
236
+ */
237
+ export interface TraceSummary {
238
+ id: string;
239
+ name: string;
240
+ status: string;
241
+ start: string;
242
+ end: string;
243
+ latencyMs: number;
244
+ cost: number;
245
+ tokens: number;
246
+ spanCount: number;
247
+ tags?: string[];
248
+ }
249
+ /**
250
+ * Paginated response for trace listing.
251
+ */
252
+ export interface TracesResponse {
253
+ traces: TraceSummary[];
254
+ total: number;
255
+ limit: number;
256
+ offset: number;
257
+ }
258
+ /**
259
+ * Individual span within a trace.
260
+ * Includes all available fields from ClickHouse for trace inspection.
261
+ */
262
+ export interface Span {
263
+ id: string;
264
+ traceId: string;
265
+ parentId: string | null;
266
+ name: string;
267
+ status: string;
268
+ statusMessage: string;
269
+ durationMs: number;
270
+ timestamp: string;
271
+ type: 'SPAN' | 'GENERATION' | 'EVENT';
272
+ model: string | null;
273
+ inputTokens: number;
274
+ outputTokens: number;
275
+ tokens: number;
276
+ cost: number;
277
+ input: string;
278
+ output: string;
279
+ outputObject: string | null;
280
+ toolCalls: string | null;
281
+ finishReason: string | null;
282
+ settings: string | null;
283
+ reasoningTokens: number;
284
+ metadata: Record<string, string>;
285
+ props: string | null;
286
+ spanKind: string;
287
+ serviceName: string;
288
+ promptName: string | null;
289
+ }
290
+ /**
291
+ * I/O payload for a single span, fetched on demand.
292
+ */
293
+ export interface SpanIO {
294
+ input: string;
295
+ output: string;
296
+ outputObject: string | null;
297
+ toolCalls: string | null;
298
+ }
299
+ /**
300
+ * Complete trace detail with all spans.
301
+ * spanScores is a map from span ID -> scores for that span,
302
+ * populated by a parallel batch query against the scores table.
303
+ */
304
+ export interface TraceDetail {
305
+ id: string;
306
+ name: string;
307
+ status: string;
308
+ start: string;
309
+ end: string;
310
+ latencyMs: number;
311
+ cost: number;
312
+ tokens: number;
313
+ input?: string;
314
+ output?: string;
315
+ spans: Span[];
316
+ /** Eval scores keyed by span ID, batch-fetched in parallel with spans. */
317
+ spanScores?: Record<string, Score[]>;
318
+ /** True when the span scores query failed; scores will be empty in that case. */
319
+ spanScoresError?: boolean;
320
+ }
321
+ /**
322
+ * Parameters for listing sessions.
323
+ */
324
+ export interface SessionsParams extends PaginationParams {
325
+ startDate?: string;
326
+ endDate?: string;
327
+ filters?: AnalyticsFilter[];
328
+ search?: string;
329
+ sortBy?: string;
330
+ sortOrder?: 'asc' | 'desc';
331
+ }
332
+ /**
333
+ * Summary of a session for list views.
334
+ */
335
+ export interface SessionSummary {
336
+ id: string;
337
+ name: string;
338
+ start: string;
339
+ end: string;
340
+ traceCount: number;
341
+ totalCost: number;
342
+ totalTokens: number;
343
+ latencyMs: number;
344
+ tags?: string[];
345
+ }
346
+ /**
347
+ * Paginated response for session listing.
348
+ */
349
+ export interface SessionsResponse {
350
+ sessions: SessionSummary[];
351
+ total: number;
352
+ limit: number;
353
+ offset: number;
354
+ }
355
+ /**
356
+ * Supported metrics for percentile calculations.
357
+ *
358
+ * Sourced from api-schemas's `PERCENTILE_METRICS` const tuple — exact
359
+ * match for the literal union, so api-types re-exports the canonical
360
+ * type to keep the two packages in lockstep.
361
+ */
362
+ import type { PercentileMetric as _PercentileMetric } from '@agentmark-ai/api-schemas';
363
+ export type PercentileMetric = _PercentileMetric;
364
+ /**
365
+ * Parameters for percentiles query.
366
+ */
367
+ export interface PercentilesParams {
368
+ range: DateRangePreset;
369
+ startDate?: string;
370
+ endDate?: string;
371
+ metric: PercentileMetric;
372
+ }
373
+ /**
374
+ * Percentile data point for time series.
375
+ */
376
+ export interface PercentilePoint {
377
+ timestamp: string;
378
+ p75: number;
379
+ p90: number;
380
+ p95: number;
381
+ p99: number;
382
+ }
383
+ /**
384
+ * Response for percentiles query.
385
+ */
386
+ export interface PercentilesResponse {
387
+ metric: PercentileMetric;
388
+ data: PercentilePoint[];
389
+ }
390
+ /**
391
+ * Status of a dependency.
392
+ */
393
+ export type DependencyStatus = 'up' | 'down';
394
+ /**
395
+ * Health status of the analytics service.
396
+ */
397
+ export type HealthStatus = 'healthy' | 'degraded' | 'unhealthy';
398
+ /**
399
+ * Health check response.
400
+ */
401
+ export interface HealthResponse {
402
+ status: HealthStatus;
403
+ timestamp: string;
404
+ dependencies: {
405
+ clickhouse: {
406
+ status: DependencyStatus;
407
+ latencyMs?: number;
408
+ error?: string;
409
+ };
410
+ };
411
+ }
412
+ /**
413
+ * Summary of a dataset run for list views.
414
+ * Aggregates data from traces that are part of a dataset evaluation.
415
+ */
416
+ export interface DatasetRunSummary {
417
+ id: string;
418
+ name: string;
419
+ datasetPath: string;
420
+ commitSha: string;
421
+ start: string;
422
+ end: string;
423
+ itemCount: number;
424
+ totalCost: number;
425
+ totalTokens: number;
426
+ avgLatencyMs: number;
427
+ avgScore: number | null;
428
+ }
429
+ /**
430
+ * Parameters for listing dataset runs.
431
+ */
432
+ export interface DatasetRunParams extends Partial<PaginationParams> {
433
+ startDate?: string;
434
+ endDate?: string;
435
+ datasetPath?: string;
436
+ }
437
+ /**
438
+ * Paginated response for dataset runs listing.
439
+ */
440
+ export interface DatasetRunsResponse {
441
+ runs: DatasetRunSummary[];
442
+ total: number;
443
+ limit: number;
444
+ offset: number;
445
+ }
446
+ /**
447
+ * Summary of a single item within a dataset run.
448
+ */
449
+ export interface DatasetItemSummary {
450
+ id: string;
451
+ traceId: string;
452
+ name: string;
453
+ expectedOutput: string;
454
+ latencyMs: number;
455
+ cost: number;
456
+ tokens: number;
457
+ score: number | null;
458
+ status: string;
459
+ }
460
+ /**
461
+ * Complete dataset run detail with all items.
462
+ */
463
+ export interface DatasetRunDetail extends DatasetRunSummary {
464
+ items: DatasetItemSummary[];
465
+ }
466
+ import type { ExperimentItemScore as _ExperimentItemScore, ExperimentSummary as _ExperimentSummary, ExperimentItemSummary as _ExperimentItemSummary, ExperimentDetail as _ExperimentDetail } from '@agentmark-ai/api-schemas';
467
+ export type ExperimentItemScore = _ExperimentItemScore;
468
+ export type ExperimentSummary = _ExperimentSummary;
469
+ export type ExperimentItemSummary = _ExperimentItemSummary;
470
+ export type ExperimentDetail = _ExperimentDetail;
471
+ /**
472
+ * Parameters for listing experiments.
473
+ */
474
+ export interface ExperimentParams extends Partial<PaginationParams> {
475
+ startDate?: string;
476
+ endDate?: string;
477
+ promptName?: string;
478
+ datasetPath?: string;
479
+ }
480
+ /**
481
+ * Paginated response for experiments listing.
482
+ */
483
+ export interface ExperimentsResponse {
484
+ experiments: ExperimentSummary[];
485
+ total: number;
486
+ limit: number;
487
+ offset: number;
488
+ filterOptions?: {
489
+ promptNames: string[];
490
+ datasetPaths: string[];
491
+ };
492
+ }
493
+ /**
494
+ * Score record from the scores table.
495
+ * Scores can be attached to either traces or spans.
496
+ */
497
+ export interface Score {
498
+ id: string;
499
+ resourceId: string;
500
+ name: string;
501
+ score: number;
502
+ label: string;
503
+ reason: string;
504
+ source: 'eval' | 'annotation';
505
+ userId?: string;
506
+ createdAt: string;
507
+ }
508
+ /**
509
+ * Parameters for querying scores.
510
+ */
511
+ export interface ScoresParams extends Partial<PaginationParams> {
512
+ resourceId?: string;
513
+ resourceType?: 'trace' | 'span';
514
+ name?: string;
515
+ source?: 'eval' | 'annotation';
516
+ sessionId?: string;
517
+ startDate?: string;
518
+ endDate?: string;
519
+ }
520
+ /**
521
+ * Paginated response for scores listing.
522
+ */
523
+ export interface ScoresResponse {
524
+ scores: Score[];
525
+ total: number;
526
+ limit: number;
527
+ offset: number;
528
+ }
529
+ /**
530
+ * Aggregated statistics for a score name.
531
+ */
532
+ export interface ScoreAggregation {
533
+ name: string;
534
+ avgScore: number;
535
+ count: number;
536
+ minScore: number;
537
+ maxScore: number;
538
+ }
539
+ /**
540
+ * Response for score aggregations query.
541
+ */
542
+ export interface ScoreAggregationsResponse {
543
+ aggregations: ScoreAggregation[];
544
+ }
545
+ /**
546
+ * Response for distinct score names query.
547
+ */
548
+ export interface ScoreNamesResponse {
549
+ names: string[];
550
+ }
551
+ /**
552
+ * Detected score type based on data analysis.
553
+ * - 'numeric': scores with varying float values, no labels
554
+ * - 'categorical': scores with non-empty string labels (not just true/false)
555
+ * - 'boolean': scores with labels 'true' and/or 'false' only
556
+ */
557
+ export type ScoreType = 'numeric' | 'categorical' | 'boolean';
558
+ /**
559
+ * A single histogram bucket for numeric score distribution.
560
+ */
561
+ export interface ScoreHistogramBucket {
562
+ bucket: number;
563
+ count: number;
564
+ }
565
+ /**
566
+ * A single category count for categorical/boolean score distribution.
567
+ */
568
+ export interface ScoreCategoryCount {
569
+ label: string;
570
+ count: number;
571
+ }
572
+ /**
573
+ * Response for score histogram/distribution query.
574
+ */
575
+ export interface ScoreHistogramResponse {
576
+ name: string;
577
+ type: ScoreType;
578
+ buckets: ScoreHistogramBucket[];
579
+ categories: ScoreCategoryCount[];
580
+ }
581
+ /**
582
+ * A single data point in a score trend time series.
583
+ */
584
+ export interface ScoreTrendPoint {
585
+ timestamp: string;
586
+ avgScore: number;
587
+ count: number;
588
+ }
589
+ /**
590
+ * Valid trend interval values.
591
+ *
592
+ * Sourced from api-schemas's `SCORE_TREND_INTERVALS` const tuple — exact
593
+ * match for the literal union, so api-types re-exports the canonical
594
+ * type to keep the two packages in lockstep.
595
+ */
596
+ import type { ScoreTrendInterval as _ScoreTrendInterval } from '@agentmark-ai/api-schemas';
597
+ export type ScoreTrendInterval = _ScoreTrendInterval;
598
+ /**
599
+ * Response for score trend query.
600
+ */
601
+ export interface ScoreTrendResponse {
602
+ name: string;
603
+ interval: ScoreTrendInterval;
604
+ points: ScoreTrendPoint[];
605
+ }
606
+ /**
607
+ * A cell in the confusion matrix for score comparison.
608
+ */
609
+ export interface ScoreComparisonCell {
610
+ labelA: string;
611
+ labelB: string;
612
+ count: number;
613
+ }
614
+ /**
615
+ * Response for score comparison (confusion matrix) query.
616
+ */
617
+ export interface ScoreComparisonResponse {
618
+ nameA: string;
619
+ nameB: string;
620
+ type: ScoreType;
621
+ matrix: ScoreComparisonCell[];
622
+ totalMatched: number;
623
+ totalA: number;
624
+ totalB: number;
625
+ }
626
+ /**
627
+ * A single point in the scatter plot (paired numeric scores).
628
+ */
629
+ export interface ScoreScatterPoint {
630
+ scoreA: number;
631
+ scoreB: number;
632
+ }
633
+ /**
634
+ * Response for numeric score scatter plot query.
635
+ */
636
+ export interface ScoreScatterResponse {
637
+ nameA: string;
638
+ nameB: string;
639
+ points: ScoreScatterPoint[];
640
+ totalMatched: number;
641
+ totalA: number;
642
+ totalB: number;
643
+ }
644
+ /**
645
+ * Filter for analytics queries from the dashboard.
646
+ * Matches the format used by the filter context.
647
+ */
648
+ export interface AnalyticsFilter {
649
+ field: string;
650
+ operator: string;
651
+ value: string | string[];
652
+ }
653
+ /**
654
+ * Supported filter fields for metrics queries.
655
+ */
656
+ export type MetricsFilterField = 'model' | 'user_id' | 'status';
657
+ /**
658
+ * Validated filter for metrics queries.
659
+ * Ensures only supported fields are used.
660
+ */
661
+ export interface ValidatedMetricsFilter {
662
+ field: MetricsFilterField;
663
+ operator: 'equals' | 'notEquals' | 'contains';
664
+ value: string;
665
+ }
666
+ /**
667
+ * String comparison operators for filtering.
668
+ */
669
+ export type StringFilterOperator = 'equals' | 'notEquals' | 'contains' | 'notContains' | 'startsWith' | 'endsWith';
670
+ /**
671
+ * Number comparison operators for filtering.
672
+ */
673
+ export type NumberFilterOperator = 'equals' | 'notEquals' | 'lt' | 'lte' | 'gt' | 'gte';
674
+ /**
675
+ * Combined filter operator type.
676
+ */
677
+ export type FilterOperator = StringFilterOperator | NumberFilterOperator;
678
+ /**
679
+ * Filter condition for a string field.
680
+ */
681
+ export interface StringFilter {
682
+ operator: StringFilterOperator;
683
+ value: string;
684
+ }
685
+ /**
686
+ * Filter condition for a number field.
687
+ */
688
+ export interface NumberFilter {
689
+ operator: NumberFilterOperator;
690
+ value: number;
691
+ }
692
+ /**
693
+ * Extended trace parameters with advanced filtering support.
694
+ */
695
+ export interface AdvancedTracesParams extends TracesParams {
696
+ modelFilter?: StringFilter;
697
+ userIdFilter?: StringFilter;
698
+ latencyFilter?: NumberFilter;
699
+ costFilter?: NumberFilter;
700
+ }
701
+ /**
702
+ * Extended metrics summary with per-request averages.
703
+ * Provides additional computed metrics for dashboard display.
704
+ */
705
+ export interface ExtendedMetricsSummary extends MetricsSummary {
706
+ avgCostPerRequest: number;
707
+ avgInputTokensPerRequest: number;
708
+ avgOutputTokensPerRequest: number;
709
+ avgTotalTokensPerRequest: number;
710
+ modelCount: number;
711
+ }
712
+ /**
713
+ * Extended metrics response with per-request averages.
714
+ */
715
+ export interface ExtendedMetricsResponse {
716
+ summary: ExtendedMetricsSummary;
717
+ timeSeries: TimeSeriesPoint[];
718
+ }
719
+ /**
720
+ * Filter column definition for the filter popover UI.
721
+ */
722
+ export interface FilterColumn {
723
+ field: string;
724
+ label: string;
725
+ type: 'string' | 'number' | 'enum';
726
+ operators: string[];
727
+ enumValues?: string[];
728
+ }
729
+ /**
730
+ * Sort configuration.
731
+ */
732
+ export interface SortConfig {
733
+ field: string;
734
+ order: 'asc' | 'desc';
735
+ }
736
+ /**
737
+ * Date range configuration for saved views.
738
+ */
739
+ export interface DateRangeConfig {
740
+ preset: 'today' | '7d' | '30d' | '90d' | 'custom';
741
+ startDate?: string;
742
+ endDate?: string;
743
+ }
744
+ /**
745
+ * V4 saved view config — supports traces and sessions pages.
746
+ * Used by the Traces/Sessions page saved views system.
747
+ */
748
+ export interface TraceFilterConfig {
749
+ version: 4;
750
+ filters?: AnalyticsFilter[];
751
+ dateRange?: DateRangeConfig;
752
+ sortBy?: SortConfig;
753
+ search?: string;
754
+ }
755
+ /**
756
+ * Analytics service interface.
757
+ * Defines the contract for analytics data access.
758
+ *
759
+ * SECURITY: All methods require TenantContext to ensure both tenantId
760
+ * and appId are provided, enforcing tenant isolation at compile time.
761
+ */
762
+ export interface IAnalyticsService {
763
+ checkConnectivity(): Promise<boolean>;
764
+ getMetrics(ctx: TenantContext, dateRange: DateRange, filters?: AnalyticsFilter[]): Promise<MetricsResponse>;
765
+ getExtendedMetrics(ctx: TenantContext, dateRange: DateRange): Promise<ExtendedMetricsResponse>;
766
+ getModelStats(ctx: TenantContext, dateRange: DateRange, limit?: number, filters?: AnalyticsFilter[]): Promise<ModelStatsResponse>;
767
+ getTraces(ctx: TenantContext, params: TracesParams): Promise<TracesResponse>;
768
+ getTraceDetail(ctx: TenantContext, traceId: string): Promise<TraceDetail | null>;
769
+ getTraceDetailLightweight(ctx: TenantContext, traceId: string): Promise<TraceDetail | null>;
770
+ getSpanIO(ctx: TenantContext, traceId: string, spanId: string): Promise<SpanIO | null>;
771
+ getSessions(ctx: TenantContext, params: SessionsParams): Promise<SessionsResponse>;
772
+ getSessionTraces(ctx: TenantContext, sessionId: string): Promise<TraceDetail[]>;
773
+ getPercentiles(ctx: TenantContext, params: PercentilesParams, filters?: AnalyticsFilter[]): Promise<PercentilesResponse>;
774
+ getDatasetRuns(ctx: TenantContext, params: DatasetRunParams): Promise<DatasetRunsResponse>;
775
+ getDatasetRunDetail(ctx: TenantContext, runId: string): Promise<DatasetRunDetail | null>;
776
+ getExperiments(ctx: TenantContext, params: ExperimentParams): Promise<ExperimentsResponse>;
777
+ getExperimentDetail(ctx: TenantContext, experimentId: string): Promise<ExperimentDetail | null>;
778
+ getScores(ctx: TenantContext, params: ScoresParams): Promise<ScoresResponse>;
779
+ getScoresBySpanIds(ctx: TenantContext, spanIds: string[]): Promise<Record<string, Score[]>>;
780
+ getScoreAggregations(ctx: TenantContext, dateRange: DateRange): Promise<ScoreAggregationsResponse>;
781
+ getDistinctScoreNames(ctx: TenantContext): Promise<ScoreNamesResponse>;
782
+ detectScoreType(ctx: TenantContext, name: string): Promise<ScoreType>;
783
+ getScoreHistogram(ctx: TenantContext, name: string, dateRange: DateRange, source?: string): Promise<ScoreHistogramResponse>;
784
+ getScoreTrend(ctx: TenantContext, name: string, interval: ScoreTrendInterval, dateRange: DateRange, source?: string): Promise<ScoreTrendResponse>;
785
+ getScoreComparison(ctx: TenantContext, nameA: string, nameB: string, dateRange: DateRange, source?: string): Promise<ScoreComparisonResponse>;
786
+ getScoreScatter(ctx: TenantContext, nameA: string, nameB: string, dateRange: DateRange, source?: string): Promise<ScoreScatterResponse>;
787
+ getDistinctMetadataKeys(ctx: TenantContext): Promise<string[]>;
788
+ getPromptLogs(ctx: TenantContext, params: PromptLogsParams): Promise<PromptLogsResponse>;
789
+ getRankingData(ctx: TenantContext, dateRange: DateRange, dimension: string, limit?: number, filters?: AnalyticsFilter[]): Promise<RankingDataResponse>;
790
+ getAggregateRequests(ctx: TenantContext, params: AggregateRequestsParams): Promise<AggregateRequestsResponse>;
791
+ getSpanKindBreakdown(ctx: TenantContext, dateRange: {
792
+ startDate: string;
793
+ endDate: string;
794
+ }): Promise<SpanKindBreakdownRecord[]>;
795
+ }
796
+ export interface SpanKindBreakdownRecord {
797
+ kind: string;
798
+ count: number;
799
+ avgLatencyMs: number;
800
+ totalCost: number;
801
+ totalTokens: number;
802
+ }
803
+ /**
804
+ * Parameters for listing prompt logs.
805
+ */
806
+ export interface PromptLogsParams extends PaginationParams {
807
+ startDate?: string;
808
+ endDate?: string;
809
+ model?: string;
810
+ userId?: string;
811
+ status?: 'OK' | 'ERROR';
812
+ sortField?: string;
813
+ sortOrder?: 'asc' | 'desc';
814
+ filters?: AnalyticsFilter[];
815
+ }
816
+ /**
817
+ * Prompt log record (GENERATION type trace with input/output).
818
+ */
819
+ export interface PromptLogRecord {
820
+ id: string;
821
+ tenantId: string;
822
+ appId: string;
823
+ cost: number;
824
+ promptTokens: number;
825
+ completionTokens: number;
826
+ latencyMs: number;
827
+ modelUsed: string;
828
+ status: string;
829
+ input: string;
830
+ output: string | null;
831
+ ts: string;
832
+ userId: string;
833
+ promptName: string;
834
+ traceId: string;
835
+ statusMessage: string;
836
+ props: string;
837
+ }
838
+ /**
839
+ * Paginated response for prompt logs listing.
840
+ */
841
+ export interface PromptLogsResponse {
842
+ logs: PromptLogRecord[];
843
+ total: number;
844
+ limit: number;
845
+ offset: number;
846
+ }
847
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Analytics Service Types
4
+ * Feature: 007-analytics-architecture-evaluation
5
+ *
6
+ * These types define the contract for the analytics service layer,
7
+ * including API request/response shapes and internal data structures.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.isFilterConfigV2 = isFilterConfigV2;
11
+ exports.isViewConfigV3 = isViewConfigV3;
12
+ /**
13
+ * Type guard for v2 saved filter configs.
14
+ */
15
+ function isFilterConfigV2(config) {
16
+ return 'version' in config && config.version === 2;
17
+ }
18
+ /**
19
+ * Type guard for v3 saved view configs.
20
+ */
21
+ function isViewConfigV3(config) {
22
+ return 'version' in config && config.version === 3;
23
+ }
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@agentmark-ai/api-types",
3
+ "version": "0.1.0",
4
+ "description": "Shared API contract types for AgentMark services",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "build": "tsc -p tsconfig.build.json",
15
+ "clean": "rm -rf dist"
16
+ },
17
+ "dependencies": {
18
+ "@agentmark-ai/api-schemas": "0.1.0"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.5.3"
22
+ }
23
+ }