feat: implement Tier 3 features — lane queue, credential redaction, token dashboard, xAI, Voyage AI

- Lane Queue: per-session FIFO queue in gateway replacing reject-when-busy (9 tests)
- Credential Redaction: redactConfig() expanded to cover 18+ secret fields (16 tests)
- Web UI Token Dashboard: system.tokenUsage endpoint + Usage page with summary cards
- xAI (Grok) Provider: OpenAI-compatible client with model pricing
- Voyage AI Embeddings: new embedding provider with configurable dimensions (5 tests)
- Update gap analysis: 90→95 match (70%→74%), Tier 3 section marked DONE
- Update state.json: test count 1001→1034, add tier3_completion entry

Total: 1034 tests passing across 85 files, typecheck clean
This commit is contained in:
William Valentin
2026-02-09 10:32:57 -08:00
parent 1d126cddfb
commit 9be8f76bc7
26 changed files with 1395 additions and 105 deletions
+70
View File
@@ -5,6 +5,7 @@ import {
GeminiEmbeddingProvider,
OllamaEmbeddingProvider,
LlamaCppEmbeddingProvider,
VoyageAIEmbeddingProvider,
} from './embeddings.js';
import type { EmbeddingConfig } from '../config/schema.js';
@@ -39,6 +40,11 @@ describe('createEmbeddingProvider', () => {
expect(provider).toBeInstanceOf(LlamaCppEmbeddingProvider);
});
it('creates Voyage provider', () => {
const provider = createEmbeddingProvider({ ...baseConfig, provider: 'voyage' });
expect(provider).toBeInstanceOf(VoyageAIEmbeddingProvider);
});
it('throws on unknown provider', () => {
expect(() => createEmbeddingProvider({ ...baseConfig, provider: 'unknown' as never })).toThrow('Unknown embedding provider');
});
@@ -157,3 +163,67 @@ describe('LlamaCppEmbeddingProvider', () => {
expect(provider.dimensions).toBe(768);
});
});
describe('VoyageAIEmbeddingProvider', () => {
it('defaults to 1024 dimensions', () => {
const config: EmbeddingConfig = {
enabled: true,
provider: 'voyage',
model: 'voyage-3',
chunk_size: 512,
chunk_overlap: 50,
top_k: 5,
hybrid_weight: 0.7,
};
const provider = new VoyageAIEmbeddingProvider(config);
expect(provider.dimensions).toBe(1024);
});
it('reports configured dimensions', () => {
const config: EmbeddingConfig = {
enabled: true,
provider: 'voyage',
model: 'voyage-3-lite',
dimensions: 512,
chunk_size: 512,
chunk_overlap: 50,
top_k: 5,
hybrid_weight: 0.7,
};
const provider = new VoyageAIEmbeddingProvider(config);
expect(provider.dimensions).toBe(512);
});
it('uses custom endpoint if provided', () => {
const config: EmbeddingConfig = {
enabled: true,
provider: 'voyage',
model: 'voyage-3',
endpoint: 'https://custom.proxy.example.com/v1',
api_key: 'test-key',
chunk_size: 512,
chunk_overlap: 50,
top_k: 5,
hybrid_weight: 0.7,
};
// Should not throw when constructing with custom endpoint
const provider = new VoyageAIEmbeddingProvider(config);
expect(provider.dimensions).toBe(1024);
});
it('uses api_key from config', () => {
const config: EmbeddingConfig = {
enabled: true,
provider: 'voyage',
model: 'voyage-3',
api_key: 'voy-test-key-123',
chunk_size: 512,
chunk_overlap: 50,
top_k: 5,
hybrid_weight: 0.7,
};
// Should construct without error when api_key is provided
const provider = new VoyageAIEmbeddingProvider(config);
expect(provider.dimensions).toBe(1024);
});
});
+44
View File
@@ -159,6 +159,48 @@ export class LlamaCppEmbeddingProvider implements EmbeddingProvider {
}
}
// ---------------------------------------------------------------------------
// Voyage AI
// ---------------------------------------------------------------------------
export class VoyageAIEmbeddingProvider implements EmbeddingProvider {
private _model: string;
private _dimensions: number;
private _apiKey: string;
private _endpoint: string;
constructor(config: EmbeddingConfig) {
this._model = config.model;
this._dimensions = config.dimensions ?? 1024;
this._apiKey = config.api_key ?? process.env.VOYAGE_API_KEY ?? '';
this._endpoint = config.endpoint ?? 'https://api.voyageai.com/v1';
}
get dimensions(): number {
return this._dimensions;
}
async embed(texts: string[]): Promise<number[][]> {
// Voyage AI's API is OpenAI-compatible for embeddings
const { default: OpenAI } = await import('openai');
const client = new OpenAI({
apiKey: this._apiKey,
baseURL: this._endpoint,
});
const response = await client.embeddings.create({
model: this._model,
input: texts,
// Note: Voyage AI does not support the `dimensions` parameter.
// Dimensions are model-dependent (voyage-3: 1024, voyage-3-lite: 512, voyage-code-3: 1024).
});
// Sort by index to ensure order matches input
const sorted = response.data.sort((a, b) => a.index - b.index);
return sorted.map((item) => item.embedding);
}
}
// ---------------------------------------------------------------------------
// Factory
// ---------------------------------------------------------------------------
@@ -176,6 +218,8 @@ export function createEmbeddingProvider(config: EmbeddingConfig): EmbeddingProvi
return new OllamaEmbeddingProvider(config);
case 'llamacpp':
return new LlamaCppEmbeddingProvider(config);
case 'voyage':
return new VoyageAIEmbeddingProvider(config);
default:
throw new Error(`Unknown embedding provider: ${(config as Record<string, unknown>).provider}`);
}