@aws/lsp-codewhisperer 0.0.75 → 0.0.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/out/client/token/bearer-token-service.json +15 -0
- package/out/language-server/agenticChat/agenticChatController.d.ts +13 -2
- package/out/language-server/agenticChat/agenticChatController.js +162 -37
- package/out/language-server/agenticChat/agenticChatController.js.map +1 -1
- package/out/language-server/agenticChat/constants/modelSelection.d.ts +10 -2
- package/out/language-server/agenticChat/constants/modelSelection.js +11 -8
- package/out/language-server/agenticChat/constants/modelSelection.js.map +1 -1
- package/out/language-server/agenticChat/errors.d.ts +1 -1
- package/out/language-server/agenticChat/errors.js.map +1 -1
- package/out/language-server/agenticChat/tools/chatDb/chatDb.d.ts +10 -1
- package/out/language-server/agenticChat/tools/chatDb/chatDb.js +44 -0
- package/out/language-server/agenticChat/tools/chatDb/chatDb.js.map +1 -1
- package/out/language-server/agenticChat/tools/chatDb/util.d.ts +5 -1
- package/out/language-server/agenticChat/tools/chatDb/util.js +7 -0
- package/out/language-server/agenticChat/tools/chatDb/util.js.map +1 -1
- package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.d.ts +1 -0
- package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js +50 -30
- package/out/language-server/agenticChat/tools/mcp/mcpEventHandler.js.map +1 -1
- package/out/language-server/agenticChat/tools/mcp/mcpManager.d.ts +4 -0
- package/out/language-server/agenticChat/tools/mcp/mcpManager.js +98 -52
- package/out/language-server/agenticChat/tools/mcp/mcpManager.js.map +1 -1
- package/out/language-server/agenticChat/tools/mcp/mcpOauthClient.d.ts +53 -0
- package/out/language-server/agenticChat/tools/mcp/mcpOauthClient.js +422 -0
- package/out/language-server/agenticChat/tools/mcp/mcpOauthClient.js.map +1 -0
- package/out/language-server/agenticChat/tools/mcp/mcpUtils.d.ts +4 -0
- package/out/language-server/agenticChat/tools/mcp/mcpUtils.js +89 -69
- package/out/language-server/agenticChat/tools/mcp/mcpUtils.js.map +1 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js +15 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReview.js.map +1 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewSchemas.d.ts +4 -4
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewTypes.d.ts +2 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewTypes.js +1 -0
- package/out/language-server/agenticChat/tools/qCodeAnalysis/codeReviewTypes.js.map +1 -1
- package/out/language-server/agenticChat/tools/qCodeAnalysis/displayFindingsSchemas.d.ts +16 -16
- package/out/language-server/inline-completion/codeWhispererServer.js +5 -5
- package/out/language-server/inline-completion/codeWhispererServer.js.map +1 -1
- package/out/language-server/inline-completion/editCompletionHandler.d.ts +1 -0
- package/out/language-server/inline-completion/editCompletionHandler.js +6 -3
- package/out/language-server/inline-completion/editCompletionHandler.js.map +1 -1
- package/out/language-server/inline-completion/session/sessionManager.d.ts +0 -2
- package/out/language-server/inline-completion/session/sessionManager.js +0 -13
- package/out/language-server/inline-completion/session/sessionManager.js.map +1 -1
- package/out/language-server/inline-completion/tracker/streakTracker.d.ts +21 -0
- package/out/language-server/inline-completion/tracker/streakTracker.js +43 -0
- package/out/language-server/inline-completion/tracker/streakTracker.js.map +1 -0
- package/out/shared/amazonQServiceManager/AmazonQTokenServiceManager.js +3 -0
- package/out/shared/amazonQServiceManager/AmazonQTokenServiceManager.js.map +1 -1
- package/out/shared/codeWhispererService.d.ts +4 -0
- package/out/shared/codeWhispererService.js +6 -0
- package/out/shared/codeWhispererService.js.map +1 -1
- package/out/shared/constants.d.ts +1 -0
- package/out/shared/constants.js +2 -1
- package/out/shared/constants.js.map +1 -1
- package/out/shared/supplementalContextUtil/crossFileContextUtil.js +10 -1
- package/out/shared/supplementalContextUtil/crossFileContextUtil.js.map +1 -1
- package/package.json +2 -2
- package/out/language-server/agenticChat/utils/agenticChatControllerHelper.d.ts +0 -8
- package/out/language-server/agenticChat/utils/agenticChatControllerHelper.js +0 -15
- package/out/language-server/agenticChat/utils/agenticChatControllerHelper.js.map +0 -1
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright Amazon.com, Inc. or its affiliates.
|
|
4
|
+
* All Rights Reserved. SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.OAuthClient = void 0;
|
|
8
|
+
const crypto = require("crypto");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
const url_1 = require("url");
|
|
11
|
+
const http = require("http");
|
|
12
|
+
const os = require("os");
|
|
13
|
+
class OAuthClient {
|
|
14
|
+
static logger;
|
|
15
|
+
static workspace;
|
|
16
|
+
static lsp;
|
|
17
|
+
static initialize(ws, logger, lsp) {
|
|
18
|
+
this.workspace = ws;
|
|
19
|
+
this.logger = logger;
|
|
20
|
+
this.lsp = lsp;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Return a valid Bearer token, reusing cache or refresh-token if possible,
|
|
24
|
+
* otherwise (when interactive) driving one PKCE flow that may launch a browser.
|
|
25
|
+
*/
|
|
26
|
+
static async getValidAccessToken(mcpBase, opts = { interactive: false }) {
|
|
27
|
+
const interactive = opts?.interactive === true;
|
|
28
|
+
const key = this.computeKey(mcpBase);
|
|
29
|
+
const regPath = path.join(this.cacheDir, `${key}.registration.json`);
|
|
30
|
+
const tokPath = path.join(this.cacheDir, `${key}.token.json`);
|
|
31
|
+
// ===== Silent branch: try cached token, then refresh, never opens a browser =====
|
|
32
|
+
if (!interactive) {
|
|
33
|
+
// 1) cached access token
|
|
34
|
+
const cachedTok = await this.read(tokPath);
|
|
35
|
+
if (cachedTok) {
|
|
36
|
+
const expiry = cachedTok.obtained_at + cachedTok.expires_in * 1000;
|
|
37
|
+
if (Date.now() < expiry) {
|
|
38
|
+
this.logger.info(`OAuth: using still-valid cached token (silent)`);
|
|
39
|
+
return cachedTok.access_token;
|
|
40
|
+
}
|
|
41
|
+
this.logger.info(`OAuth: cached token expired → try refresh (silent)`);
|
|
42
|
+
}
|
|
43
|
+
// 2) refresh-token grant (if we have registration and refresh token)
|
|
44
|
+
const savedReg = await this.read(regPath);
|
|
45
|
+
if (cachedTok?.refresh_token && savedReg) {
|
|
46
|
+
try {
|
|
47
|
+
const meta = await this.discoverAS(mcpBase);
|
|
48
|
+
const refreshed = await this.refreshGrant(meta, savedReg, mcpBase, cachedTok.refresh_token);
|
|
49
|
+
if (refreshed) {
|
|
50
|
+
await this.write(tokPath, refreshed);
|
|
51
|
+
this.logger.info(`OAuth: refresh grant succeeded (silent)`);
|
|
52
|
+
return refreshed.access_token;
|
|
53
|
+
}
|
|
54
|
+
this.logger.info(`OAuth: refresh grant did not succeed (silent)`);
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
this.logger.warn(`OAuth: silent refresh failed — ${e instanceof Error ? e.message : String(e)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// 3) no token in silent mode → caller should surface auth-required UI
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
// ===== Interactive branch: may open a browser (PKCE) =====
|
|
64
|
+
// 1) Spin up (or reuse) loopback server + redirect URI
|
|
65
|
+
let server = null;
|
|
66
|
+
let redirectUri;
|
|
67
|
+
const savedReg = await this.read(regPath);
|
|
68
|
+
if (savedReg) {
|
|
69
|
+
const port = Number(new url_1.URL(savedReg.redirect_uri).port);
|
|
70
|
+
const normalized = `http://127.0.0.1:${port}`;
|
|
71
|
+
server = http.createServer();
|
|
72
|
+
try {
|
|
73
|
+
await this.listen(server, port, '127.0.0.1');
|
|
74
|
+
redirectUri = normalized;
|
|
75
|
+
this.logger.info(`OAuth: reusing redirect URI ${redirectUri}`);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
if (e.code === 'EADDRINUSE') {
|
|
79
|
+
try {
|
|
80
|
+
server.close();
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
/* ignore */
|
|
84
|
+
}
|
|
85
|
+
this.logger.warn(`Port ${port} in use; falling back to new random port`);
|
|
86
|
+
({ server, redirectUri } = await this.buildCallbackServer());
|
|
87
|
+
this.logger.info(`OAuth: new redirect URI ${redirectUri}`);
|
|
88
|
+
await this.workspace.fs.rm(regPath);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
throw e;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
const created = await this.buildCallbackServer();
|
|
97
|
+
server = created.server;
|
|
98
|
+
redirectUri = created.redirectUri;
|
|
99
|
+
this.logger.info(`OAuth: new redirect URI ${redirectUri}`);
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
// 2) Try still-valid cached access_token
|
|
103
|
+
const cached = await this.read(tokPath);
|
|
104
|
+
if (cached) {
|
|
105
|
+
const expiry = cached.obtained_at + cached.expires_in * 1000;
|
|
106
|
+
if (Date.now() < expiry) {
|
|
107
|
+
this.logger.info(`OAuth: using still-valid cached token`);
|
|
108
|
+
return cached.access_token;
|
|
109
|
+
}
|
|
110
|
+
this.logger.info(`OAuth: cached token expired → try refresh`);
|
|
111
|
+
}
|
|
112
|
+
// 3) Discover AS metadata
|
|
113
|
+
let meta;
|
|
114
|
+
try {
|
|
115
|
+
meta = await this.discoverAS(mcpBase);
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
throw new Error(`OAuth discovery failed: ${e?.message ?? String(e)}`);
|
|
119
|
+
}
|
|
120
|
+
// 4) Register (or reuse) a dynamic client
|
|
121
|
+
const scopes = ['openid', 'offline_access'];
|
|
122
|
+
let reg;
|
|
123
|
+
try {
|
|
124
|
+
reg = await this.obtainClient(meta, regPath, scopes, redirectUri);
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
throw new Error(`OAuth client registration failed: ${e?.message ?? String(e)}`);
|
|
128
|
+
}
|
|
129
|
+
// 5) Refresh-token grant (one shot)
|
|
130
|
+
const attemptedRefresh = !!cached?.refresh_token;
|
|
131
|
+
if (cached?.refresh_token) {
|
|
132
|
+
const refreshed = await this.refreshGrant(meta, reg, mcpBase, cached.refresh_token);
|
|
133
|
+
if (refreshed) {
|
|
134
|
+
await this.write(tokPath, refreshed);
|
|
135
|
+
this.logger.info(`OAuth: refresh grant succeeded`);
|
|
136
|
+
return refreshed.access_token;
|
|
137
|
+
}
|
|
138
|
+
this.logger.info(`OAuth: refresh grant failed`);
|
|
139
|
+
}
|
|
140
|
+
// 6) PKCE interactive flow
|
|
141
|
+
try {
|
|
142
|
+
const fresh = await this.pkceGrant(meta, reg, mcpBase, scopes, redirectUri, server);
|
|
143
|
+
await this.write(tokPath, fresh);
|
|
144
|
+
return fresh.access_token;
|
|
145
|
+
}
|
|
146
|
+
catch (e) {
|
|
147
|
+
const suffix = attemptedRefresh ? ' after refresh attempt' : '';
|
|
148
|
+
throw new Error(`OAuth authorization (PKCE) failed${suffix}: ${e?.message ?? String(e)}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
if (server) {
|
|
153
|
+
await new Promise(res => server.close(() => res()));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Spin up a one‑time HTTP listener on localhost:randomPort */
|
|
158
|
+
static async buildCallbackServer() {
|
|
159
|
+
const server = http.createServer();
|
|
160
|
+
await this.listen(server, 0, '127.0.0.1');
|
|
161
|
+
const port = server.address().port;
|
|
162
|
+
return { server, redirectUri: `http://127.0.0.1:${port}` };
|
|
163
|
+
}
|
|
164
|
+
/** Discover OAuth endpoints by HEAD/WWW‑Authenticate, well‑known, or fallback */
|
|
165
|
+
static async discoverAS(rs) {
|
|
166
|
+
// a) HEAD → WWW‑Authenticate → resource_metadata
|
|
167
|
+
try {
|
|
168
|
+
this.logger.info('MCP OAuth: attempting discovery via WWW-Authenticate header');
|
|
169
|
+
const h = await this.fetchCompat(rs.toString(), { method: 'HEAD' });
|
|
170
|
+
const header = h.headers.get('www-authenticate') || '';
|
|
171
|
+
const m = /resource_metadata=(?:"([^"]+)"|([^,\s]+))/i.exec(header);
|
|
172
|
+
if (m) {
|
|
173
|
+
const metaUrl = new url_1.URL(m[1] || m[2], rs).toString();
|
|
174
|
+
this.logger.info(`OAuth: resource_metadata → ${metaUrl}`);
|
|
175
|
+
const raw = await this.json(metaUrl);
|
|
176
|
+
return await this.fetchASFromResourceMeta(raw, metaUrl);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
this.logger.info('MCP OAuth: no resource_metadata found in WWW-Authenticate header');
|
|
181
|
+
}
|
|
182
|
+
// b) well‑known on resource host
|
|
183
|
+
this.logger.info('MCP OAuth: attempting discovery via well-known endpoints');
|
|
184
|
+
const probes = [
|
|
185
|
+
new url_1.URL('.well-known/oauth-authorization-server', rs).toString(),
|
|
186
|
+
new url_1.URL('.well-known/openid-configuration', rs).toString(),
|
|
187
|
+
`${rs.origin}/.well-known/oauth-authorization-server`,
|
|
188
|
+
`${rs.origin}/.well-known/openid-configuration`,
|
|
189
|
+
];
|
|
190
|
+
for (const url of probes) {
|
|
191
|
+
try {
|
|
192
|
+
this.logger.info(`MCP OAuth: probing well-known endpoint → ${url}`);
|
|
193
|
+
return await this.json(url);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
this.logger.info(`OAuth: well-known endpoint probe failed for ${url}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// c) fallback to static OAuth2 endpoints
|
|
200
|
+
const base = (rs.origin + rs.pathname).replace(/\/+$/, '');
|
|
201
|
+
this.logger.warn(`OAuth: all discovery attempts failed, synthesizing endpoints from ${base}`);
|
|
202
|
+
return {
|
|
203
|
+
authorization_endpoint: `${base}/authorize`,
|
|
204
|
+
token_endpoint: `${base}/access_token`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
/** Follow `authorization_server(s)` in resource_metadata JSON */
|
|
208
|
+
static async fetchASFromResourceMeta(raw, metaUrl) {
|
|
209
|
+
let asBase = raw.authorization_server;
|
|
210
|
+
if (!asBase && Array.isArray(raw.authorization_servers)) {
|
|
211
|
+
asBase = raw.authorization_servers[0];
|
|
212
|
+
}
|
|
213
|
+
if (!asBase) {
|
|
214
|
+
throw new Error(`resource_metadata at ${metaUrl} lacked authorization_server(s)`);
|
|
215
|
+
}
|
|
216
|
+
// Attempt both OAuth‑AS and OIDC well‑known
|
|
217
|
+
for (const p of ['.well-known/oauth-authorization-server', '.well-known/openid-configuration']) {
|
|
218
|
+
try {
|
|
219
|
+
return await this.json(new url_1.URL(p, asBase).toString());
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// next
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// fallback to static OAuth2 endpoints
|
|
226
|
+
this.logger.warn(`OAuth: no well-known on ${asBase}, falling back to static endpoints`);
|
|
227
|
+
return {
|
|
228
|
+
authorization_endpoint: `${asBase}/authorize`,
|
|
229
|
+
token_endpoint: `${asBase}/access_token`,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/** DCR: POST client metadata → client_id; cache to disk */
|
|
233
|
+
static async obtainClient(meta, file, scopes, redirectUri) {
|
|
234
|
+
const existing = await this.read(file);
|
|
235
|
+
if (existing && (!existing.expires_at || existing.expires_at * 1000 > Date.now())) {
|
|
236
|
+
this.logger.info(`OAuth: reusing client_id ${existing.client_id}`);
|
|
237
|
+
return existing;
|
|
238
|
+
}
|
|
239
|
+
if (!meta.registration_endpoint) {
|
|
240
|
+
throw new Error('OAuth: AS does not support dynamic registration');
|
|
241
|
+
}
|
|
242
|
+
const body = {
|
|
243
|
+
client_name: 'AWS MCP LSP',
|
|
244
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
245
|
+
response_types: ['code'],
|
|
246
|
+
token_endpoint_auth_method: 'none',
|
|
247
|
+
scope: scopes.join(' '),
|
|
248
|
+
redirect_uris: [redirectUri],
|
|
249
|
+
};
|
|
250
|
+
const resp = await this.json(meta.registration_endpoint, {
|
|
251
|
+
method: 'POST',
|
|
252
|
+
headers: { 'content-type': 'application/json' },
|
|
253
|
+
body: JSON.stringify(body),
|
|
254
|
+
});
|
|
255
|
+
const reg = {
|
|
256
|
+
client_id: resp.client_id,
|
|
257
|
+
client_secret: resp.client_secret,
|
|
258
|
+
expires_at: resp.client_secret_expires_at,
|
|
259
|
+
redirect_uri: redirectUri,
|
|
260
|
+
};
|
|
261
|
+
await this.write(file, reg);
|
|
262
|
+
return reg;
|
|
263
|
+
}
|
|
264
|
+
/** Try one refresh_token grant; returns new Token or `undefined` */
|
|
265
|
+
static async refreshGrant(meta, reg, rs, refresh) {
|
|
266
|
+
const form = new url_1.URLSearchParams({
|
|
267
|
+
grant_type: 'refresh_token',
|
|
268
|
+
refresh_token: refresh,
|
|
269
|
+
client_id: reg.client_id,
|
|
270
|
+
resource: rs.toString(),
|
|
271
|
+
});
|
|
272
|
+
const res = await this.fetchCompat(meta.token_endpoint, {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
275
|
+
body: form,
|
|
276
|
+
});
|
|
277
|
+
if (!res.ok) {
|
|
278
|
+
const msg = await res.text().catch(() => '');
|
|
279
|
+
this.logger.warn(`OAuth: refresh grant HTTP ${res.status} — ${msg?.slice(0, 300)}`);
|
|
280
|
+
return undefined;
|
|
281
|
+
}
|
|
282
|
+
const tokenResponse = (await res.json());
|
|
283
|
+
return { ...tokenResponse, obtained_at: Date.now() };
|
|
284
|
+
}
|
|
285
|
+
/** One PKCE flow: browser + loopback → code → token */
|
|
286
|
+
static async pkceGrant(meta, reg, rs, scopes, redirectUri, server) {
|
|
287
|
+
const DEFAULT_PKCE_TIMEOUT_MS = 90_000;
|
|
288
|
+
// a) generate PKCE params
|
|
289
|
+
const verifier = this.b64url(crypto.randomBytes(32));
|
|
290
|
+
const challenge = this.b64url(crypto.createHash('sha256').update(verifier).digest());
|
|
291
|
+
const state = this.b64url(crypto.randomBytes(16));
|
|
292
|
+
// b) build authorize URL + launch browser
|
|
293
|
+
const authz = new url_1.URL(meta.authorization_endpoint);
|
|
294
|
+
authz.search = new url_1.URLSearchParams({
|
|
295
|
+
client_id: reg.client_id,
|
|
296
|
+
response_type: 'code',
|
|
297
|
+
code_challenge: challenge,
|
|
298
|
+
code_challenge_method: 'S256',
|
|
299
|
+
resource: rs.toString(),
|
|
300
|
+
scope: scopes.join(' '),
|
|
301
|
+
redirect_uri: redirectUri,
|
|
302
|
+
state: state,
|
|
303
|
+
}).toString();
|
|
304
|
+
await this.lsp.window.showDocument({ uri: authz.toString(), external: true });
|
|
305
|
+
// c) wait for code on our loopback
|
|
306
|
+
const waitForFlow = new Promise(resolve => {
|
|
307
|
+
server.on('request', (req, res) => {
|
|
308
|
+
const u = new url_1.URL(req.url || '/', redirectUri);
|
|
309
|
+
const c = u.searchParams.get('code') || '';
|
|
310
|
+
const s = u.searchParams.get('state') || '';
|
|
311
|
+
const e = u.searchParams.get('error') || undefined;
|
|
312
|
+
const ed = u.searchParams.get('error_description') || undefined;
|
|
313
|
+
res.writeHead(200, { 'content-type': 'text/html' }).end('<h2>You may close this tab.</h2>');
|
|
314
|
+
resolve({ code: c, rxState: s, err: e, errDesc: ed });
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
const { code, rxState, err, errDesc } = await Promise.race([
|
|
318
|
+
waitForFlow,
|
|
319
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('authorization_timed_out')), DEFAULT_PKCE_TIMEOUT_MS)),
|
|
320
|
+
]);
|
|
321
|
+
if (err) {
|
|
322
|
+
throw new Error(`Authorization error: ${err}${errDesc ? ` - ${errDesc}` : ''}`);
|
|
323
|
+
}
|
|
324
|
+
if (!code || rxState !== state)
|
|
325
|
+
throw new Error('Invalid authorization response (state mismatch)');
|
|
326
|
+
// d) exchange code for token
|
|
327
|
+
const form2 = new url_1.URLSearchParams({
|
|
328
|
+
grant_type: 'authorization_code',
|
|
329
|
+
code,
|
|
330
|
+
code_verifier: verifier,
|
|
331
|
+
client_id: reg.client_id,
|
|
332
|
+
redirect_uri: redirectUri,
|
|
333
|
+
resource: rs.toString(),
|
|
334
|
+
});
|
|
335
|
+
const res2 = await this.fetchCompat(meta.token_endpoint, {
|
|
336
|
+
method: 'POST',
|
|
337
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
338
|
+
body: form2,
|
|
339
|
+
});
|
|
340
|
+
if (!res2.ok) {
|
|
341
|
+
const txt = await res2.text().catch(() => '');
|
|
342
|
+
throw new Error(`Token exchange failed (HTTP ${res2.status}): ${txt?.slice(0, 300)}`);
|
|
343
|
+
}
|
|
344
|
+
const tk = (await res2.json());
|
|
345
|
+
return { ...tk, obtained_at: Date.now() };
|
|
346
|
+
}
|
|
347
|
+
/** Fetch + error‑check + parse JSON */
|
|
348
|
+
static async json(url, init) {
|
|
349
|
+
const r = await this.fetchCompat(url, init);
|
|
350
|
+
if (!r.ok) {
|
|
351
|
+
const txt = await r.text().catch(() => '');
|
|
352
|
+
throw new Error(`HTTP ${r.status}@${url} — ${txt}`);
|
|
353
|
+
}
|
|
354
|
+
return (await r.json());
|
|
355
|
+
}
|
|
356
|
+
/** Read & parse JSON file via workspace.fs */
|
|
357
|
+
static async read(file) {
|
|
358
|
+
try {
|
|
359
|
+
if (!(await this.workspace.fs.exists(file)))
|
|
360
|
+
return undefined;
|
|
361
|
+
const buf = await this.workspace.fs.readFile(file);
|
|
362
|
+
return JSON.parse(buf.toString());
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return undefined;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/** Write JSON, then clamp file perms to 0600 (owner read/write) */
|
|
369
|
+
static async write(file, obj) {
|
|
370
|
+
const dir = path.dirname(file);
|
|
371
|
+
await this.workspace.fs.mkdir(dir, { recursive: true });
|
|
372
|
+
await this.workspace.fs.writeFile(file, JSON.stringify(obj, null, 2), { mode: 0o600 });
|
|
373
|
+
}
|
|
374
|
+
/** SHA‑256 of resourceServer URL → hex key */
|
|
375
|
+
static computeKey(rs) {
|
|
376
|
+
return crypto
|
|
377
|
+
.createHash('sha256')
|
|
378
|
+
.update(rs.origin + rs.pathname)
|
|
379
|
+
.digest('hex');
|
|
380
|
+
}
|
|
381
|
+
/** RFC‑7636 base64url without padding */
|
|
382
|
+
static b64url(buf) {
|
|
383
|
+
return buf.toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
384
|
+
}
|
|
385
|
+
/** Directory for caching registration + tokens */
|
|
386
|
+
static cacheDir = path.join(os.homedir(), '.aws', 'sso', 'cache');
|
|
387
|
+
/**
|
|
388
|
+
* Await server.listen() but reject if it emits 'error' (eg EADDRINUSE),
|
|
389
|
+
* so callers can handle it immediately instead of hanging.
|
|
390
|
+
*/
|
|
391
|
+
static listen(server, port, host = '127.0.0.1') {
|
|
392
|
+
return new Promise((resolve, reject) => {
|
|
393
|
+
const onListening = () => {
|
|
394
|
+
server.off('error', onError);
|
|
395
|
+
resolve();
|
|
396
|
+
};
|
|
397
|
+
const onError = (err) => {
|
|
398
|
+
server.off('listening', onListening);
|
|
399
|
+
reject(err);
|
|
400
|
+
};
|
|
401
|
+
server.once('listening', onListening);
|
|
402
|
+
server.once('error', onError);
|
|
403
|
+
server.listen(port, host);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Fetch compatibility: use global fetch on Node >= 18, otherwise dynamically import('node-fetch').
|
|
408
|
+
* Using Function('return import(...)') avoids downleveling to require() in CJS builds.
|
|
409
|
+
*/
|
|
410
|
+
static async fetchCompat(url, init) {
|
|
411
|
+
const globalObj = globalThis;
|
|
412
|
+
if (typeof globalObj.fetch === 'function') {
|
|
413
|
+
return globalObj.fetch(url, init);
|
|
414
|
+
}
|
|
415
|
+
// Dynamic import of ESM node-fetch (only when global fetch is unavailable)
|
|
416
|
+
const mod = await Function('return import("node-fetch")')();
|
|
417
|
+
const f = mod.default ?? mod;
|
|
418
|
+
return f(url, init);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
exports.OAuthClient = OAuthClient;
|
|
422
|
+
//# sourceMappingURL=mcpOauthClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpOauthClient.js","sourceRoot":"","sources":["../../../../../src/language-server/agenticChat/tools/mcp/mcpOauthClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -74,6 +74,10 @@ export declare function normalizePathFromUri(path: string, logging?: Logger): st
|
|
|
74
74
|
*/
|
|
75
75
|
export declare function migrateToAgentConfig(workspace: Workspace, logging: Logger, agent: Agent): Promise<void>;
|
|
76
76
|
export declare function saveAgentConfig(workspace: Workspace, logging: Logger, config: AgentConfig, configPath: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Save only server-specific changes to agent config file
|
|
79
|
+
*/
|
|
80
|
+
export declare function saveServerSpecificAgentConfig(workspace: Workspace, logging: Logger, serverName: string, serverConfig: any, serverTools: string[], serverAllowedTools: string[], configPath: string): Promise<void>;
|
|
77
81
|
export declare const MAX_TOOL_NAME_LENGTH = 64;
|
|
78
82
|
/**
|
|
79
83
|
* Create a namespaced tool name from server and tool names.
|
|
@@ -21,6 +21,7 @@ exports.sanitizeName = sanitizeName;
|
|
|
21
21
|
exports.normalizePathFromUri = normalizePathFromUri;
|
|
22
22
|
exports.migrateToAgentConfig = migrateToAgentConfig;
|
|
23
23
|
exports.saveAgentConfig = saveAgentConfig;
|
|
24
|
+
exports.saveServerSpecificAgentConfig = saveServerSpecificAgentConfig;
|
|
24
25
|
exports.createNamespacedToolName = createNamespacedToolName;
|
|
25
26
|
const vscode_uri_1 = require("vscode-uri");
|
|
26
27
|
const mcpTypes_1 = require("./mcpTypes");
|
|
@@ -168,7 +169,9 @@ const DEFAULT_AGENT_RAW = `{
|
|
|
168
169
|
"README.md",
|
|
169
170
|
".amazonq/rules/**/*.md"
|
|
170
171
|
],
|
|
171
|
-
"resources": []
|
|
172
|
+
"resources": [],
|
|
173
|
+
"createHooks": [],
|
|
174
|
+
"promptHooks": []
|
|
172
175
|
}`;
|
|
173
176
|
const DEFAULT_PERSONA_RAW = `{
|
|
174
177
|
"mcpServers": [
|
|
@@ -725,43 +728,35 @@ async function migrateConfigToAgent(workspace, logging, configPath, personaPath,
|
|
|
725
728
|
const normalizedConfigPath = normalizePathFromUri(configPath, logging);
|
|
726
729
|
const normalizedPersonaPath = normalizePathFromUri(personaPath, logging);
|
|
727
730
|
agentPath = normalizePathFromUri(agentPath);
|
|
728
|
-
// Check if agent
|
|
731
|
+
// Check if config and agent files exist
|
|
732
|
+
const configExists = await workspace.fs.exists(normalizedConfigPath).catch(() => false);
|
|
729
733
|
const agentExists = await workspace.fs.exists(agentPath).catch(() => false);
|
|
730
|
-
//
|
|
731
|
-
|
|
734
|
+
// Only migrate if agent file does not exist
|
|
735
|
+
// If config exists, migrate from it; if not, create default agent config
|
|
732
736
|
if (agentExists) {
|
|
733
|
-
|
|
734
|
-
const raw = (await workspace.fs.readFile(agentPath)).toString().trim();
|
|
735
|
-
existingAgentConfig = raw ? JSON.parse(raw) : undefined;
|
|
736
|
-
}
|
|
737
|
-
catch (err) {
|
|
738
|
-
logging.warn(`Failed to read existing agent config at ${agentPath}: ${err}`);
|
|
739
|
-
}
|
|
737
|
+
return;
|
|
740
738
|
}
|
|
741
739
|
// Read MCP server configs directly from file
|
|
742
740
|
const serverConfigs = {};
|
|
743
741
|
try {
|
|
744
|
-
const
|
|
745
|
-
if (
|
|
746
|
-
const
|
|
747
|
-
if (
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
};
|
|
763
|
-
logging.info(`Added server ${name} to serverConfigs`);
|
|
764
|
-
}
|
|
742
|
+
const raw = (await workspace.fs.readFile(normalizedConfigPath)).toString().trim();
|
|
743
|
+
if (raw) {
|
|
744
|
+
const config = JSON.parse(raw);
|
|
745
|
+
if (config.mcpServers && typeof config.mcpServers === 'object') {
|
|
746
|
+
// Add each server to the serverConfigs
|
|
747
|
+
for (const [name, serverConfig] of Object.entries(config.mcpServers)) {
|
|
748
|
+
serverConfigs[name] = {
|
|
749
|
+
command: serverConfig.command,
|
|
750
|
+
args: Array.isArray(serverConfig.args) ? serverConfig.args : undefined,
|
|
751
|
+
env: typeof serverConfig.env === 'object' ? serverConfig.env : undefined,
|
|
752
|
+
initializationTimeout: typeof serverConfig.initializationTimeout === 'number'
|
|
753
|
+
? serverConfig.initializationTimeout
|
|
754
|
+
: undefined,
|
|
755
|
+
timeout: typeof serverConfig.timeout === 'number'
|
|
756
|
+
? serverConfig.timeout
|
|
757
|
+
: undefined,
|
|
758
|
+
};
|
|
759
|
+
logging.info(`Added server ${name} to serverConfigs`);
|
|
765
760
|
}
|
|
766
761
|
}
|
|
767
762
|
}
|
|
@@ -787,45 +782,21 @@ async function migrateConfigToAgent(workspace, logging, configPath, personaPath,
|
|
|
787
782
|
logging.warn(`Failed to read persona config at ${normalizedPersonaPath}: ${err}`);
|
|
788
783
|
}
|
|
789
784
|
// Convert to agent config
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
//
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
...newAgentConfig.mcpServers,
|
|
802
|
-
...existingAgentConfig.mcpServers,
|
|
803
|
-
},
|
|
804
|
-
// Merge tools lists without duplicates
|
|
805
|
-
tools: [...new Set([...existingAgentConfig.tools, ...newAgentConfig.tools])],
|
|
806
|
-
allowedTools: [...new Set([...existingAgentConfig.allowedTools, ...newAgentConfig.allowedTools])],
|
|
807
|
-
// Merge tool settings, preferring existing ones
|
|
808
|
-
toolsSettings: {
|
|
809
|
-
...newAgentConfig.toolsSettings,
|
|
810
|
-
...existingAgentConfig.toolsSettings,
|
|
811
|
-
},
|
|
812
|
-
// Keep other properties from existing config
|
|
813
|
-
includedFiles: existingAgentConfig.includedFiles || newAgentConfig.includedFiles,
|
|
814
|
-
createHooks: existingAgentConfig.createHooks || newAgentConfig.createHooks,
|
|
815
|
-
promptHooks: [
|
|
816
|
-
...new Set([...(existingAgentConfig.promptHooks || []), ...(newAgentConfig.promptHooks || [])]),
|
|
817
|
-
],
|
|
818
|
-
resources: [...new Set([...(existingAgentConfig.resources || []), ...(newAgentConfig.resources || [])])],
|
|
819
|
-
};
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
finalAgentConfig = newAgentConfig;
|
|
823
|
-
logging.info(`Using new config (no existing config to merge)`);
|
|
824
|
-
}
|
|
785
|
+
const agentConfig = convertPersonaToAgent(personaConfig, serverConfigs, agent);
|
|
786
|
+
// Parse default values from DEFAULT_AGENT_RAW
|
|
787
|
+
const defaultAgent = JSON.parse(DEFAULT_AGENT_RAW);
|
|
788
|
+
// Add complete agent format sections using default values
|
|
789
|
+
agentConfig.name = defaultAgent.name;
|
|
790
|
+
agentConfig.description = defaultAgent.description;
|
|
791
|
+
agentConfig.version = defaultAgent.version;
|
|
792
|
+
agentConfig.includedFiles = defaultAgent.includedFiles;
|
|
793
|
+
agentConfig.resources = defaultAgent.resources;
|
|
794
|
+
agentConfig.createHooks = defaultAgent.createHooks;
|
|
795
|
+
agentConfig.promptHooks = defaultAgent.promptHooks;
|
|
825
796
|
// Save agent config
|
|
826
797
|
try {
|
|
827
|
-
await saveAgentConfig(workspace, logging,
|
|
828
|
-
logging.info(`Successfully
|
|
798
|
+
await saveAgentConfig(workspace, logging, agentConfig, agentPath);
|
|
799
|
+
logging.info(`Successfully created agent config at ${agentPath}`);
|
|
829
800
|
}
|
|
830
801
|
catch (err) {
|
|
831
802
|
logging.error(`Failed to save agent config to ${agentPath}: ${err}`);
|
|
@@ -844,6 +815,55 @@ async function saveAgentConfig(workspace, logging, config, configPath) {
|
|
|
844
815
|
throw err;
|
|
845
816
|
}
|
|
846
817
|
}
|
|
818
|
+
/**
|
|
819
|
+
* Save only server-specific changes to agent config file
|
|
820
|
+
*/
|
|
821
|
+
async function saveServerSpecificAgentConfig(workspace, logging, serverName, serverConfig, serverTools, serverAllowedTools, configPath) {
|
|
822
|
+
try {
|
|
823
|
+
await workspace.fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
824
|
+
// Read existing config
|
|
825
|
+
let existingConfig;
|
|
826
|
+
try {
|
|
827
|
+
const raw = await workspace.fs.readFile(configPath);
|
|
828
|
+
existingConfig = JSON.parse(raw.toString());
|
|
829
|
+
}
|
|
830
|
+
catch {
|
|
831
|
+
// If file doesn't exist, create minimal config
|
|
832
|
+
existingConfig = {
|
|
833
|
+
name: 'default-agent',
|
|
834
|
+
version: '1.0.0',
|
|
835
|
+
description: 'Agent configuration',
|
|
836
|
+
mcpServers: {},
|
|
837
|
+
tools: [],
|
|
838
|
+
allowedTools: [],
|
|
839
|
+
toolsSettings: {},
|
|
840
|
+
includedFiles: [],
|
|
841
|
+
resources: [],
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
// Remove existing server tools from arrays
|
|
845
|
+
const serverPrefix = `@${serverName}`;
|
|
846
|
+
existingConfig.tools = existingConfig.tools.filter(tool => tool !== serverPrefix && !tool.startsWith(`${serverPrefix}/`));
|
|
847
|
+
existingConfig.allowedTools = existingConfig.allowedTools.filter(tool => tool !== serverPrefix && !tool.startsWith(`${serverPrefix}/`));
|
|
848
|
+
if (serverConfig === null) {
|
|
849
|
+
// Remove server entirely
|
|
850
|
+
delete existingConfig.mcpServers[serverName];
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
// Update or add server
|
|
854
|
+
existingConfig.mcpServers[serverName] = serverConfig;
|
|
855
|
+
// Add new server tools
|
|
856
|
+
existingConfig.tools.push(...serverTools);
|
|
857
|
+
existingConfig.allowedTools.push(...serverAllowedTools);
|
|
858
|
+
}
|
|
859
|
+
await workspace.fs.writeFile(configPath, JSON.stringify(existingConfig, null, 2));
|
|
860
|
+
logging.info(`Saved server-specific agent config for ${serverName} to ${configPath}`);
|
|
861
|
+
}
|
|
862
|
+
catch (err) {
|
|
863
|
+
logging.error(`Failed to save server-specific agent config to ${configPath}: ${err.message}`);
|
|
864
|
+
throw err;
|
|
865
|
+
}
|
|
866
|
+
}
|
|
847
867
|
exports.MAX_TOOL_NAME_LENGTH = 64;
|
|
848
868
|
/**
|
|
849
869
|
* Create a namespaced tool name from server and tool names.
|