Skip to content

Commit 9b4f62f

Browse files
Fix incorrect languageModel.enabled diagnostic warning on plugins (#343)
* Initial plan * Fix language model warning when enabled flag is absent Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> * Harden boolean checks for language model diagnostics Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> * Update language model plugin metadata per PR feedback Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> * fix: replace requiresLanguageModel with usesLanguageModel for correct plugins languageModel is optional, not required — it enhances output for plugins that can use a local model. Updated metadata to mark the three plugins that actually use it (OpenAIMockResponsePlugin, OpenApiSpecGeneratorPlugin, TypeSpecGeneratorPlugin) and downgraded diagnostic from Warning to Information. Fixes #342 * chore: remove .DS_Store files * docs: update changelog with language model diagnostic fix * Fix shell test by removing fs.existsSync stubbing Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> * docs: update README diagnostic and quick fix descriptions for language model * Fix Windows fixture path resolution in tests Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> * Harden fixture path lookup for Windows test runner Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> * Document local language model quick fix in README and changelog Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> * Move 1.13.0 quick-fix note to Added changelog section Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> Co-authored-by: Garry Trinder <garry@trinder365.co.uk>
1 parent a6bb2ef commit 9b4f62f

15 files changed

Lines changed: 72 additions & 83 deletions

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
1010
## [1.13.0] - Unreleased
1111

12+
### Added:
13+
14+
- Quick Fixes: Enable local language model fix now adds or updates `languageModel.enabled: true` for supported plugins only
15+
16+
### Fixed:
17+
18+
- Diagnostics: Language model diagnostic now correctly targets plugins that can use a local language model (OpenAIMockResponsePlugin, OpenApiSpecGeneratorPlugin, TypeSpecGeneratorPlugin) and shows as an informational hint instead of a warning
19+
1220
## [1.12.0] - 2026-01-29
1321

1422
### Added:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ Real-time validation of your configuration files. Click any diagnostic code to v
175175
| `invalidSchema` | Schema version doesn't match installed Dev Proxy |
176176
| `invalidConfigSection` | Config section not used by any plugin |
177177
| `deprecatedPluginPath` | Using old plugin DLL path (pre-v0.29) |
178-
| `missingLanguageModel` | Plugin requires language model configuration |
178+
| `missingLanguageModel` | Plugin can use a local language model to enhance its output |
179179
| `noEnabledPlugins` | No plugins are enabled |
180180
| `reporterPosition` | Reporter plugin should be last |
181181
| `summaryWithoutReporter` | Summary plugin needs a reporter |
@@ -196,7 +196,7 @@ One-click fixes for common issues:
196196
- **Update schema** - Match schema to installed Dev Proxy version (config file or config sections)
197197
- **Update plugin path** - Fix deprecated `dev-proxy-plugins.dll` paths (single or all at once)
198198
- **Remove unknown property** - Remove properties not defined in config section schema
199-
- **Add languageModel configuration** - Enable language model for AI plugins
199+
- **Enable local language model** - Add or update `languageModel.enabled: true` for plugins that support it
200200
- **Add plugin configuration** - Add optional config section for plugins that support it
201201
- **Add missing config section** - Create config section when plugin references one that doesn't exist
202202

src/code-actions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ function registerLanguageModelFixes(context: vscode.ExtensionContext) {
269269
}
270270

271271
const fix = new vscode.CodeAction(
272-
'Add languageModel configuration',
272+
'Enable local language model',
273273
vscode.CodeActionKind.QuickFix,
274274
);
275275

src/data/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export function getPluginDocUrl(name: string): string | undefined {
4848
*/
4949
export function getLanguageModelPlugins(): string[] {
5050
return Object.entries(pluginSnippets)
51-
.filter(([_, config]) => config.requiresLanguageModel)
51+
.filter(([_, config]) => config.usesLanguageModel)
5252
.map(([name]) => name);
5353
}
5454

src/data/plugins.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,14 @@
133133
"config": {
134134
"name": "devproxy-plugin-language-model-failure-config",
135135
"required": true
136-
},
137-
"requiresLanguageModel": true
136+
}
138137
},
139138
"LanguageModelRateLimitingPlugin": {
140139
"instance": "devproxy-plugin-language-model-rate-limiting",
141140
"config": {
142141
"name": "devproxy-plugin-language-model-rate-limiting-config",
143142
"required": true
144-
},
145-
"requiresLanguageModel": true
143+
}
146144
},
147145
"LatencyPlugin": {
148146
"instance": "devproxy-plugin-latency",
@@ -203,7 +201,8 @@
203201
"instance": "devproxy-plugin-odsp-search-guidance"
204202
},
205203
"OpenAIMockResponsePlugin": {
206-
"instance": "devproxy-plugin-openai-mock-response"
204+
"instance": "devproxy-plugin-openai-mock-response",
205+
"usesLanguageModel": true
207206
},
208207
"OpenAITelemetryPlugin": {
209208
"instance": "devproxy-plugin-openai-telemetry",
@@ -220,7 +219,8 @@
220219
"config": {
221220
"name": "devproxy-plugin-open-api-spec-generator-config",
222221
"required": false
223-
}
222+
},
223+
"usesLanguageModel": true
224224
},
225225
"RateLimitingPlugin": {
226226
"instance": "devproxy-plugin-rate-limiting",
@@ -244,7 +244,8 @@
244244
"config": {
245245
"name": "devproxy-plugin-typespec-generator-config",
246246
"required": false
247-
}
247+
},
248+
"usesLanguageModel": true
248249
},
249250
"UrlDiscoveryPlugin": {
250251
"instance": "devproxy-plugin-url-discovery"

src/data/plugins.schema.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@
4949
}
5050
}
5151
},
52-
"requiresLanguageModel": {
52+
"usesLanguageModel": {
5353
"type": "boolean",
54-
"description": "Whether the plugin requires a language model to be configured"
54+
"description": "Whether the plugin can use a local language model to enhance its output"
5555
}
5656
}
5757
},

src/diagnostics.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ function checkLanguageModelRequirements(
583583
const pluginName = (pluginNameNode.value as parse.LiteralNode).value as string;
584584
const pluginSnippet = pluginSnippets[pluginName];
585585

586-
if (!pluginSnippet?.requiresLanguageModel) {
586+
if (!pluginSnippet?.usesLanguageModel) {
587587
return;
588588
}
589589

@@ -599,8 +599,8 @@ function checkLanguageModelRequirements(
599599
if (isPluginEnabled && !isLanguageModelEnabled) {
600600
const diagnostic = new vscode.Diagnostic(
601601
getRangeFromASTNode(pluginNameNode.value),
602-
`${pluginName} requires languageModel.enabled to be set to true.`,
603-
vscode.DiagnosticSeverity.Warning,
602+
`${pluginName} can use a local language model to enhance its output. Add languageModel configuration to enable this.`,
603+
vscode.DiagnosticSeverity.Information,
604604
);
605605
diagnostic.code = getDiagnosticCode(DiagnosticCodes.missingLanguageModel);
606606
diagnostics.push(diagnostic);

src/test/code-actions.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ suite('Code Actions', () => {
372372
vscode.CodeActionKind.QuickFix.value
373373
);
374374

375-
const lmFix = codeActions?.find(a => a.title === 'Add languageModel configuration');
375+
const lmFix = codeActions?.find(a => a.title === 'Enable local language model');
376376
assert.strictEqual(lmFix, undefined, 'Should not provide fix without diagnostic');
377377
});
378378
});
@@ -506,7 +506,7 @@ suite('Language Model Code Action Logic', () => {
506506
const docContent = `{
507507
"plugins": [
508508
{
509-
"name": "LanguageModelFailurePlugin"
509+
"name": "OpenAIMockResponsePlugin"
510510
}
511511
],
512512
"languageModel": {
@@ -526,7 +526,7 @@ suite('Language Model Code Action Logic', () => {
526526
const docContent = `{
527527
"plugins": [
528528
{
529-
"name": "LanguageModelFailurePlugin"
529+
"name": "OpenAIMockResponsePlugin"
530530
}
531531
],
532532
"languageModel": {
@@ -546,7 +546,7 @@ suite('Language Model Code Action Logic', () => {
546546
const docContent = `{
547547
"plugins": [
548548
{
549-
"name": "LanguageModelFailurePlugin"
549+
"name": "OpenAIMockResponsePlugin"
550550
}
551551
]
552552
}`;

src/test/data.test.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,17 @@ suite('getLanguageModelPlugins', () => {
6262
assert.ok(Array.isArray(plugins), 'Should return an array');
6363
});
6464

65-
test('should include known language model plugins', () => {
65+
test('should include plugins that use a language model', () => {
6666
const plugins = getLanguageModelPlugins();
67-
assert.ok(
68-
plugins.includes('LanguageModelFailurePlugin'),
69-
'Should include LanguageModelFailurePlugin'
70-
);
71-
assert.ok(
72-
plugins.includes('LanguageModelRateLimitingPlugin'),
73-
'Should include LanguageModelRateLimitingPlugin'
74-
);
67+
assert.ok(plugins.includes('OpenAIMockResponsePlugin'), 'Should include OpenAIMockResponsePlugin');
68+
assert.ok(plugins.includes('OpenApiSpecGeneratorPlugin'), 'Should include OpenApiSpecGeneratorPlugin');
69+
assert.ok(plugins.includes('TypeSpecGeneratorPlugin'), 'Should include TypeSpecGeneratorPlugin');
70+
});
71+
72+
test('should not include language model failure and rate limiting plugins', () => {
73+
const plugins = getLanguageModelPlugins();
74+
assert.ok(!plugins.includes('LanguageModelFailurePlugin'));
75+
assert.ok(!plugins.includes('LanguageModelRateLimitingPlugin'));
7576
});
7677

7778
test('should not include non-language-model plugins', () => {

src/test/examples/config-language-model-disabled.json

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.29.0/rc.schema.json",
33
"plugins": [
44
{
5-
"name": "LanguageModelFailurePlugin",
5+
"name": "OpenAIMockResponsePlugin",
66
"enabled": true,
7-
"pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
8-
"configSection": "devproxy-plugin-language-model-failure-config"
7+
"pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll"
98
}
109
],
1110
"urlsToWatch": ["https://api.openai.com/*"],
1211
"logLevel": "information",
1312
"languageModel": {
1413
"enabled": false
15-
},
16-
"devproxy-plugin-language-model-failure-config": {
17-
"failureRate": 10
1814
}
1915
}

0 commit comments

Comments
 (0)