diff --git a/.changeset/cli-nano-gpt-router-models.md b/.changeset/cli-nano-gpt-router-models.md new file mode 100644 index 00000000000..649ef6b7056 --- /dev/null +++ b/.changeset/cli-nano-gpt-router-models.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Fix CLI `/model list` returning "No models available" for nano-gpt provider diff --git a/cli/src/commands/model.ts b/cli/src/commands/model.ts index c0a891612ef..fb92d5e31bc 100644 --- a/cli/src/commands/model.ts +++ b/cli/src/commands/model.ts @@ -57,6 +57,7 @@ async function ensureRouterModels(context: CommandContext): Promise { "io-intelligence", "vercel-ai-gateway", "ovhcloud", + "nano-gpt", ].includes(routerName) if (!needsRouterModels) { diff --git a/cli/src/constants/providers/__tests__/models.test.ts b/cli/src/constants/providers/__tests__/models.test.ts index 3141ee8e8c3..d4ea5da3d76 100644 --- a/cli/src/constants/providers/__tests__/models.test.ts +++ b/cli/src/constants/providers/__tests__/models.test.ts @@ -216,6 +216,20 @@ describe("Static Provider Models", () => { deepinfra: {}, "vercel-ai-gateway": {}, ovhcloud: {}, + "nano-gpt": { + "deepseek/deepseek-v3.2": { + contextWindow: 128000, + supportsPromptCache: false, + inputPrice: 0.14, + outputPrice: 0.28, + }, + "openai/gpt-4o": { + contextWindow: 128000, + supportsPromptCache: false, + inputPrice: 2.5, + outputPrice: 10, + }, + }, } it("should return router models for openrouter provider", () => { @@ -261,6 +275,41 @@ describe("Static Provider Models", () => { expect(result.models).toBeDefined() expect(Object.keys(result.models).length).toBe(0) }) + + describe("nano-gpt provider", () => { + it("should return router models for nano-gpt provider", () => { + const result = getModelsByProvider({ + provider: "nano-gpt", + routerModels: mockRouterModels, + kilocodeDefaultModel: "", + }) + + expect(result.models).toBe(mockRouterModels["nano-gpt"]) + expect(Object.keys(result.models)).toContain("deepseek/deepseek-v3.2") + expect(Object.keys(result.models)).toContain("openai/gpt-4o") + }) + + it("should return empty models when routerModels is null", () => { + const result = getModelsByProvider({ + provider: "nano-gpt", + routerModels: null, + kilocodeDefaultModel: "", + }) + + expect(result.models).toEqual({}) + }) + + it("should have correct default model for nano-gpt", () => { + const result = getModelsByProvider({ + provider: "nano-gpt", + routerModels: mockRouterModels, + kilocodeDefaultModel: "", + }) + + // Default model should be defined + expect(result.defaultModel).toBeDefined() + }) + }) }) describe("getModelsByProvider - Edge Cases", () => { @@ -350,6 +399,10 @@ describe("Static Provider Models", () => { expect(PROVIDER_TO_ROUTER_NAME.litellm).toBe("litellm") }) + it("should map nano-gpt to nano-gpt router name", () => { + expect(PROVIDER_TO_ROUTER_NAME["nano-gpt"]).toBe("nano-gpt") + }) + it("should map static providers to null", () => { expect(PROVIDER_TO_ROUTER_NAME.anthropic).toBeNull() expect(PROVIDER_TO_ROUTER_NAME.gemini).toBeNull() @@ -366,6 +419,10 @@ describe("Static Provider Models", () => { expect(providerSupportsModelList("litellm")).toBe(true) }) + it("should return true for nano-gpt provider", () => { + expect(providerSupportsModelList("nano-gpt")).toBe(true) + }) + it("should return false for static providers", () => { expect(providerSupportsModelList("anthropic")).toBe(false) expect(providerSupportsModelList("gemini")).toBe(false) @@ -380,6 +437,10 @@ describe("Static Provider Models", () => { expect(getRouterNameForProvider("ollama")).toBe("ollama") }) + it("should return nano-gpt for nano-gpt provider", () => { + expect(getRouterNameForProvider("nano-gpt")).toBe("nano-gpt") + }) + it("should return null for static providers", () => { expect(getRouterNameForProvider("anthropic")).toBeNull() expect(getRouterNameForProvider("gemini")).toBeNull() @@ -392,6 +453,10 @@ describe("Static Provider Models", () => { expect(getModelFieldForProvider("ollama")).toBe("ollamaModelId") }) + it("should return nanoGptModelId for nano-gpt provider", () => { + expect(getModelFieldForProvider("nano-gpt")).toBe("nanoGptModelId") + }) + it("should return null for static providers", () => { expect(getModelFieldForProvider("anthropic")).toBeNull() expect(getModelFieldForProvider("gemini")).toBeNull() diff --git a/cli/src/constants/providers/models.ts b/cli/src/constants/providers/models.ts index 20ba42460d1..61b361f5f38 100644 --- a/cli/src/constants/providers/models.ts +++ b/cli/src/constants/providers/models.ts @@ -66,6 +66,7 @@ export type RouterName = | "deepinfra" | "vercel-ai-gateway" | "ovhcloud" + | "nano-gpt" /** * ModelInfo interface - mirrors the one from packages/types/src/model.ts @@ -125,7 +126,7 @@ export const PROVIDER_TO_ROUTER_NAME: Record = lmstudio: "lmstudio", litellm: "litellm", glama: "glama", - "nano-gpt": null, + "nano-gpt": "nano-gpt", unbound: "unbound", requesty: "requesty", deepinfra: "deepinfra", @@ -461,6 +462,8 @@ export function getModelIdKey(provider: ProviderName): string { return "vercelAiGatewayModelId" case "ovhcloud": return "ovhCloudAiEndpointsModelId" + case "nano-gpt": + return "nanoGptModelId" default: return "apiModelId" }