From aeaaa3cdc2f18d30d17eda727654456e67d65ea2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 28 May 2026 20:10:38 +0000 Subject: [PATCH 1/9] Initial plan From 52d9917a828b7c1f0c8ef176b1b4635366452dc5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 28 May 2026 20:16:32 +0000 Subject: [PATCH 2/9] Fix tsdk relative path overwrite and unnecessary prompt - Add relativeTsdkPath to DetectedVersion to store portable relative path - promptUseWorkspaceVersion: skip prompt when existing tsdk already resolves to a workspace install (auto opt-in without modifying settings) - promptUseWorkspaceVersion: write relative path when user clicks Allow - promptSelectVersion: use relative path and compare against exePath for active version indicator Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- _extension/src/session.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 6bb76a1cf03..9758a956189 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -349,6 +349,7 @@ interface DetectedVersion { label: string; version: string; tsdkPath: string; + relativeTsdkPath: string; exePath: string; } @@ -362,6 +363,7 @@ async function findWorkspaceNativePreviewPackages(): Promise label: folder.name, version: resolved?.version ?? "unknown", tsdkPath: path.normalize(packagePath.fsPath), + relativeTsdkPath: "./node_modules/@typescript/native-preview", exePath: resolved?.path ?? "", }); } @@ -391,14 +393,14 @@ async function promptSelectVersion(context: vscode.ExtensionContext, client: Cli // Workspace versions if (vscode.workspace.isTrusted) { for (const wsVersion of workspaceVersions) { - const isActive = currentExePath === wsVersion.tsdkPath; + const isActive = currentExePath === wsVersion.exePath; items.push({ label: (isActive ? "• " : "") + "Use Workspace Version", description: wsVersion.version, - detail: wsVersion.tsdkPath, + detail: wsVersion.relativeTsdkPath, run: async () => { await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); - await config.update("tsdk", wsVersion.tsdkPath, vscode.ConfigurationTarget.Workspace); + await config.update("tsdk", wsVersion.relativeTsdkPath, vscode.ConfigurationTarget.Workspace); outputChannel.appendLine(`Switched to workspace tsgo version (${wsVersion.version}).`); }, }); @@ -473,6 +475,18 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext const workspaceVersions = await findWorkspaceNativePreviewPackages(); if (workspaceVersions.length === 0) return; + // If the existing tsdk setting already resolves to a workspace install, + // treat it as already opted in — don't prompt and don't overwrite the setting. + const config = vscode.workspace.getConfiguration("typescript.native-preview"); + const currentTsdk = config.get("tsdk"); + if (currentTsdk) { + const resolvedCurrent = await resolveTsdkPathToExe(currentTsdk); + if (resolvedCurrent && workspaceVersions.some(ws => ws.exePath === resolvedCurrent.path)) { + await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); + return; + } + } + const wsVersion = workspaceVersions[0]; const allow = "Allow"; const dismiss = "Dismiss"; @@ -488,8 +502,7 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext if (result === allow) { if (!vscode.workspace.isTrusted) return; await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); - const config = vscode.workspace.getConfiguration("typescript.native-preview"); - await config.update("tsdk", wsVersion.tsdkPath, vscode.ConfigurationTarget.Workspace); + await config.update("tsdk", wsVersion.relativeTsdkPath, vscode.ConfigurationTarget.Workspace); await vscode.commands.executeCommand("typescript.native-preview.restart"); } else if (result === suppress) { From 545303b810b597ce4df96c6bbaeb48e3434c2c02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 28 May 2026 22:56:48 +0000 Subject: [PATCH 3/9] Apply review suggestion: use plain dash in comment Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- _extension/src/session.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 9758a956189..5a726dbaa5b 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -476,7 +476,7 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext if (workspaceVersions.length === 0) return; // If the existing tsdk setting already resolves to a workspace install, - // treat it as already opted in — don't prompt and don't overwrite the setting. + // treat it as already opted in - don't prompt and don't overwrite the setting. const config = vscode.workspace.getConfiguration("typescript.native-preview"); const currentTsdk = config.get("tsdk"); if (currentTsdk) { From ac405f33f41b602604bd590a7671ab337fb946b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 28 May 2026 23:07:37 +0000 Subject: [PATCH 4/9] Restart session on early-return opt-in; fix multi-root workspace relative paths Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- _extension/src/session.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 5a726dbaa5b..991fad1dc57 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -355,15 +355,23 @@ interface DetectedVersion { async function findWorkspaceNativePreviewPackages(): Promise { const results: DetectedVersion[] = []; - for (const folder of vscode.workspace.workspaceFolders ?? []) { + const folders = vscode.workspace.workspaceFolders ?? []; + for (let i = 0; i < folders.length; i++) { + const folder = folders[i]; const packagePath = vscode.Uri.joinPath(folder.uri, "node_modules", "@typescript", "native-preview"); const resolved = await resolveTsdkPathToExe(path.normalize(packagePath.fsPath)); if (!resolved) continue; + // Use a relative path only for the first workspace folder since + // workspaceResolve anchors relative paths there. For other folders, + // fall back to the absolute path so the setting resolves correctly. + const relativeTsdkPath = i === 0 + ? "./node_modules/@typescript/native-preview" + : path.normalize(packagePath.fsPath); results.push({ label: folder.name, version: resolved?.version ?? "unknown", tsdkPath: path.normalize(packagePath.fsPath), - relativeTsdkPath: "./node_modules/@typescript/native-preview", + relativeTsdkPath, exePath: resolved?.path ?? "", }); } @@ -483,6 +491,8 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext const resolvedCurrent = await resolveTsdkPathToExe(currentTsdk); if (resolvedCurrent && workspaceVersions.some(ws => ws.exePath === resolvedCurrent.path)) { await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); + // Restart so the workspace tsdk takes effect for the current session. + await vscode.commands.executeCommand("typescript.native-preview.restart"); return; } } From 1c4303d16fe9d4af02313f86dfb8374ae5e9f14e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 18:02:59 +0000 Subject: [PATCH 5/9] Remove silent auto-opt-in; always prompt for trust, preserve existing tsdk on Allow Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com> --- _extension/src/session.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 991fad1dc57..656101f06fe 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -483,20 +483,7 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext const workspaceVersions = await findWorkspaceNativePreviewPackages(); if (workspaceVersions.length === 0) return; - // If the existing tsdk setting already resolves to a workspace install, - // treat it as already opted in - don't prompt and don't overwrite the setting. const config = vscode.workspace.getConfiguration("typescript.native-preview"); - const currentTsdk = config.get("tsdk"); - if (currentTsdk) { - const resolvedCurrent = await resolveTsdkPathToExe(currentTsdk); - if (resolvedCurrent && workspaceVersions.some(ws => ws.exePath === resolvedCurrent.path)) { - await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); - // Restart so the workspace tsdk takes effect for the current session. - await vscode.commands.executeCommand("typescript.native-preview.restart"); - return; - } - } - const wsVersion = workspaceVersions[0]; const allow = "Allow"; const dismiss = "Dismiss"; @@ -512,7 +499,14 @@ export async function promptUseWorkspaceVersion(context: vscode.ExtensionContext if (result === allow) { if (!vscode.workspace.isTrusted) return; await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); - await config.update("tsdk", wsVersion.relativeTsdkPath, vscode.ConfigurationTarget.Workspace); + // Only write tsdk if it isn't already pointing at the workspace install, + // so we don't overwrite a committed relative path with a new value. + const currentTsdk = config.get("tsdk"); + const resolvedCurrent = currentTsdk ? await resolveTsdkPathToExe(currentTsdk) : undefined; + const alreadyResolved = resolvedCurrent && workspaceVersions.some(ws => ws.exePath === resolvedCurrent.path); + if (!alreadyResolved) { + await config.update("tsdk", wsVersion.relativeTsdkPath, vscode.ConfigurationTarget.Workspace); + } await vscode.commands.executeCommand("typescript.native-preview.restart"); } else if (result === suppress) { From 32b4cd7b771726e451d74426495b8281ca971e5d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 18:17:53 +0000 Subject: [PATCH 6/9] Don't remove tsdk from settings when switching to bundled; only toggle trust flag Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com> --- _extension/src/session.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 656101f06fe..3c5d564e498 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -393,7 +393,6 @@ async function promptSelectVersion(context: vscode.ExtensionContext, client: Cli detail: builtinExe.path, run: async () => { await context.workspaceState.update(useWorkspaceTsdkStorageKey, false); - await config.update("tsdk", undefined, vscode.ConfigurationTarget.Workspace); outputChannel.appendLine("Switched to bundled tsgo version."); }, }); From d90c019d999623f60f5b92b0aed77744d6ad2c74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 18:47:00 +0000 Subject: [PATCH 7/9] Suppress prompt when user explicitly switches to bundled via version picker Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com> --- _extension/src/session.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 3c5d564e498..202c0ed9800 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -393,6 +393,9 @@ async function promptSelectVersion(context: vscode.ExtensionContext, client: Cli detail: builtinExe.path, run: async () => { await context.workspaceState.update(useWorkspaceTsdkStorageKey, false); + // Suppress the workspace-version prompt so it doesn't re-fire + // after the user explicitly chose bundled. + await context.workspaceState.update("typescript.native-preview.suppressPromptWorkspaceTsdk", true); outputChannel.appendLine("Switched to bundled tsgo version."); }, }); @@ -407,6 +410,7 @@ async function promptSelectVersion(context: vscode.ExtensionContext, client: Cli detail: wsVersion.relativeTsdkPath, run: async () => { await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); + await context.workspaceState.update("typescript.native-preview.suppressPromptWorkspaceTsdk", false); await config.update("tsdk", wsVersion.relativeTsdkPath, vscode.ConfigurationTarget.Workspace); outputChannel.appendLine(`Switched to workspace tsgo version (${wsVersion.version}).`); }, From 6f4959e94620542277dbad224f8545cc8990e639 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 19:05:37 +0000 Subject: [PATCH 8/9] refactor: extract relative workspace path constant in findWorkspaceNativePreviewPackages Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- _extension/src/session.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 202c0ed9800..4ed1d0b8d52 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -356,16 +356,17 @@ interface DetectedVersion { async function findWorkspaceNativePreviewPackages(): Promise { const results: DetectedVersion[] = []; const folders = vscode.workspace.workspaceFolders ?? []; + const relativeWorkspacePath = "node_modules/@typescript/native-preview"; for (let i = 0; i < folders.length; i++) { const folder = folders[i]; - const packagePath = vscode.Uri.joinPath(folder.uri, "node_modules", "@typescript", "native-preview"); + const packagePath = vscode.Uri.joinPath(folder.uri, ...relativeWorkspacePath.split("/")); const resolved = await resolveTsdkPathToExe(path.normalize(packagePath.fsPath)); if (!resolved) continue; // Use a relative path only for the first workspace folder since // workspaceResolve anchors relative paths there. For other folders, // fall back to the absolute path so the setting resolves correctly. const relativeTsdkPath = i === 0 - ? "./node_modules/@typescript/native-preview" + ? `./${relativeWorkspacePath}` : path.normalize(packagePath.fsPath); results.push({ label: folder.name, From 51ebaaf3e2773fb402f17b84265b8aeb582d340a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 29 May 2026 19:06:22 +0000 Subject: [PATCH 9/9] refactor: hoist path segment split outside the loop Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- _extension/src/session.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_extension/src/session.ts b/_extension/src/session.ts index 4ed1d0b8d52..11b02bde953 100644 --- a/_extension/src/session.ts +++ b/_extension/src/session.ts @@ -357,9 +357,10 @@ async function findWorkspaceNativePreviewPackages(): Promise const results: DetectedVersion[] = []; const folders = vscode.workspace.workspaceFolders ?? []; const relativeWorkspacePath = "node_modules/@typescript/native-preview"; + const pathSegments = relativeWorkspacePath.split("/"); for (let i = 0; i < folders.length; i++) { const folder = folders[i]; - const packagePath = vscode.Uri.joinPath(folder.uri, ...relativeWorkspacePath.split("/")); + const packagePath = vscode.Uri.joinPath(folder.uri, ...pathSegments); const resolved = await resolveTsdkPathToExe(path.normalize(packagePath.fsPath)); if (!resolved) continue; // Use a relative path only for the first workspace folder since