feat(llm): add native NanoGPT provider support (#131)

Align NanoGPT integration with the published OpenAI-compatible API contract, including model discovery, configuration/setup surfaces, and secret-redaction safeguards.\n\nFixes #129.
This commit is contained in:
robbee184-spec authored and GitHub committed 2026-07-30 22:58:45 -04:00
1 parent 8ccea7c82a
commit 8df967dd39
13 files changed
+264 -9

No files matched your search

+31 -2
View File
@@ -582,7 +582,7 @@ class AnthropicAdapter implements LLMProviderAdapter {
class OpenAIAdapter implements LLMProviderAdapter {
name = 'openai';
private config: LLMConfig;
protected config: LLMConfig;
constructor(config: LLMConfig) {
this.config = config;
@@ -683,6 +683,24 @@ class OpenAIAdapter implements LLMProviderAdapter {
}
}
// =============================================================================
// NANOGPT ADAPTER
// =============================================================================
class NanoGPTAdapter extends OpenAIAdapter {
name = 'nanogpt';
validateConfig(): { valid: boolean; error?: string } {
if (!this.config.apiKey) {
return {
valid: false,
error: 'NanoGPT API key is required. Set NANOGPT_API_KEY. Docs: https://docs.nano-gpt.com/authentication',
};
}
return { valid: true };
}
}
// =============================================================================
// MOCK ADAPTER (for testing)
// =============================================================================
@@ -1473,6 +1491,8 @@ export class LLMBackbone extends EventEmitter<LLMEvents> {
return new OpenAIAdapter(config); // DeepSeek native API is OpenAI-compatible
case 'huggingface':
return new OpenAIAdapter(config); // HF Inference Providers router is OpenAI-compatible (baseUrl ends in /v1)
case 'nanogpt':
return new NanoGPTAdapter(config);
case 'codex':
return new CodexAdapter(config);
case 'mock':
@@ -1773,6 +1793,12 @@ export function createHuggingFaceBackbone(apiKey?: string, model?: string): LLMB
return new LLMBackbone(llmConfig);
}
export function createNanoGPTBackbone(apiKey?: string, model?: string): LLMBackbone {
const llmConfig = config.getLLMConfig('nanogpt', model);
if (apiKey) llmConfig.apiKey = apiKey;
return new LLMBackbone(llmConfig);
}
export function createLiteLLMBackbone(apiKey?: string, model?: string, baseUrl?: string): LLMBackbone {
const llmConfig = config.getLLMConfig('litellm', model);
if (apiKey) llmConfig.apiKey = apiKey;
@@ -1803,7 +1829,7 @@ export function createLocalBackbone(model?: string, baseUrl?: string): LLMBackbo
* Create the best available backbone based on configured API keys
*/
export function createBestAvailableBackbone(): LLMBackbone {
// Priority: OpenRouter > Venice > LiteLLM > Anthropic > OpenAI > DeepSeek > HuggingFace > Local > Mock
// Priority: OpenRouter > Venice > LiteLLM > Anthropic > OpenAI > DeepSeek > HuggingFace > NanoGPT > Local > Mock
const providers = config.getConfiguredProviders();
if (providers.includes('openrouter')) {
@@ -1827,6 +1853,9 @@ export function createBestAvailableBackbone(): LLMBackbone {
if (providers.includes('huggingface')) {
return createHuggingFaceBackbone();
}
if (providers.includes('nanogpt')) {
return createNanoGPTBackbone();
}
// Default to mock if no API keys configured
console.warn('No API keys configured. Using mock provider.');