Skip to content

Commit

Permalink
fix(Inline Edit): removes reasoning models from selector (#7238)
Browse files Browse the repository at this point in the history
This PR addresses the issue where models with reasoning capabilities
were causing edits to fail when selected in the Inline Edit model
selector.

Changes Made

- Added logic to filter out the ModelUsage.Edit capability from any
model that has the reasoning capability Introduced new model
capabilities reasoning and tools to properly identify models with these
features Added corresponding model tags Reasoning and Tools to the tag
enum Updated code to maintain the model capabilities but selectively
remove edit usage when reasoning is detected Added entry to the
changelog to document this fix
- Implementation Details
- The core fix is implemented by checking if a model's capabilities
include 'reasoning' and, if so, removing the Edit usage from that
model's available usages. This prevents reasoning-enabled models from
appearing in the Inline Edit model selector while maintaining their
availability for chat and other supported features.

## Test Plan

The change has been tested to ensure that:

- Reasoning models no longer appear in the Inline Edit model selector 
- Reasoning models remain available for chat and other supported
features
- Non-reasoning models with edit capability still work as expected

Before - connect to dotcom and open the inline edit model selector, 3.7
sonnet is listed in the dropdown


![image](https://github.com/user-attachments/assets/585dc922-5eb1-4009-8e03-28826013c4f4)


After - 3.7 removed


![image](https://github.com/user-attachments/assets/df30e861-08a1-4b1d-a9b3-545635f280a4)
  • Loading branch information
abeatrix authored Feb 25, 2025
1 parent 2332872 commit a7ec5fb
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ object Constants {
const val power = "power"
const val priority = "priority"
const val pro = "pro"
const val reasoning = "reasoning"
const val `recently-used` = "recently used"
const val recommended = "recommended"
const val `rename-file` = "rename-file"
Expand All @@ -95,6 +96,7 @@ object Constants {
const val system = "system"
const val terminal = "terminal"
const val tool = "tool"
const val tools = "tools"
const val trace = "trace"
const val tree = "tree"
const val `tree-sitter` = "tree-sitter"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@file:Suppress("FunctionName", "ClassName", "unused", "EnumEntryName", "UnusedImport")
package com.sourcegraph.cody.agent.protocol_generated;

typealias ModelTag = String // One of: power, speed, balanced, other, recommended, deprecated, experimental, waitlist, on-waitlist, early-access, internal, pro, free, enterprise, gateway, byok, local, ollama, dev, stream-disabled, vision
typealias ModelTag = String // One of: power, speed, balanced, other, recommended, deprecated, experimental, waitlist, on-waitlist, early-access, internal, pro, free, enterprise, gateway, byok, local, ollama, dev, stream-disabled, vision, reasoning, tools

83 changes: 81 additions & 2 deletions lib/shared/src/models/model.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { ModelTag } from '..'
import { getServerModelTags, toLegacyModel } from './model'
import { ModelTag, ModelUsage } from '..'
import { type ServerModel, createModelFromServerModel, getServerModelTags, toLegacyModel } from './model'

describe('getServerModelTags', () => {
it('returns basic tags for a standard model', () => {
Expand Down Expand Up @@ -59,3 +59,82 @@ describe('toLegacyModel', () => {
expect(toLegacyModel('a::b:c')).toBe('a::b:c')
})
})

describe('createModelFromServerModel', () => {
it('removes Edit usage from models with reasoning capability', () => {
// Arrange - model with both reasoning and edit capabilities
const reasoningEditModel = {
modelRef: 'anthropic::1::claude-3-sonnet',
displayName: 'Claude 3 Sonnet',
modelName: 'claude-3-sonnet',
capabilities: ['reasoning', 'edit', 'chat'],
category: 'accuracy',
status: 'stable',
tier: ModelTag.Pro,
contextWindow: {
maxInputTokens: 100000,
maxOutputTokens: 4000,
},
} satisfies ServerModel

// Act
const result = createModelFromServerModel(reasoningEditModel)

// Assert
expect(result.usage).toContain(ModelUsage.Chat)
expect(result.usage).not.toContain(ModelUsage.Edit)
expect(result.tags).toContain(ModelTag.Power) // Check that other attributes are preserved
})

it('preserves Edit usage for models without reasoning capability', () => {
// Arrange - similar model but without reasoning capability
const editOnlyModel = {
modelRef: 'anthropic::1::claude-instant',
displayName: 'Claude Instant',
modelName: 'claude-instant',
capabilities: ['edit', 'chat'],
category: ModelTag.Speed,
status: 'stable',
tier: ModelTag.Pro,
contextWindow: {
maxInputTokens: 100000,
maxOutputTokens: 4000,
},
} satisfies ServerModel

// Act
const result = createModelFromServerModel(editOnlyModel)

// Assert
expect(result.usage).toContain(ModelUsage.Edit)
expect(result.usage).toContain(ModelUsage.Chat)
})

it('correctly handles models with reasoning but no edit capability', () => {
// Arrange - model with reasoning but no edit capability
const reasoningOnlyModel = {
modelRef: 'anthropic::1::claude-3-opus',
displayName: 'Claude 3 Opus',
modelName: 'claude-3-opus',
capabilities: ['reasoning', 'chat', 'edit'],
category: ModelTag.Power,
status: 'stable',
tier: ModelTag.Enterprise,
contextWindow: {
maxInputTokens: 100000,
maxOutputTokens: 4000,
},
} satisfies ServerModel

// Act
const result = createModelFromServerModel(reasoningOnlyModel)

// Assert
expect(result.usage).toContain(ModelUsage.Chat)
expect(result.usage).not.toContain(ModelUsage.Edit)
// Also check that reasoning is reflected in tags
expect(result.tags).toContain(ModelTag.Power)
expect(result.tags).toContain(ModelTag.Enterprise)
expect(result.tags).not.toContain(ModelUsage.Edit)
})
})
11 changes: 8 additions & 3 deletions lib/shared/src/models/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ export function createModelFromServerModel({
input: maxInputTokens,
output: maxOutputTokens,
}
const usage = capabilities.flatMap(capabilityToUsage)
// NOTE: Model with reasoning enabled should only be used for chat.
if (capabilities.includes('reasoning') && usage.includes(ModelUsage.Edit)) {
usage.splice(usage.indexOf(ModelUsage.Edit), 1)
}
// Use Extended Context Window
if (maxInputTokens === EXTENDED_CHAT_INPUT_TOKEN_BUDGET + EXTENDED_USER_CONTEXT_TOKEN_BUDGET) {
_contextWindow.input = EXTENDED_CHAT_INPUT_TOKEN_BUDGET
Expand All @@ -151,7 +156,7 @@ export function createModelFromServerModel({
return createModel({
id: modelRef,
modelRef: ref,
usage: capabilities.flatMap(capabilityToUsage),
usage,
contextWindow: _contextWindow,
clientSideConfig,
tags: getServerModelTags(capabilities, category, status, tier),
Expand All @@ -164,11 +169,11 @@ function capabilityToUsage(capability: ModelCapability): ModelUsage[] {
switch (capability) {
case 'autocomplete':
return [ModelUsage.Autocomplete]
case 'edit':
return [ModelUsage.Edit]
case 'chat':
return [ModelUsage.Chat]
// unknown capability should be handled as tags.
case 'edit':
return [ModelUsage.Edit]
default:
return []
}
Expand Down
3 changes: 2 additions & 1 deletion lib/shared/src/models/modelsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export type ModelStatus =
| ModelTag.Deprecated
| ModelTag.Internal
export type ModelTier = ModelTag.Free | ModelTag.Pro | ModelTag.Enterprise
export type ModelCapability = 'chat' | 'autocomplete' | 'edit' | 'vision'
/** Must match types on github.com/sourcegraph/sourcegraph/-/blob/internal/modelconfig/types/model.go */
export type ModelCapability = 'chat' | 'autocomplete' | 'edit' | 'vision' | 'reasoning' | 'tools'

export interface ContextWindow {
maxInputTokens: number
Expand Down
2 changes: 2 additions & 0 deletions lib/shared/src/models/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ export enum ModelTag {
// Additional Info about the model. e.g. capabilities
StreamDisabled = 'stream-disabled', // Model does not support streaming
Vision = 'vision', // Model supports vision capabilities
Reasoning = 'reasoning', // Model supports reasoning capabilities
Tools = 'tools', // Model supports tools capabilities
}
7 changes: 7 additions & 0 deletions vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ This is a log of all notable changes to Cody for VS Code.

<!--- {/_ CHANGELOG_START _/} -->

## Unreleased

### Fix

- Remove reasoning models from Inline Edit model selector that could cause edits to fail. [#7238](https://github.com/sourcegraph/cody/pull/7238)

## 1.70.3

### Refactor
Expand All @@ -15,6 +21,7 @@ This is a log of all notable changes to Cody for VS Code.
### Features

#### Webview

- Add support for <think> tags in Chat Message [#6845](https://github.com/sourcegraph/cody/pull/6845)

## 1.70.2
Expand Down

0 comments on commit a7ec5fb

Please sign in to comment.