Skip to content

Commit 20925f5

Browse files
committed
clean
1 parent 0ae577c commit 20925f5

File tree

3 files changed

+38
-23
lines changed

3 files changed

+38
-23
lines changed

packages/amazonq/src/extension.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
maybeShowMinVscodeWarning,
3434
Experiments,
3535
isSageMaker,
36+
isAmazonInternalOs,
3637
} from 'aws-core-vscode/shared'
3738
import { ExtStartUpSources } from 'aws-core-vscode/telemetry'
3839
import { VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
@@ -43,6 +44,7 @@ import { registerCommands } from './commands'
4344
import { focusAmazonQPanel } from 'aws-core-vscode/codewhispererChat'
4445
import { activate as activateAmazonqLsp } from './lsp/activation'
4546
import { activate as activateInlineCompletion } from './app/inline/activation'
47+
import { hasGlibcPatch } from './lsp/client'
4648

4749
export const amazonQContextPrefix = 'amazonq'
4850

@@ -119,8 +121,12 @@ export async function activateAmazonQCommon(context: vscode.ExtensionContext, is
119121
}
120122
// This contains every lsp agnostic things (auth, security scan, code scan)
121123
await activateCodeWhisperer(extContext as ExtContext)
122-
if (Experiments.instance.get('amazonqLSP', true) || Auth.instance.isInternalAmazonUser()) {
124+
if (
125+
(Experiments.instance.get('amazonqLSP', true) || Auth.instance.isInternalAmazonUser()) &&
126+
(!isAmazonInternalOs() || (await hasGlibcPatch()))
127+
) {
123128
// start the Amazon Q LSP for internal users first
129+
// for AL2, start LSP if glibc patch is found
124130
await activateAmazonqLsp(context)
125131
}
126132
if (!Experiments.instance.get('amazonqLSPInline', false)) {

packages/amazonq/src/lsp/client.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import vscode, { env, version } from 'vscode'
77
import * as nls from 'vscode-nls'
88
import * as crypto from 'crypto'
9+
import * as path from 'path'
910
import { LanguageClient, LanguageClientOptions, RequestType, State } from 'vscode-languageclient'
1011
import { InlineCompletionManager } from '../app/inline/completion'
1112
import { AmazonQLspAuth, encryptionKey, notificationTypes } from './auth'
@@ -32,14 +33,21 @@ import {
3233
getLogger,
3334
undefinedIfEmpty,
3435
getOptOutPreference,
36+
isAmazonInternalOs,
37+
fs,
3538
} from 'aws-core-vscode/shared'
3639
import { activate } from './chat/activation'
3740
import { AmazonQResourcePaths } from './lspInstaller'
3841
import { ConfigSection, isValidConfigSection, toAmazonQLSPLogLevel } from './config'
42+
import { chmodSync } from 'fs'
3943

4044
const localize = nls.loadMessageBundle()
4145
const logger = getLogger('amazonqLsp.lspClient')
4246

47+
export async function hasGlibcPatch(): Promise<boolean> {
48+
return await fs.exists('/opt/vsc-sysroot/lib64/ld-linux-x86-64.so.2')
49+
}
50+
4351
export async function startLanguageServer(
4452
extensionContext: vscode.ExtensionContext,
4553
resourcePaths: AmazonQResourcePaths
@@ -55,18 +63,32 @@ export async function startLanguageServer(
5563
'--pre-init-encryption',
5664
'--set-credentials-encryption-key',
5765
]
66+
67+
const documentSelector = [{ scheme: 'file', language: '*' }]
68+
69+
const clientId = 'amazonq'
70+
const traceServerEnabled = Settings.instance.isSet(`${clientId}.trace.server`)
71+
72+
// apply the GLIBC 2.28 path to node js runtime binary
73+
if (isAmazonInternalOs() && (await hasGlibcPatch())) {
74+
const nodeWrapper = `
75+
#! /bin/bash
76+
exec /opt/vsc-sysroot/lib64/ld-linux-x86-64.so.2 --library-path /opt/vsc-sysroot/lib64 ${resourcePaths.node} "$@"
77+
`
78+
const nodeWrapperPath = path.join(path.dirname(resourcePaths.node), 'node-wrapper')
79+
await fs.writeFile(nodeWrapperPath, nodeWrapper)
80+
chmodSync(nodeWrapperPath, 0o755)
81+
resourcePaths.node = nodeWrapperPath
82+
getLogger('amazonqLsp').info(`Patched node runtime with GLIBC to ${resourcePaths.node}`)
83+
}
84+
5885
const serverOptions = createServerOptions({
5986
encryptionKey,
6087
executable: resourcePaths.node,
6188
serverModule,
6289
execArgv: argv,
6390
})
6491

65-
const documentSelector = [{ scheme: 'file', language: '*' }]
66-
67-
const clientId = 'amazonq'
68-
const traceServerEnabled = Settings.instance.isSet(`${clientId}.trace.server`)
69-
7092
await validateNodeExe(resourcePaths.node, resourcePaths.lsp, argv, logger)
7193

7294
// Options to control the language client

packages/core/src/shared/lsp/utils/platform.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ToolkitError } from '../../errors'
77
import { Logger } from '../../logger/logger'
88
import { ChildProcess } from '../../utilities/processUtils'
99
import { waitUntil } from '../../utilities/timeoutUtils'
10-
import { isAmazonInternalOs, isDebugInstance } from '../../vscode/env'
10+
import { isDebugInstance } from '../../vscode/env'
1111

1212
export function getNodeExecutableName(): string {
1313
return process.platform === 'win32' ? 'node.exe' : 'node'
@@ -26,25 +26,12 @@ function getEncryptionInit(key: Buffer): string {
2626
return JSON.stringify(request) + '\n'
2727
}
2828

29-
// use dynamic linking to let node binary
30-
// pick up GLIBC >= 2.28
31-
const al2Config = {
32-
path: '/opt/vsc-sysroot/lib64/ld-linux-x86-64.so.2',
33-
args: ['--library-path', '/opt/vsc-sysroot/lib64'],
34-
}
35-
function createNodeProcess(nodePath: string, args: string[]) {
36-
return new ChildProcess(
37-
isAmazonInternalOs() ? al2Config.path : nodePath,
38-
isAmazonInternalOs() ? [...al2Config.args, nodePath, ...args] : [...args],
39-
{ logging: 'no' }
40-
)
41-
}
4229
/**
4330
* Checks that we can actually run the `node` executable and execute code with it.
4431
*/
4532
export async function validateNodeExe(nodePath: string, lsp: string, args: string[], logger: Logger) {
4633
// Check that we can start `node` by itself.
47-
const proc = createNodeProcess(nodePath, ['-e', 'console.log("ok " + process.version)'])
34+
const proc = new ChildProcess(nodePath, ['-e', 'console.log("ok " + process.version)'], { logging: 'no' })
4835
const r = await proc.run()
4936
const ok = r.exitCode === 0 && r.stdout.includes('ok')
5037
if (!ok) {
@@ -54,7 +41,7 @@ export async function validateNodeExe(nodePath: string, lsp: string, args: strin
5441
}
5542

5643
// Check that we can start `node …/lsp.js --stdio …`.
57-
const lspProc = createNodeProcess(nodePath, [lsp, ...args])
44+
const lspProc = new ChildProcess(nodePath, [lsp, ...args])
5845

5946
try {
6047
// Start asynchronously (it never stops; we need to stop it below).
@@ -103,7 +90,7 @@ export function createServerOptions({
10390
if (isDebugInstance()) {
10491
args.unshift('--inspect=6080')
10592
}
106-
const lspProcess = createNodeProcess(executable, args)
93+
const lspProcess = new ChildProcess(executable, args)
10794
// this is a long running process, awaiting it will never resolve
10895
void lspProcess.run()
10996

0 commit comments

Comments
 (0)