languageModels.ts ×31

Frontier kind: Code frontier

unlabeled · c_cd915aa927b6

2 tests · 32326 LOC · 158 files · introduces 0 tests · 106 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
31 ranges106 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
3302 ranges32326 lines · 158 files · Browse complete extent
All tests (intent)
2 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 106 introduced LOC across 31 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/contrib/chat/common/languageModels.ts 106 introduced LOC · 31 ranges

Open complete file

1605
1606 async updateLanguageModelsProviderGroupApiKey(vendorId: string, providerGroupName: string): Promise<void> {
1607 > const vendor = this.getVendors().find(({ vendor }) => vendor === vendorId); languageModels.ts
1608 > const schema = vendor?.configuration as IJSONSchema | undefined;
1609 > const apiKeySchema = schema?.properties?.apiKey;
1610 > if (!vendor || !schema || !apiKeySchema) {
1611 return;
1612 }
1614 > const existing = this._languageModelsConfigurationService.getLanguageModelsProviderGroups().find(group => group.vendor === vendorId && group.name === providerGroupName);
1615 > if (!existing) {
1616 throw new Error(`Language model provider group ${providerGroupName} for vendor ${vendorId} not found.`);
1617 }
1619 > try {
1620 > const existingConfiguration = await this._resolveConfiguration(existing, schema);
1621 > const apiKey = await this.promptForValue(existing.name, 'apiKey', apiKeySchema, !!schema.required?.includes('apiKey'), existingConfiguration);
1622 > if (apiKey === undefined || apiKey === existingConfiguration.apiKey) {
1623 return;
1624 }
1637 throw error;
1638 }
1640
1641 async addLanguageModelsProviderGroupModel(vendorId: string, providerGroupName: string): Promise<void> {
1882
1883 private async promptForValue(groupName: string, property: string, propertySchema: IJSONSchema | undefined, required: boolean, existing: IStringDictionary<unknown> | undefined): Promise<unknown | undefined> {
1884 > if (!propertySchema) { languageModels.ts
1885 return undefined;
1886 }
1888 > if (!this.canPromptForProperty(propertySchema)) {
1889 return undefined;
1890 }
1892 > if (propertySchema.type === 'array' && propertySchema.items && !Array.isArray(propertySchema.items) && propertySchema.items.enum) {
1893 const selectedItems = await this.promptForArray(groupName, property, propertySchema);
1894 if (selectedItems === undefined) {
1897 return selectedItems;
1898 }
1900 > if (propertySchema.type === 'string' && Array.isArray(propertySchema.enum) && propertySchema.enum.length > 0) {
1901 return this.promptForEnum(groupName, property, propertySchema, existing);
1902 }
1904 > const value = await this.promptForInput(groupName, property, propertySchema, required, existing);
1905 > if (value === undefined) {
1906 return undefined;
1907 }
1909 > return value;
1910 > }
1911
1912 private canPromptForProperty(propertySchema: IJSONSchema | undefined): boolean {
1913 > if (!propertySchema || typeof propertySchema === 'boolean') { languageModels.ts
1914 return false;
1915 }
1917 > if (propertySchema.type === 'array' && propertySchema.items && !Array.isArray(propertySchema.items) && propertySchema.items.enum) {
1918 return true;
1919 }
1921 > if (propertySchema.type === 'string' || propertySchema.type === 'number' || propertySchema.type === 'integer' || propertySchema.type === 'boolean') {
1922 > return true;
1923 > }
1924
1925 return false;
1927
1928 private getDescriptionPlaintext(propertySchema: IJSONSchema): string | undefined {
1929 > if (propertySchema.description) { languageModels.ts
1930 return propertySchema.description;
1931 }
1932 > const md = propertySchema.markdownDescription; languageModels.ts
1933 > if (!md) {
1934 > return undefined;
1935 > }
1936 // Quick input renders plain text only. Strip the inline markdown features used by
1937 // our schemas (inline code, bold/italic, links) so users see readable help.
1941 .replace(/\*([^*]+)\*/g, '$1')
1942 .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
1944
1945 private async promptForArray(groupName: string, property: string, propertySchema: IJSONSchema): Promise<string[] | undefined> {
2016
2017 private async promptForInput(groupName: string, property: string, propertySchema: IJSONSchema, required: boolean, existing: IStringDictionary<unknown> | undefined): Promise<string | number | boolean | undefined> {
2018 > const disposables = new DisposableStore(); languageModels.ts
2019 > try {
2020 > const validate = (value: string): string | undefined => {
2021 > if (!value && required) {
2022 return localize('valueRequired', "Value is required");
2023 }
2024 > return undefined; languageModels.ts
2025 > };
2026 >
2027 > const value = await new Promise<string | undefined>((resolve, reject) => {
2028 > const inputBox = disposables.add(this._quickInputService.createInputBox());
2029 > inputBox.title = `${groupName}: ${propertySchema.title ?? property}`;
2030 > inputBox.placeholder = localize('enterValue', "Enter value for {0}", property);
2031 > inputBox.password = !!propertySchema.secret;
2032 > inputBox.ignoreFocusOut = true;
2033 > if (existing?.[property]) {
2034 > inputBox.value = String(existing?.[property]);
2035 > } else if (propertySchema.default) {
2036 inputBox.value = String(propertySchema.default);
2037 }
2038 > const promptText = this.getDescriptionPlaintext(propertySchema); languageModels.ts
2039 > if (promptText) {
2040 inputBox.prompt = promptText;
2041 }
2043 > disposables.add(inputBox.onDidChangeValue(value => {
2044 > const message = validate(value);
2045 > if (message) {
2046 inputBox.validationMessage = message;
2047 inputBox.severity = Severity.Error;
2048 > } else { languageModels.ts
2049 > inputBox.validationMessage = undefined;
2050 > inputBox.severity = Severity.Ignore;
2051 > }
2052 > }));
2053 >
2054 > disposables.add(inputBox.onDidAccept(() => {
2055 > const message = validate(inputBox.value);
2056 > if (message) {
2057 inputBox.validationMessage = message;
2058 inputBox.severity = Severity.Error;
2059 return;
2060 }
2061 > resolve(inputBox.value); languageModels.ts
2062 > inputBox.hide();
2063 > }));
2064 >
2065 > disposables.add(inputBox.onDidHide((e) => {
2066 > if (e.reason === QuickInputHideReason.Gesture) {
2067 reject(new CancellationError());
2068 > } else { languageModels.ts
2069 > resolve(undefined);
2070 > }
2071 > }));
2072 >
2073 > inputBox.show();
2074 > });
2075 >
2076 > if (!value) {
2077 return undefined; // User cancelled
2078 }
2080 > if (propertySchema.type === 'number' || propertySchema.type === 'integer') {
2081 return Number(value);
2082 > } else if (propertySchema.type === 'boolean') { languageModels.ts
2083 return value === 'true';
2084 > } else { languageModels.ts
2085 > return value;
2086 > }
2087 >
2088 > } finally {
2089 > disposables.dispose();
2090 > }
2091 > }
2092
2093 private encodeSecretKey(property: string): string {
2096
2097 private decodeSecretKey(secretInput: unknown): string | undefined {
2098 > if (!isString(secretInput)) { languageModels.ts
2099 return undefined;
2100 }
2101 > return secretInput.substring(secretInput.indexOf(':') + 1, secretInput.length - 1); languageModels.ts
2102 > }
2103
2104 private _clearModelCache(vendor: string): Map<string, ILanguageModelChatMetadata> {
2131 continue;
2132 }
2133 > let value = group[key]; languageModels.ts
2134 if (schema.properties?.[key]?.secret) {
2135 > const secretKey = this.decodeSecretKey(value); languageModels.ts
2136 > value = secretKey ? await this._secretStorageService.get(secretKey) : undefined;
2137 > }
2138 > result[key] = value;
2139 > }
2140
2141 return result;