Files
goodbuddy/src/shared/embedding-contracts.test.ts
T

153 lines
4.1 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
embeddingDiagnosticResultSchema,
embeddingIndexJobSchema,
embeddingIndexStatusSchema,
knowledgeEmbeddingIndexSnapshotSchema,
embeddingSafeErrorSchema,
isEmbeddingIndexJobActive
} from './embedding-contracts'
describe('embedding contracts', () => {
it('accepts a real successful model test result', () => {
expect(
embeddingDiagnosticResultSchema.parse({
status: 'available',
provider: 'openai-compatible',
model: 'text-embedding-3-small',
checkedAt: 1_700_000_000_000,
latencyMs: 184,
dimensions: 1_536
})
).toMatchObject({
status: 'available',
latencyMs: 184,
dimensions: 1_536
})
expect(
embeddingDiagnosticResultSchema.safeParse({
status: 'available',
provider: 'provider',
model: 'slow-local-model',
checkedAt: 1_700_000_000_000,
latencyMs: 120_001,
dimensions: 4_096
}).success
).toBe(true)
expect(
embeddingDiagnosticResultSchema.safeParse({
status: 'available',
provider: 'provider',
model: 'model',
checkedAt: 1,
latencyMs: 1,
dimensions: 0,
reachable: true
}).success
).toBe(false)
})
it('bounds safe failures and excludes raw provider details', () => {
expect(
embeddingSafeErrorSchema.safeParse({
code: 'authentication',
message: '身份验证失败。',
retryable: false,
rawResponse: '{"api_key":"secret"}'
}).success
).toBe(false)
expect(
embeddingSafeErrorSchema.safeParse({
code: 'unknown',
message: 'x'.repeat(501),
retryable: false
}).success
).toBe(false)
})
it('validates queued, running and terminal index jobs', () => {
const base = {
id: 'job-1',
provider: 'provider',
model: 'model',
createdAt: 10
}
const queued = embeddingIndexJobSchema.parse({
...base,
status: 'queued',
progress: { completed: 0, total: 0, percent: 0 }
})
const running = embeddingIndexJobSchema.parse({
...base,
status: 'running',
startedAt: 11,
progress: { completed: 3, total: 4, percent: 75 }
})
expect(isEmbeddingIndexJobActive(queued)).toBe(true)
expect(isEmbeddingIndexJobActive(running)).toBe(true)
for (const status of ['completed', 'failed', 'cancelled'] as const) {
const result = embeddingIndexJobSchema.safeParse({
...base,
status,
startedAt: 11,
completedAt: 12,
progress:
status === 'completed'
? { completed: 4, total: 4, percent: 100 }
: { completed: 2, total: 4, percent: 50 },
...(status === 'failed'
? {
error: {
code: 'network',
message: '无法连接到向量服务。',
retryable: true
}
}
: {})
})
expect(result.success, status).toBe(true)
}
})
it('exposes only the persisted rebuild job in index status', () => {
const parsed = embeddingIndexStatusSchema.parse({
job: {
id: 'job-new',
status: 'running',
provider: 'provider',
model: 'new-model',
progress: { completed: 5, total: 20, percent: 25 },
createdAt: 11,
startedAt: 12
}
})
expect(parsed.job?.model).toBe('new-model')
expect(
embeddingIndexStatusSchema.safeParse({
job: null,
servingSnapshot: null
}).success
).toBe(false)
})
it('validates library-scoped embedding coverage totals', () => {
const base = {
knowledgeBaseId: '11111111-1111-4111-8111-111111111111',
enabled: true,
coverage: { total: 4, indexed: 2, missing: 1, error: 1 },
indexStatus: { job: null }
}
expect(
knowledgeEmbeddingIndexSnapshotSchema.safeParse(base).success
).toBe(true)
expect(
knowledgeEmbeddingIndexSnapshotSchema.safeParse({
...base,
coverage: { total: 4, indexed: 2, missing: 2, error: 1 }
}).success
).toBe(false)
})
})