From be5181ef3148fefcf50caa309d9f2e92933bb186 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sat, 7 Feb 2026 15:16:51 -0800 Subject: [PATCH 1/7] feat: enable agent mode support for LM Studio models Add LM Studio to PROVIDER_TOOL_SUPPORT by referencing Ollama's tool support implementation. LM Studio uses an OpenAI-compatible API similar to Ollama, so the same model compatibility logic applies. Fixes #5182 --- core/llm/toolSupport.test.ts | 25 +++++++++++++++++++++++++ core/llm/toolSupport.ts | 1 + 2 files changed, 26 insertions(+) diff --git a/core/llm/toolSupport.test.ts b/core/llm/toolSupport.test.ts index 7981dac5f71..308d3ae7ed8 100644 --- a/core/llm/toolSupport.test.ts +++ b/core/llm/toolSupport.test.ts @@ -277,6 +277,30 @@ describe("PROVIDER_TOOL_SUPPORT", () => { }); }); + describe("lmstudio", () => { + const supportsFn = PROVIDER_TOOL_SUPPORT["lmstudio"]; + + it("should return true for supported models (same as ollama)", () => { + expect(supportsFn("llama3.1")).toBe(true); + expect(supportsFn("llama3.2-8b")).toBe(true); + expect(supportsFn("qwen2")).toBe(true); + expect(supportsFn("mixtral-8x7b")).toBe(true); + expect(supportsFn("mistral-7b")).toBe(true); + }); + + it("should return false for explicitly unsupported models (same as ollama)", () => { + expect(supportsFn("vision")).toBe(false); + expect(supportsFn("math")).toBe(false); + expect(supportsFn("guard")).toBe(false); + }); + + it("should handle case insensitivity (same as ollama)", () => { + expect(supportsFn("LLAMA3.1")).toBe(true); + expect(supportsFn("MIXTRAL-8x7b")).toBe(true); + expect(supportsFn("VISION")).toBe(false); + }); + }); + describe("xAI", () => { const supportsFn = PROVIDER_TOOL_SUPPORT["xAI"]; @@ -339,6 +363,7 @@ describe("PROVIDER_TOOL_SUPPORT", () => { expect(PROVIDER_TOOL_SUPPORT["gemini"]("")).toBe(false); expect(PROVIDER_TOOL_SUPPORT["bedrock"]("")).toBe(false); expect(PROVIDER_TOOL_SUPPORT["ollama"]("")).toBe(false); + expect(PROVIDER_TOOL_SUPPORT["lmstudio"]("")).toBe(false); expect(PROVIDER_TOOL_SUPPORT["novita"]("")).toBe(false); }); diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 6dd5592f0b4..818626c6aa4 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -189,6 +189,7 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = return false; }, + lmstudio: (model) => PROVIDER_TOOL_SUPPORT["ollama"](model), sambanova: (model) => { // https://docs.sambanova.ai/cloud/docs/capabilities/function-calling if ( From 71d355ec445f6c7b0855059def2b2e18756ec1d5 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sat, 7 Feb 2026 20:12:08 -0800 Subject: [PATCH 2/7] fix: normalize hyphenated model IDs for LM Studio tool support LM Studio uses hyphenated model identifiers (e.g., "Meta-Llama-3.1-8B-Instruct-GGUF"), but the Ollama heuristic checks for non-hyphenated patterns like "llama3.1". This fix normalizes hyphenated model names by removing hyphens before delegating to Ollama's tool support logic, enabling agent mode for LM Studio models with hyphenated IDs. Added comprehensive tests for hyphenated model names including: - Meta-Llama-3.1-8B-Instruct-GGUF - Qwen2-7B-Instruct - Mixtral-8x7B-Instruct-v0.1 - Case insensitivity checks - Negative tests for unsupported models like "Llama-Vision-Free" Addresses feedback from Cubic AI bot review. --- core/llm/toolSupport.test.ts | 21 +++++++++++++++++++++ core/llm/toolSupport.ts | 7 ++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/core/llm/toolSupport.test.ts b/core/llm/toolSupport.test.ts index 308d3ae7ed8..7d68e86159c 100644 --- a/core/llm/toolSupport.test.ts +++ b/core/llm/toolSupport.test.ts @@ -288,17 +288,38 @@ describe("PROVIDER_TOOL_SUPPORT", () => { expect(supportsFn("mistral-7b")).toBe(true); }); + it("should return true for LM Studio hyphenated model IDs", () => { + // LM Studio uses hyphenated model identifiers like "Meta-Llama-3.1-8B-Instruct-GGUF" + expect(supportsFn("Meta-Llama-3.1-8B-Instruct-GGUF")).toBe(true); + expect(supportsFn("Meta-Llama-3.2-3B-Instruct")).toBe(true); + expect(supportsFn("Qwen2-7B-Instruct")).toBe(true); + expect(supportsFn("Mixtral-8x7B-Instruct-v0.1")).toBe(true); + expect(supportsFn("Mistral-7B-Instruct-v0.2")).toBe(true); + expect(supportsFn("llama-3.1-8b-instruct")).toBe(true); + }); + it("should return false for explicitly unsupported models (same as ollama)", () => { expect(supportsFn("vision")).toBe(false); expect(supportsFn("math")).toBe(false); expect(supportsFn("guard")).toBe(false); }); + it("should return false for hyphenated unsupported model names", () => { + expect(supportsFn("Llama-Vision-Free")).toBe(false); + expect(supportsFn("Math-Solver-7B")).toBe(false); + expect(supportsFn("Guard-Model")).toBe(false); + }); + it("should handle case insensitivity (same as ollama)", () => { expect(supportsFn("LLAMA3.1")).toBe(true); expect(supportsFn("MIXTRAL-8x7b")).toBe(true); expect(supportsFn("VISION")).toBe(false); }); + + it("should handle case insensitivity with hyphenated names", () => { + expect(supportsFn("META-LLAMA-3.1-8B-INSTRUCT")).toBe(true); + expect(supportsFn("Qwen2-7B-Instruct-GGUF")).toBe(true); + }); }); describe("xAI", () => { diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 818626c6aa4..79302717bd9 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -189,7 +189,12 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = return false; }, - lmstudio: (model) => PROVIDER_TOOL_SUPPORT["ollama"](model), + lmstudio: (model) => { + // LM Studio uses hyphenated model IDs (e.g., "Meta-Llama-3.1-8B-Instruct-GGUF") + // Convert to format that matches Ollama's heuristic (e.g., "llama3.1") + const normalized = model.toLowerCase().replace(/-/g, ""); + return PROVIDER_TOOL_SUPPORT["ollama"](normalized); + }, sambanova: (model) => { // https://docs.sambanova.ai/cloud/docs/capabilities/function-calling if ( From 8b04ae1845e90b67aec9bc46474e28f9a4d43617 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sun, 8 Feb 2026 01:24:34 -0800 Subject: [PATCH 3/7] Fix LM Studio model ID tool support with proper hyphen normalization Improve the LM Studio tool support check to first verify exclusions on the original model ID before normalizing hyphens. This ensures that models like 'Mistral-Openorca-GGUF' are correctly excluded from tool support, while allowing hyphenated variants of supported models like 'Meta-Llama-3.1-8B-Instruct-GGUF'. The previous implementation would remove all hyphens before checking Ollama's heuristics, which could bypass exclusion rules for models like mistral-openorca. --- core/llm/toolSupport.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 79302717bd9..fc3fb65198c 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -191,7 +191,12 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = }, lmstudio: (model) => { // LM Studio uses hyphenated model IDs (e.g., "Meta-Llama-3.1-8B-Instruct-GGUF") - // Convert to format that matches Ollama's heuristic (e.g., "llama3.1") + // Check Ollama's exclusions first (before normalizing hyphens) + const ollamaResult = PROVIDER_TOOL_SUPPORT["ollama"](model); + if (!ollamaResult) { + return false; + } + // If Ollama says yes, also check with normalized version to catch hyphenated variants const normalized = model.toLowerCase().replace(/-/g, ""); return PROVIDER_TOOL_SUPPORT["ollama"](normalized); }, From 61471b37f9714e0d391481f6cc9c3b98a28ea83f Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sun, 8 Feb 2026 05:05:33 -0800 Subject: [PATCH 4/7] fix: check exclusions before early return in LM Studio tool support The LM Studio handler was checking Ollama's full heuristic (which doesn't match hyphenated names) before trying the normalized version. This caused hyphenated LM Studio model IDs like "Meta-Llama-3.1-8B-Instruct-GGUF" to be incorrectly rejected. Now checks exclusions separately first, then falls back to the normalized (hyphen-removed) name for Ollama's support check. --- core/llm/toolSupport.ts | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index fc3fb65198c..768f38d96f7 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -191,13 +191,29 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = }, lmstudio: (model) => { // LM Studio uses hyphenated model IDs (e.g., "Meta-Llama-3.1-8B-Instruct-GGUF") - // Check Ollama's exclusions first (before normalizing hyphens) - const ollamaResult = PROVIDER_TOOL_SUPPORT["ollama"](model); - if (!ollamaResult) { + // First check exclusions on both raw and normalized names + const lower = model.toLowerCase(); + const normalized = lower.replace(/-/g, ""); + const exclusions = ["vision", "math", "guard", "mistrallite"]; + if ( + exclusions.some( + (part) => lower.includes(part) || normalized.includes(part), + ) + ) { + return false; + } + // Check "mistral-openorca" specifically (hyphen-sensitive exclusion) + if ( + lower.includes("mistral-openorca") || + lower.includes("mistralopenorca") + ) { return false; } - // If Ollama says yes, also check with normalized version to catch hyphenated variants - const normalized = model.toLowerCase().replace(/-/g, ""); + // Try Ollama's support check with the raw model name first + if (PROVIDER_TOOL_SUPPORT["ollama"](model)) { + return true; + } + // Fall back to normalized (hyphen-removed) version for LM Studio's hyphenated IDs return PROVIDER_TOOL_SUPPORT["ollama"](normalized); }, sambanova: (model) => { From f83aeed2545a4ba3c35ff639b072acd3d82ee1c3 Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sun, 8 Feb 2026 05:20:12 -0800 Subject: [PATCH 5/7] fix: correct model ID normalization order for LM Studio Check exclusions on both raw and normalized (hyphen-stripped) model names before delegating to Ollama's heuristic. This ensures: 1. Hyphenated exclusions like "mistral-openorca" are caught on the raw name 2. Non-hyphenated variants like "MistralOpenOrca" are caught on the normalized name before the "mistral" support pattern matches 3. Hyphenated LM Studio IDs like "Meta-Llama-3.1-8B" still get detected via the normalized fallback to Ollama --- core/llm/toolSupport.test.ts | 11 +++++++++++ core/llm/toolSupport.ts | 32 +++++++++++++++++++------------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/core/llm/toolSupport.test.ts b/core/llm/toolSupport.test.ts index 7d68e86159c..0b47e4f58a5 100644 --- a/core/llm/toolSupport.test.ts +++ b/core/llm/toolSupport.test.ts @@ -302,6 +302,17 @@ describe("PROVIDER_TOOL_SUPPORT", () => { expect(supportsFn("vision")).toBe(false); expect(supportsFn("math")).toBe(false); expect(supportsFn("guard")).toBe(false); + expect(supportsFn("mistrallite")).toBe(false); + expect(supportsFn("mistral-openorca")).toBe(false); + }); + + it("should return false for mistral-openorca in all forms", () => { + // Hyphenated form (matches Ollama's exclusion directly) + expect(supportsFn("mistral-openorca")).toBe(false); + // Non-hyphenated form (must not bypass exclusion via "mistral" support match) + expect(supportsFn("MistralOpenOrca")).toBe(false); + // With suffix + expect(supportsFn("Mistral-OpenOrca-7B")).toBe(false); }); it("should return false for hyphenated unsupported model names", () => { diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 768f38d96f7..3269e585a3b 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -191,30 +191,36 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = }, lmstudio: (model) => { // LM Studio uses hyphenated model IDs (e.g., "Meta-Llama-3.1-8B-Instruct-GGUF") - // First check exclusions on both raw and normalized names + // that don't match Ollama's substring patterns (e.g., "llama3.1"). + // Strategy: check exclusions on both raw and normalized forms first, + // then try Ollama's heuristic with both raw and normalized forms. const lower = model.toLowerCase(); const normalized = lower.replace(/-/g, ""); - const exclusions = ["vision", "math", "guard", "mistrallite"]; + + // 1. Check exclusions on both raw and normalized names. + // Ollama's exclusion list uses "mistral-openorca" (with hyphen), + // so we must also check the hyphen-stripped form "mistralopenorca" + // to catch models like "MistralOpenOrca". if ( - exclusions.some( - (part) => lower.includes(part) || normalized.includes(part), + ["vision", "math", "guard", "mistrallite", "mistral-openorca"].some( + (part) => lower.includes(part), ) ) { return false; } - // Check "mistral-openorca" specifically (hyphen-sensitive exclusion) - if ( - lower.includes("mistral-openorca") || - lower.includes("mistralopenorca") - ) { + if (normalized.includes("mistralopenorca")) { return false; } - // Try Ollama's support check with the raw model name first - if (PROVIDER_TOOL_SUPPORT["ollama"](model)) { + + // 2. Try Ollama's heuristic with the raw name first + const ollamaFn = PROVIDER_TOOL_SUPPORT["ollama"]; + if (ollamaFn(model)) { return true; } - // Fall back to normalized (hyphen-removed) version for LM Studio's hyphenated IDs - return PROVIDER_TOOL_SUPPORT["ollama"](normalized); + + // 3. Fall back to normalized (hyphen-stripped) name for LM Studio IDs + // e.g., "Meta-Llama-3.1-8B" → "metallama3.18b" matches "llama3.1" + return ollamaFn(normalized); }, sambanova: (model) => { // https://docs.sambanova.ai/cloud/docs/capabilities/function-calling From dc47a957d11a5c8e586db5b8346d998e2302815d Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sun, 8 Feb 2026 10:09:33 -0800 Subject: [PATCH 6/7] fix: check exclusions on both raw and normalized model names for LM Studio The exclusion check only tested the lowercased model name, missing cases where hyphenated names like "Mistral-Lite" normalize to "mistrallite" which should match the exclusion pattern. --- core/llm/toolSupport.test.ts | 6 ++++++ core/llm/toolSupport.ts | 15 ++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/core/llm/toolSupport.test.ts b/core/llm/toolSupport.test.ts index 0b47e4f58a5..5be68bfa21c 100644 --- a/core/llm/toolSupport.test.ts +++ b/core/llm/toolSupport.test.ts @@ -321,6 +321,12 @@ describe("PROVIDER_TOOL_SUPPORT", () => { expect(supportsFn("Guard-Model")).toBe(false); }); + it("should return false for mistrallite in hyphenated forms", () => { + // Hyphenated form "mistral-lite" normalizes to "mistrallite" which must be excluded + expect(supportsFn("Mistral-Lite")).toBe(false); + expect(supportsFn("mistral-lite")).toBe(false); + }); + it("should handle case insensitivity (same as ollama)", () => { expect(supportsFn("LLAMA3.1")).toBe(true); expect(supportsFn("MIXTRAL-8x7b")).toBe(true); diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 3269e585a3b..6ed91c2b4e2 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -201,16 +201,21 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = // Ollama's exclusion list uses "mistral-openorca" (with hyphen), // so we must also check the hyphen-stripped form "mistralopenorca" // to catch models like "MistralOpenOrca". + const exclusions = [ + "vision", + "math", + "guard", + "mistrallite", + "mistral-openorca", + ]; if ( - ["vision", "math", "guard", "mistrallite", "mistral-openorca"].some( - (part) => lower.includes(part), + exclusions.some( + (part) => + lower.includes(part) || normalized.includes(part.replace(/-/g, "")), ) ) { return false; } - if (normalized.includes("mistralopenorca")) { - return false; - } // 2. Try Ollama's heuristic with the raw name first const ollamaFn = PROVIDER_TOOL_SUPPORT["ollama"]; From cfff26f5220df2197cc15b68497cc5e2a7c80a8f Mon Sep 17 00:00:00 2001 From: Varun Chawla Date: Sun, 8 Feb 2026 12:11:01 -0800 Subject: [PATCH 7/7] fix: check exclusions against both raw and normalized model IDs for LM Studio Extract isExcluded helper that tests a given name against each exclusion pattern in both its original and hyphen-stripped forms. Call it with both the raw lowercased model name and the normalized (hyphen-stripped) form so that e.g. "mistral-lite" is correctly caught by the "mistrallite" exclusion regardless of which path is evaluated. --- core/llm/toolSupport.ts | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/core/llm/toolSupport.ts b/core/llm/toolSupport.ts index 6ed91c2b4e2..dfee0889521 100644 --- a/core/llm/toolSupport.ts +++ b/core/llm/toolSupport.ts @@ -192,15 +192,16 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = lmstudio: (model) => { // LM Studio uses hyphenated model IDs (e.g., "Meta-Llama-3.1-8B-Instruct-GGUF") // that don't match Ollama's substring patterns (e.g., "llama3.1"). - // Strategy: check exclusions on both raw and normalized forms first, - // then try Ollama's heuristic with both raw and normalized forms. + // We check exclusions against BOTH the raw lowercased name and the + // normalized (hyphen-stripped) form so that e.g. "mistral-lite" + // is correctly caught by the "mistrallite" exclusion. const lower = model.toLowerCase(); const normalized = lower.replace(/-/g, ""); - // 1. Check exclusions on both raw and normalized names. - // Ollama's exclusion list uses "mistral-openorca" (with hyphen), - // so we must also check the hyphen-stripped form "mistralopenorca" - // to catch models like "MistralOpenOrca". + // Exclusions must be checked against both raw and normalized IDs. + // "mistrallite" catches both "mistrallite" (raw) and "mistral-lite" + // (normalized → "mistrallite"). "mistral-openorca" catches both the + // hyphenated form and "MistralOpenOrca" (normalized → "mistralopenorca"). const exclusions = [ "vision", "math", @@ -208,24 +209,21 @@ export const PROVIDER_TOOL_SUPPORT: Record boolean> = "mistrallite", "mistral-openorca", ]; - if ( + const isExcluded = (name: string) => exclusions.some( (part) => - lower.includes(part) || normalized.includes(part.replace(/-/g, "")), - ) - ) { + name.includes(part) || name.includes(part.replace(/-/g, "")), + ); + + if (isExcluded(lower) || isExcluded(normalized)) { return false; } - // 2. Try Ollama's heuristic with the raw name first + // Delegate to Ollama's heuristic with raw name first (covers patterns + // that contain hyphens, e.g. "command-r"), then with the normalized + // name (covers LM Studio IDs like "Meta-Llama-3.1-8B" → "llama3.1"). const ollamaFn = PROVIDER_TOOL_SUPPORT["ollama"]; - if (ollamaFn(model)) { - return true; - } - - // 3. Fall back to normalized (hyphen-stripped) name for LM Studio IDs - // e.g., "Meta-Llama-3.1-8B" → "metallama3.18b" matches "llama3.1" - return ollamaFn(normalized); + return ollamaFn(model) || ollamaFn(normalized); }, sambanova: (model) => { // https://docs.sambanova.ai/cloud/docs/capabilities/function-calling