From 4e5cfda64fc4320237f5f65c6a47843f2d84c52a Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Thu, 2 Jul 2026 21:48:06 +0900 Subject: [PATCH] fix: resolve node-pty binaries from unpacked asar in Copilot shim --- .../copilotcli/node/nodePtyShim.ts | 18 +++++++++++++----- .../copilotcli/node/test/nodePtyShim.spec.ts | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/extensions/copilot/src/extension/chatSessions/copilotcli/node/nodePtyShim.ts b/extensions/copilot/src/extension/chatSessions/copilotcli/node/nodePtyShim.ts index bb355320413..5b4628a71ae 100644 --- a/extensions/copilot/src/extension/chatSessions/copilotcli/node/nodePtyShim.ts +++ b/extensions/copilot/src/extension/chatSessions/copilotcli/node/nodePtyShim.ts @@ -52,11 +52,19 @@ async function _ensureNodePtyShim(extensionPath: string, vscodeAppRoot: string, } export async function resolveNodePtySourcePath(vscodeAppRoot: string, logService: ILogService): Promise { - const nodePtyRoot = path.join(vscodeAppRoot, 'node_modules', 'node-pty'); - const candidatePaths = [ - path.join(nodePtyRoot, 'build', 'Release'), - path.join(nodePtyRoot, 'prebuilds', process.platform + '-' + process.arch), - ]; + // In a packaged build VS Code's `node_modules` is bundled into a + // `node_modules.asar` archive and native binaries are extracted alongside it + // into `node_modules.asar.unpacked`. Check both roots so the shim works in + // development (plain `node_modules`) and in a packaged install + // (`node_modules.asar.unpacked`). + const nodeModulesRoots = ['node_modules', 'node_modules.asar.unpacked']; + const candidatePaths = nodeModulesRoots.flatMap(root => { + const nodePtyRoot = path.join(vscodeAppRoot, root, 'node-pty'); + return [ + path.join(nodePtyRoot, 'build', 'Release'), + path.join(nodePtyRoot, 'prebuilds', process.platform + '-' + process.arch), + ]; + }); for (const candidatePath of candidatePaths) { if (await isDirectory(candidatePath)) { diff --git a/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/nodePtyShim.spec.ts b/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/nodePtyShim.spec.ts index aefa359a698..11675e9b9fb 100644 --- a/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/nodePtyShim.spec.ts +++ b/extensions/copilot/src/extension/chatSessions/copilotcli/node/test/nodePtyShim.spec.ts @@ -38,6 +38,22 @@ describe('nodePtyShim', () => { await expect(resolveNodePtySourcePath(testDir, logService)).resolves.toBe(prebuildDir); }); + it('resolves node-pty from node_modules.asar.unpacked in a packaged build', async () => { + const unpackedBuildDir = join(testDir, 'node_modules.asar.unpacked', 'node-pty', 'build', 'Release'); + await mkdir(unpackedBuildDir, { recursive: true }); + + await expect(resolveNodePtySourcePath(testDir, logService)).resolves.toBe(unpackedBuildDir); + }); + + it('prefers plain node_modules over node_modules.asar.unpacked', async () => { + const buildDir = join(testDir, 'node_modules', 'node-pty', 'build', 'Release'); + const unpackedBuildDir = join(testDir, 'node_modules.asar.unpacked', 'node-pty', 'build', 'Release'); + await mkdir(buildDir, { recursive: true }); + await mkdir(unpackedBuildDir, { recursive: true }); + + await expect(resolveNodePtySourcePath(testDir, logService)).resolves.toBe(buildDir); + }); + it('throws when node-pty binaries are missing', async () => { await expect(resolveNodePtySourcePath(testDir, logService)).rejects.toThrow('Unable to find node-pty binaries'); });