ai-experiments 2.3.0 → 2.4.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,310 @@
1
+ /**
2
+ * Event tracking for experiments
3
+ */
4
+ /**
5
+ * Default tracking configuration
6
+ */
7
+ let trackingConfig = {
8
+ backend: createConsoleBackend(),
9
+ enabled: true,
10
+ metadata: {},
11
+ };
12
+ /**
13
+ * Configure tracking
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { configureTracking } from 'ai-experiments'
18
+ *
19
+ * // Use console backend (default)
20
+ * configureTracking({
21
+ * enabled: true,
22
+ * metadata: { projectId: 'my-project' },
23
+ * })
24
+ *
25
+ * // Use custom backend
26
+ * configureTracking({
27
+ * backend: {
28
+ * track: async (event) => {
29
+ * await fetch('/api/analytics', {
30
+ * method: 'POST',
31
+ * body: JSON.stringify(event),
32
+ * })
33
+ * },
34
+ * },
35
+ * })
36
+ *
37
+ * // Disable tracking
38
+ * configureTracking({ enabled: false })
39
+ * ```
40
+ */
41
+ export function configureTracking(options) {
42
+ trackingConfig = {
43
+ backend: options.backend ?? trackingConfig.backend,
44
+ enabled: options.enabled ?? trackingConfig.enabled,
45
+ metadata: options.metadata ?? trackingConfig.metadata,
46
+ };
47
+ }
48
+ /**
49
+ * Track an event
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * import { track } from 'ai-experiments'
54
+ *
55
+ * track({
56
+ * type: 'experiment.start',
57
+ * timestamp: new Date(),
58
+ * data: {
59
+ * experimentId: 'my-experiment',
60
+ * variantCount: 3,
61
+ * },
62
+ * })
63
+ * ```
64
+ */
65
+ export function track(event) {
66
+ if (!trackingConfig.enabled) {
67
+ return;
68
+ }
69
+ // Merge global metadata
70
+ const enrichedEvent = {
71
+ ...event,
72
+ data: {
73
+ ...event.data,
74
+ ...trackingConfig.metadata,
75
+ },
76
+ };
77
+ // Track via backend (handle both sync and async)
78
+ const result = trackingConfig.backend.track(enrichedEvent);
79
+ if (result instanceof Promise) {
80
+ // Don't await - fire and forget
81
+ result.catch((error) => {
82
+ console.error('Error tracking event:', error);
83
+ });
84
+ }
85
+ }
86
+ /**
87
+ * Flush pending events
88
+ *
89
+ * Call this before the process exits to ensure all events are sent.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import { flush } from 'ai-experiments'
94
+ *
95
+ * process.on('SIGINT', async () => {
96
+ * await flush()
97
+ * process.exit(0)
98
+ * })
99
+ * ```
100
+ */
101
+ export async function flush() {
102
+ if (trackingConfig.backend.flush) {
103
+ await trackingConfig.backend.flush();
104
+ }
105
+ }
106
+ /**
107
+ * Create a console-based tracking backend
108
+ *
109
+ * Logs events to console.log in a human-readable format.
110
+ */
111
+ export function createConsoleBackend(options) {
112
+ const { verbose = false } = options ?? {};
113
+ return {
114
+ track: (event) => {
115
+ const timestamp = event.timestamp.toISOString();
116
+ if (verbose) {
117
+ console.log(`[${timestamp}] ${event.type}`, event.data);
118
+ }
119
+ else {
120
+ // Condensed format
121
+ const key = extractKey(event);
122
+ console.log(`[${timestamp}] ${event.type} ${key}`);
123
+ }
124
+ },
125
+ };
126
+ }
127
+ /**
128
+ * Create an in-memory tracking backend that stores events
129
+ *
130
+ * Useful for testing or collecting events for batch processing.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * import { createMemoryBackend } from 'ai-experiments'
135
+ *
136
+ * const backend = createMemoryBackend()
137
+ * configureTracking({ backend })
138
+ *
139
+ * // Run experiments...
140
+ *
141
+ * // Get all events
142
+ * const events = backend.getEvents()
143
+ * console.log(`Tracked ${events.length} events`)
144
+ *
145
+ * // Clear events
146
+ * backend.clear()
147
+ * ```
148
+ */
149
+ export function createMemoryBackend() {
150
+ const events = [];
151
+ return {
152
+ track: (event) => {
153
+ events.push(event);
154
+ },
155
+ getEvents: () => [...events],
156
+ clear: () => {
157
+ events.length = 0;
158
+ },
159
+ };
160
+ }
161
+ /**
162
+ * Create a batching tracking backend
163
+ *
164
+ * Batches events and sends them in groups to reduce network overhead.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * import { createBatchBackend } from 'ai-experiments'
169
+ *
170
+ * const backend = createBatchBackend({
171
+ * batchSize: 10,
172
+ * flushInterval: 5000, // 5 seconds
173
+ * send: async (events) => {
174
+ * await fetch('/api/analytics/batch', {
175
+ * method: 'POST',
176
+ * body: JSON.stringify({ events }),
177
+ * })
178
+ * },
179
+ * })
180
+ *
181
+ * configureTracking({ backend })
182
+ * ```
183
+ */
184
+ export function createBatchBackend(options) {
185
+ const { batchSize, flushInterval, send } = options;
186
+ const batch = [];
187
+ let flushTimer = null;
188
+ const flush = async () => {
189
+ if (batch.length === 0)
190
+ return;
191
+ const eventsToSend = [...batch];
192
+ batch.length = 0;
193
+ try {
194
+ await send(eventsToSend);
195
+ }
196
+ catch (error) {
197
+ console.error('Error sending batch:', error);
198
+ // Re-add failed events to batch (simple retry strategy)
199
+ batch.unshift(...eventsToSend);
200
+ }
201
+ };
202
+ const scheduleFlush = () => {
203
+ if (flushTimer) {
204
+ clearTimeout(flushTimer);
205
+ }
206
+ if (flushInterval) {
207
+ flushTimer = setTimeout(() => {
208
+ flush().catch(console.error);
209
+ }, flushInterval);
210
+ }
211
+ };
212
+ return {
213
+ track: (event) => {
214
+ batch.push(event);
215
+ // Auto-flush if batch is full
216
+ if (batch.length >= batchSize) {
217
+ flush().catch(console.error);
218
+ }
219
+ else {
220
+ scheduleFlush();
221
+ }
222
+ },
223
+ flush: async () => {
224
+ if (flushTimer) {
225
+ clearTimeout(flushTimer);
226
+ flushTimer = null;
227
+ }
228
+ await flush();
229
+ },
230
+ };
231
+ }
232
+ /**
233
+ * Create a file-based tracking backend
234
+ *
235
+ * Writes events to a file (JSONL format).
236
+ *
237
+ * @example
238
+ * ```ts
239
+ * import { createFileBackend } from 'ai-experiments'
240
+ *
241
+ * const backend = createFileBackend({
242
+ * path: './experiments.jsonl',
243
+ * })
244
+ *
245
+ * configureTracking({ backend })
246
+ * ```
247
+ */
248
+ export function createFileBackend(options) {
249
+ // Note: This requires Node.js fs module
250
+ // Import dynamically to avoid breaking in non-Node environments
251
+ let fs = null;
252
+ let writeStream = null;
253
+ const ensureStream = async () => {
254
+ if (!writeStream) {
255
+ try {
256
+ fs = await import('fs');
257
+ writeStream = fs.createWriteStream(options.path, { flags: 'a' });
258
+ }
259
+ catch (error) {
260
+ console.error('Failed to create file stream:', error);
261
+ throw error;
262
+ }
263
+ }
264
+ return writeStream;
265
+ };
266
+ return {
267
+ track: async (event) => {
268
+ try {
269
+ const stream = await ensureStream();
270
+ const line = JSON.stringify(event) + '\n';
271
+ stream.write(line);
272
+ }
273
+ catch (error) {
274
+ console.error('Failed to write event to file:', error);
275
+ }
276
+ },
277
+ flush: async () => {
278
+ if (writeStream) {
279
+ return new Promise((resolve, reject) => {
280
+ writeStream.end((error) => {
281
+ if (error)
282
+ reject(error);
283
+ else
284
+ resolve();
285
+ });
286
+ });
287
+ }
288
+ },
289
+ };
290
+ }
291
+ /**
292
+ * Extract a key identifier from event data for logging
293
+ */
294
+ function extractKey(event) {
295
+ const data = event.data;
296
+ if ('experimentId' in data)
297
+ return `exp=${data['experimentId']}`;
298
+ if ('variantId' in data)
299
+ return `variant=${data['variantId']}`;
300
+ if ('runId' in data)
301
+ return `run=${data['runId']}`;
302
+ return '';
303
+ }
304
+ /**
305
+ * Get current tracking configuration
306
+ */
307
+ export function getTrackingConfig() {
308
+ return { ...trackingConfig };
309
+ }
310
+ //# sourceMappingURL=tracking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracking.js","sourceRoot":"","sources":["../src/tracking.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Core types for AI experimentation
3
+ */
4
+ /**
5
+ * A variant within an experiment
6
+ */
7
+ export interface ExperimentVariant<TConfig = unknown> {
8
+ /** Unique identifier for the variant */
9
+ id: string;
10
+ /** Human-readable name */
11
+ name: string;
12
+ /** Variant configuration */
13
+ config: TConfig;
14
+ /** Weight for weighted random selection (default: 1) */
15
+ weight?: number;
16
+ /** Optional description */
17
+ description?: string;
18
+ }
19
+ /**
20
+ * Configuration for an experiment
21
+ */
22
+ export interface ExperimentConfig<TConfig = unknown, TResult = unknown> {
23
+ /** Unique experiment identifier */
24
+ id: string;
25
+ /** Human-readable name */
26
+ name: string;
27
+ /** Experiment description */
28
+ description?: string;
29
+ /** List of variants to test */
30
+ variants: ExperimentVariant<TConfig>[];
31
+ /** Function to execute for each variant */
32
+ execute: (config: TConfig, context?: ExperimentContext) => Promise<TResult> | TResult;
33
+ /** Optional success metric function */
34
+ metric?: (result: TResult) => number | Promise<number>;
35
+ /** Metadata for the experiment */
36
+ metadata?: Record<string, unknown>;
37
+ }
38
+ /**
39
+ * Context passed to experiment execution
40
+ */
41
+ export interface ExperimentContext {
42
+ /** Experiment ID */
43
+ experimentId: string;
44
+ /** Variant ID */
45
+ variantId: string;
46
+ /** Run ID (unique per execution) */
47
+ runId: string;
48
+ /** Timestamp when execution started */
49
+ startedAt: Date;
50
+ /** Additional context data */
51
+ data?: Record<string, unknown>;
52
+ }
53
+ /**
54
+ * Result of executing an experiment variant
55
+ */
56
+ export interface ExperimentResult<TResult = unknown> {
57
+ /** Experiment ID */
58
+ experimentId: string;
59
+ /** Variant ID */
60
+ variantId: string;
61
+ /** Variant name */
62
+ variantName: string;
63
+ /** Run ID */
64
+ runId: string;
65
+ /** Execution result */
66
+ result: TResult;
67
+ /** Computed metric value (if metric function provided) */
68
+ metricValue?: number;
69
+ /** Execution duration in milliseconds */
70
+ duration: number;
71
+ /** Timestamp when execution started */
72
+ startedAt: Date;
73
+ /** Timestamp when execution completed */
74
+ completedAt: Date;
75
+ /** Error if execution failed */
76
+ error?: Error;
77
+ /** Success flag */
78
+ success: boolean;
79
+ /** Additional metadata */
80
+ metadata?: Record<string, unknown>;
81
+ }
82
+ /**
83
+ * Summary of experiment results across all variants
84
+ */
85
+ export interface ExperimentSummary<TResult = unknown> {
86
+ /** Experiment ID */
87
+ experimentId: string;
88
+ /** Experiment name */
89
+ experimentName: string;
90
+ /** Results for each variant */
91
+ results: ExperimentResult<TResult>[];
92
+ /** Best performing variant (by metric) */
93
+ bestVariant?: {
94
+ variantId: string;
95
+ variantName: string;
96
+ metricValue: number;
97
+ };
98
+ /** Total execution duration */
99
+ totalDuration: number;
100
+ /** Number of successful runs */
101
+ successCount: number;
102
+ /** Number of failed runs */
103
+ failureCount: number;
104
+ /** Timestamp when experiment started */
105
+ startedAt: Date;
106
+ /** Timestamp when experiment completed */
107
+ completedAt: Date;
108
+ }
109
+ /**
110
+ * Options for running an experiment
111
+ */
112
+ export interface RunExperimentOptions {
113
+ /** Run variants in parallel (default: true) */
114
+ parallel?: boolean;
115
+ /** Maximum concurrent executions (default: unlimited) */
116
+ maxConcurrency?: number;
117
+ /** Stop on first error (default: false) */
118
+ stopOnError?: boolean;
119
+ /** Custom context data */
120
+ context?: Record<string, unknown>;
121
+ /** Event callbacks */
122
+ onVariantStart?: (variantId: string, variantName: string) => void;
123
+ onVariantComplete?: (result: ExperimentResult) => void;
124
+ onVariantError?: (variantId: string, error: Error) => void;
125
+ }
126
+ /**
127
+ * Parameters for cartesian product generation
128
+ */
129
+ export type CartesianParams = Record<string, unknown[]>;
130
+ /**
131
+ * Result of cartesian product - array of parameter combinations
132
+ */
133
+ export type CartesianResult<T extends CartesianParams> = Array<{
134
+ [K in keyof T]: T[K][number];
135
+ }>;
136
+ /**
137
+ * Decision options
138
+ */
139
+ export interface DecideOptions<T> {
140
+ /** Options to choose from */
141
+ options: T[];
142
+ /** Scoring function for each option */
143
+ score: (option: T) => number | Promise<number>;
144
+ /** Context or prompt for decision making */
145
+ context?: string;
146
+ /** Whether to return all options sorted by score (default: false) */
147
+ returnAll?: boolean;
148
+ }
149
+ /**
150
+ * Result of a decision
151
+ */
152
+ export interface DecisionResult<T> {
153
+ /** The selected option */
154
+ selected: T;
155
+ /** Score of the selected option */
156
+ score: number;
157
+ /** All options with their scores (if returnAll was true) */
158
+ allOptions?: Array<{
159
+ option: T;
160
+ score: number;
161
+ }>;
162
+ }
163
+ /**
164
+ * Tracking event types
165
+ */
166
+ export type TrackingEventType = 'experiment.start' | 'experiment.complete' | 'variant.start' | 'variant.complete' | 'variant.error' | 'metric.computed' | 'decision.made';
167
+ /**
168
+ * Tracking event
169
+ */
170
+ export interface TrackingEvent {
171
+ /** Event type */
172
+ type: TrackingEventType;
173
+ /** Timestamp */
174
+ timestamp: Date;
175
+ /** Event data */
176
+ data: Record<string, unknown>;
177
+ }
178
+ /**
179
+ * Tracking backend interface
180
+ */
181
+ export interface TrackingBackend {
182
+ /** Track an event */
183
+ track(event: TrackingEvent): void | Promise<void>;
184
+ /** Flush pending events */
185
+ flush?(): void | Promise<void>;
186
+ }
187
+ /**
188
+ * Options for tracking configuration
189
+ */
190
+ export interface TrackingOptions {
191
+ /** Custom tracking backend */
192
+ backend?: TrackingBackend;
193
+ /** Whether tracking is enabled (default: true) */
194
+ enabled?: boolean;
195
+ /** Additional metadata to include with all events */
196
+ metadata?: Record<string, unknown>;
197
+ }
198
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,OAAO,GAAG,OAAO;IAClD,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,4BAA4B;IAC5B,MAAM,EAAE,OAAO,CAAA;IACf,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;IACpE,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+BAA+B;IAC/B,QAAQ,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,CAAA;IACtC,2CAA2C;IAC3C,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAA;IACrF,uCAAuC;IACvC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACtD,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,SAAS,EAAE,IAAI,CAAA;IACf,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,OAAO,GAAG,OAAO;IACjD,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa;IACb,KAAK,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,MAAM,EAAE,OAAO,CAAA;IACf,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,SAAS,EAAE,IAAI,CAAA;IACf,yCAAyC;IACzC,WAAW,EAAE,IAAI,CAAA;IACjB,gCAAgC;IAChC,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,mBAAmB;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,OAAO,GAAG,OAAO;IAClD,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,sBAAsB;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,+BAA+B;IAC/B,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAA;IACpC,0CAA0C;IAC1C,WAAW,CAAC,EAAE;QACZ,SAAS,EAAE,MAAM,CAAA;QACjB,WAAW,EAAE,MAAM,CAAA;QACnB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAA;IACrB,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,wCAAwC;IACxC,SAAS,EAAE,IAAI,CAAA;IACf,0CAA0C;IAC1C,WAAW,EAAE,IAAI,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,sBAAsB;IACtB,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IACjE,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAA;IACtD,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAC3D;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAA;AAEvD;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,eAAe,IAAI,KAAK,CAAC;KAC5D,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;CAC7B,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,6BAA6B;IAC7B,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ,uCAAuC;IACvC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9C,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,0BAA0B;IAC1B,QAAQ,EAAE,CAAC,CAAA;IACX,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACjD;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,kBAAkB,GAClB,qBAAqB,GACrB,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,iBAAiB,GACjB,eAAe,CAAA;AAEnB;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iBAAiB;IACjB,IAAI,EAAE,iBAAiB,CAAA;IACvB,gBAAgB;IAChB,SAAS,EAAE,IAAI,CAAA;IACf,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,KAAK,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,2BAA2B;IAC3B,KAAK,CAAC,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,kDAAkD;IAClD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core types for AI experimentation
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-experiments",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "Runtime A/B testing for AI variants in production - traffic splitting, decision strategies, and ClickHouse-backed outcome tracking",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,8 +24,8 @@
24
24
  "clean": "rm -rf dist"
25
25
  },
26
26
  "dependencies": {
27
- "ai-database": "2.3.0",
28
- "ai-functions": "2.3.0"
27
+ "ai-database": "2.4.0",
28
+ "ai-functions": "2.4.0"
29
29
  },
30
30
  "keywords": [
31
31
  "ai",