agentic-qe 3.7.21 → 3.8.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.
- package/.claude/helpers/brain-checkpoint.cjs +4 -1
- package/.claude/helpers/statusline-v3.cjs +3 -1
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +45 -0
- package/README.md +2 -14
- package/assets/helpers/statusline-v3.cjs +3 -1
- package/dist/cli/brain-commands.js +6 -10
- package/dist/cli/bundle.js +7441 -4327
- package/dist/cli/commands/audit.d.ts +43 -0
- package/dist/cli/commands/audit.js +125 -0
- package/dist/cli/commands/hooks.js +29 -6
- package/dist/cli/commands/init.js +1 -73
- package/dist/cli/commands/learning.js +270 -13
- package/dist/cli/commands/ruvector-commands.d.ts +15 -0
- package/dist/cli/commands/ruvector-commands.js +271 -0
- package/dist/cli/handlers/init-handler.d.ts +0 -1
- package/dist/cli/handlers/init-handler.js +0 -6
- package/dist/cli/index.js +4 -2
- package/dist/context/sources/defect-source.js +2 -2
- package/dist/context/sources/memory-source.js +2 -2
- package/dist/context/sources/requirements-source.js +2 -2
- package/dist/coordination/behavior-tree/decorators.d.ts +108 -0
- package/dist/coordination/behavior-tree/decorators.js +251 -0
- package/dist/coordination/behavior-tree/index.d.ts +12 -0
- package/dist/coordination/behavior-tree/index.js +15 -0
- package/dist/coordination/behavior-tree/nodes.d.ts +165 -0
- package/dist/coordination/behavior-tree/nodes.js +338 -0
- package/dist/coordination/behavior-tree/qe-trees.d.ts +105 -0
- package/dist/coordination/behavior-tree/qe-trees.js +181 -0
- package/dist/coordination/coherence-action-gate.d.ts +284 -0
- package/dist/coordination/coherence-action-gate.js +512 -0
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.js +8 -0
- package/dist/coordination/reasoning-qec.d.ts +315 -0
- package/dist/coordination/reasoning-qec.js +585 -0
- package/dist/coordination/task-executor.d.ts +16 -0
- package/dist/coordination/task-executor.js +99 -0
- package/dist/coordination/workflow-orchestrator.d.ts +29 -0
- package/dist/coordination/workflow-orchestrator.js +42 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.d.ts +135 -0
- package/dist/domains/visual-accessibility/cnn-visual-regression.js +327 -0
- package/dist/domains/visual-accessibility/index.d.ts +1 -0
- package/dist/domains/visual-accessibility/index.js +4 -0
- package/dist/governance/coherence-validator.d.ts +112 -0
- package/dist/governance/coherence-validator.js +180 -0
- package/dist/governance/index.d.ts +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/witness-chain.d.ts +311 -0
- package/dist/governance/witness-chain.js +509 -0
- package/dist/init/index.d.ts +0 -2
- package/dist/init/index.js +0 -1
- package/dist/init/init-wizard-steps.d.ts +10 -0
- package/dist/init/init-wizard-steps.js +87 -1
- package/dist/init/init-wizard.d.ts +1 -9
- package/dist/init/init-wizard.js +3 -69
- package/dist/init/orchestrator.js +0 -1
- package/dist/init/phases/01-detection.js +0 -27
- package/dist/init/phases/07-hooks.js +6 -4
- package/dist/init/phases/phase-interface.d.ts +0 -1
- package/dist/init/settings-merge.js +1 -1
- package/dist/integrations/browser/qe-dashboard/clustering.d.ts +48 -0
- package/dist/integrations/browser/qe-dashboard/clustering.js +183 -0
- package/dist/integrations/browser/qe-dashboard/index.d.ts +12 -0
- package/dist/integrations/browser/qe-dashboard/index.js +15 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.d.ts +165 -0
- package/dist/integrations/browser/qe-dashboard/pattern-explorer.js +260 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.d.ts +144 -0
- package/dist/integrations/browser/qe-dashboard/wasm-vector-store.js +277 -0
- package/dist/integrations/ruvector/cognitive-container-codec.d.ts +51 -0
- package/dist/integrations/ruvector/cognitive-container-codec.js +180 -0
- package/dist/integrations/ruvector/cognitive-container.d.ts +125 -0
- package/dist/integrations/ruvector/cognitive-container.js +306 -0
- package/dist/integrations/ruvector/coherence-gate.d.ts +309 -0
- package/dist/integrations/ruvector/coherence-gate.js +631 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.d.ts +176 -0
- package/dist/integrations/ruvector/compressed-hnsw-integration.js +301 -0
- package/dist/integrations/ruvector/dither-adapter.d.ts +122 -0
- package/dist/integrations/ruvector/dither-adapter.js +295 -0
- package/dist/integrations/ruvector/domain-transfer.d.ts +129 -0
- package/dist/integrations/ruvector/domain-transfer.js +220 -0
- package/dist/integrations/ruvector/feature-flags.d.ts +214 -2
- package/dist/integrations/ruvector/feature-flags.js +167 -2
- package/dist/integrations/ruvector/filter-adapter.d.ts +71 -0
- package/dist/integrations/ruvector/filter-adapter.js +285 -0
- package/dist/integrations/ruvector/gnn-wrapper.d.ts +20 -0
- package/dist/integrations/ruvector/gnn-wrapper.js +40 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.d.ts +237 -0
- package/dist/integrations/ruvector/hnsw-health-monitor.js +394 -0
- package/dist/integrations/ruvector/index.d.ts +8 -2
- package/dist/integrations/ruvector/index.js +18 -2
- package/dist/integrations/ruvector/interfaces.d.ts +40 -0
- package/dist/integrations/ruvector/sona-persistence.d.ts +54 -0
- package/dist/integrations/ruvector/sona-persistence.js +162 -0
- package/dist/integrations/ruvector/sona-three-loop.d.ts +392 -0
- package/dist/integrations/ruvector/sona-three-loop.js +814 -0
- package/dist/integrations/ruvector/sona-wrapper.d.ts +97 -0
- package/dist/integrations/ruvector/sona-wrapper.js +147 -3
- package/dist/integrations/ruvector/spectral-math.d.ts +101 -0
- package/dist/integrations/ruvector/spectral-math.js +254 -0
- package/dist/integrations/ruvector/temporal-compression.d.ts +163 -0
- package/dist/integrations/ruvector/temporal-compression.js +318 -0
- package/dist/integrations/ruvector/thompson-sampler.d.ts +61 -0
- package/dist/integrations/ruvector/thompson-sampler.js +118 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.d.ts +80 -0
- package/dist/integrations/ruvector/transfer-coherence-stub.js +63 -0
- package/dist/integrations/ruvector/transfer-verification.d.ts +119 -0
- package/dist/integrations/ruvector/transfer-verification.js +115 -0
- package/dist/kernel/hnsw-adapter.d.ts +52 -1
- package/dist/kernel/hnsw-adapter.js +139 -4
- package/dist/kernel/hnsw-index-provider.d.ts +5 -0
- package/dist/kernel/native-hnsw-backend.d.ts +110 -0
- package/dist/kernel/native-hnsw-backend.js +408 -0
- package/dist/kernel/unified-memory.js +5 -6
- package/dist/learning/aqe-learning-engine.d.ts +2 -0
- package/dist/learning/aqe-learning-engine.js +65 -0
- package/dist/learning/experience-capture-middleware.js +20 -0
- package/dist/learning/experience-capture.d.ts +10 -0
- package/dist/learning/experience-capture.js +34 -0
- package/dist/learning/index.d.ts +2 -2
- package/dist/learning/index.js +4 -4
- package/dist/learning/metrics-tracker.d.ts +11 -0
- package/dist/learning/metrics-tracker.js +29 -13
- package/dist/learning/pattern-lifecycle.d.ts +30 -1
- package/dist/learning/pattern-lifecycle.js +92 -20
- package/dist/learning/pattern-store.d.ts +8 -0
- package/dist/learning/pattern-store.js +8 -2
- package/dist/learning/qe-unified-memory.js +1 -28
- package/dist/learning/regret-tracker.d.ts +201 -0
- package/dist/learning/regret-tracker.js +361 -0
- package/dist/mcp/bundle.js +5915 -474
- package/dist/routing/index.d.ts +4 -2
- package/dist/routing/index.js +3 -1
- package/dist/routing/neural-tiny-dancer-router.d.ts +268 -0
- package/dist/routing/neural-tiny-dancer-router.js +514 -0
- package/dist/routing/queen-integration.js +5 -5
- package/dist/routing/routing-config.d.ts +6 -0
- package/dist/routing/routing-config.js +1 -0
- package/dist/routing/simple-neural-router.d.ts +76 -0
- package/dist/routing/simple-neural-router.js +202 -0
- package/dist/routing/tiny-dancer-router.d.ts +20 -1
- package/dist/routing/tiny-dancer-router.js +21 -2
- package/dist/test-scheduling/dag-attention-scheduler.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-scheduler.js +358 -0
- package/dist/test-scheduling/dag-attention-types.d.ts +81 -0
- package/dist/test-scheduling/dag-attention-types.js +10 -0
- package/dist/test-scheduling/index.d.ts +1 -0
- package/dist/test-scheduling/index.js +4 -0
- package/dist/test-scheduling/pipeline.d.ts +8 -0
- package/dist/test-scheduling/pipeline.js +28 -0
- package/package.json +6 -2
- package/dist/cli/commands/migrate.d.ts +0 -9
- package/dist/cli/commands/migrate.js +0 -566
- package/dist/init/init-wizard-migration.d.ts +0 -52
- package/dist/init/init-wizard-migration.js +0 -345
- package/dist/init/migration/config-migrator.d.ts +0 -31
- package/dist/init/migration/config-migrator.js +0 -149
- package/dist/init/migration/data-migrator.d.ts +0 -72
- package/dist/init/migration/data-migrator.js +0 -232
- package/dist/init/migration/detector.d.ts +0 -44
- package/dist/init/migration/detector.js +0 -105
- package/dist/init/migration/index.d.ts +0 -8
- package/dist/init/migration/index.js +0 -8
- package/dist/learning/v2-to-v3-migration.d.ts +0 -86
- package/dist/learning/v2-to-v3-migration.js +0 -529
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal Tensor Compression Service
|
|
3
|
+
* ADR-085: Temporal Tensor Pattern Compression
|
|
4
|
+
*
|
|
5
|
+
* Compresses pattern embeddings based on access patterns using tiered
|
|
6
|
+
* quantization. Hot patterns retain full precision, while cold patterns
|
|
7
|
+
* are aggressively compressed to save memory.
|
|
8
|
+
*
|
|
9
|
+
* TypeScript implementation using Int8Array (4x compression for all tiers).
|
|
10
|
+
* No native package exists — this IS the production implementation.
|
|
11
|
+
*
|
|
12
|
+
* Tiers (logical bit depths, stored as Int8Array):
|
|
13
|
+
* - HOT (last 7 days): 8-bit quantization (4x compression)
|
|
14
|
+
* - WARM (7-30 days): 5-bit quantization (4x actual, 6.4x theoretical)
|
|
15
|
+
* - COLD (30+ days): 3-bit quantization (4x actual, 10.7x theoretical)
|
|
16
|
+
*
|
|
17
|
+
* All tiers deliver 4x compression because Int8Array uses 1 byte per
|
|
18
|
+
* element regardless of logical bit depth.
|
|
19
|
+
*
|
|
20
|
+
* @module integrations/ruvector/temporal-compression
|
|
21
|
+
*/
|
|
22
|
+
/** Access-frequency tier for a pattern embedding */
|
|
23
|
+
export type CompressionTier = 'hot' | 'warm' | 'cold';
|
|
24
|
+
/**
|
|
25
|
+
* Compressed vector representation.
|
|
26
|
+
* Stores quantized data alongside the parameters needed for decompression.
|
|
27
|
+
*/
|
|
28
|
+
export interface CompressedVector {
|
|
29
|
+
/** Quantized integer data */
|
|
30
|
+
readonly data: Int8Array;
|
|
31
|
+
/** Scale factor used during quantization */
|
|
32
|
+
readonly scale: number;
|
|
33
|
+
/** Offset (minimum value) used during quantization */
|
|
34
|
+
readonly offset: number;
|
|
35
|
+
/** Compression tier applied */
|
|
36
|
+
readonly tier: CompressionTier;
|
|
37
|
+
/** Original vector dimensionality */
|
|
38
|
+
readonly originalLength: number;
|
|
39
|
+
/** Bit depth used for quantization */
|
|
40
|
+
readonly bitDepth: number;
|
|
41
|
+
/** Original byte size (float32 = 4 bytes per element) */
|
|
42
|
+
readonly originalByteSize: number;
|
|
43
|
+
/** Compressed byte size (actual storage: data.byteLength) */
|
|
44
|
+
readonly compressedByteSize: number;
|
|
45
|
+
/** Actual byte size in memory (always data.byteLength — 1 byte per Int8 element) */
|
|
46
|
+
readonly actualByteSize: number;
|
|
47
|
+
/** Theoretical byte size if true bit-packing were used (native only) */
|
|
48
|
+
readonly theoreticalByteSize: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Compression statistics for monitoring
|
|
52
|
+
*/
|
|
53
|
+
export interface CompressionStats {
|
|
54
|
+
/** Total vectors compressed */
|
|
55
|
+
totalCompressed: number;
|
|
56
|
+
/** Vectors by tier */
|
|
57
|
+
byTier: Record<CompressionTier, number>;
|
|
58
|
+
/** Average compression ratio per tier */
|
|
59
|
+
avgCompressionRatio: Record<CompressionTier, number>;
|
|
60
|
+
/** Total bytes saved */
|
|
61
|
+
totalBytesSaved: number;
|
|
62
|
+
/** Total original bytes */
|
|
63
|
+
totalOriginalBytes: number;
|
|
64
|
+
/** Total compressed bytes */
|
|
65
|
+
totalCompressedBytes: number;
|
|
66
|
+
/** Whether using native implementation */
|
|
67
|
+
usingNative: boolean;
|
|
68
|
+
/** Whether native bit-packing is in use (false in TS fallback) */
|
|
69
|
+
usesNativeBitPacking: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** Hot tier: accessed within the last 7 days */
|
|
72
|
+
declare const HOT_THRESHOLD_DAYS = 7;
|
|
73
|
+
/** Warm tier: accessed within the last 30 days */
|
|
74
|
+
declare const WARM_THRESHOLD_DAYS = 30;
|
|
75
|
+
/** Quantization parameters per tier */
|
|
76
|
+
declare const TIER_CONFIG: Record<CompressionTier, {
|
|
77
|
+
bitDepth: number;
|
|
78
|
+
min: number;
|
|
79
|
+
max: number;
|
|
80
|
+
}>;
|
|
81
|
+
/** Theoretical compression ratios assuming true bit-packing (native only) */
|
|
82
|
+
declare const THEORETICAL_COMPRESSION_RATIOS: Record<CompressionTier, number>;
|
|
83
|
+
/** Actual compression ratio in the TypeScript fallback (Float32 -> Int8 = 4x for all tiers) */
|
|
84
|
+
declare const ACTUAL_FALLBACK_RATIO = 4;
|
|
85
|
+
/**
|
|
86
|
+
* Temporal Compression Service
|
|
87
|
+
*
|
|
88
|
+
* Provides tiered quantization of pattern embedding vectors based on
|
|
89
|
+
* how recently they were accessed. Supports both a native Rust/NAPI
|
|
90
|
+
* implementation and a pure TypeScript fallback.
|
|
91
|
+
*/
|
|
92
|
+
export declare class TemporalCompressionService {
|
|
93
|
+
private stats;
|
|
94
|
+
/** Running sum of ratios per tier for average calculation */
|
|
95
|
+
private ratioSums;
|
|
96
|
+
private initialized;
|
|
97
|
+
/**
|
|
98
|
+
* Initialize the service, attempting to load the native module.
|
|
99
|
+
* Safe to call multiple times; subsequent calls are no-ops.
|
|
100
|
+
*/
|
|
101
|
+
initialize(): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Check if the temporal compression feature flag is enabled.
|
|
104
|
+
*/
|
|
105
|
+
isEnabled(): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Classify a last-access date into a compression tier.
|
|
108
|
+
*
|
|
109
|
+
* @param lastAccessDate - When the pattern was last accessed
|
|
110
|
+
* @returns The compression tier for the pattern
|
|
111
|
+
*/
|
|
112
|
+
classifyTier(lastAccessDate: Date): CompressionTier;
|
|
113
|
+
/**
|
|
114
|
+
* Compress a float32 embedding vector according to the specified tier.
|
|
115
|
+
*
|
|
116
|
+
* @param vector - The original float32 embedding
|
|
117
|
+
* @param tier - Compression tier to apply
|
|
118
|
+
* @returns Compressed vector with metadata for decompression
|
|
119
|
+
*/
|
|
120
|
+
compress(vector: Float32Array, tier: CompressionTier): CompressedVector;
|
|
121
|
+
/**
|
|
122
|
+
* Decompress a compressed vector back to Float32Array.
|
|
123
|
+
*
|
|
124
|
+
* The output is an approximation of the original due to quantization loss.
|
|
125
|
+
* Consumers receive a standard Float32Array transparently.
|
|
126
|
+
*
|
|
127
|
+
* @param compressed - The compressed vector to restore
|
|
128
|
+
* @returns Reconstructed Float32Array
|
|
129
|
+
*/
|
|
130
|
+
decompress(compressed: CompressedVector): Float32Array;
|
|
131
|
+
/**
|
|
132
|
+
* Get current compression statistics for monitoring.
|
|
133
|
+
*/
|
|
134
|
+
getCompressionStats(): CompressionStats;
|
|
135
|
+
/**
|
|
136
|
+
* Reset compression statistics. Useful for testing or periodic reporting.
|
|
137
|
+
*/
|
|
138
|
+
resetStats(): void;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Compute cosine similarity between two vectors.
|
|
142
|
+
* Returns a value in [-1, 1] where 1 means identical direction.
|
|
143
|
+
*/
|
|
144
|
+
export declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
|
|
145
|
+
/**
|
|
146
|
+
* Get or create the shared TemporalCompressionService singleton.
|
|
147
|
+
*/
|
|
148
|
+
export declare function getTemporalCompressionService(): Promise<TemporalCompressionService>;
|
|
149
|
+
/**
|
|
150
|
+
* Create a new TemporalCompressionService (non-singleton, for testing).
|
|
151
|
+
*/
|
|
152
|
+
export declare function createTemporalCompressionService(): TemporalCompressionService;
|
|
153
|
+
/**
|
|
154
|
+
* Reset the shared singleton. Primarily for test cleanup.
|
|
155
|
+
*/
|
|
156
|
+
export declare function resetTemporalCompressionService(): void;
|
|
157
|
+
export { TIER_CONFIG, THEORETICAL_COMPRESSION_RATIOS, ACTUAL_FALLBACK_RATIO, HOT_THRESHOLD_DAYS, WARM_THRESHOLD_DAYS };
|
|
158
|
+
/**
|
|
159
|
+
* @deprecated Use THEORETICAL_COMPRESSION_RATIOS instead.
|
|
160
|
+
* Kept for backwards compatibility with existing consumers.
|
|
161
|
+
*/
|
|
162
|
+
export declare const EXPECTED_COMPRESSION_RATIOS: Record<CompressionTier, number>;
|
|
163
|
+
//# sourceMappingURL=temporal-compression.d.ts.map
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal Tensor Compression Service
|
|
3
|
+
* ADR-085: Temporal Tensor Pattern Compression
|
|
4
|
+
*
|
|
5
|
+
* Compresses pattern embeddings based on access patterns using tiered
|
|
6
|
+
* quantization. Hot patterns retain full precision, while cold patterns
|
|
7
|
+
* are aggressively compressed to save memory.
|
|
8
|
+
*
|
|
9
|
+
* TypeScript implementation using Int8Array (4x compression for all tiers).
|
|
10
|
+
* No native package exists — this IS the production implementation.
|
|
11
|
+
*
|
|
12
|
+
* Tiers (logical bit depths, stored as Int8Array):
|
|
13
|
+
* - HOT (last 7 days): 8-bit quantization (4x compression)
|
|
14
|
+
* - WARM (7-30 days): 5-bit quantization (4x actual, 6.4x theoretical)
|
|
15
|
+
* - COLD (30+ days): 3-bit quantization (4x actual, 10.7x theoretical)
|
|
16
|
+
*
|
|
17
|
+
* All tiers deliver 4x compression because Int8Array uses 1 byte per
|
|
18
|
+
* element regardless of logical bit depth.
|
|
19
|
+
*
|
|
20
|
+
* @module integrations/ruvector/temporal-compression
|
|
21
|
+
*/
|
|
22
|
+
import { LoggerFactory } from '../../logging/index.js';
|
|
23
|
+
import { getRuVectorFeatureFlags } from './feature-flags.js';
|
|
24
|
+
const logger = LoggerFactory.create('temporal-compression');
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Constants
|
|
27
|
+
// ============================================================================
|
|
28
|
+
/** Hot tier: accessed within the last 7 days */
|
|
29
|
+
const HOT_THRESHOLD_DAYS = 7;
|
|
30
|
+
/** Warm tier: accessed within the last 30 days */
|
|
31
|
+
const WARM_THRESHOLD_DAYS = 30;
|
|
32
|
+
/** Quantization parameters per tier */
|
|
33
|
+
const TIER_CONFIG = {
|
|
34
|
+
hot: { bitDepth: 8, min: -128, max: 127 },
|
|
35
|
+
warm: { bitDepth: 5, min: -16, max: 15 },
|
|
36
|
+
cold: { bitDepth: 3, min: -4, max: 3 },
|
|
37
|
+
};
|
|
38
|
+
/** Theoretical compression ratios assuming true bit-packing (native only) */
|
|
39
|
+
const THEORETICAL_COMPRESSION_RATIOS = {
|
|
40
|
+
hot: 4.0, // 32-bit -> 8-bit = 4x
|
|
41
|
+
warm: 6.4, // 32-bit -> 5-bit ~ 6.4x
|
|
42
|
+
cold: 10.7, // 32-bit -> 3-bit ~ 10.7x
|
|
43
|
+
};
|
|
44
|
+
/** Actual compression ratio in the TypeScript fallback (Float32 -> Int8 = 4x for all tiers) */
|
|
45
|
+
const ACTUAL_FALLBACK_RATIO = 4.0;
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Native module detection
|
|
48
|
+
// ============================================================================
|
|
49
|
+
/** Whether native ruvector-temporal-tensor is available */
|
|
50
|
+
let nativeAvailable = null;
|
|
51
|
+
let nativeModule = null;
|
|
52
|
+
/**
|
|
53
|
+
* Check native module availability.
|
|
54
|
+
* No native package exists for temporal compression — always returns false.
|
|
55
|
+
* The TypeScript implementation IS the production implementation.
|
|
56
|
+
*/
|
|
57
|
+
async function tryLoadNativeModule() {
|
|
58
|
+
if (nativeAvailable !== null)
|
|
59
|
+
return nativeAvailable;
|
|
60
|
+
nativeAvailable = false;
|
|
61
|
+
nativeModule = null;
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// TypeScript Fallback Quantization
|
|
66
|
+
// ============================================================================
|
|
67
|
+
/**
|
|
68
|
+
* Quantize a float32 vector to the specified bit depth.
|
|
69
|
+
*
|
|
70
|
+
* Maps values linearly from [min, max] of the input to the integer range
|
|
71
|
+
* determined by the bit depth (stored as Int8Array for uniformity).
|
|
72
|
+
*/
|
|
73
|
+
function quantize(vector, tier) {
|
|
74
|
+
const config = TIER_CONFIG[tier];
|
|
75
|
+
const range = config.max - config.min; // integer range for this bit depth
|
|
76
|
+
if (vector.length === 0) {
|
|
77
|
+
return { data: new Int8Array(0), scale: 1, offset: 0 };
|
|
78
|
+
}
|
|
79
|
+
// Find min/max of input vector
|
|
80
|
+
let vMin = vector[0];
|
|
81
|
+
let vMax = vector[0];
|
|
82
|
+
for (let i = 1; i < vector.length; i++) {
|
|
83
|
+
if (vector[i] < vMin)
|
|
84
|
+
vMin = vector[i];
|
|
85
|
+
if (vector[i] > vMax)
|
|
86
|
+
vMax = vector[i];
|
|
87
|
+
}
|
|
88
|
+
// Avoid division by zero for constant vectors
|
|
89
|
+
const vRange = vMax - vMin;
|
|
90
|
+
const scale = vRange === 0 ? 1 : vRange / range;
|
|
91
|
+
const offset = vMin;
|
|
92
|
+
const data = new Int8Array(vector.length);
|
|
93
|
+
for (let i = 0; i < vector.length; i++) {
|
|
94
|
+
// Map float -> integer range, then shift to [config.min, config.max]
|
|
95
|
+
const normalized = vRange === 0 ? 0 : (vector[i] - offset) / scale;
|
|
96
|
+
let quantized = Math.round(normalized) + config.min;
|
|
97
|
+
// Clamp to valid range
|
|
98
|
+
quantized = Math.max(config.min, Math.min(config.max, quantized));
|
|
99
|
+
data[i] = quantized;
|
|
100
|
+
}
|
|
101
|
+
return { data, scale, offset };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Dequantize an Int8Array back to Float32Array using stored scale and offset.
|
|
105
|
+
*/
|
|
106
|
+
function dequantize(data, scale, offset, tier) {
|
|
107
|
+
const config = TIER_CONFIG[tier];
|
|
108
|
+
const result = new Float32Array(data.length);
|
|
109
|
+
for (let i = 0; i < data.length; i++) {
|
|
110
|
+
result[i] = (data[i] - config.min) * scale + offset;
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
// ============================================================================
|
|
115
|
+
// Temporal Compression Service
|
|
116
|
+
// ============================================================================
|
|
117
|
+
/**
|
|
118
|
+
* Temporal Compression Service
|
|
119
|
+
*
|
|
120
|
+
* Provides tiered quantization of pattern embedding vectors based on
|
|
121
|
+
* how recently they were accessed. Supports both a native Rust/NAPI
|
|
122
|
+
* implementation and a pure TypeScript fallback.
|
|
123
|
+
*/
|
|
124
|
+
export class TemporalCompressionService {
|
|
125
|
+
stats = {
|
|
126
|
+
totalCompressed: 0,
|
|
127
|
+
byTier: { hot: 0, warm: 0, cold: 0 },
|
|
128
|
+
avgCompressionRatio: { hot: 0, warm: 0, cold: 0 },
|
|
129
|
+
totalBytesSaved: 0,
|
|
130
|
+
totalOriginalBytes: 0,
|
|
131
|
+
totalCompressedBytes: 0,
|
|
132
|
+
usingNative: false,
|
|
133
|
+
usesNativeBitPacking: false,
|
|
134
|
+
};
|
|
135
|
+
/** Running sum of ratios per tier for average calculation */
|
|
136
|
+
ratioSums = { hot: 0, warm: 0, cold: 0 };
|
|
137
|
+
initialized = false;
|
|
138
|
+
/**
|
|
139
|
+
* Initialize the service, attempting to load the native module.
|
|
140
|
+
* Safe to call multiple times; subsequent calls are no-ops.
|
|
141
|
+
*/
|
|
142
|
+
async initialize() {
|
|
143
|
+
if (this.initialized)
|
|
144
|
+
return;
|
|
145
|
+
const native = await tryLoadNativeModule();
|
|
146
|
+
this.stats.usingNative = native;
|
|
147
|
+
this.stats.usesNativeBitPacking = native;
|
|
148
|
+
this.initialized = true;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if the temporal compression feature flag is enabled.
|
|
152
|
+
*/
|
|
153
|
+
isEnabled() {
|
|
154
|
+
const flags = getRuVectorFeatureFlags();
|
|
155
|
+
return flags.useTemporalCompression === true;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Classify a last-access date into a compression tier.
|
|
159
|
+
*
|
|
160
|
+
* @param lastAccessDate - When the pattern was last accessed
|
|
161
|
+
* @returns The compression tier for the pattern
|
|
162
|
+
*/
|
|
163
|
+
classifyTier(lastAccessDate) {
|
|
164
|
+
const now = Date.now();
|
|
165
|
+
const daysSinceAccess = (now - lastAccessDate.getTime()) / (1000 * 60 * 60 * 24);
|
|
166
|
+
if (daysSinceAccess < HOT_THRESHOLD_DAYS)
|
|
167
|
+
return 'hot';
|
|
168
|
+
if (daysSinceAccess < WARM_THRESHOLD_DAYS)
|
|
169
|
+
return 'warm';
|
|
170
|
+
return 'cold';
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Compress a float32 embedding vector according to the specified tier.
|
|
174
|
+
*
|
|
175
|
+
* @param vector - The original float32 embedding
|
|
176
|
+
* @param tier - Compression tier to apply
|
|
177
|
+
* @returns Compressed vector with metadata for decompression
|
|
178
|
+
*/
|
|
179
|
+
compress(vector, tier) {
|
|
180
|
+
const originalByteSize = vector.length * 4; // float32 = 4 bytes
|
|
181
|
+
let data;
|
|
182
|
+
let scale;
|
|
183
|
+
let offset;
|
|
184
|
+
if (nativeAvailable && nativeModule) {
|
|
185
|
+
const result = nativeModule.compress(vector, TIER_CONFIG[tier].bitDepth);
|
|
186
|
+
data = result.data;
|
|
187
|
+
scale = result.scale;
|
|
188
|
+
offset = result.offset;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const result = quantize(vector, tier);
|
|
192
|
+
data = result.data;
|
|
193
|
+
scale = result.scale;
|
|
194
|
+
offset = result.offset;
|
|
195
|
+
}
|
|
196
|
+
const effectiveBitsPerElement = TIER_CONFIG[tier].bitDepth;
|
|
197
|
+
// Actual storage: Int8Array uses 1 byte per element regardless of logical bit depth.
|
|
198
|
+
// Theoretical: what a true bit-packing implementation would achieve.
|
|
199
|
+
const actualByteSize = data.byteLength;
|
|
200
|
+
const theoreticalByteSize = Math.ceil((vector.length * effectiveBitsPerElement) / 8);
|
|
201
|
+
const compressedByteSize = actualByteSize;
|
|
202
|
+
const ratio = compressedByteSize > 0 ? originalByteSize / compressedByteSize : 1;
|
|
203
|
+
// Update stats
|
|
204
|
+
this.stats.totalCompressed++;
|
|
205
|
+
this.stats.byTier[tier]++;
|
|
206
|
+
this.ratioSums[tier] += ratio;
|
|
207
|
+
this.stats.avgCompressionRatio[tier] = this.ratioSums[tier] / this.stats.byTier[tier];
|
|
208
|
+
this.stats.totalOriginalBytes += originalByteSize;
|
|
209
|
+
this.stats.totalCompressedBytes += compressedByteSize;
|
|
210
|
+
this.stats.totalBytesSaved += (originalByteSize - compressedByteSize);
|
|
211
|
+
return {
|
|
212
|
+
data,
|
|
213
|
+
scale,
|
|
214
|
+
offset,
|
|
215
|
+
tier,
|
|
216
|
+
originalLength: vector.length,
|
|
217
|
+
bitDepth: effectiveBitsPerElement,
|
|
218
|
+
originalByteSize,
|
|
219
|
+
compressedByteSize,
|
|
220
|
+
actualByteSize,
|
|
221
|
+
theoreticalByteSize,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Decompress a compressed vector back to Float32Array.
|
|
226
|
+
*
|
|
227
|
+
* The output is an approximation of the original due to quantization loss.
|
|
228
|
+
* Consumers receive a standard Float32Array transparently.
|
|
229
|
+
*
|
|
230
|
+
* @param compressed - The compressed vector to restore
|
|
231
|
+
* @returns Reconstructed Float32Array
|
|
232
|
+
*/
|
|
233
|
+
decompress(compressed) {
|
|
234
|
+
if (nativeAvailable && nativeModule) {
|
|
235
|
+
return nativeModule.decompress(compressed.data, compressed.scale, compressed.offset, compressed.originalLength);
|
|
236
|
+
}
|
|
237
|
+
return dequantize(compressed.data, compressed.scale, compressed.offset, compressed.tier);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get current compression statistics for monitoring.
|
|
241
|
+
*/
|
|
242
|
+
getCompressionStats() {
|
|
243
|
+
return { ...this.stats };
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Reset compression statistics. Useful for testing or periodic reporting.
|
|
247
|
+
*/
|
|
248
|
+
resetStats() {
|
|
249
|
+
this.stats = {
|
|
250
|
+
totalCompressed: 0,
|
|
251
|
+
byTier: { hot: 0, warm: 0, cold: 0 },
|
|
252
|
+
avgCompressionRatio: { hot: 0, warm: 0, cold: 0 },
|
|
253
|
+
totalBytesSaved: 0,
|
|
254
|
+
totalOriginalBytes: 0,
|
|
255
|
+
totalCompressedBytes: 0,
|
|
256
|
+
usingNative: this.stats.usingNative,
|
|
257
|
+
usesNativeBitPacking: this.stats.usesNativeBitPacking,
|
|
258
|
+
};
|
|
259
|
+
this.ratioSums = { hot: 0, warm: 0, cold: 0 };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// ============================================================================
|
|
263
|
+
// Cosine Similarity Utility (for quality validation)
|
|
264
|
+
// ============================================================================
|
|
265
|
+
/**
|
|
266
|
+
* Compute cosine similarity between two vectors.
|
|
267
|
+
* Returns a value in [-1, 1] where 1 means identical direction.
|
|
268
|
+
*/
|
|
269
|
+
export function cosineSimilarity(a, b) {
|
|
270
|
+
if (a.length !== b.length || a.length === 0)
|
|
271
|
+
return 0;
|
|
272
|
+
let dotProduct = 0;
|
|
273
|
+
let normA = 0;
|
|
274
|
+
let normB = 0;
|
|
275
|
+
for (let i = 0; i < a.length; i++) {
|
|
276
|
+
dotProduct += a[i] * b[i];
|
|
277
|
+
normA += a[i] * a[i];
|
|
278
|
+
normB += b[i] * b[i];
|
|
279
|
+
}
|
|
280
|
+
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
|
|
281
|
+
return denominator === 0 ? 0 : dotProduct / denominator;
|
|
282
|
+
}
|
|
283
|
+
// ============================================================================
|
|
284
|
+
// Singleton & Factory
|
|
285
|
+
// ============================================================================
|
|
286
|
+
let sharedInstance = null;
|
|
287
|
+
/**
|
|
288
|
+
* Get or create the shared TemporalCompressionService singleton.
|
|
289
|
+
*/
|
|
290
|
+
export async function getTemporalCompressionService() {
|
|
291
|
+
if (!sharedInstance) {
|
|
292
|
+
sharedInstance = new TemporalCompressionService();
|
|
293
|
+
await sharedInstance.initialize();
|
|
294
|
+
}
|
|
295
|
+
return sharedInstance;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Create a new TemporalCompressionService (non-singleton, for testing).
|
|
299
|
+
*/
|
|
300
|
+
export function createTemporalCompressionService() {
|
|
301
|
+
return new TemporalCompressionService();
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Reset the shared singleton. Primarily for test cleanup.
|
|
305
|
+
*/
|
|
306
|
+
export function resetTemporalCompressionService() {
|
|
307
|
+
sharedInstance = null;
|
|
308
|
+
}
|
|
309
|
+
// ============================================================================
|
|
310
|
+
// Exports
|
|
311
|
+
// ============================================================================
|
|
312
|
+
export { TIER_CONFIG, THEORETICAL_COMPRESSION_RATIOS, ACTUAL_FALLBACK_RATIO, HOT_THRESHOLD_DAYS, WARM_THRESHOLD_DAYS };
|
|
313
|
+
/**
|
|
314
|
+
* @deprecated Use THEORETICAL_COMPRESSION_RATIOS instead.
|
|
315
|
+
* Kept for backwards compatibility with existing consumers.
|
|
316
|
+
*/
|
|
317
|
+
export const EXPECTED_COMPRESSION_RATIOS = THEORETICAL_COMPRESSION_RATIOS;
|
|
318
|
+
//# sourceMappingURL=temporal-compression.js.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thompson Sampling with Beta Priors (Task 2.3, ADR-084)
|
|
3
|
+
*
|
|
4
|
+
* Provides a Thompson Sampler for balancing exploration/exploitation in
|
|
5
|
+
* cross-domain transfer decisions. Each domain pair maintains a Beta(alpha, beta)
|
|
6
|
+
* distribution that is updated based on transfer outcomes.
|
|
7
|
+
*
|
|
8
|
+
* @module integrations/ruvector/thompson-sampler
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Thompson Sampling with Beta priors for exploration/exploitation balance.
|
|
12
|
+
*
|
|
13
|
+
* Each domain pair maintains a Beta(alpha, beta) distribution where:
|
|
14
|
+
* - alpha = number of successes + 1 (prior)
|
|
15
|
+
* - beta = number of failures + 1 (prior)
|
|
16
|
+
*
|
|
17
|
+
* Sampling from this distribution naturally balances exploration (uncertain
|
|
18
|
+
* pairs with wide distributions) and exploitation (proven pairs with
|
|
19
|
+
* narrow distributions centered on high success rates).
|
|
20
|
+
*/
|
|
21
|
+
export declare class ThompsonSampler {
|
|
22
|
+
/** Beta distribution alpha params: successes + 1 */
|
|
23
|
+
private alphas;
|
|
24
|
+
/** Beta distribution beta params: failures + 1 */
|
|
25
|
+
private betas;
|
|
26
|
+
/**
|
|
27
|
+
* Sample from the Beta distribution for a domain pair.
|
|
28
|
+
*
|
|
29
|
+
* @param domainPair - Key identifying the source->target pair
|
|
30
|
+
* @returns Sampled probability of transfer success
|
|
31
|
+
*/
|
|
32
|
+
sample(domainPair: string): number;
|
|
33
|
+
/**
|
|
34
|
+
* Update the Beta distribution after observing a transfer outcome.
|
|
35
|
+
*
|
|
36
|
+
* @param domainPair - Key identifying the source->target pair
|
|
37
|
+
* @param success - Whether the transfer was successful
|
|
38
|
+
*/
|
|
39
|
+
update(domainPair: string, success: boolean): void;
|
|
40
|
+
/** Get the mean of the Beta distribution: alpha / (alpha + beta) */
|
|
41
|
+
getMean(domainPair: string): number;
|
|
42
|
+
/** Get the total number of observations (excluding priors) */
|
|
43
|
+
getObservationCount(domainPair: string): number;
|
|
44
|
+
/** Get the alpha (success count + 1) for a domain pair */
|
|
45
|
+
getAlpha(domainPair: string): number;
|
|
46
|
+
/** Get the beta (failure count + 1) for a domain pair */
|
|
47
|
+
getBeta(domainPair: string): number;
|
|
48
|
+
/**
|
|
49
|
+
* Sample from Beta(alpha, beta) via the Gamma-ratio method:
|
|
50
|
+
* X ~ Gamma(alpha, 1), Y ~ Gamma(beta, 1), return X / (X + Y).
|
|
51
|
+
*/
|
|
52
|
+
private sampleBeta;
|
|
53
|
+
/**
|
|
54
|
+
* Sample from Gamma(shape, 1) using Marsaglia-Tsang for shape >= 1
|
|
55
|
+
* and rejection method for shape < 1.
|
|
56
|
+
*/
|
|
57
|
+
private sampleGamma;
|
|
58
|
+
/** Standard normal sample via Box-Muller transform */
|
|
59
|
+
private standardNormal;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=thompson-sampler.d.ts.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thompson Sampling with Beta Priors (Task 2.3, ADR-084)
|
|
3
|
+
*
|
|
4
|
+
* Provides a Thompson Sampler for balancing exploration/exploitation in
|
|
5
|
+
* cross-domain transfer decisions. Each domain pair maintains a Beta(alpha, beta)
|
|
6
|
+
* distribution that is updated based on transfer outcomes.
|
|
7
|
+
*
|
|
8
|
+
* @module integrations/ruvector/thompson-sampler
|
|
9
|
+
*/
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Thompson Sampler
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Thompson Sampling with Beta priors for exploration/exploitation balance.
|
|
15
|
+
*
|
|
16
|
+
* Each domain pair maintains a Beta(alpha, beta) distribution where:
|
|
17
|
+
* - alpha = number of successes + 1 (prior)
|
|
18
|
+
* - beta = number of failures + 1 (prior)
|
|
19
|
+
*
|
|
20
|
+
* Sampling from this distribution naturally balances exploration (uncertain
|
|
21
|
+
* pairs with wide distributions) and exploitation (proven pairs with
|
|
22
|
+
* narrow distributions centered on high success rates).
|
|
23
|
+
*/
|
|
24
|
+
export class ThompsonSampler {
|
|
25
|
+
/** Beta distribution alpha params: successes + 1 */
|
|
26
|
+
alphas = new Map();
|
|
27
|
+
/** Beta distribution beta params: failures + 1 */
|
|
28
|
+
betas = new Map();
|
|
29
|
+
/**
|
|
30
|
+
* Sample from the Beta distribution for a domain pair.
|
|
31
|
+
*
|
|
32
|
+
* @param domainPair - Key identifying the source->target pair
|
|
33
|
+
* @returns Sampled probability of transfer success
|
|
34
|
+
*/
|
|
35
|
+
sample(domainPair) {
|
|
36
|
+
const alpha = this.alphas.get(domainPair) ?? 1;
|
|
37
|
+
const beta = this.betas.get(domainPair) ?? 1;
|
|
38
|
+
return this.sampleBeta(alpha, beta);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Update the Beta distribution after observing a transfer outcome.
|
|
42
|
+
*
|
|
43
|
+
* @param domainPair - Key identifying the source->target pair
|
|
44
|
+
* @param success - Whether the transfer was successful
|
|
45
|
+
*/
|
|
46
|
+
update(domainPair, success) {
|
|
47
|
+
if (success) {
|
|
48
|
+
this.alphas.set(domainPair, (this.alphas.get(domainPair) ?? 1) + 1);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.betas.set(domainPair, (this.betas.get(domainPair) ?? 1) + 1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Get the mean of the Beta distribution: alpha / (alpha + beta) */
|
|
55
|
+
getMean(domainPair) {
|
|
56
|
+
const alpha = this.alphas.get(domainPair) ?? 1;
|
|
57
|
+
const beta = this.betas.get(domainPair) ?? 1;
|
|
58
|
+
return alpha / (alpha + beta);
|
|
59
|
+
}
|
|
60
|
+
/** Get the total number of observations (excluding priors) */
|
|
61
|
+
getObservationCount(domainPair) {
|
|
62
|
+
const alpha = this.alphas.get(domainPair) ?? 1;
|
|
63
|
+
const beta = this.betas.get(domainPair) ?? 1;
|
|
64
|
+
return (alpha - 1) + (beta - 1);
|
|
65
|
+
}
|
|
66
|
+
/** Get the alpha (success count + 1) for a domain pair */
|
|
67
|
+
getAlpha(domainPair) {
|
|
68
|
+
return this.alphas.get(domainPair) ?? 1;
|
|
69
|
+
}
|
|
70
|
+
/** Get the beta (failure count + 1) for a domain pair */
|
|
71
|
+
getBeta(domainPair) {
|
|
72
|
+
return this.betas.get(domainPair) ?? 1;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Sample from Beta(alpha, beta) via the Gamma-ratio method:
|
|
76
|
+
* X ~ Gamma(alpha, 1), Y ~ Gamma(beta, 1), return X / (X + Y).
|
|
77
|
+
*/
|
|
78
|
+
sampleBeta(alpha, beta) {
|
|
79
|
+
const x = this.sampleGamma(alpha);
|
|
80
|
+
const y = this.sampleGamma(beta);
|
|
81
|
+
if (x + y === 0)
|
|
82
|
+
return 0.5;
|
|
83
|
+
return x / (x + y);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Sample from Gamma(shape, 1) using Marsaglia-Tsang for shape >= 1
|
|
87
|
+
* and rejection method for shape < 1.
|
|
88
|
+
*/
|
|
89
|
+
sampleGamma(shape) {
|
|
90
|
+
if (shape < 1) {
|
|
91
|
+
const u = Math.random();
|
|
92
|
+
return this.sampleGamma(shape + 1) * Math.pow(u, 1 / shape);
|
|
93
|
+
}
|
|
94
|
+
const d = shape - 1 / 3;
|
|
95
|
+
const c = 1 / Math.sqrt(9 * d);
|
|
96
|
+
for (;;) {
|
|
97
|
+
let x;
|
|
98
|
+
let v;
|
|
99
|
+
do {
|
|
100
|
+
x = this.standardNormal();
|
|
101
|
+
v = 1 + c * x;
|
|
102
|
+
} while (v <= 0);
|
|
103
|
+
v = v * v * v;
|
|
104
|
+
const u = Math.random();
|
|
105
|
+
if (u < 1 - 0.0331 * x * x * x * x)
|
|
106
|
+
return d * v;
|
|
107
|
+
if (Math.log(u) < 0.5 * x * x + d * (1 - v + Math.log(v)))
|
|
108
|
+
return d * v;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Standard normal sample via Box-Muller transform */
|
|
112
|
+
standardNormal() {
|
|
113
|
+
const u1 = Math.random();
|
|
114
|
+
const u2 = Math.random();
|
|
115
|
+
return Math.sqrt(-2 * Math.log(u1 || 1e-10)) * Math.cos(2 * Math.PI * u2);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=thompson-sampler.js.map
|