Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lat.md/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ Provider is auto-detected from the resolved key prefix:

- `sk-...` — OpenAI (uses `text-embedding-3-small`, 1536 dims)
- `vck_...` — Vercel AI Gateway (uses `openai/text-embedding-3-small`, 1536 dims)
- `di_...` — DeepInfra (uses `Qwen/Qwen3-Embedding-0.6B`, 1024 dims; `di_` prefix is stripped before the key is sent)
- `sk-ant-...` — Anthropic (not supported, errors with guidance)
- `REPLAY_LAT_LLM_KEY::<url>` — test-only replay server for offline testing

Expand Down
2 changes: 1 addition & 1 deletion lat.md/tests/search.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Tests in `tests/search.test.ts`.

## Provider Detection

Unit tests (always run). Verify `detectProvider` correctly identifies OpenAI (`sk-`), Vercel (`vck_`), rejects Anthropic (`sk-ant-`) with a helpful message, and rejects unknown prefixes.
Unit tests (always run). Verify `detectProvider` correctly identifies OpenAI (`sk-`), Vercel (`vck_`), DeepInfra (`di_`), rejects Anthropic (`sk-ant-`) with a helpful message, and rejects unknown prefixes. For DeepInfra, also verify that the `di_` prefix is stripped from the key before it appears in the `Authorization` header.

## RAG Replay Tests

Expand Down
14 changes: 13 additions & 1 deletion src/search/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ const vercel: EmbeddingProvider = {
}),
};

const deepinfra: EmbeddingProvider = {
name: 'deepinfra',
apiBase: 'https://api.deepinfra.com/v1/openai',
model: 'Qwen/Qwen3-Embedding-0.6B',
dimensions: 1024,
headers: (key) => ({
Authorization: `Bearer ${key.startsWith('di_') ? key.slice('di_'.length) : key}`,
'Content-Type': 'application/json',
}),
};

export function detectProvider(key: string): EmbeddingProvider {
if (key.startsWith('REPLAY_LAT_LLM_KEY::')) {
const replayUrl = key.slice('REPLAY_LAT_LLM_KEY::'.length);
Expand All @@ -46,7 +57,8 @@ export function detectProvider(key: string): EmbeddingProvider {
}
if (key.startsWith('vck_')) return vercel;
if (key.startsWith('sk-')) return openai;
if (key.startsWith('di_')) return deepinfra;
throw new Error(
`Unrecognized LAT_LLM_KEY prefix. Supported: OpenAI (sk-...), Vercel AI Gateway (vck_...).`,
`Unrecognized LAT_LLM_KEY prefix. Supported: OpenAI (sk-...), Vercel AI Gateway (vck_...), DeepInfra (di_...).`,
);
}
10 changes: 10 additions & 0 deletions tests/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ describe('detectProvider', () => {
expect(p.name).toBe('vercel');
});

it('detects DeepInfra key', () => {
const p = detectProvider('di_abc123');
expect(p.name).toBe('deepinfra');
});

it('strips di_ prefix from DeepInfra key in Authorization header', () => {
const p = detectProvider('di_abc123');
expect(p.headers('di_abc123').Authorization).toBe('Bearer abc123');
});

it('rejects Anthropic key with helpful message', () => {
expect(() => detectProvider('sk-ant-abc123')).toThrow(/Anthropic/);
});
Expand Down
Loading