@sparkleideas/integration 3.0.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,485 @@
1
+ /**
2
+ * Feature Flags Configuration System
3
+ *
4
+ * Provides runtime feature flag management for v3 integration,
5
+ * enabling gradual rollout, A/B testing, and environment-specific
6
+ * feature enablement.
7
+ *
8
+ * @module v3/integration/feature-flags
9
+ * @version 3.0.0-alpha.1
10
+ */
11
+
12
+ import { EventEmitter } from 'events';
13
+ import type { FeatureFlags, DEFAULT_FEATURE_FLAGS } from './types.js';
14
+
15
+ /**
16
+ * Feature flag metadata
17
+ */
18
+ interface FeatureFlagInfo {
19
+ /** Flag name */
20
+ name: keyof FeatureFlags;
21
+ /** Human-readable description */
22
+ description: string;
23
+ /** Default value */
24
+ defaultValue: boolean;
25
+ /** Whether the flag is experimental */
26
+ experimental: boolean;
27
+ /** Performance impact if enabled */
28
+ performanceImpact: 'none' | 'low' | 'medium' | 'high';
29
+ /** Dependencies on other flags */
30
+ dependencies: (keyof FeatureFlags)[];
31
+ /** Minimum SDK version required */
32
+ minSDKVersion?: string;
33
+ }
34
+
35
+ /**
36
+ * Feature flag definitions with metadata
37
+ */
38
+ const FEATURE_FLAG_DEFINITIONS: Record<keyof FeatureFlags, FeatureFlagInfo> = {
39
+ enableSONA: {
40
+ name: 'enableSONA',
41
+ description: 'Enable SONA (Self-Optimizing Neural Architecture) learning system',
42
+ defaultValue: true,
43
+ experimental: false,
44
+ performanceImpact: 'low',
45
+ dependencies: [],
46
+ },
47
+ enableFlashAttention: {
48
+ name: 'enableFlashAttention',
49
+ description: 'Enable Flash Attention for 2.49x-7.47x speedup',
50
+ defaultValue: true,
51
+ experimental: false,
52
+ performanceImpact: 'none',
53
+ dependencies: [],
54
+ },
55
+ enableAgentDB: {
56
+ name: 'enableAgentDB',
57
+ description: 'Enable AgentDB vector search with HNSW indexing',
58
+ defaultValue: true,
59
+ experimental: false,
60
+ performanceImpact: 'low',
61
+ dependencies: [],
62
+ },
63
+ enableTrajectoryTracking: {
64
+ name: 'enableTrajectoryTracking',
65
+ description: 'Enable trajectory tracking for experience replay',
66
+ defaultValue: true,
67
+ experimental: false,
68
+ performanceImpact: 'low',
69
+ dependencies: ['enableSONA'],
70
+ },
71
+ enableGNN: {
72
+ name: 'enableGNN',
73
+ description: 'Enable GNN query refinement for +12.4% recall improvement',
74
+ defaultValue: true,
75
+ experimental: false,
76
+ performanceImpact: 'medium',
77
+ dependencies: ['enableAgentDB'],
78
+ minSDKVersion: '2.0.0',
79
+ },
80
+ enableIntelligenceBridge: {
81
+ name: 'enableIntelligenceBridge',
82
+ description: 'Enable intelligence bridge tools for pattern management',
83
+ defaultValue: true,
84
+ experimental: false,
85
+ performanceImpact: 'low',
86
+ dependencies: ['enableSONA'],
87
+ },
88
+ enableQUICTransport: {
89
+ name: 'enableQUICTransport',
90
+ description: 'Enable QUIC transport for faster agent communication',
91
+ defaultValue: false,
92
+ experimental: true,
93
+ performanceImpact: 'low',
94
+ dependencies: [],
95
+ minSDKVersion: '2.0.1',
96
+ },
97
+ enableNightlyLearning: {
98
+ name: 'enableNightlyLearning',
99
+ description: 'Enable automated nightly learning cycles',
100
+ defaultValue: false,
101
+ experimental: true,
102
+ performanceImpact: 'high',
103
+ dependencies: ['enableSONA', 'enableTrajectoryTracking'],
104
+ minSDKVersion: '2.0.1',
105
+ },
106
+ enableAutoConsolidation: {
107
+ name: 'enableAutoConsolidation',
108
+ description: 'Enable automatic pattern consolidation',
109
+ defaultValue: true,
110
+ experimental: false,
111
+ performanceImpact: 'low',
112
+ dependencies: ['enableSONA'],
113
+ },
114
+ };
115
+
116
+ /**
117
+ * Feature flag source (where the value came from)
118
+ */
119
+ type FlagSource = 'default' | 'config' | 'environment' | 'runtime';
120
+
121
+ /**
122
+ * FeatureFlagManager - Runtime feature flag management
123
+ */
124
+ export class FeatureFlagManager extends EventEmitter {
125
+ private flags: FeatureFlags;
126
+ private sources: Map<keyof FeatureFlags, FlagSource> = new Map();
127
+ private overrides: Map<keyof FeatureFlags, boolean> = new Map();
128
+ private initialized: boolean = false;
129
+
130
+ constructor(initialFlags?: Partial<FeatureFlags>) {
131
+ super();
132
+ this.flags = this.initializeFlags(initialFlags);
133
+ }
134
+
135
+ /**
136
+ * Initialize the feature flag manager
137
+ */
138
+ async initialize(): Promise<void> {
139
+ if (this.initialized) {
140
+ return;
141
+ }
142
+
143
+ // Load from environment variables
144
+ this.loadFromEnvironment();
145
+
146
+ // Validate dependencies
147
+ this.validateDependencies();
148
+
149
+ this.initialized = true;
150
+ this.emit('initialized', { flags: this.getAllFlags() });
151
+ }
152
+
153
+ /**
154
+ * Get all feature flags
155
+ */
156
+ getAllFlags(): FeatureFlags {
157
+ const result = { ...this.flags };
158
+
159
+ // Apply overrides
160
+ for (const [flag, value] of this.overrides) {
161
+ result[flag] = value;
162
+ }
163
+
164
+ return result;
165
+ }
166
+
167
+ /**
168
+ * Check if a feature is enabled
169
+ */
170
+ isEnabled(flag: keyof FeatureFlags): boolean {
171
+ // Check override first
172
+ if (this.overrides.has(flag)) {
173
+ return this.overrides.get(flag)!;
174
+ }
175
+ return this.flags[flag];
176
+ }
177
+
178
+ /**
179
+ * Enable a feature
180
+ */
181
+ enable(flag: keyof FeatureFlags, runtime: boolean = true): void {
182
+ const previousValue = this.isEnabled(flag);
183
+
184
+ // Check dependencies
185
+ const info = FEATURE_FLAG_DEFINITIONS[flag];
186
+ for (const dep of info.dependencies) {
187
+ if (!this.isEnabled(dep)) {
188
+ throw new Error(
189
+ `Cannot enable '${flag}': dependency '${dep}' is not enabled`
190
+ );
191
+ }
192
+ }
193
+
194
+ if (runtime) {
195
+ this.overrides.set(flag, true);
196
+ this.sources.set(flag, 'runtime');
197
+ } else {
198
+ this.flags[flag] = true;
199
+ this.sources.set(flag, 'config');
200
+ }
201
+
202
+ if (!previousValue) {
203
+ this.emit('flag-changed', { flag, previousValue, newValue: true });
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Disable a feature
209
+ */
210
+ disable(flag: keyof FeatureFlags, runtime: boolean = true): void {
211
+ const previousValue = this.isEnabled(flag);
212
+
213
+ // Check for dependent features
214
+ const dependents = this.getDependentFlags(flag);
215
+ for (const dep of dependents) {
216
+ if (this.isEnabled(dep)) {
217
+ console.warn(
218
+ `Warning: Disabling '${flag}' may affect '${dep}' which depends on it`
219
+ );
220
+ }
221
+ }
222
+
223
+ if (runtime) {
224
+ this.overrides.set(flag, false);
225
+ this.sources.set(flag, 'runtime');
226
+ } else {
227
+ this.flags[flag] = false;
228
+ this.sources.set(flag, 'config');
229
+ }
230
+
231
+ if (previousValue) {
232
+ this.emit('flag-changed', { flag, previousValue, newValue: false });
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Toggle a feature
238
+ */
239
+ toggle(flag: keyof FeatureFlags): boolean {
240
+ const current = this.isEnabled(flag);
241
+ if (current) {
242
+ this.disable(flag);
243
+ } else {
244
+ this.enable(flag);
245
+ }
246
+ return !current;
247
+ }
248
+
249
+ /**
250
+ * Reset a feature to its default value
251
+ */
252
+ reset(flag: keyof FeatureFlags): void {
253
+ const info = FEATURE_FLAG_DEFINITIONS[flag];
254
+ const previousValue = this.isEnabled(flag);
255
+
256
+ this.overrides.delete(flag);
257
+ this.flags[flag] = info.defaultValue;
258
+ this.sources.set(flag, 'default');
259
+
260
+ if (previousValue !== info.defaultValue) {
261
+ this.emit('flag-changed', {
262
+ flag,
263
+ previousValue,
264
+ newValue: info.defaultValue
265
+ });
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Reset all features to default values
271
+ */
272
+ resetAll(): void {
273
+ this.overrides.clear();
274
+ for (const [flag, info] of Object.entries(FEATURE_FLAG_DEFINITIONS)) {
275
+ this.flags[flag as keyof FeatureFlags] = info.defaultValue;
276
+ this.sources.set(flag as keyof FeatureFlags, 'default');
277
+ }
278
+ this.emit('flags-reset');
279
+ }
280
+
281
+ /**
282
+ * Get feature flag information
283
+ */
284
+ getFlagInfo(flag: keyof FeatureFlags): FeatureFlagInfo & {
285
+ currentValue: boolean;
286
+ source: FlagSource;
287
+ } {
288
+ return {
289
+ ...FEATURE_FLAG_DEFINITIONS[flag],
290
+ currentValue: this.isEnabled(flag),
291
+ source: this.sources.get(flag) || 'default',
292
+ };
293
+ }
294
+
295
+ /**
296
+ * Get all flag information
297
+ */
298
+ getAllFlagInfo(): Array<FeatureFlagInfo & {
299
+ currentValue: boolean;
300
+ source: FlagSource;
301
+ }> {
302
+ return Object.keys(FEATURE_FLAG_DEFINITIONS).map(
303
+ flag => this.getFlagInfo(flag as keyof FeatureFlags)
304
+ );
305
+ }
306
+
307
+ /**
308
+ * Get enabled experimental features
309
+ */
310
+ getEnabledExperimentalFeatures(): (keyof FeatureFlags)[] {
311
+ return Object.entries(FEATURE_FLAG_DEFINITIONS)
312
+ .filter(([flag, info]) => info.experimental && this.isEnabled(flag as keyof FeatureFlags))
313
+ .map(([flag]) => flag as keyof FeatureFlags);
314
+ }
315
+
316
+ /**
317
+ * Get performance impact of enabled features
318
+ */
319
+ getPerformanceImpact(): {
320
+ none: (keyof FeatureFlags)[];
321
+ low: (keyof FeatureFlags)[];
322
+ medium: (keyof FeatureFlags)[];
323
+ high: (keyof FeatureFlags)[];
324
+ overall: 'none' | 'low' | 'medium' | 'high';
325
+ } {
326
+ const result = {
327
+ none: [] as (keyof FeatureFlags)[],
328
+ low: [] as (keyof FeatureFlags)[],
329
+ medium: [] as (keyof FeatureFlags)[],
330
+ high: [] as (keyof FeatureFlags)[],
331
+ overall: 'none' as 'none' | 'low' | 'medium' | 'high',
332
+ };
333
+
334
+ for (const [flag, info] of Object.entries(FEATURE_FLAG_DEFINITIONS)) {
335
+ if (this.isEnabled(flag as keyof FeatureFlags)) {
336
+ result[info.performanceImpact].push(flag as keyof FeatureFlags);
337
+ }
338
+ }
339
+
340
+ // Determine overall impact
341
+ if (result.high.length > 0) {
342
+ result.overall = 'high';
343
+ } else if (result.medium.length > 0) {
344
+ result.overall = 'medium';
345
+ } else if (result.low.length > 0) {
346
+ result.overall = 'low';
347
+ }
348
+
349
+ return result;
350
+ }
351
+
352
+ /**
353
+ * Create feature flags from profile
354
+ */
355
+ static fromProfile(profile: 'minimal' | 'standard' | 'full' | 'experimental'): FeatureFlags {
356
+ const profiles: Record<string, Partial<FeatureFlags>> = {
357
+ minimal: {
358
+ enableSONA: false,
359
+ enableFlashAttention: true,
360
+ enableAgentDB: true,
361
+ enableTrajectoryTracking: false,
362
+ enableGNN: false,
363
+ enableIntelligenceBridge: false,
364
+ enableQUICTransport: false,
365
+ enableNightlyLearning: false,
366
+ enableAutoConsolidation: false,
367
+ },
368
+ standard: {
369
+ enableSONA: true,
370
+ enableFlashAttention: true,
371
+ enableAgentDB: true,
372
+ enableTrajectoryTracking: true,
373
+ enableGNN: true,
374
+ enableIntelligenceBridge: true,
375
+ enableQUICTransport: false,
376
+ enableNightlyLearning: false,
377
+ enableAutoConsolidation: true,
378
+ },
379
+ full: {
380
+ enableSONA: true,
381
+ enableFlashAttention: true,
382
+ enableAgentDB: true,
383
+ enableTrajectoryTracking: true,
384
+ enableGNN: true,
385
+ enableIntelligenceBridge: true,
386
+ enableQUICTransport: true,
387
+ enableNightlyLearning: true,
388
+ enableAutoConsolidation: true,
389
+ },
390
+ experimental: {
391
+ enableSONA: true,
392
+ enableFlashAttention: true,
393
+ enableAgentDB: true,
394
+ enableTrajectoryTracking: true,
395
+ enableGNN: true,
396
+ enableIntelligenceBridge: true,
397
+ enableQUICTransport: true,
398
+ enableNightlyLearning: true,
399
+ enableAutoConsolidation: true,
400
+ },
401
+ };
402
+
403
+ const base: Record<string, boolean> = {};
404
+ for (const [flag, info] of Object.entries(FEATURE_FLAG_DEFINITIONS)) {
405
+ base[flag] = info.defaultValue;
406
+ }
407
+
408
+ return { ...base, ...profiles[profile] } as FeatureFlags;
409
+ }
410
+
411
+ // ===== Private Methods =====
412
+
413
+ private initializeFlags(initial?: Partial<FeatureFlags>): FeatureFlags {
414
+ const flags = {} as FeatureFlags;
415
+
416
+ for (const [flag, info] of Object.entries(FEATURE_FLAG_DEFINITIONS)) {
417
+ const key = flag as keyof FeatureFlags;
418
+ flags[key] = initial?.[key] ?? info.defaultValue;
419
+ this.sources.set(key, initial?.[key] !== undefined ? 'config' : 'default');
420
+ }
421
+
422
+ return flags;
423
+ }
424
+
425
+ private loadFromEnvironment(): void {
426
+ for (const flag of Object.keys(FEATURE_FLAG_DEFINITIONS)) {
427
+ const envVar = `CLAUDE_FLOW_${flag.replace(/([A-Z])/g, '_$1').toUpperCase()}`;
428
+ const envValue = process.env[envVar];
429
+
430
+ if (envValue !== undefined) {
431
+ const boolValue = envValue.toLowerCase() === 'true' || envValue === '1';
432
+ this.flags[flag as keyof FeatureFlags] = boolValue;
433
+ this.sources.set(flag as keyof FeatureFlags, 'environment');
434
+ }
435
+ }
436
+ }
437
+
438
+ private validateDependencies(): void {
439
+ for (const [flag, info] of Object.entries(FEATURE_FLAG_DEFINITIONS)) {
440
+ if (this.isEnabled(flag as keyof FeatureFlags)) {
441
+ for (const dep of info.dependencies) {
442
+ if (!this.isEnabled(dep)) {
443
+ console.warn(
444
+ `Warning: '${flag}' depends on '${dep}' which is disabled. ` +
445
+ `'${flag}' may not work correctly.`
446
+ );
447
+ }
448
+ }
449
+ }
450
+ }
451
+ }
452
+
453
+ private getDependentFlags(flag: keyof FeatureFlags): (keyof FeatureFlags)[] {
454
+ return Object.entries(FEATURE_FLAG_DEFINITIONS)
455
+ .filter(([_, info]) => info.dependencies.includes(flag))
456
+ .map(([name]) => name as keyof FeatureFlags);
457
+ }
458
+ }
459
+
460
+ /**
461
+ * Create and initialize a feature flag manager
462
+ */
463
+ export async function createFeatureFlagManager(
464
+ initialFlags?: Partial<FeatureFlags>
465
+ ): Promise<FeatureFlagManager> {
466
+ const manager = new FeatureFlagManager(initialFlags);
467
+ await manager.initialize();
468
+ return manager;
469
+ }
470
+
471
+ /**
472
+ * Default feature flag manager instance
473
+ */
474
+ let defaultManager: FeatureFlagManager | null = null;
475
+
476
+ /**
477
+ * Get the default feature flag manager
478
+ */
479
+ export async function getDefaultFeatureFlagManager(): Promise<FeatureFlagManager> {
480
+ if (!defaultManager) {
481
+ defaultManager = new FeatureFlagManager();
482
+ await defaultManager.initialize();
483
+ }
484
+ return defaultManager;
485
+ }