From 6244ea9fdfcb9dc2ed533701a4b81ce75d982ed9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:51:45 +0000 Subject: [PATCH 01/13] Initial plan From 7632e7cd6a4a6d31dde5c625df8d4e4b68670580 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:59:06 +0000 Subject: [PATCH 02/13] Fix language model warning when enabled flag is absent Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- src/diagnostics.ts | 9 ++++++--- src/test/schema.test.ts | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 6775433..b64381c 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -554,7 +554,7 @@ function checkLanguageModelRequirements( 'Identifier', 'languageModel' ); - let isLanguageModelEnabled = false; + let isLanguageModelEnabled: boolean | undefined; if (languageModelNode && languageModelNode.value.type === 'Object') { const languageModelObjectNode = languageModelNode.value as parse.ObjectNode; @@ -564,7 +564,10 @@ function checkLanguageModelRequirements( 'enabled' ); if (enabledNode && enabledNode.value.type === 'Literal') { - isLanguageModelEnabled = (enabledNode.value as parse.LiteralNode).value as boolean; + const enabledValue = (enabledNode.value as parse.LiteralNode).value; + if (typeof enabledValue === 'boolean') { + isLanguageModelEnabled = enabledValue; + } } } @@ -596,7 +599,7 @@ function checkLanguageModelRequirements( const isPluginEnabled = enabledNode ? (enabledNode.value as parse.LiteralNode).value as boolean : false; - if (isPluginEnabled && !isLanguageModelEnabled) { + if (isPluginEnabled && isLanguageModelEnabled === false) { const diagnostic = new vscode.Diagnostic( getRangeFromASTNode(pluginNameNode.value), `${pluginName} requires languageModel.enabled to be set to true.`, diff --git a/src/test/schema.test.ts b/src/test/schema.test.ts index 646e335..fc275ce 100644 --- a/src/test/schema.test.ts +++ b/src/test/schema.test.ts @@ -97,6 +97,28 @@ suite('schema', () => { }; assert.deepStrictEqual(actual, expected); }); + + test('should not show warning for language model plugins when languageModel.enabled is missing', async () => { + const fileName = 'config-language-model-required.json'; + const filePath = getFixturePath(fileName); + const document = await vscode.workspace.openTextDocument(filePath); + await sleep(1000); + const diagnostics = vscode.languages.getDiagnostics(document.uri); + + const missingLanguageModelDiagnostics = diagnostics.filter(d => { + const code = + typeof d.code === 'object' && d.code !== null + ? (d.code as { value: string }).value + : d.code; + return code === 'missingLanguageModel'; + }); + + assert.strictEqual( + missingLanguageModelDiagnostics.length, + 0, + 'Should not have missingLanguageModel diagnostics when languageModel.enabled is missing' + ); + }); }); suite('config section schema validation', () => { From b25d4c68cec24928f003d9c2f1fd7191133e9e50 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:01:18 +0000 Subject: [PATCH 03/13] Harden boolean checks for language model diagnostics Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- src/diagnostics.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/diagnostics.ts b/src/diagnostics.ts index b64381c..9a3dac1 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -596,8 +596,13 @@ function checkLanguageModelRequirements( 'Identifier', 'enabled', ); - const isPluginEnabled = enabledNode ? - (enabledNode.value as parse.LiteralNode).value as boolean : false; + let isPluginEnabled = false; + if (enabledNode && enabledNode.value.type === 'Literal') { + const enabledValue = (enabledNode.value as parse.LiteralNode).value; + if (typeof enabledValue === 'boolean') { + isPluginEnabled = enabledValue; + } + } if (isPluginEnabled && isLanguageModelEnabled === false) { const diagnostic = new vscode.Diagnostic( From df82a58d3cd869686d150479013a638e2e54d34e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:12:46 +0000 Subject: [PATCH 04/13] Update language model plugin metadata per PR feedback Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- src/data/plugins.json | 6 ++---- src/diagnostics.ts | 18 +++++------------- src/test/data.test.ts | 12 +++--------- src/test/schema.test.ts | 22 ---------------------- 4 files changed, 10 insertions(+), 48 deletions(-) diff --git a/src/data/plugins.json b/src/data/plugins.json index 3e04f90..e65c2b0 100644 --- a/src/data/plugins.json +++ b/src/data/plugins.json @@ -133,16 +133,14 @@ "config": { "name": "devproxy-plugin-language-model-failure-config", "required": true - }, - "requiresLanguageModel": true + } }, "LanguageModelRateLimitingPlugin": { "instance": "devproxy-plugin-language-model-rate-limiting", "config": { "name": "devproxy-plugin-language-model-rate-limiting-config", "required": true - }, - "requiresLanguageModel": true + } }, "LatencyPlugin": { "instance": "devproxy-plugin-latency", diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 9a3dac1..6775433 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -554,7 +554,7 @@ function checkLanguageModelRequirements( 'Identifier', 'languageModel' ); - let isLanguageModelEnabled: boolean | undefined; + let isLanguageModelEnabled = false; if (languageModelNode && languageModelNode.value.type === 'Object') { const languageModelObjectNode = languageModelNode.value as parse.ObjectNode; @@ -564,10 +564,7 @@ function checkLanguageModelRequirements( 'enabled' ); if (enabledNode && enabledNode.value.type === 'Literal') { - const enabledValue = (enabledNode.value as parse.LiteralNode).value; - if (typeof enabledValue === 'boolean') { - isLanguageModelEnabled = enabledValue; - } + isLanguageModelEnabled = (enabledNode.value as parse.LiteralNode).value as boolean; } } @@ -596,15 +593,10 @@ function checkLanguageModelRequirements( 'Identifier', 'enabled', ); - let isPluginEnabled = false; - if (enabledNode && enabledNode.value.type === 'Literal') { - const enabledValue = (enabledNode.value as parse.LiteralNode).value; - if (typeof enabledValue === 'boolean') { - isPluginEnabled = enabledValue; - } - } + const isPluginEnabled = enabledNode ? + (enabledNode.value as parse.LiteralNode).value as boolean : false; - if (isPluginEnabled && isLanguageModelEnabled === false) { + if (isPluginEnabled && !isLanguageModelEnabled) { const diagnostic = new vscode.Diagnostic( getRangeFromASTNode(pluginNameNode.value), `${pluginName} requires languageModel.enabled to be set to true.`, diff --git a/src/test/data.test.ts b/src/test/data.test.ts index 941a9ab..cb72d00 100644 --- a/src/test/data.test.ts +++ b/src/test/data.test.ts @@ -62,16 +62,10 @@ suite('getLanguageModelPlugins', () => { assert.ok(Array.isArray(plugins), 'Should return an array'); }); - test('should include known language model plugins', () => { + test('should not include language model failure and rate limiting plugins', () => { const plugins = getLanguageModelPlugins(); - assert.ok( - plugins.includes('LanguageModelFailurePlugin'), - 'Should include LanguageModelFailurePlugin' - ); - assert.ok( - plugins.includes('LanguageModelRateLimitingPlugin'), - 'Should include LanguageModelRateLimitingPlugin' - ); + assert.ok(!plugins.includes('LanguageModelFailurePlugin')); + assert.ok(!plugins.includes('LanguageModelRateLimitingPlugin')); }); test('should not include non-language-model plugins', () => { diff --git a/src/test/schema.test.ts b/src/test/schema.test.ts index fc275ce..646e335 100644 --- a/src/test/schema.test.ts +++ b/src/test/schema.test.ts @@ -97,28 +97,6 @@ suite('schema', () => { }; assert.deepStrictEqual(actual, expected); }); - - test('should not show warning for language model plugins when languageModel.enabled is missing', async () => { - const fileName = 'config-language-model-required.json'; - const filePath = getFixturePath(fileName); - const document = await vscode.workspace.openTextDocument(filePath); - await sleep(1000); - const diagnostics = vscode.languages.getDiagnostics(document.uri); - - const missingLanguageModelDiagnostics = diagnostics.filter(d => { - const code = - typeof d.code === 'object' && d.code !== null - ? (d.code as { value: string }).value - : d.code; - return code === 'missingLanguageModel'; - }); - - assert.strictEqual( - missingLanguageModelDiagnostics.length, - 0, - 'Should not have missingLanguageModel diagnostics when languageModel.enabled is missing' - ); - }); }); suite('config section schema validation', () => { From 0c301c620b199c57863992267ff191bd311a3d46 Mon Sep 17 00:00:00 2001 From: Garry Trinder Date: Thu, 26 Feb 2026 17:42:33 +0000 Subject: [PATCH 05/13] fix: replace requiresLanguageModel with usesLanguageModel for correct plugins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .DS_Store | Bin 0 -> 6148 bytes src/.DS_Store | Bin 0 -> 6148 bytes src/code-actions.ts | 2 +- src/data/index.ts | 2 +- src/data/plugins.json | 9 ++++++--- src/data/plugins.schema.json | 4 ++-- src/diagnostics.ts | 6 +++--- src/test/.DS_Store | Bin 0 -> 6148 bytes src/test/code-actions.test.ts | 8 ++++---- src/test/data.test.ts | 7 +++++++ .../config-language-model-disabled.json | 8 ++------ .../config-language-model-enabled.json | 16 ++++------------ .../config-language-model-required.json | 18 +++++------------- src/types.ts | 2 +- 14 files changed, 36 insertions(+), 46 deletions(-) create mode 100644 .DS_Store create mode 100644 src/.DS_Store create mode 100644 src/test/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..81229e8d26382bd3469cb3d9bb2de3f1954844ac GIT binary patch literal 6148 zcmeH~Jqp4=5QS&dB4Cr!avKle4VIuM@B*S@B?yZB9^E%TjnP_yyn&f-XEsBUS7b9H zqQmpN5$Q#wgBxXSVPuMYE)TiO>2iLYjtb*@FJ*K=2U&T%hcRwa*e@u>x3=Er<$CqZN!+^)bZi z-VT<$t|nVB+C_8t(7dzS6a&*}7cEF&S{)2jfC`Khm`C2*`M-mIoBu~GOsN1B_%j7` zvE6S6yi}g8AFpTiLso6w;GkcQ@b(jc#E#+>+ztE17GO=bASy8a2)GOkRN$uyya2`( B5q1Co literal 0 HcmV?d00001 diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c3ac046f6c51a2cd4bc2df32c603e493458c382e GIT binary patch literal 6148 zcmeH~F^{dt=u>Bl;zddfqZjB=JE!l7EiIwCR znHYd=e=Zwf1hAw#vGy=AV?N-4FWm9?zTD5J+wJN_+D8XGrH`2G=e8gPq<|EV0#ZN< z%t(Pe#+RQndL})J6p#Y*P{6+rh3>4$))}7;h8O|Jf#oo+W0oL`7s#4yovhF-rw7Yc zi!sFO(N31Ut|nV&Z-?dZVR>isDTZdf9afmotOgXMfE1W0u;}^d=l`Dm-~2ymQ7Q$b zz?&&x!|t%#@}=@@{quTWKW5d}jZVhp3{O7+O#CQb(Zjf3d_mS^>tuzdAAyiTK?=N7 FfnTX=61e~X literal 0 HcmV?d00001 diff --git a/src/code-actions.ts b/src/code-actions.ts index 593a49a..26e389f 100644 --- a/src/code-actions.ts +++ b/src/code-actions.ts @@ -269,7 +269,7 @@ function registerLanguageModelFixes(context: vscode.ExtensionContext) { } const fix = new vscode.CodeAction( - 'Add languageModel configuration', + 'Enable local language model', vscode.CodeActionKind.QuickFix, ); diff --git a/src/data/index.ts b/src/data/index.ts index 155df5b..8942864 100644 --- a/src/data/index.ts +++ b/src/data/index.ts @@ -48,7 +48,7 @@ export function getPluginDocUrl(name: string): string | undefined { */ export function getLanguageModelPlugins(): string[] { return Object.entries(pluginSnippets) - .filter(([_, config]) => config.requiresLanguageModel) + .filter(([_, config]) => config.usesLanguageModel) .map(([name]) => name); } diff --git a/src/data/plugins.json b/src/data/plugins.json index e65c2b0..471274d 100644 --- a/src/data/plugins.json +++ b/src/data/plugins.json @@ -201,7 +201,8 @@ "instance": "devproxy-plugin-odsp-search-guidance" }, "OpenAIMockResponsePlugin": { - "instance": "devproxy-plugin-openai-mock-response" + "instance": "devproxy-plugin-openai-mock-response", + "usesLanguageModel": true }, "OpenAITelemetryPlugin": { "instance": "devproxy-plugin-openai-telemetry", @@ -218,7 +219,8 @@ "config": { "name": "devproxy-plugin-open-api-spec-generator-config", "required": false - } + }, + "usesLanguageModel": true }, "RateLimitingPlugin": { "instance": "devproxy-plugin-rate-limiting", @@ -242,7 +244,8 @@ "config": { "name": "devproxy-plugin-typespec-generator-config", "required": false - } + }, + "usesLanguageModel": true }, "UrlDiscoveryPlugin": { "instance": "devproxy-plugin-url-discovery" diff --git a/src/data/plugins.schema.json b/src/data/plugins.schema.json index df4d313..8e8ca5c 100644 --- a/src/data/plugins.schema.json +++ b/src/data/plugins.schema.json @@ -49,9 +49,9 @@ } } }, - "requiresLanguageModel": { + "usesLanguageModel": { "type": "boolean", - "description": "Whether the plugin requires a language model to be configured" + "description": "Whether the plugin can use a local language model to enhance its output" } } }, diff --git a/src/diagnostics.ts b/src/diagnostics.ts index 6775433..b4007f6 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -583,7 +583,7 @@ function checkLanguageModelRequirements( const pluginName = (pluginNameNode.value as parse.LiteralNode).value as string; const pluginSnippet = pluginSnippets[pluginName]; - if (!pluginSnippet?.requiresLanguageModel) { + if (!pluginSnippet?.usesLanguageModel) { return; } @@ -599,8 +599,8 @@ function checkLanguageModelRequirements( if (isPluginEnabled && !isLanguageModelEnabled) { const diagnostic = new vscode.Diagnostic( getRangeFromASTNode(pluginNameNode.value), - `${pluginName} requires languageModel.enabled to be set to true.`, - vscode.DiagnosticSeverity.Warning, + `${pluginName} can use a local language model to enhance its output. Add languageModel configuration to enable this.`, + vscode.DiagnosticSeverity.Information, ); diagnostic.code = getDiagnosticCode(DiagnosticCodes.missingLanguageModel); diagnostics.push(diagnostic); diff --git a/src/test/.DS_Store b/src/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..34c19f72621762b66da6b77134538776a4fc41fc GIT binary patch literal 6148 zcmeHKJ8r`;3?*9+2D*66s4Mgag5jQ^7f8~ilM5Fx3Uu_8bLD7#{0t4;Z0Qm_0@RZz zJ_&k*X^M#UUx#OrPDEO`p`2`3o9&yg>>(oxgyW1)8RaPR`(b`tW&a&8ZVS%0?BwG& ze?Lv5ZPKU!6`%rCfC^B7n<|jywSBtjsXUAdP=R|;z`hR!ZdenSK>u`L@D>2rAnb;@ z_Y%Nj0bosB0ug~}P=P_!Y%w(Gh?mT(iA!M6MYH+PyjinDQNJDM7f% { vscode.CodeActionKind.QuickFix.value ); - const lmFix = codeActions?.find(a => a.title === 'Add languageModel configuration'); + const lmFix = codeActions?.find(a => a.title === 'Enable local language model'); assert.strictEqual(lmFix, undefined, 'Should not provide fix without diagnostic'); }); }); @@ -506,7 +506,7 @@ suite('Language Model Code Action Logic', () => { const docContent = `{ "plugins": [ { - "name": "LanguageModelFailurePlugin" + "name": "OpenAIMockResponsePlugin" } ], "languageModel": { @@ -526,7 +526,7 @@ suite('Language Model Code Action Logic', () => { const docContent = `{ "plugins": [ { - "name": "LanguageModelFailurePlugin" + "name": "OpenAIMockResponsePlugin" } ], "languageModel": { @@ -546,7 +546,7 @@ suite('Language Model Code Action Logic', () => { const docContent = `{ "plugins": [ { - "name": "LanguageModelFailurePlugin" + "name": "OpenAIMockResponsePlugin" } ] }`; diff --git a/src/test/data.test.ts b/src/test/data.test.ts index cb72d00..83fdc43 100644 --- a/src/test/data.test.ts +++ b/src/test/data.test.ts @@ -62,6 +62,13 @@ suite('getLanguageModelPlugins', () => { assert.ok(Array.isArray(plugins), 'Should return an array'); }); + test('should include plugins that use a language model', () => { + const plugins = getLanguageModelPlugins(); + assert.ok(plugins.includes('OpenAIMockResponsePlugin'), 'Should include OpenAIMockResponsePlugin'); + assert.ok(plugins.includes('OpenApiSpecGeneratorPlugin'), 'Should include OpenApiSpecGeneratorPlugin'); + assert.ok(plugins.includes('TypeSpecGeneratorPlugin'), 'Should include TypeSpecGeneratorPlugin'); + }); + test('should not include language model failure and rate limiting plugins', () => { const plugins = getLanguageModelPlugins(); assert.ok(!plugins.includes('LanguageModelFailurePlugin')); diff --git a/src/test/examples/config-language-model-disabled.json b/src/test/examples/config-language-model-disabled.json index 2703a8b..b7841fd 100644 --- a/src/test/examples/config-language-model-disabled.json +++ b/src/test/examples/config-language-model-disabled.json @@ -2,18 +2,14 @@ "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.29.0/rc.schema.json", "plugins": [ { - "name": "LanguageModelFailurePlugin", + "name": "OpenAIMockResponsePlugin", "enabled": true, - "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", - "configSection": "devproxy-plugin-language-model-failure-config" + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" } ], "urlsToWatch": ["https://api.openai.com/*"], "logLevel": "information", "languageModel": { "enabled": false - }, - "devproxy-plugin-language-model-failure-config": { - "failureRate": 10 } } diff --git a/src/test/examples/config-language-model-enabled.json b/src/test/examples/config-language-model-enabled.json index 6641015..0c21b24 100644 --- a/src/test/examples/config-language-model-enabled.json +++ b/src/test/examples/config-language-model-enabled.json @@ -2,27 +2,19 @@ "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.29.0/rc.schema.json", "plugins": [ { - "name": "LanguageModelFailurePlugin", + "name": "OpenAIMockResponsePlugin", "enabled": true, - "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", - "configSection": "devproxy-plugin-language-model-failure-config" + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" }, { - "name": "LanguageModelRateLimitingPlugin", + "name": "OpenApiSpecGeneratorPlugin", "enabled": true, - "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", - "configSection": "devproxy-plugin-language-model-rate-limiting-config" + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" } ], "urlsToWatch": ["https://api.openai.com/*"], "logLevel": "information", "languageModel": { "enabled": true - }, - "devproxy-plugin-language-model-failure-config": { - "failureRate": 10 - }, - "devproxy-plugin-language-model-rate-limiting-config": { - "requestsPerMinute": 100 } } diff --git a/src/test/examples/config-language-model-required.json b/src/test/examples/config-language-model-required.json index f615726..3b22e57 100644 --- a/src/test/examples/config-language-model-required.json +++ b/src/test/examples/config-language-model-required.json @@ -2,24 +2,16 @@ "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v0.29.0/rc.schema.json", "plugins": [ { - "name": "LanguageModelFailurePlugin", + "name": "OpenAIMockResponsePlugin", "enabled": true, - "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", - "configSection": "devproxy-plugin-language-model-failure-config" + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" }, { - "name": "LanguageModelRateLimitingPlugin", + "name": "OpenApiSpecGeneratorPlugin", "enabled": true, - "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll", - "configSection": "devproxy-plugin-language-model-rate-limiting-config" + "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll" } ], "urlsToWatch": ["https://api.openai.com/*"], - "logLevel": "information", - "devproxy-plugin-language-model-failure-config": { - "failureRate": 10 - }, - "devproxy-plugin-language-model-rate-limiting-config": { - "requestsPerMinute": 100 - } + "logLevel": "information" } diff --git a/src/types.ts b/src/types.ts index 4d3b675..f242cb8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -14,7 +14,7 @@ export type PluginSnippets = { [key: string]: { instance: string; config?: PluginConfig; - requiresLanguageModel?: boolean; + usesLanguageModel?: boolean; }; }; From 1b8a25e8beef0d89d1b9cdc0f87f0c5c2b5856bf Mon Sep 17 00:00:00 2001 From: Garry Trinder Date: Thu, 26 Feb 2026 17:42:45 +0000 Subject: [PATCH 06/13] chore: remove .DS_Store files --- .DS_Store | Bin 6148 -> 0 bytes src/.DS_Store | Bin 6148 -> 0 bytes src/test/.DS_Store | Bin 6148 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store delete mode 100644 src/.DS_Store delete mode 100644 src/test/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 81229e8d26382bd3469cb3d9bb2de3f1954844ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jqp4=5QS&dB4Cr!avKle4VIuM@B*S@B?yZB9^E%TjnP_yyn&f-XEsBUS7b9H zqQmpN5$Q#wgBxXSVPuMYE)TiO>2iLYjtb*@FJ*K=2U&T%hcRwa*e@u>x3=Er<$CqZN!+^)bZi z-VT<$t|nVB+C_8t(7dzS6a&*}7cEF&S{)2jfC`Khm`C2*`M-mIoBu~GOsN1B_%j7` zvE6S6yi}g8AFpTiLso6w;GkcQ@b(jc#E#+>+ztE17GO=bASy8a2)GOkRN$uyya2`( B5q1Co diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index c3ac046f6c51a2cd4bc2df32c603e493458c382e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~F^{dt=u>Bl;zddfqZjB=JE!l7EiIwCR znHYd=e=Zwf1hAw#vGy=AV?N-4FWm9?zTD5J+wJN_+D8XGrH`2G=e8gPq<|EV0#ZN< z%t(Pe#+RQndL})J6p#Y*P{6+rh3>4$))}7;h8O|Jf#oo+W0oL`7s#4yovhF-rw7Yc zi!sFO(N31Ut|nV&Z-?dZVR>isDTZdf9afmotOgXMfE1W0u;}^d=l`Dm-~2ymQ7Q$b zz?&&x!|t%#@}=@@{quTWKW5d}jZVhp3{O7+O#CQb(Zjf3d_mS^>tuzdAAyiTK?=N7 FfnTX=61e~X diff --git a/src/test/.DS_Store b/src/test/.DS_Store deleted file mode 100644 index 34c19f72621762b66da6b77134538776a4fc41fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJ8r`;3?*9+2D*66s4Mgag5jQ^7f8~ilM5Fx3Uu_8bLD7#{0t4;Z0Qm_0@RZz zJ_&k*X^M#UUx#OrPDEO`p`2`3o9&yg>>(oxgyW1)8RaPR`(b`tW&a&8ZVS%0?BwG& ze?Lv5ZPKU!6`%rCfC^B7n<|jywSBtjsXUAdP=R|;z`hR!ZdenSK>u`L@D>2rAnb;@ z_Y%Nj0bosB0ug~}P=P_!Y%w(Gh?mT(iA!M6MYH+PyjinDQNJDM7f% Date: Thu, 26 Feb 2026 20:27:57 +0000 Subject: [PATCH 07/13] docs: update changelog with language model diagnostic fix --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2686ff5..1a905f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.13.0] - Unreleased +### Fixed: + +- 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 + ## [1.12.0] - 2026-01-29 ### Added: From 6f6d0457e939f9d5877dd79aef2c794e107b565d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:13:51 +0000 Subject: [PATCH 08/13] Fix shell test by removing fs.existsSync stubbing Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- src/test/shell.test.ts | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/test/shell.test.ts b/src/test/shell.test.ts index 7c6749b..310a757 100644 --- a/src/test/shell.test.ts +++ b/src/test/shell.test.ts @@ -3,8 +3,6 @@ * Tests for pure utility functions in shell.ts. */ import * as assert from 'assert'; -import * as sinon from 'sinon'; -import * as fs from 'fs'; import { getPackageIdentifier, resolveDevProxyExecutable } from '../utils/shell'; import { PackageManager, @@ -44,15 +42,7 @@ suite('getPackageIdentifier', () => { }); suite('resolveDevProxyExecutable', () => { - let existsSyncStub: sinon.SinonStub; - - setup(() => { - existsSyncStub = sinon.stub(fs, 'existsSync'); - }); - - teardown(() => { - sinon.restore(); - }); + const NONEXISTENT_DEVPROXY_COMMAND = 'devproxy-command-that-does-not-exist-for-tests'; test('should return custom path when provided and non-empty', async () => { const customPath = '/custom/path/to/devproxy'; @@ -67,22 +57,18 @@ suite('resolveDevProxyExecutable', () => { }); test('should ignore empty custom path and proceed with auto-detection', async () => { - // With empty custom path and no auto-detection success, should return bare command - existsSyncStub.returns(false); - const result = await resolveDevProxyExecutable('devproxy', ''); + const result = await resolveDevProxyExecutable(NONEXISTENT_DEVPROXY_COMMAND, ''); // Will fall through to bare command since nothing else succeeds - assert.strictEqual(result, 'devproxy'); + assert.strictEqual(result, NONEXISTENT_DEVPROXY_COMMAND); }); test('should ignore whitespace-only custom path', async () => { - existsSyncStub.returns(false); - const result = await resolveDevProxyExecutable('devproxy', ' '); - assert.strictEqual(result, 'devproxy'); + const result = await resolveDevProxyExecutable(NONEXISTENT_DEVPROXY_COMMAND, ' '); + assert.strictEqual(result, NONEXISTENT_DEVPROXY_COMMAND); }); test('should handle undefined custom path', async () => { - existsSyncStub.returns(false); - const result = await resolveDevProxyExecutable('devproxy', undefined); - assert.strictEqual(result, 'devproxy'); + const result = await resolveDevProxyExecutable(NONEXISTENT_DEVPROXY_COMMAND, undefined); + assert.strictEqual(result, NONEXISTENT_DEVPROXY_COMMAND); }); }); From 85be796eaaf854b572b1732eec4047d1c2a46303 Mon Sep 17 00:00:00 2001 From: Garry Trinder Date: Thu, 26 Feb 2026 21:19:53 +0000 Subject: [PATCH 09/13] docs: update README diagnostic and quick fix descriptions for language model --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 31cf367..9a1453a 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,7 @@ Real-time validation of your configuration files. Click any diagnostic code to v | `invalidSchema` | Schema version doesn't match installed Dev Proxy | | `invalidConfigSection` | Config section not used by any plugin | | `deprecatedPluginPath` | Using old plugin DLL path (pre-v0.29) | -| `missingLanguageModel` | Plugin requires language model configuration | +| `missingLanguageModel` | Plugin can use a local language model to enhance its output | | `noEnabledPlugins` | No plugins are enabled | | `reporterPosition` | Reporter plugin should be last | | `summaryWithoutReporter` | Summary plugin needs a reporter | @@ -196,7 +196,7 @@ One-click fixes for common issues: - **Update schema** - Match schema to installed Dev Proxy version (config file or config sections) - **Update plugin path** - Fix deprecated `dev-proxy-plugins.dll` paths (single or all at once) - **Remove unknown property** - Remove properties not defined in config section schema -- **Add languageModel configuration** - Enable language model for AI plugins +- **Enable local language model** - Add language model configuration for plugins that support it - **Add plugin configuration** - Add optional config section for plugins that support it - **Add missing config section** - Create config section when plugin references one that doesn't exist From d08b6ac5ad3f73f71dd4411ceb221207a0c1f790 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:26:05 +0000 Subject: [PATCH 10/13] Fix Windows fixture path resolution in tests Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- src/test/helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/helpers.ts b/src/test/helpers.ts index 58ed363..5593bd5 100644 --- a/src/test/helpers.ts +++ b/src/test/helpers.ts @@ -8,8 +8,8 @@ import { DevProxyInstall } from '../types'; * avoiding the need to copy them to out/ during build. */ export function getFixturePath(fileName: string): string { - // process.cwd() is the workspace root when running tests via VS Code test runner - return path.resolve(process.cwd(), 'src', 'test', 'examples', fileName); + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? process.cwd(); + return path.resolve(workspaceRoot, 'src', 'test', 'examples', fileName); } /** From 68c84834e0986a9acc47bda5bff4740d6aba7435 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:38:28 +0000 Subject: [PATCH 11/13] Harden fixture path lookup for Windows test runner Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- src/test/helpers.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/test/helpers.ts b/src/test/helpers.ts index 5593bd5..843b521 100644 --- a/src/test/helpers.ts +++ b/src/test/helpers.ts @@ -1,3 +1,4 @@ +import * as fs from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; import { DevProxyInstall } from '../types'; @@ -8,8 +9,20 @@ import { DevProxyInstall } from '../types'; * avoiding the need to copy them to out/ during build. */ export function getFixturePath(fileName: string): string { - const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? process.cwd(); - return path.resolve(workspaceRoot, 'src', 'test', 'examples', fileName); + const candidateRoots = [ + process.cwd(), + path.resolve(__dirname, '..', '..'), + vscode.workspace.workspaceFolders?.[0]?.uri.fsPath, + ].filter((root): root is string => Boolean(root)); + + for (const root of candidateRoots) { + const fixturePath = path.resolve(root, 'src', 'test', 'examples', fileName); + if (fs.existsSync(fixturePath)) { + return fixturePath; + } + } + + return path.resolve(process.cwd(), 'src', 'test', 'examples', fileName); } /** From c60e63dc930a05a6d4de1743b6a407485a7753dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 09:48:04 +0000 Subject: [PATCH 12/13] Document local language model quick fix in README and changelog Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- CHANGELOG.md | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a905f0..8545e11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed: - 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 +- Quick Fixes: Enable local language model fix now adds or updates `languageModel.enabled: true` for supported plugins only ## [1.12.0] - 2026-01-29 diff --git a/README.md b/README.md index 9a1453a..91258ff 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ One-click fixes for common issues: - **Update schema** - Match schema to installed Dev Proxy version (config file or config sections) - **Update plugin path** - Fix deprecated `dev-proxy-plugins.dll` paths (single or all at once) - **Remove unknown property** - Remove properties not defined in config section schema -- **Enable local language model** - Add language model configuration for plugins that support it +- **Enable local language model** - Add or update `languageModel.enabled: true` for plugins that support it - **Add plugin configuration** - Add optional config section for plugins that support it - **Add missing config section** - Create config section when plugin references one that doesn't exist From b9fb47120f1979e291845cd3503b130e73fe1d97 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 09:51:31 +0000 Subject: [PATCH 13/13] Move 1.13.0 quick-fix note to Added changelog section Co-authored-by: garrytrinder <11563347+garrytrinder@users.noreply.github.com> --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8545e11..ec0e8b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.13.0] - Unreleased +### Added: + +- Quick Fixes: Enable local language model fix now adds or updates `languageModel.enabled: true` for supported plugins only + ### Fixed: - 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 -- Quick Fixes: Enable local language model fix now adds or updates `languageModel.enabled: true` for supported plugins only ## [1.12.0] - 2026-01-29