diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 1b9c7eb2b08..8a99d63cb4c 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1691,6 +1691,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I LanguageModelSystemMessage: extHostTypes.LanguageModelChatSystemMessage, LanguageModelUserMessage: extHostTypes.LanguageModelChatUserMessage, LanguageModelAssistantMessage: extHostTypes.LanguageModelChatAssistantMessage, + LanguageModelError: extHostTypes.LanguageModelError, NewSymbolName: extHostTypes.NewSymbolName, NewSymbolNameTag: extHostTypes.NewSymbolNameTag, InlineEdit: extHostTypes.InlineEdit, diff --git a/src/vs/workbench/api/common/extHostLanguageModels.ts b/src/vs/workbench/api/common/extHostLanguageModels.ts index e51c875984d..ea10161e75f 100644 --- a/src/vs/workbench/api/common/extHostLanguageModels.ts +++ b/src/vs/workbench/api/common/extHostLanguageModels.ts @@ -8,6 +8,7 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ILogService } from 'vs/platform/log/common/log'; import { ExtHostLanguageModelsShape, IMainContext, MainContext, MainThreadLanguageModelsShape } from 'vs/workbench/api/common/extHost.protocol'; import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters'; +import { LanguageModelError } from 'vs/workbench/api/common/extHostTypes'; import type * as vscode from 'vscode'; import { Progress } from 'vs/platform/progress/common/progress'; import { IChatMessage, IChatResponseFragment, ILanguageModelChatMetadata } from 'vs/workbench/contrib/chat/common/languageModels'; @@ -232,14 +233,14 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape { const metadata = await this._proxy.$prepareChatAccess(from, languageModelId, options.justification); if (!metadata || !this._languageModelIds.has(languageModelId)) { - throw new Error(`Language model '${languageModelId}' is unknown.`); + throw LanguageModelError.NotFound(`Language model '${languageModelId}' is unknown.`); } if (this._isUsingAuth(from, metadata)) { const success = await this._getAuthAccess(extension, { identifier: metadata.extension, displayName: metadata.auth.providerLabel }, options.justification, options.silent); if (!success || !this._modelAccessList.get(from)?.has(metadata.extension)) { - throw new Error(`Language model '${languageModelId}' cannot be used by '${from.value}'.`); + throw LanguageModelError.NoPermissions(`Language model '${languageModelId}' cannot be used by '${from.value}'.`); } } @@ -270,7 +271,11 @@ export class ExtHostLanguageModels implements ExtHostLanguageModelsShape { await barrier.wait(); if (error) { - throw new Error(`Language model '${languageModelId}' errored, check cause for more details`, { cause: error }); + throw new LanguageModelError( + `Language model '${languageModelId}' errored, check cause for more details`, + 'Unknown', + error + ); } return res.apiObject; diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index 4eec0964cd2..2e1ff171d1f 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -4297,6 +4297,26 @@ export class LanguageModelChatAssistantMessage { } } +export class LanguageModelError extends Error { + + static NotFound(message?: string): LanguageModelError { + return new LanguageModelError(message, LanguageModelError.NotFound.name); + } + + static NoPermissions(message?: string): LanguageModelError { + return new LanguageModelError(message, LanguageModelError.NoPermissions.name); + } + + readonly code: string; + + constructor(message?: string, code?: string, cause?: Error) { + super(message, { cause }); + this.name = 'LanguageModelError'; + this.code = code ?? ''; + } + +} + //#endregion //#region ai diff --git a/src/vscode-dts/vscode.proposed.languageModels.d.ts b/src/vscode-dts/vscode.proposed.languageModels.d.ts index 59b053f149d..775e4d5e1dc 100644 --- a/src/vscode-dts/vscode.proposed.languageModels.d.ts +++ b/src/vscode-dts/vscode.proposed.languageModels.d.ts @@ -104,6 +104,36 @@ declare module 'vscode' { readonly removed: readonly string[]; } + /** + * An error type for language model specific errors. + * + * Consumers of language models should check the code property to determine specific + * failure causes, like `if(someError.code === vscode.LanguageModelError.NotFound.name) {...}` + * for the case of referring to an unknown language model. + */ + export class LanguageModelError extends Error { + + /** + * The language model does not exist. + */ + static NotFound(message?: string): LanguageModelError; + + /** + * The requestor does not have permissions to use this + * language model + */ + static NoPermissions(message?: string): LanguageModelError; + + /** + * A code that identifies this error. + * + * Possible values are names of errors, like {@linkcode LanguageModelError.NotFound NotFound}, + * or `Unknown` for unspecified errors from the language model itself. In the latter case the + * `cause`-property will contain the actual error. + */ + readonly code: string; + } + /** * Options for making a chat request using a language model. * @@ -151,9 +181,9 @@ declare module 'vscode' { * @returns A thenable that resolves to a {@link LanguageModelChatResponse}. The promise will reject when making the request failed. */ // TODO@API refine doc - // TODO@API define specific error types? - // TODO@API NAME: sendChatRequest, fetchChatResponse, makeChatRequest, chat, chatRequest sendChatRequest // TODO@API ExtensionContext#permission#languageModels: { languageModel: string: LanguageModelAccessInformation} + // TODO@API ✅ define specific error types? + // TODO@API ✅ NAME: sendChatRequest, fetchChatResponse, makeChatRequest, chat, chatRequest sendChatRequest // TODO@API ✅ NAME: LanguageModelChatXYZMessage // TODO@API ✅ errors on everything that prevents us to make the actual request // TODO@API ✅ double auth