Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
57 changes: 57 additions & 0 deletions core/llm/toolSupport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,62 @@ 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 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);
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", () => {
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", () => {
const supportsFn = PROVIDER_TOOL_SUPPORT["xAI"];

Expand Down Expand Up @@ -339,6 +395,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);
});

Expand Down
33 changes: 33 additions & 0 deletions core/llm/toolSupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,39 @@ export const PROVIDER_TOOL_SUPPORT: Record<string, (model: string) => boolean> =

return false;
},
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.
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".
if (
["vision", "math", "guard", "mistrallite", "mistral-openorca"].some(
(part) => lower.includes(part),
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated
)
) {
return false;
}
if (normalized.includes("mistralopenorca")) {
return false;
}

// 2. Try Ollama's heuristic with the raw name first
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);
},
sambanova: (model) => {
// https://docs.sambanova.ai/cloud/docs/capabilities/function-calling
if (
Expand Down
Loading