@savvagent/sdk 1.0.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,599 @@
1
+ /**
2
+ * Savvagent SDK Types
3
+ */
4
+ /**
5
+ * Configuration for initializing the FlagClient
6
+ */
7
+ interface FlagClientConfig {
8
+ /** SDK API key (starts with sdk_) */
9
+ apiKey: string;
10
+ /** Application ID for application-scoped flags (omit for enterprise flags only) */
11
+ applicationId?: string;
12
+ /** Base URL for the Savvagent API (default: production URL) */
13
+ baseUrl?: string;
14
+ /** Enable real-time flag updates via SSE (default: true) */
15
+ enableRealtime?: boolean;
16
+ /** Cache TTL in milliseconds (default: 60000 = 1 minute) */
17
+ cacheTtl?: number;
18
+ /** Enable telemetry tracking (default: true) */
19
+ enableTelemetry?: boolean;
20
+ /** Default flag values when evaluation fails */
21
+ defaults?: Record<string, boolean>;
22
+ /** Custom error handler */
23
+ onError?: (error: Error) => void;
24
+ /** Default language for targeting (overrides browser detection) */
25
+ defaultLanguage?: string;
26
+ /** Disable automatic browser language detection (default: false) */
27
+ disableLanguageDetection?: boolean;
28
+ }
29
+ /**
30
+ * Context passed to flag evaluation
31
+ */
32
+ interface FlagContext {
33
+ /** User ID for targeted rollouts (logged-in users) */
34
+ user_id?: string;
35
+ /** Anonymous ID for consistent rollouts (anonymous users) */
36
+ anonymous_id?: string;
37
+ /** Session ID as fallback identifier */
38
+ session_id?: string;
39
+ /** Application ID for application-scoped flags (auto-injected from config) */
40
+ application_id?: string;
41
+ /** User's language for language targeting (BCP 47 format, e.g., "en", "en-US") */
42
+ language?: string;
43
+ /** Custom attributes for targeting rules */
44
+ attributes?: Record<string, any>;
45
+ /** Environment (dev, staging, production) */
46
+ environment?: string;
47
+ }
48
+ /**
49
+ * Result from flag evaluation
50
+ */
51
+ interface FlagEvaluationResult {
52
+ /** Flag key */
53
+ key: string;
54
+ /** Evaluated value */
55
+ value: boolean;
56
+ /** Reason for the value (cached, evaluated, default) */
57
+ reason: 'cached' | 'evaluated' | 'default' | 'error';
58
+ /** Metadata about the flag */
59
+ metadata?: {
60
+ flagId?: string;
61
+ description?: string;
62
+ scope?: string | null;
63
+ configuration?: any;
64
+ variation?: string | null;
65
+ timestamp?: number;
66
+ };
67
+ }
68
+ /**
69
+ * Telemetry event for flag evaluation
70
+ */
71
+ interface EvaluationEvent {
72
+ flagKey: string;
73
+ result: boolean;
74
+ context?: FlagContext;
75
+ durationMs: number;
76
+ traceId?: string;
77
+ timestamp: string;
78
+ }
79
+ /**
80
+ * Telemetry event for errors in flagged code
81
+ */
82
+ interface ErrorEvent {
83
+ flagKey: string;
84
+ flagEnabled: boolean;
85
+ errorType: string;
86
+ errorMessage: string;
87
+ stackTrace?: string;
88
+ context?: FlagContext;
89
+ traceId?: string;
90
+ timestamp: string;
91
+ }
92
+ /**
93
+ * Cache entry for flag values
94
+ */
95
+ interface CacheEntry {
96
+ value: boolean;
97
+ expiresAt: number;
98
+ flagId?: string;
99
+ }
100
+ /**
101
+ * Real-time update event from SSE
102
+ */
103
+ interface FlagUpdateEvent {
104
+ type: 'flag.updated' | 'flag.deleted' | 'flag.created';
105
+ flagKey: string;
106
+ data?: any;
107
+ }
108
+
109
+ /**
110
+ * Savvagent Client for feature flag evaluation with AI-powered error detection
111
+ */
112
+ declare class FlagClient {
113
+ private config;
114
+ private cache;
115
+ private telemetry;
116
+ private realtime;
117
+ private anonymousId;
118
+ private userId;
119
+ private detectedLanguage;
120
+ constructor(config: FlagClientConfig);
121
+ /**
122
+ * Get or create an anonymous ID for consistent flag evaluation
123
+ * @returns Anonymous ID from localStorage or newly generated
124
+ */
125
+ private getOrCreateAnonymousId;
126
+ /**
127
+ * Set a custom anonymous ID
128
+ * Useful for cross-device tracking or custom identifier schemes
129
+ * @param id - The anonymous ID to use
130
+ */
131
+ setAnonymousId(id: string): void;
132
+ /**
133
+ * Set the user ID for logged-in users
134
+ * This takes precedence over anonymous ID
135
+ * @param userId - The user ID (or null to clear)
136
+ */
137
+ setUserId(userId: string | null): void;
138
+ /**
139
+ * Get the current user ID
140
+ */
141
+ getUserId(): string | null;
142
+ /**
143
+ * Get the current anonymous ID
144
+ */
145
+ getAnonymousId(): string;
146
+ /**
147
+ * Build the context for flag evaluation
148
+ * @param overrides - Context overrides
149
+ */
150
+ private buildContext;
151
+ /**
152
+ * Check if a feature flag is enabled
153
+ * @param flagKey - The flag key to evaluate
154
+ * @param context - Optional context for targeting
155
+ * @returns Promise<boolean>
156
+ */
157
+ isEnabled(flagKey: string, context?: FlagContext): Promise<boolean>;
158
+ /**
159
+ * Evaluate a feature flag and return detailed result
160
+ * @param flagKey - The flag key to evaluate
161
+ * @param context - Optional context for targeting
162
+ * @returns Promise<FlagEvaluationResult>
163
+ */
164
+ evaluate(flagKey: string, context?: FlagContext): Promise<FlagEvaluationResult>;
165
+ /**
166
+ * Execute code conditionally based on flag value
167
+ * @param flagKey - The flag key to check
168
+ * @param callback - Function to execute if flag is enabled
169
+ * @param context - Optional context for targeting
170
+ */
171
+ withFlag<T>(flagKey: string, callback: () => T | Promise<T>, context?: FlagContext): Promise<T | null>;
172
+ /**
173
+ * Manually track an error with flag context
174
+ * @param flagKey - The flag key associated with the error
175
+ * @param error - The error that occurred
176
+ * @param context - Optional context
177
+ */
178
+ trackError(flagKey: string, error: Error, context?: FlagContext): void;
179
+ /**
180
+ * Subscribe to real-time updates for a specific flag
181
+ * @param flagKey - Flag key or '*' for all flags
182
+ * @param callback - Callback when flag is updated
183
+ * @returns Unsubscribe function
184
+ */
185
+ subscribe(flagKey: string, callback: () => void): () => void;
186
+ /**
187
+ * Get all cached flag keys
188
+ */
189
+ getCachedFlags(): string[];
190
+ /**
191
+ * Clear the flag cache
192
+ */
193
+ clearCache(): void;
194
+ /**
195
+ * Check if real-time connection is active
196
+ */
197
+ isRealtimeConnected(): boolean;
198
+ /**
199
+ * Close the client and cleanup resources
200
+ */
201
+ close(): void;
202
+ }
203
+
204
+ /**
205
+ * Simple in-memory cache for flag values with TTL
206
+ */
207
+ declare class FlagCache {
208
+ private cache;
209
+ private ttl;
210
+ constructor(ttl?: number);
211
+ /**
212
+ * Get a cached flag value
213
+ */
214
+ get(key: string): boolean | null;
215
+ /**
216
+ * Set a flag value in cache
217
+ */
218
+ set(key: string, value: boolean, flagId?: string): void;
219
+ /**
220
+ * Invalidate a specific flag
221
+ */
222
+ invalidate(key: string): void;
223
+ /**
224
+ * Clear all cached flags
225
+ */
226
+ clear(): void;
227
+ /**
228
+ * Get all cached keys
229
+ */
230
+ keys(): string[];
231
+ }
232
+
233
+ /**
234
+ * Telemetry service for tracking flag evaluations and errors
235
+ */
236
+ declare class TelemetryService {
237
+ private baseUrl;
238
+ private apiKey;
239
+ private enabled;
240
+ private queue;
241
+ private flushInterval;
242
+ private maxBatchSize;
243
+ private timer;
244
+ constructor(baseUrl: string, apiKey: string, enabled?: boolean);
245
+ /**
246
+ * Track a flag evaluation
247
+ */
248
+ trackEvaluation(event: EvaluationEvent): void;
249
+ /**
250
+ * Track an error in flagged code
251
+ */
252
+ trackError(event: ErrorEvent): void;
253
+ /**
254
+ * Start the batch sender interval
255
+ */
256
+ private startBatchSender;
257
+ /**
258
+ * Flush the telemetry queue
259
+ */
260
+ private flush;
261
+ /**
262
+ * Send evaluation events to backend
263
+ */
264
+ private sendEvaluations;
265
+ /**
266
+ * Send error events to backend
267
+ */
268
+ private sendErrors;
269
+ /**
270
+ * Stop the telemetry service
271
+ */
272
+ stop(): void;
273
+ /**
274
+ * Generate a trace ID for distributed tracing
275
+ */
276
+ static generateTraceId(): string;
277
+ }
278
+
279
+ /**
280
+ * Real-time updates service using Server-Sent Events (SSE)
281
+ */
282
+ declare class RealtimeService {
283
+ private baseUrl;
284
+ private apiKey;
285
+ private eventSource;
286
+ private reconnectAttempts;
287
+ private maxReconnectAttempts;
288
+ private reconnectDelay;
289
+ private maxReconnectDelay;
290
+ private listeners;
291
+ private onConnectionChange?;
292
+ constructor(baseUrl: string, apiKey: string, onConnectionChange?: (connected: boolean) => void);
293
+ /**
294
+ * Connect to SSE stream
295
+ */
296
+ connect(): void;
297
+ /**
298
+ * Handle incoming SSE messages
299
+ */
300
+ private handleMessage;
301
+ /**
302
+ * Handle disconnection and attempt reconnect
303
+ */
304
+ private handleDisconnect;
305
+ /**
306
+ * Subscribe to flag updates
307
+ * @param flagKey - Specific flag key or '*' for all flags
308
+ * @param listener - Callback function
309
+ */
310
+ subscribe(flagKey: string, listener: (event: FlagUpdateEvent) => void): () => void;
311
+ /**
312
+ * Disconnect from SSE stream
313
+ */
314
+ disconnect(): void;
315
+ /**
316
+ * Check if connected
317
+ */
318
+ isConnected(): boolean;
319
+ }
320
+
321
+ interface components {
322
+ schemas: {
323
+ ArchiveRequest: {
324
+ reason?: string | null;
325
+ };
326
+ ArchivedFlag: {
327
+ /** Format: uuid */
328
+ application_id?: string | null;
329
+ archive_reason?: string | null;
330
+ /** Format: date-time */
331
+ archived_at: string;
332
+ /** Format: uuid */
333
+ archived_by: string;
334
+ auto_disable_after_end?: boolean | null;
335
+ /** Format: date-time */
336
+ created_at: string;
337
+ /** Format: uuid */
338
+ created_by?: string | null;
339
+ description?: string | null;
340
+ environments: components["schemas"]["JsonValue"];
341
+ /** Format: uuid */
342
+ id: string;
343
+ key: string;
344
+ name: string;
345
+ /** Format: uuid */
346
+ organization_id: string;
347
+ /** Format: date-time */
348
+ scheduled_end_at?: string | null;
349
+ /** Format: date-time */
350
+ scheduled_start_at?: string | null;
351
+ scheduling_timezone?: string | null;
352
+ scope: string;
353
+ status: string;
354
+ /** Format: date-time */
355
+ updated_at: string;
356
+ variations?: components["schemas"]["JsonValue"] | null;
357
+ /** Format: int32 */
358
+ version: number;
359
+ };
360
+ AuditLogQuery: {
361
+ action?: string | null;
362
+ /** Format: date-time */
363
+ end_date?: string | null;
364
+ /** Format: uuid */
365
+ flag_id?: string | null;
366
+ /** Format: int64 */
367
+ limit?: number | null;
368
+ /** Format: int64 */
369
+ offset?: number | null;
370
+ /** Format: uuid */
371
+ organization_id?: string | null;
372
+ /** Format: date-time */
373
+ start_date?: string | null;
374
+ /** Format: uuid */
375
+ user_id?: string | null;
376
+ };
377
+ CheckKeyQuery: {
378
+ key: string;
379
+ };
380
+ /**
381
+ * @example {
382
+ * "application_id": "123e4567-e89b-12d3-a456-426614174002",
383
+ * "description": "Experimental new feature",
384
+ * "environments": {
385
+ * "development": {
386
+ * "enabled": true,
387
+ * "rolloutPercentage": 100
388
+ * },
389
+ * "production": {
390
+ * "enabled": false,
391
+ * "rolloutPercentage": 0
392
+ * }
393
+ * },
394
+ * "key": "new-feature",
395
+ * "name": "New Feature",
396
+ * "scope": "application"
397
+ * }
398
+ */
399
+ CreateFlag: {
400
+ /** Format: uuid */
401
+ application_id?: string | null;
402
+ auto_disable_after_end?: boolean | null;
403
+ description?: string | null;
404
+ environments: components["schemas"]["JsonValue"];
405
+ key: string;
406
+ name: string;
407
+ /** Format: date-time */
408
+ scheduled_end_at?: string | null;
409
+ /** Format: date-time */
410
+ scheduled_start_at?: string | null;
411
+ scheduling_timezone?: string | null;
412
+ scope?: string | null;
413
+ variations?: components["schemas"]["JsonValue"] | null;
414
+ };
415
+ /**
416
+ * @example {
417
+ * "context": {
418
+ * "attributes": {
419
+ * "country": "US",
420
+ * "plan": "premium"
421
+ * },
422
+ * "user_id": "user-123"
423
+ * }
424
+ * }
425
+ */
426
+ EvaluateFlag: {
427
+ context?: components["schemas"]["JsonValue"] | null;
428
+ };
429
+ /**
430
+ * @example {
431
+ * "application_id": "123e4567-e89b-12d3-a456-426614174002",
432
+ * "description": "Enable new streamlined checkout experience",
433
+ * "environments": {
434
+ * "production": {
435
+ * "enabled": true,
436
+ * "rolloutPercentage": 25
437
+ * }
438
+ * },
439
+ * "id": "123e4567-e89b-12d3-a456-426614174000",
440
+ * "key": "new-checkout-flow",
441
+ * "name": "New Checkout Flow",
442
+ * "organization_id": "123e4567-e89b-12d3-a456-426614174001",
443
+ * "scope": "application",
444
+ * "status": "active",
445
+ * "version": 1
446
+ * }
447
+ */
448
+ FeatureFlag: {
449
+ /** Format: uuid */
450
+ application_id?: string | null;
451
+ auto_disable_after_end?: boolean | null;
452
+ /** Format: date-time */
453
+ created_at: string;
454
+ /** Format: uuid */
455
+ created_by?: string | null;
456
+ description?: string | null;
457
+ environments: components["schemas"]["JsonValue"];
458
+ /** Format: uuid */
459
+ id: string;
460
+ key: string;
461
+ name: string;
462
+ /** Format: uuid */
463
+ organization_id: string;
464
+ /** Format: date-time */
465
+ scheduled_end_at?: string | null;
466
+ /** Format: date-time */
467
+ scheduled_start_at?: string | null;
468
+ scheduling_timezone?: string | null;
469
+ scope: string;
470
+ status: string;
471
+ /** Format: date-time */
472
+ updated_at: string;
473
+ variations?: components["schemas"]["JsonValue"] | null;
474
+ /** Format: int32 */
475
+ version: number;
476
+ };
477
+ FlagAuditLog: {
478
+ action: string;
479
+ changes?: components["schemas"]["JsonValue"] | null;
480
+ /** Format: uuid */
481
+ flag_id?: string | null;
482
+ flag_key: string;
483
+ /** Format: uuid */
484
+ id: string;
485
+ ip_address?: string | null;
486
+ /** Format: uuid */
487
+ organization_id: string;
488
+ /** Format: date-time */
489
+ timestamp: string;
490
+ user_agent?: string | null;
491
+ user_email?: string | null;
492
+ /** Format: uuid */
493
+ user_id?: string | null;
494
+ };
495
+ FlagError: {
496
+ ai_analysis?: components["schemas"]["JsonValue"] | null;
497
+ context?: components["schemas"]["JsonValue"] | null;
498
+ error_message?: string | null;
499
+ error_type: string;
500
+ flag_enabled: boolean;
501
+ /** Format: uuid */
502
+ flag_id: string;
503
+ /** Format: uuid */
504
+ id: string;
505
+ /** Format: uuid */
506
+ organization_id: string;
507
+ stack_trace?: string | null;
508
+ /** Format: date-time */
509
+ timestamp: string;
510
+ trace_id?: string | null;
511
+ };
512
+ FlagEvaluation: {
513
+ context?: components["schemas"]["JsonValue"] | null;
514
+ /** Format: float */
515
+ duration_ms?: number | null;
516
+ /** Format: uuid */
517
+ flag_id: string;
518
+ /** Format: uuid */
519
+ id: string;
520
+ /** Format: uuid */
521
+ organization_id: string;
522
+ result: boolean;
523
+ /** Format: date-time */
524
+ timestamp: string;
525
+ trace_id?: string | null;
526
+ };
527
+ /**
528
+ * @example {
529
+ * "enabled": true,
530
+ * "key": "new-checkout-flow",
531
+ * "scope": "application",
532
+ * "timestamp": 1699564800
533
+ * }
534
+ */
535
+ FlagEvaluationResponse: {
536
+ configuration?: components["schemas"]["JsonValue"] | null;
537
+ context?: components["schemas"]["JsonValue"] | null;
538
+ enabled: boolean;
539
+ key: string;
540
+ scope?: string | null;
541
+ /** Format: int64 */
542
+ timestamp: number;
543
+ variation?: string | null;
544
+ };
545
+ /** @description Generic JSON value - can be any valid JSON type */
546
+ JsonValue: Record<string, never>;
547
+ ListFlagsQuery: {
548
+ /**
549
+ * Format: uuid
550
+ * @description Filter by application_id (only for application-scoped flags)
551
+ */
552
+ application_id?: string | null;
553
+ /**
554
+ * Format: uuid
555
+ * @description Filter by organization_id
556
+ */
557
+ organization_id?: string | null;
558
+ /** @description Filter by scope: 'enterprise', 'application', or omit for all */
559
+ scope?: string | null;
560
+ };
561
+ UpdateFlag: {
562
+ auto_disable_after_end?: boolean | null;
563
+ description?: string | null;
564
+ environments?: components["schemas"]["JsonValue"] | null;
565
+ name?: string | null;
566
+ /** Format: date-time */
567
+ scheduled_end_at?: string | null;
568
+ /** Format: date-time */
569
+ scheduled_start_at?: string | null;
570
+ scheduling_timezone?: string | null;
571
+ status?: string | null;
572
+ variations?: components["schemas"]["JsonValue"] | null;
573
+ };
574
+ UserActivity: {
575
+ email: string;
576
+ /** Format: int64 */
577
+ flags_archived?: number | null;
578
+ /** Format: int64 */
579
+ flags_created?: number | null;
580
+ /** Format: int64 */
581
+ flags_deleted?: number | null;
582
+ /** Format: int64 */
583
+ flags_updated?: number | null;
584
+ /** Format: date-time */
585
+ last_action_at?: string | null;
586
+ /** Format: int64 */
587
+ total_actions?: number | null;
588
+ /** Format: uuid */
589
+ user_id: string;
590
+ };
591
+ };
592
+ responses: never;
593
+ parameters: never;
594
+ requestBodies: never;
595
+ headers: never;
596
+ pathItems: never;
597
+ }
598
+
599
+ export { type components as ApiTypes, type CacheEntry, type ErrorEvent, type EvaluationEvent, FlagCache, FlagClient, type FlagClientConfig, type FlagContext, type FlagEvaluationResult, type FlagUpdateEvent, RealtimeService, TelemetryService, type components };