Skip to content

[Bug] Plugin Not Detecting Chat Models - Missing nemotron and glm in categorizeModel() #7

@oliveiraantoniocc

Description

@oliveiraantoniocc

[Bug] OpenCode Plugin Not Detecting Chat Models - Incorrectly Classifies nemotron and glm as Unknown

Summary

The opencode-lmstudio plugin fails to detect certain chat models (nvidia/nemotron and zai-org/glm) as chat-capable models, resulting in a warning message that only embedding models are available even when valid chat models are loaded in LM Studio.

Current Behavior

When using LM Studio with OpenCode integration through the opencode-lmstudio plugin, users see this warning:

[opencode-lmstudio] Only embedding models found. To use chat models:
{
  steps: [
    "1. Open LM Studio application",
    "2. Download a chat model (e.g., llama-3.2-3b-instruct)",
    "3. Load the model in LM Studio",
    "4. Ensure server is running"
  ]
}

Even when valid chat models are already loaded and working:

  • nvidia/nemotron-3-nano
  • zai-org/glm-4.6v-flash
  • qwen/qwen3-vl-30b (this one works correctly)

Environment

  • OpenCode: Latest version (via Bun)
  • Plugin: opencode-lmstudio@0.3.0 (installed globally via bun add -g opencode-lmstudio)
  • LM Studio: Running locally on http://127.0.0.1:1234/v1
  • Available Models:
    • nvidia/nemotron-3-nano (chat model - NOT detected)
    • zai-org/glm-4.6v-flash (chat/vision model - NOT detected)
    • qwen/qwen3-vl-30b (chat/vision model - correctly detected)
    • text-embedding-nomic-embed-text-v1.5 (embedding model - correctly detected)

Root Cause Analysis

I analyzed the plugin source code and found the issue:

File: ~/.bun/install/global/node_modules/opencode-lmstudio/src/utils/index.ts
Function: categorizeModel() (lines 6-18)

export function categorizeModel(modelId: string): 'chat' | 'embedding' | 'unknown' {
  const lowerId = modelId.toLowerCase()
  if (lowerId.includes('embedding') || lowerId.includes('embed')) {
    return 'embedding'
  }
  if (lowerId.includes('gpt') || lowerId.includes('llama') || 
      lowerId.includes('claude') || lowerId.includes('qwen') ||
      lowerId.includes('mistral') || lowerId.includes('gemma') ||
      lowerId.includes('phi') || lowerId.includes('falcon')) {
    return 'chat'
  }
  return 'unknown'  // ← nemotron and glm fall through to here!
}

The Problem: The function only checks for specific model family names. Models like nvidia/nemotron-3-nano and zai-org/glm-4.6v-flash don't contain any of these keywords, so they're classified as 'unknown'.

File: src/plugin/enhance-config.ts (lines 70-108)

The plugin counts models by category when discovering them, but only counts newly discovered models. When models are pre-configured in opencode.json, they're in existingModels and skipped by the counting logic.

Additionally, on lines 122-131, the warning is triggered when chatModelsCount === 0 && embeddingModelsCount > 0, which happens when:

  1. All chat models are pre-configured (not counted as "discovered")
  2. Only the embedding model is newly discovered
  3. Result: Warning shown even though chat models exist

Steps to Reproduce

  1. Install LM Studio and load these models:

    • nvidia/nemotron-3-nano
    • zai-org/glm-4.6v-flash
    • qwen/qwen3-vl-30b
  2. Install opencode-lmstudio plugin:

    bun add -g opencode-lmstudio@latest
  3. Create opencode.json:

    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": ["opencode-lmstudio@latest"],
      "provider": {
        "lmstudio": {
          "npm": "@ai-sdk/openai-compatible",
          "name": "LM Studio",
          "options": {
            "baseURL": "http://127.0.0.1:1234/v1"
          }
        }
      }
    }
  4. Run OpenCode:

    opencode web
  5. Observe: Warning appears about only finding embedding models

  6. Verify models work:

    # Test with curl - works perfectly!
    curl -X POST http://localhost:1234/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "nvidia/nemotron-3-nano",
        "messages": [{"role": "user", "content": "Hello"}]
      }'
    # ✅ Returns valid response

Proposed Solution

Fix 1: Add Missing Model Families to categorizeModel()

File: src/utils/index.ts, lines 11-14

// Current:
if (lowerId.includes('gpt') || lowerId.includes('llama') || 
    lowerId.includes('claude') || lowerId.includes('qwen') ||
    lowerId.includes('mistral') || lowerId.includes('gemma') ||
    lowerId.includes('phi') || lowerId.includes('falcon')) {
  return 'chat'
}

// Proposed fix - add nemotron and glm:
if (lowerId.includes('gpt') || lowerId.includes('llama') || 
    lowerId.includes('claude') || lowerId.includes('qwen') ||
    lowerId.includes('mistral') || lowerId.includes('gemma') ||
    lowerId.includes('phi') || lowerId.includes('falcon') ||
    lowerId.includes('nemotron') || lowerId.includes('glm')) {  // ← ADD THESE
  return 'chat'
}

Fix 2: Count Existing Configured Models

File: src/plugin/enhance-config.ts, after line 68

// Add BEFORE the model discovery loop:
// First, count existing configured models
for (const existingKey of Object.keys(existingModels)) {
  const existingModel = existingModels[existingKey]
  const modelId = existingModel.id || existingKey
  const modelType = categorizeModel(modelId)
  if (modelType === 'chat') {
    chatModelsCount++
  } else if (modelType === 'embedding') {
    embeddingModelsCount++
  }
}

This ensures pre-configured models are counted, preventing false warnings.

Verification

After applying Fix 1 manually to test:

# Test script showing the fix works:
cat > /tmp/test-categorize.ts << 'EOF'
function categorizeModel(modelId: string): 'chat' | 'embedding' | 'unknown' {
  const lowerId = modelId.toLowerCase()
  if (lowerId.includes('embedding') || lowerId.includes('embed')) {
    return 'embedding'
  }
  if (lowerId.includes('gpt') || lowerId.includes('llama') || 
      lowerId.includes('claude') || lowerId.includes('qwen') ||
      lowerId.includes('mistral') || lowerId.includes('gemma') ||
      lowerId.includes('phi') || lowerId.includes('falcon') ||
      lowerId.includes('nemotron') || lowerId.includes('glm')) {
    return 'chat'
  }
  return 'unknown'
}

console.log('nvidia/nemotron-3-nano ->', categorizeModel('nvidia/nemotron-3-nano'))
console.log('zai-org/glm-4.6v-flash ->', categorizeModel('zai-org/glm-4.6v-flash'))
console.log('qwen/qwen3-vl-30b ->', categorizeModel('qwen/qwen3-vl-30b'))
EOF

bun run /tmp/test-categorize.ts

Output:

nvidia/nemotron-3-nano -> chat     ✅
zai-org/glm-4.6v-flash -> chat     ✅
qwen/qwen3-vl-30b -> chat          ✅

Impact

Who This Affects:

  • Users of LM Studio with OpenCode
  • Anyone using nvidia/nemotron or zhipu/glm model families
  • Anyone who pre-configures models in opencode.json

Current Workaround:
The models actually work fine! The warning is incorrect. Users can:

  1. Ignore the warning
  2. Manually specify models in config with explicit capabilities:
    "models": {
      "nvidia/nemotron-3-nano": {
        "id": "nvidia/nemotron-3-nano",
        "name": "Nemotron 3 Nano",
        "tool_call": true,
        "temperature": true
      }
    }

After Fix:

  • No false warnings
  • Automatic detection of more model families
  • Better user experience

Additional Context

Popular Models That Would Benefit:

  • NVIDIA Nemotron series (3B-70B+ parameters)
  • Zhipu AI GLM series (ChatGLM, GLM-4, etc.)
  • Future model families not in the hardcoded list

Suggested Long-Term Improvement:

Instead of hardcoding model names, consider using the LM Studio API's model metadata or a more flexible pattern matching approach that:

  1. Checks if the model supports /v1/chat/completions endpoint
  2. Looks for chat-related capabilities in the model metadata
  3. Falls back to embedding if it only supports /v1/embeddings

This would make the plugin more maintainable and future-proof.

Related


Labels: bug, opencode-lmstudio
Priority: Low (cosmetic warning, functionality works)

Let me know if you need any additional information or testing!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions