Skip to content

Commit 2be96ab

Browse files
authored
Merge branch 'main' into eli/prompt-tile-style-clean
2 parents 2712eee + b5dc5c5 commit 2be96ab

32 files changed

Lines changed: 745 additions & 129 deletions

File tree

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@ function f(x: number, y: string): void { }
133133
- Look for existing test patterns before creating new structures
134134
- Use `describe` and `test` consistently with existing patterns
135135
- If you create any temporary new files, scripts, or helper files for iteration, clean up these files by removing them at the end of the task
136+
- Do not use `any` or `unknown` as the type for variables, parameters, or return values unless absolutely necessary. If they need type annotations, they should have proper types or interfaces defined.

build/lib/tsb/builder.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/lib/tsb/builder.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,9 @@ export function createTypeScriptBuilder(config: IConfiguration, projectFile: str
440440
messageText: `CYCLIC dependency: ${error}`
441441
});
442442
}
443+
delete oldErrors[filename];
443444
newErrors[filename] = cyclicDepErrors;
445+
cyclicDepErrors.forEach(d => onError(d));
444446
}
445447

446448
}).then(() => {

extensions/mermaid-chat-features/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/theme-defaults/themes/dark_modern.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@
8888
"sideBarTitle.foreground": "#CCCCCC",
8989
"statusBar.background": "#181818",
9090
"statusBar.border": "#2B2B2B",
91+
"statusBarItem.hoverBackground": "#F1F1F133",
92+
"statusBarItem.hoverForeground": "#FFFFFF",
9193
"statusBar.debuggingBackground": "#0078D4",
9294
"statusBar.debuggingForeground": "#FFFFFF",
9395
"statusBar.focusBorder": "#0078D4",

extensions/theme-defaults/themes/light_modern.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@
104104
"statusBar.background": "#F8F8F8",
105105
"statusBar.foreground": "#3B3B3B",
106106
"statusBar.border": "#E5E5E5",
107-
"statusBarItem.hoverBackground": "#B8B8B850",
107+
"statusBarItem.hoverBackground": "#1F1F1F11",
108+
"statusBarItem.hoverForeground": "#000000",
108109
"statusBarItem.compactHoverBackground": "#CCCCCC",
109110
"statusBar.debuggingBackground": "#FD716C",
110111
"statusBar.debuggingForeground": "#000000",

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "code-oss-dev",
33
"version": "1.105.0",
4-
"distro": "9e823daeded19d4a7c8f7e3ba36ca5d3c68d8350",
4+
"distro": "8b551ae26e4dadc3f6ece34bbbc3feea81ce4a97",
55
"author": {
66
"name": "Microsoft Corporation"
77
},
@@ -239,4 +239,4 @@
239239
"optionalDependencies": {
240240
"windows-foreground-love": "0.5.0"
241241
}
242-
}
242+
}

src/vs/base/common/oauth.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,3 +957,120 @@ export function scopesMatch(scopes1: readonly string[], scopes2: readonly string
957957

958958
return sortedScopes1.every((scope, index) => scope === sortedScopes2[index]);
959959
}
960+
961+
interface CommonResponse {
962+
status: number;
963+
statusText: string;
964+
json(): Promise<any>;
965+
text(): Promise<string>;
966+
}
967+
968+
interface IFetcher {
969+
(input: string, init: { method: string; headers: Record<string, string> }): Promise<CommonResponse>;
970+
}
971+
972+
export interface IFetchResourceMetadataOptions {
973+
/**
974+
* Headers to include only when the resource metadata URL has the same origin as the target resource
975+
*/
976+
sameOriginHeaders?: Record<string, string>;
977+
/**
978+
* Optional custom fetch implementation (defaults to global fetch)
979+
*/
980+
fetch?: IFetcher;
981+
}
982+
983+
/**
984+
* Fetches and validates OAuth 2.0 protected resource metadata from the given URL.
985+
*
986+
* @param targetResource The target resource URL to compare origins with (e.g., the MCP server URL)
987+
* @param resourceMetadataUrl Optional URL to fetch the resource metadata from. If not provided, will try well-known URIs.
988+
* @param options Configuration options for the fetch operation
989+
* @returns Promise that resolves to the validated resource metadata
990+
* @throws Error if the fetch fails, returns non-200 status, or the response is invalid
991+
*/
992+
export async function fetchResourceMetadata(
993+
targetResource: string,
994+
resourceMetadataUrl: string | undefined,
995+
options: IFetchResourceMetadataOptions = {}
996+
): Promise<IAuthorizationProtectedResourceMetadata> {
997+
const {
998+
sameOriginHeaders = {},
999+
fetch: fetchImpl = fetch
1000+
} = options;
1001+
1002+
const targetResourceUrlObj = new URL(targetResource);
1003+
1004+
// If no resourceMetadataUrl is provided, try well-known URIs as per RFC 9728
1005+
let urlsToTry: string[];
1006+
if (!resourceMetadataUrl) {
1007+
// Try in order: 1) with path appended, 2) at root
1008+
const pathComponent = targetResourceUrlObj.pathname === '/' ? undefined : targetResourceUrlObj.pathname;
1009+
const rootUrl = `${targetResourceUrlObj.origin}${AUTH_PROTECTED_RESOURCE_METADATA_DISCOVERY_PATH}`;
1010+
if (pathComponent) {
1011+
// Only try both URLs if we have a path component
1012+
urlsToTry = [
1013+
`${rootUrl}${pathComponent}`,
1014+
rootUrl
1015+
];
1016+
} else {
1017+
// If target is already at root, only try the root URL once
1018+
urlsToTry = [rootUrl];
1019+
}
1020+
} else {
1021+
urlsToTry = [resourceMetadataUrl];
1022+
}
1023+
1024+
const errors: Error[] = [];
1025+
for (const urlToTry of urlsToTry) {
1026+
try {
1027+
// Determine if we should include same-origin headers
1028+
let headers: Record<string, string> = {
1029+
'Accept': 'application/json'
1030+
};
1031+
1032+
const resourceMetadataUrlObj = new URL(urlToTry);
1033+
if (resourceMetadataUrlObj.origin === targetResourceUrlObj.origin) {
1034+
headers = {
1035+
...headers,
1036+
...sameOriginHeaders
1037+
};
1038+
}
1039+
1040+
const response = await fetchImpl(urlToTry, { method: 'GET', headers });
1041+
if (response.status !== 200) {
1042+
let errorText: string;
1043+
try {
1044+
errorText = await response.text();
1045+
} catch {
1046+
errorText = response.statusText;
1047+
}
1048+
errors.push(new Error(`Failed to fetch resource metadata from ${urlToTry}: ${response.status} ${errorText}`));
1049+
continue;
1050+
}
1051+
1052+
const body = await response.json();
1053+
if (isAuthorizationProtectedResourceMetadata(body)) {
1054+
// Use URL constructor for normalization - it handles hostname case and trailing slashes
1055+
const prmValue = new URL(body.resource).toString();
1056+
const targetValue = targetResourceUrlObj.toString();
1057+
if (prmValue !== targetValue) {
1058+
throw new Error(`Protected Resource Metadata resource property value "${prmValue}" (length: ${prmValue.length}) does not match target server url "${targetValue}" (length: ${targetValue.length}). These MUST match to follow OAuth spec https://datatracker.ietf.org/doc/html/rfc9728#PRConfigurationValidation`);
1059+
}
1060+
return body;
1061+
} else {
1062+
errors.push(new Error(`Invalid resource metadata from ${urlToTry}. Expected to follow shape of https://datatracker.ietf.org/doc/html/rfc9728#name-protected-resource-metadata (Hints: is scopes_supported an array? Is resource a string?). Current payload: ${JSON.stringify(body)}`));
1063+
continue;
1064+
}
1065+
} catch (e) {
1066+
errors.push(e instanceof Error ? e : new Error(String(e)));
1067+
continue;
1068+
}
1069+
}
1070+
// If we've tried all URLs and none worked, throw the error(s)
1071+
if (errors.length === 1) {
1072+
throw errors[0];
1073+
} else {
1074+
throw new AggregateError(errors, 'Failed to fetch resource metadata from all attempted URLs');
1075+
}
1076+
}

0 commit comments

Comments
 (0)