-
Notifications
You must be signed in to change notification settings - Fork 3.6k
build(vscode): remove bundled esbuild; require user-installed esbuild for config.ts #8016
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fb1c29e
77547ab
86c2c17
c994365
c2d4ab1
ff5b62d
f4cc42d
8b1d347
b1bb2b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,6 @@ import { | |
ModelRole, | ||
} from "@continuedev/config-yaml"; | ||
import * as JSONC from "comment-json"; | ||
import * as tar from "tar"; | ||
|
||
import { | ||
BrowserSerializedContinueConfig, | ||
|
@@ -696,102 +695,43 @@ function escapeSpacesInPath(p: string): string { | |
return p.replace(/ /g, "\\ "); | ||
} | ||
|
||
async function handleEsbuildInstallation(ide: IDE, ideType: IdeType) { | ||
// JetBrains is currently the only IDE that we've reached the plugin size limit and | ||
// therefore need to install esbuild manually to reduce the size | ||
if (ideType !== "jetbrains") { | ||
return; | ||
} | ||
|
||
const globalContext = new GlobalContext(); | ||
if (globalContext.get("hasDismissedConfigTsNoticeJetBrains")) { | ||
return; | ||
} | ||
|
||
const esbuildPath = getEsbuildBinaryPath(); | ||
|
||
if (fs.existsSync(esbuildPath)) { | ||
return; | ||
} | ||
|
||
console.debug("No esbuild binary detected"); | ||
|
||
const shouldInstall = await promptEsbuildInstallation(ide); | ||
|
||
if (shouldInstall) { | ||
await downloadAndInstallEsbuild(ide); | ||
} | ||
} | ||
|
||
async function promptEsbuildInstallation(ide: IDE): Promise<boolean> { | ||
const installMsg = "Install esbuild"; | ||
const dismissMsg = "Dismiss"; | ||
|
||
const res = await ide.showToast( | ||
"warning", | ||
"You're using a custom 'config.ts' file, which requires 'esbuild' to be installed. Would you like to install it now?", | ||
dismissMsg, | ||
installMsg, | ||
); | ||
|
||
if (res === dismissMsg) { | ||
const globalContext = new GlobalContext(); | ||
globalContext.update("hasDismissedConfigTsNoticeJetBrains", true); | ||
return false; | ||
} | ||
|
||
return res === installMsg; | ||
} | ||
|
||
/** | ||
* The download logic is adapted from here: https://esbuild.github.io/getting-started/#download-a-build | ||
*/ | ||
async function downloadAndInstallEsbuild(ide: IDE) { | ||
const esbuildPath = getEsbuildBinaryPath(); | ||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "esbuild-")); | ||
async function handleEsbuildInstallation( | ||
ide: IDE, | ||
_ideType: IdeType, | ||
): Promise<boolean> { | ||
// Only check when config.ts is going to be used; never auto-install. | ||
const installCmd = "npm i [email protected] --prefix ~/.continue"; | ||
|
||
// Try to detect a user-installed esbuild (normal resolution) | ||
try { | ||
const target = `${os.platform()}-${os.arch()}`; | ||
const version = "0.19.11"; | ||
const url = `https://registry.npmjs.org/@esbuild/${target}/-/${target}-${version}.tgz`; | ||
const tgzPath = path.join(tempDir, `esbuild-${version}.tgz`); | ||
|
||
console.debug(`Downloading esbuild from: ${url}`); | ||
execSync(`curl -fo "${tgzPath}" "${url}"`); | ||
|
||
console.debug(`Extracting tgz file to: ${tempDir}`); | ||
await tar.x({ | ||
file: tgzPath, | ||
cwd: tempDir, | ||
strip: 2, // Remove the top two levels of directories | ||
}); | ||
|
||
// Ensure the destination directory exists | ||
const destDir = path.dirname(esbuildPath); | ||
if (!fs.existsSync(destDir)) { | ||
fs.mkdirSync(destDir, { recursive: true }); | ||
} | ||
|
||
// Move the file | ||
const extractedBinaryPath = path.join(tempDir, "esbuild"); | ||
fs.renameSync(extractedBinaryPath, esbuildPath); | ||
|
||
// Ensure the binary is executable (not needed on Windows) | ||
if (os.platform() !== "win32") { | ||
fs.chmodSync(esbuildPath, 0o755); | ||
await import("esbuild"); | ||
return true; // available | ||
} catch { | ||
// Try resolving from ~/.continue/node_modules as a courtesy | ||
try { | ||
const userEsbuild = path.join( | ||
os.homedir(), | ||
".continue", | ||
"node_modules", | ||
"esbuild", | ||
); | ||
const candidate = require.resolve("esbuild", { paths: [userEsbuild] }); | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
require(candidate); | ||
return true; // available via ~/.continue | ||
} catch { | ||
// Not available → show friendly instructions and opt out of building | ||
await ide.showToast( | ||
"error", | ||
[ | ||
"config.ts has been deprecated and esbuild is no longer automatically installed by Continue.", | ||
"To use config.ts, install esbuild manually:", | ||
"", | ||
` ${installCmd}`, | ||
].join("\n"), | ||
); | ||
return false; | ||
} | ||
|
||
// Clean up | ||
fs.unlinkSync(tgzPath); | ||
fs.rmSync(tempDir, { recursive: true }); | ||
|
||
await ide.showToast( | ||
"info", | ||
`'esbuild' successfully installed to ${esbuildPath}`, | ||
); | ||
} catch (error) { | ||
console.error("Error downloading or saving esbuild binary:", error); | ||
throw error; | ||
} | ||
} | ||
|
||
|
@@ -866,8 +806,15 @@ async function buildConfigTsandReadConfigJs(ide: IDE, ideType: IdeType) { | |
return; | ||
} | ||
|
||
await handleEsbuildInstallation(ide, ideType); | ||
await tryBuildConfigTs(); | ||
// Only bother with esbuild if config.ts is actually customized | ||
if (currentContent.trim() !== DEFAULT_CONFIG_TS_CONTENTS.trim()) { | ||
const ok = await handleEsbuildInstallation(ide, ideType); | ||
if (!ok) { | ||
// esbuild not available → we already showed a friendly message; skip building | ||
return; | ||
} | ||
await tryBuildConfigTs(); | ||
} | ||
Comment on lines
+809
to
+817
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the goal from @sestinj 's feedback was just to provide the deprecation message to user's that have modified their config.ts , not to attempt to use their locally installed esbuild. The general goal here is rip out all the config.ts logic but give a heads up to those affected. Could we modify this to instead just show the toast with that in mind? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @RomneyDa @Patrick-Erichsen @sestinj : The current code is based on feedback from Dallin in my now closed PR:
As you requested I kept all the config.ts related logic, still letting the end user use config.ts if they have installed esbuild themselves. This PR leaves a deprecation message and the next logical step would be to remove all code pertaining to config.ts. This PR supersedes my two earlier attempts: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @joffeoja chatted with @Patrick-Erichsen, sounds like we'll move forward with this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @RomneyDa @Patrick-Erichsen Sounds good. Do I have to do anything more on my part? |
||
|
||
return readConfigJs(); | ||
} | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,9 +20,7 @@ const { | |
buildGui, | ||
copyOnnxRuntimeFromNodeModules, | ||
copyTreeSitterWasms, | ||
copyTreeSitterTagQryFiles, | ||
copyNodeModules, | ||
downloadEsbuildBinary, | ||
downloadRipgrepBinary, | ||
copySqliteBinary, | ||
installNodeModuleInTempDirAndCopyToCurrent, | ||
|
@@ -90,9 +88,6 @@ async function package(target, os, arch, exe) { | |
// Copy tree-sitter-wasm files | ||
await copyTreeSitterWasms(); | ||
|
||
// Copy tree-sitter tag query files | ||
await copyTreeSitterTagQryFiles(); | ||
|
||
// Install and copy over native modules | ||
// *** onnxruntime-node *** | ||
await copyOnnxRuntimeFromNodeModules(target); | ||
|
@@ -116,12 +111,6 @@ async function package(target, os, arch, exe) { | |
lancePackageToInstall, | ||
"@lancedb", | ||
); | ||
// *** esbuild *** | ||
// await installNodeModuleInTempDirAndCopyToCurrent( | ||
// "[email protected]", | ||
// "@esbuild", | ||
// ); | ||
await downloadEsbuildBinary(target); | ||
|
||
// *** sqlite *** | ||
await downloadSqliteBinary(target); | ||
|
@@ -187,19 +176,11 @@ async function package(target, os, arch, exe) { | |
|
||
// out/node_modules (to be accessed by extension.js) | ||
`out/node_modules/@vscode/ripgrep/bin/rg${exe}`, | ||
`out/node_modules/@esbuild/${ | ||
target === "win32-arm64" | ||
? "esbuild.exe" | ||
: target === "win32-x64" | ||
? "win32-x64/esbuild.exe" | ||
: `${target}/bin/esbuild` | ||
}`, | ||
`out/node_modules/@lancedb/vectordb-${ | ||
os === "win32" | ||
? "win32-x64-msvc" | ||
: `${target}${os === "linux" ? "-gnu" : ""}` | ||
}/index.node`, | ||
`out/node_modules/esbuild/lib/main.js`, | ||
]); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ const { | |
autodetectPlatformAndArch, | ||
} = require("../../../scripts/util/index"); | ||
|
||
const { copySqlite, copyEsbuild } = require("./download-copy-sqlite-esbuild"); | ||
const { copySqlite } = require("./download-copy-sqlite"); | ||
const { generateAndCopyConfigYamlSchema } = require("./generate-copy-config"); | ||
const { installAndCopyNodeModules } = require("./install-copy-nodemodule"); | ||
const { npmInstall } = require("./npm-install"); | ||
|
@@ -303,14 +303,9 @@ void (async () => { | |
); | ||
|
||
await Promise.all([ | ||
copyEsbuild(target), | ||
copySqlite(target), | ||
installAndCopyNodeModules(packageToInstall, "@lancedb"), | ||
]); | ||
} else { | ||
// Download esbuild from npm in tmp and copy over | ||
console.log("[info] npm installing esbuild binary"); | ||
await installAndCopyNodeModules("[email protected]", "@esbuild"); | ||
} | ||
} | ||
|
||
|
@@ -349,13 +344,7 @@ void (async () => { | |
}); | ||
|
||
// Copy node_modules for pre-built binaries | ||
const NODE_MODULES_TO_COPY = [ | ||
"esbuild", | ||
"@esbuild", | ||
"@lancedb", | ||
"@vscode/ripgrep", | ||
"workerpool", | ||
]; | ||
const NODE_MODULES_TO_COPY = ["@lancedb", "@vscode/ripgrep", "workerpool"]; | ||
|
||
fs.mkdirSync("out/node_modules", { recursive: true }); | ||
|
||
|
@@ -382,9 +371,6 @@ void (async () => { | |
), | ||
); | ||
|
||
// delete esbuild/bin because platform-specific @esbuild is downloaded | ||
fs.rmSync(`out/node_modules/esbuild/bin`, { recursive: true }); | ||
|
||
console.log(`[info] Copied ${NODE_MODULES_TO_COPY.join(", ")}`); | ||
|
||
// Copy over any worker files | ||
|
@@ -442,15 +428,7 @@ void (async () => { | |
|
||
// out/node_modules (to be accessed by extension.js) | ||
`out/node_modules/@vscode/ripgrep/bin/rg${exe}`, | ||
`out/node_modules/@esbuild/${ | ||
target === "win32-arm64" | ||
? "esbuild.exe" | ||
: target === "win32-x64" | ||
? "win32-x64/esbuild.exe" | ||
: `${target}/bin/esbuild` | ||
}`, | ||
`out/node_modules/@lancedb/vectordb-${target}${isWinTarget ? "-msvc" : ""}${isLinuxTarget ? "-gnu" : ""}/index.node`, | ||
`out/node_modules/esbuild/lib/main.js`, | ||
]); | ||
|
||
console.log( | ||
|
Uh oh!
There was an error while loading. Please reload this page.