diff --git a/src/test/vscode-settings-entry.test.ts b/src/test/vscode-settings-entry.test.ts new file mode 100644 index 0000000..ac30ea6 --- /dev/null +++ b/src/test/vscode-settings-entry.test.ts @@ -0,0 +1,32 @@ +import * as assert from "node:assert"; +import { readFileSync } from "node:fs"; +import { extensionSettingsQuery } from "../vscode-settings.js"; + +suite("VS Code settings entry", () => { + test("builds an @ext filter from publisher and name", () => { + assert.strictEqual(extensionSettingsQuery("auchan", "pion-code"), "@ext:auchan.pion-code"); + }); + + test("falls back to the known extension identity", () => { + assert.strictEqual(extensionSettingsQuery(undefined, undefined), "@ext:auchan.pion-code"); + assert.strictEqual(extensionSettingsQuery(" ", " "), "@ext:auchan.pion-code"); + }); + + test("gear opens native settings and the panel executes the filtered command", () => { + const handlers = readFileSync( + new URL("../../src/webview/handlers/index.ts", import.meta.url), + "utf8", + ); + assert.match(handlers, /pi-sb-settings/); + assert.match(handlers, /postMessage\(\{ type: "openVscodeSettings" \}\)/); + + const panel = readFileSync( + new URL("../../src/webview-panel.ts", import.meta.url), + "utf8", + ); + assert.match(panel, /case "openVscodeSettings"/); + assert.match(panel, /extensionSettingsQuery\(pkg\.publisher, pkg\.name\)/); + assert.match(panel, /"workbench\.action\.openSettings"/); + assert.match(panel, /Open Pi on Code settings in VS Code/); + }); +}); diff --git a/src/vscode-settings.ts b/src/vscode-settings.ts new file mode 100644 index 0000000..20406c1 --- /dev/null +++ b/src/vscode-settings.ts @@ -0,0 +1,13 @@ +/** + * Query string for the VS Code Settings editor that filters to this + * extension, e.g. `@ext:auchan.pion-code`. + */ +export function extensionSettingsQuery(publisher?: unknown, name?: unknown): string { + const resolvedPublisher = typeof publisher === "string" && publisher.trim() + ? publisher.trim() + : "auchan"; + const resolvedName = typeof name === "string" && name.trim() + ? name.trim() + : "pion-code"; + return `@ext:${resolvedPublisher}.${resolvedName}`; +} diff --git a/src/webview-panel.ts b/src/webview-panel.ts index 3a2fc85..ba96d40 100644 --- a/src/webview-panel.ts +++ b/src/webview-panel.ts @@ -8,6 +8,7 @@ import { resolveMarkdownImagePath, } from "./local-markdown-image.js"; import { mergeInitialHistoryEvents } from "./history-event-sync.js"; +import { extensionSettingsQuery } from "./vscode-settings.js"; import { SessionCapabilitySnapshot } from "./capability-snapshot.js"; import { piError } from "./logger.js"; import { getWorkspaceCwd } from "./workspace-context.js"; @@ -682,6 +683,19 @@ export class PiWebviewPanel { this.piService.emitScopedModels(); break; + // Open the native VS Code Settings filtered to this extension + case "openVscodeSettings": { + const pkg = (this.context.extension?.packageJSON ?? {}) as { + publisher?: unknown; + name?: unknown; + }; + await vscode.commands.executeCommand( + "workbench.action.openSettings", + extensionSettingsQuery(pkg.publisher, pkg.name), + ); + break; + } + // Context budget picker case "pickContextBudget": void this.triggerContextBudgetPicker(); @@ -1063,7 +1077,7 @@ export class PiWebviewPanel {
capabilities: 0
0%
-
⚙
+
⚙
diff --git a/src/webview/handlers/index.ts b/src/webview/handlers/index.ts index 5d8c221..669d665 100644 --- a/src/webview/handlers/index.ts +++ b/src/webview/handlers/index.ts @@ -2213,7 +2213,8 @@ export function sendPrompt(modeOverride?: "steer" | "queue"): void { let sbSettings = document.getElementById("pi-sb-settings"); if (sbSettings) { sbSettings.addEventListener("click", function () { - toggleSettingsPanel(); + // Gear opens the native VS Code Settings filtered to this extension. + window.__vscode.postMessage({ type: "openVscodeSettings" }); }); }