From e6e0a64d567ae79c8c981cd97c2c4337c7e2dabd Mon Sep 17 00:00:00 2001 From: JinmingYang <2214962083@qq.com> Date: Fri, 28 Jul 2023 22:51:25 +0800 Subject: [PATCH] feat(gpt-runner-core): add custom request headers and model names tips for special api url support --- .vscode/settings.json | 1 + README.md | 2 +- README_CN.md | 2 +- docs/gpt-config.cn.md | 42 +++- docs/gpt-config.en.md | 42 +++- package.json | 6 +- packages/gpt-runner-cli/package.json | 4 +- packages/gpt-runner-core/package.json | 9 +- .../chains/models/anthropic.model.ts | 36 +++- .../chains/models/hugging-face.model.ts | 2 +- .../langchain/chains/models/openai.model.ts | 80 ++++++- .../gpt-runner-core/src/langchain/types.ts | 1 + .../src/common/helpers/config.ts | 1 + .../src/common/helpers/constants.ts | 28 ++- .../common/types/config/anthropic.config.ts | 9 +- .../src/common/types/config/base.config.ts | 7 + .../types/config/hugging-face.config.ts | 8 +- .../src/common/types/config/openai.config.ts | 9 +- .../src/common/types/config/user.config.ts | 28 ++- .../src/common/types/server.ts | 10 + .../src/common/zod/config/anthropic.zod.ts | 8 +- .../src/common/zod/config/base.zod.ts | 6 +- .../src/common/zod/config/hugging-face.zod.ts | 4 +- .../src/common/zod/config/index.ts | 19 +- .../src/common/zod/config/openai.zod.ts | 8 +- .../src/common/zod/config/user.config.ts | 4 + .../src/common/zod/server.zod.ts | 8 +- packages/gpt-runner-vscode/package.json | 6 +- .../gpt-runner-web/client/src/networks/llm.ts | 15 +- .../settings/components/about/index.tsx | 2 +- .../anthropic-settings/model-settings.tsx | 25 +-- .../anthropic-settings/secrets-settings.tsx | 4 +- .../model-settings/base-model-settings.tsx | 33 ++- .../model-settings/base-secrets-settings.tsx | 4 +- .../components/model-settings/index.tsx | 6 +- .../openai-settings/model-settings.tsx | 33 +-- .../openai-settings/secrets-settings.tsx | 4 +- packages/gpt-runner-web/package.json | 8 +- .../server/src/controllers/llm.controller.ts | 26 ++- .../server/src/services/llm.service.ts | 91 ++++++-- pnpm-lock.yaml | 202 +++++++++--------- 41 files changed, 591 insertions(+), 252 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5a46197..dec9837 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -54,6 +54,7 @@ "ovsx", "ponyfill", "pycache", + "Referer", "rehype", "rubberband", "svgr", diff --git a/README.md b/README.md index cad2cce..78a14d6 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Use GPT-Runner to manage your AI presets, engage in AI-powered conversations wit [CLI](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-cli/) / [Web Page](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-web/) / [VSCode Extension](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-vscode/) / [Issues](https://github.com/nicepkg/gpt-runner/issues) / [Buy Me a Coffee](https://bmc.link/jinmingyang) -[终端工具](https://github.com/nicepkg/gpt-runner/blob/main/packages/gpt-runner-cli/README_CN.md) / [网页版](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-web/) / [VSCode 扩展](https://github.com/nicepkg/gpt-runner/blob/main/packages/gpt-runner-vscode/README_CN.md) / [反馈](https://github.com/nicepkg/gpt-runner/issues) / [打赏开发者](https://github.com/nicepkg/gpt-runner/assets/35005637/98a4962a-8a2e-4177-8781-1e1ee886ecdc) +[终端工具](https://github.com/nicepkg/gpt-runner/blob/main/packages/gpt-runner-cli/README_CN.md) / [网页版](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-web/) / [VSCode 扩展](https://github.com/nicepkg/gpt-runner/blob/main/packages/gpt-runner-vscode/README_CN.md) / [反馈](https://github.com/nicepkg/gpt-runner/issues) / [打赏开发者](https://user-images.githubusercontent.com/35005637/255805279-da299e44-ab7a-4038-b945-86d33128a775.jpg) [cli-url]: https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-cli/ [cli-image]: https://img.shields.io/badge/CLI-Node.js-green?logo=node.js diff --git a/README_CN.md b/README_CN.md index 0a56e4e..39889a3 100644 --- a/README_CN.md +++ b/README_CN.md @@ -14,7 +14,7 @@ [![GitHub stars](https://img.shields.io/github/stars/nicepkg/gpt-runner?style=social)][gpt-runner-url] -[终端工具](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-cli/README_CN.md) / [网页版](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-web/) / [VSCode 扩展](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-vscode/README_CN.md) / [反馈](https://github.com/nicepkg/gpt-runner/issues) / [打赏开发者](https://github.com/nicepkg/gpt-runner/assets/35005637/98a4962a-8a2e-4177-8781-1e1ee886ecdc) +[终端工具](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-cli/README_CN.md) / [网页版](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-web/) / [VSCode 扩展](https://github.com/nicepkg/gpt-runner/tree/main/packages/gpt-runner-vscode/README_CN.md) / [反馈](https://github.com/nicepkg/gpt-runner/issues) / [打赏开发者](https://user-images.githubusercontent.com/35005637/255805279-da299e44-ab7a-4038-b945-86d33128a775.jpg) [cli-url]: https://github.com/nicepkg/gpt-runner/blob/main/packages/gpt-runner-cli/README_CN.md [cli-image]: https://img.shields.io/badge/CLI-Node.js-green?logo=node.js diff --git a/docs/gpt-config.cn.md b/docs/gpt-config.cn.md index 40e2349..c269f66 100644 --- a/docs/gpt-config.cn.md +++ b/docs/gpt-config.cn.md @@ -101,6 +101,33 @@ export interface UserConfig { * @default true */ respectGitIgnore?: boolean + + /** + * api 配置 + * @default {} + * @example + * { + * "https://api.openai.com/*": { + * "modelNames": ["gpt-3.5-turbo-16k", "gpt-4"], + * "httpRequestHeader": { + * "User-Agent": "GPT-Runner" + * } + * } + * } + */ + urlConfig?: { + [urlMatch: string]: { + /** + * 将会展示在模型选择器里的模型名称 + */ + modelNames?: string[] + + /** + * 需要额外补充的请求头 + */ + httpRequestHeader?: Record + } + } } export interface ModelConfig { @@ -179,7 +206,20 @@ export default defineConfig({ "**/.serverless", "**/.parcel-cache" ], - "respectGitIgnore": true + "respectGitIgnore": true, + "urlConfig": { + "https://openrouter.ai/*": { + "modelNames": [ + "openai/gpt-3.5-turbo-16k", + "openai/gpt-4", + "openai/gpt-4-32k" + ], + "httpRequestHeader": { + "HTTP-Referer": "http://localhost:3003/", + "X-Title": "localhost" + } + } + } } ``` diff --git a/docs/gpt-config.en.md b/docs/gpt-config.en.md index 0ac2094..a27d270 100644 --- a/docs/gpt-config.en.md +++ b/docs/gpt-config.en.md @@ -101,6 +101,33 @@ export interface UserConfig { * @default true */ respectGitIgnore?: boolean + + /** + * api url configuration + * @default {} + * @example + * { + * "https://api.openai.com/*": { + * "modelNames": ["gpt-3.5-turbo-16k", "gpt-4"], + * "httpRequestHeader": { + * "User-Agent": "GPT-Runner" + * } + * } + * } + */ + urlConfig?: { + [urlMatch: string]: { + /** + * The model name that will be displayed in the model selector + */ + modelNames?: string[] + + /** + * Additional request headers are required + */ + httpRequestHeader?: Record + } + } } export interface ModelConfig { @@ -179,7 +206,20 @@ export default defineConfig({ "**/.serverless", "**/.parcel-cache" ], - "respectGitIgnore": true + "respectGitIgnore": true, + "urlConfig": { + "https://openrouter.ai/*": { + "modelNames": [ + "openai/gpt-3.5-turbo-16k", + "openai/gpt-4", + "openai/gpt-4-32k" + ], + "httpRequestHeader": { + "HTTP-Referer": "http://localhost:3003/", + "X-Title": "localhost" + } + } + } } ``` diff --git a/package.json b/package.json index be98595..cff3f6a 100644 --- a/package.json +++ b/package.json @@ -33,13 +33,13 @@ "@types/fs-extra": "^11.0.1", "@types/node": "^18.16.19", "@types/prettier": "^2.7.3", - "@types/react": "^18.2.15", + "@types/react": "^18.2.17", "@vitejs/plugin-legacy": "^4.1.1", "@vitest/ui": "^0.33.0", "bumpp": "^9.1.1", "eslint": "8.45.0", "esno": "^0.17.0", - "execa": "^7.1.1", + "execa": "^7.2.0", "fast-glob": "^3.3.1", "fs-extra": "^11.1.1", "jiti": "^1.19.1", @@ -77,4 +77,4 @@ "eslint --cache --fix" ] } -} +} \ No newline at end of file diff --git a/packages/gpt-runner-cli/package.json b/packages/gpt-runner-cli/package.json index 5cc7c00..0e7008c 100644 --- a/packages/gpt-runner-cli/package.json +++ b/packages/gpt-runner-cli/package.json @@ -53,7 +53,7 @@ "chokidar": "^3.5.3", "colorette": "^2.0.20", "consola": "^3.2.3", - "execa": "^7.1.1", + "execa": "^7.2.0", "wait-port": "^1.0.4" } -} +} \ No newline at end of file diff --git a/packages/gpt-runner-core/package.json b/packages/gpt-runner-core/package.json index 714ad63..8276b94 100644 --- a/packages/gpt-runner-core/package.json +++ b/packages/gpt-runner-core/package.json @@ -48,8 +48,13 @@ "dependencies": { "@nicepkg/gpt-runner-shared": "workspace:*", "ignore": "^5.2.4", - "langchain": "^0.0.116", + "langchain": "^0.0.118", "unconfig": "^0.3.9", + "uuid": "^9.0.0", "zod": "^3.21.4" + }, + "devDependencies": { + "@anthropic-ai/sdk": "^0.5.8", + "openai": "^3.3.0" } -} +} \ No newline at end of file diff --git a/packages/gpt-runner-core/src/langchain/chains/models/anthropic.model.ts b/packages/gpt-runner-core/src/langchain/chains/models/anthropic.model.ts index 91a3340..6103652 100644 --- a/packages/gpt-runner-core/src/langchain/chains/models/anthropic.model.ts +++ b/packages/gpt-runner-core/src/langchain/chains/models/anthropic.model.ts @@ -1,16 +1,22 @@ import type { BaseLanguageModel } from 'langchain/dist/base_language' -import { ChatModelType } from '@nicepkg/gpt-runner-shared/common' +import { ChatModelType, DEFAULT_API_BASE_PATH } from '@nicepkg/gpt-runner-shared/common' import { ChatAnthropic } from 'langchain/chat_models/anthropic' import { CallbackManager } from 'langchain/callbacks' +import type { Anthropic } from '@anthropic-ai/sdk' import type { GetModelParams } from '../type' +interface ChatAnthropicInstance extends Omit, 'batchClient' | 'streamingClient'> { + batchClient?: Anthropic + streamingClient?: Anthropic +} + export function getAnthropicModel(params: GetModelParams): BaseLanguageModel | null { - const { streaming, model, onTokenStream, onComplete, onError } = params + const { streaming, model, buildRequestHeaders, onTokenStream, onComplete, onError } = params if (model.type === ChatModelType.Anthropic) { const { secrets, modelName, temperature, maxTokens, topP, topK } = model - return new ChatAnthropic({ + const chatAnthropic = new ChatAnthropic({ streaming, maxRetries: 1, anthropicApiKey: secrets?.apiKey, @@ -42,7 +48,31 @@ export function getAnthropicModel(params: GetModelParams): BaseLanguageModel | n } }, }), + }) as unknown as ChatAnthropicInstance + + // langchain not support custom anthropic api request header + // so we need to rewrite the create method + const rewriteClientKey = ['batchClient', 'streamingClient'] as const + + rewriteClientKey.forEach((key) => { + if (chatAnthropic[key]) { + const oldCreate = chatAnthropic[key]?.completions.create + chatAnthropic[key]!.completions.create = async function (this: any, body, options) { + const finalRequestHeaders = buildRequestHeaders?.(secrets?.basePath || DEFAULT_API_BASE_PATH[ChatModelType.Anthropic], options?.headers as any) || options?.headers + + const finalOptions: typeof options = { + ...options, + headers: { + ...finalRequestHeaders, + }, + } + const res = await oldCreate?.apply(this, [body, finalOptions] as any) + return res + } as Anthropic['completions']['create'] + } }) + + return chatAnthropic } return null diff --git a/packages/gpt-runner-core/src/langchain/chains/models/hugging-face.model.ts b/packages/gpt-runner-core/src/langchain/chains/models/hugging-face.model.ts index 667ea05..43003f3 100644 --- a/packages/gpt-runner-core/src/langchain/chains/models/hugging-face.model.ts +++ b/packages/gpt-runner-core/src/langchain/chains/models/hugging-face.model.ts @@ -4,7 +4,7 @@ import { HuggingFaceInference } from 'langchain/llms/hf' import type { GetModelParams } from '../type' export function getHuggingFaceModel(params: GetModelParams): BaseLanguageModel | null { - const { model, onTokenStream, onComplete, onError } = params + const { model, buildRequestHeaders, onTokenStream, onComplete, onError } = params if (model.type === ChatModelType.HuggingFace) { const { secrets, modelName, temperature, maxTokens, topP, topK, frequencyPenalty } = model diff --git a/packages/gpt-runner-core/src/langchain/chains/models/openai.model.ts b/packages/gpt-runner-core/src/langchain/chains/models/openai.model.ts index ebd8daa..d5ac66a 100644 --- a/packages/gpt-runner-core/src/langchain/chains/models/openai.model.ts +++ b/packages/gpt-runner-core/src/langchain/chains/models/openai.model.ts @@ -1,11 +1,13 @@ import type { BaseLanguageModel } from 'langchain/dist/base_language' -import { ChatModelType } from '@nicepkg/gpt-runner-shared/common' +import { ChatModelType, DEFAULT_API_BASE_PATH, STREAM_DONE_FLAG, tryParseJson, tryStringifyJson } from '@nicepkg/gpt-runner-shared/common' import { ChatOpenAI } from 'langchain/chat_models/openai' import { CallbackManager } from 'langchain/callbacks' +import type { CreateChatCompletionResponse } from 'openai' +import * as uuid from 'uuid' import type { GetModelParams } from '../type' export function getOpenaiModel(params: GetModelParams): BaseLanguageModel | null { - const { streaming, model, onTokenStream, onComplete, onError } = params + const { streaming, model, buildRequestHeaders, onTokenStream, onComplete, onError } = params if (model.type === ChatModelType.Openai) { const { secrets, modelName, temperature, maxTokens, topP, frequencyPenalty, presencePenalty } = model @@ -21,7 +23,16 @@ export function getOpenaiModel(params: GetModelParams): BaseLanguageModel | null secrets.apiKey = 'unknown' // tell langchain don't throw error for missing api key } - return new ChatOpenAI({ + const finalAxiosRequestHeaders = buildRequestHeaders?.(secrets?.basePath || DEFAULT_API_BASE_PATH[ChatModelType.Openai], axiosBaseOptions.headers) || axiosBaseOptions.headers + + const finalAxiosBaseOptions = { + ...axiosBaseOptions, + headers: { + ...finalAxiosRequestHeaders, + }, + } + + const chatOpenAI = new ChatOpenAI({ streaming, maxRetries: 1, openAIApiKey: secrets?.apiKey, @@ -33,7 +44,7 @@ export function getOpenaiModel(params: GetModelParams): BaseLanguageModel | null presencePenalty, configuration: { ...secrets, - baseOptions: axiosBaseOptions, + baseOptions: finalAxiosBaseOptions, }, callbackManager: CallbackManager.fromHandlers({ handleLLMNewToken: async (token: string) => { @@ -58,6 +69,67 @@ export function getOpenaiModel(params: GetModelParams): BaseLanguageModel | null }, }), }) + + const oldCompletionWithRetry = chatOpenAI.completionWithRetry + chatOpenAI.completionWithRetry = async function (request, options) { + const finalOptions = { + ...options, + /** + * @params e { + * data: '{"choices":[{"index":0,"delta":{"content":"hin"},"finish_reason":null}],"model":"gpt-3.5-turbo-0613"}', + * event: '', + * id: '', + * retry: undefined + * } + */ + onmessage(e: any) { + if (e.data !== STREAM_DONE_FLAG) { + /** + * { + * "choices":[{ + * "index":0, + * "delta":{ + * "content":" unterstüt" + * },"finish_reason":null + * }], + * "model": "gpt-4-32k-0613", + * "id": "8069ec8f-c3c5-4fc9-9b3c-12031ece228f", + * "created":1690540898482, + * "usage": { + * "prompt_tokens": 0, + * "completion_tokens": 0, + * "total_tokens": 0 + * } + * } + */ + const finalEventData = tryParseJson(e?.data) as CreateChatCompletionResponse + + // process e as openai response to fix some issue for third-party api + if (!finalEventData.id) + finalEventData.id = uuid.v4() + + if (!finalEventData.created) + finalEventData.created = Date.now() + + if (!finalEventData.usage) { + finalEventData.usage = { + prompt_tokens: 0, + completion_tokens: 0, + total_tokens: 0, + } + } + + e.data = tryStringifyJson(finalEventData) + } + + return (options as any)?.onmessage?.(e) + }, + } as typeof options + + return oldCompletionWithRetry.apply(this, [request, finalOptions]) + } + + return chatOpenAI } return null diff --git a/packages/gpt-runner-core/src/langchain/types.ts b/packages/gpt-runner-core/src/langchain/types.ts index 0c1e284..f6148fa 100644 --- a/packages/gpt-runner-core/src/langchain/types.ts +++ b/packages/gpt-runner-core/src/langchain/types.ts @@ -3,6 +3,7 @@ export interface BaseModelParams { messages?: Message[] systemPrompt?: string systemPromptAsUserPrompt?: boolean + buildRequestHeaders?: (url: string, requestHeaders: Record | undefined) => Record | void onTokenStream?: (token: string) => void onComplete?: () => void onError?: (err: any) => void diff --git a/packages/gpt-runner-shared/src/common/helpers/config.ts b/packages/gpt-runner-shared/src/common/helpers/config.ts index 16ad3f6..5294f96 100644 --- a/packages/gpt-runner-shared/src/common/helpers/config.ts +++ b/packages/gpt-runner-shared/src/common/helpers/config.ts @@ -22,6 +22,7 @@ export function userConfigWithDefault(userConfig?: Partial) { excludes: DEFAULT_EXCLUDE_FILES, exts: ['.gpt.md'], respectGitIgnore: true, + urlConfig: {}, ...userConfig, } as const) satisfies ReadonlyDeep } diff --git a/packages/gpt-runner-shared/src/common/helpers/constants.ts b/packages/gpt-runner-shared/src/common/helpers/constants.ts index 9a38f68..7cb197f 100644 --- a/packages/gpt-runner-shared/src/common/helpers/constants.ts +++ b/packages/gpt-runner-shared/src/common/helpers/constants.ts @@ -1,9 +1,33 @@ +import { ChatModelType } from '../types' + export const MIN_NODE_VERSION = '16.15.0' export const SECRET_KEY_PLACEHOLDER = '********' export const STREAM_DONE_FLAG = '[DONE]' export const GPT_RUNNER_OFFICIAL_FOLDER = '.gpt-runner' -export const DEFAULT_ANTHROPIC_API_BASE_PATH = 'https://api.anthropic.com' -export const DEFAULT_OPENAI_API_BASE_PATH = 'https://api.openai.com/v1' + +export const DEFAULT_API_BASE_PATH: { + [Key in ChatModelType]: string +} = { + [ChatModelType.Anthropic]: 'https://api.anthropic.com', + [ChatModelType.HuggingFace]: 'https://api-inference.huggingface.co', + [ChatModelType.Openai]: 'https://api.openai.com/v1', +} + +export const DEFAULT_MODEL_NAMES_FOR_CHOOSE: { + [Key in ChatModelType]: string[] +} = { + [ChatModelType.Anthropic]: [ + 'claude-2', + 'claude-instant-1', + ], + [ChatModelType.HuggingFace]: [], + [ChatModelType.Openai]: [ + 'gpt-3.5-turbo-16k', + 'gpt-4', + 'gpt-4-32k', + 'gpt-3.5-turbo', + ], +} export const DEFAULT_EXCLUDE_FILES = [ '**/node_modules', diff --git a/packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts b/packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts index c150006..9cfe98c 100644 --- a/packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts +++ b/packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts @@ -1,16 +1,11 @@ import type { ChatModelType } from '../enum' -import type { BaseModelConfig } from './base.config' +import type { BaseModelConfig, BaseSecrets } from './base.config' -export interface AnthropicSecrets { +export interface AnthropicSecrets extends BaseSecrets { /** * The API key to use for Anthropic API requests. */ apiKey?: string - - /** - * override Anthropic base API url - */ - basePath?: string } export interface AnthropicModelConfig extends BaseModelConfig { diff --git a/packages/gpt-runner-shared/src/common/types/config/base.config.ts b/packages/gpt-runner-shared/src/common/types/config/base.config.ts index faf5d88..a94f8b7 100644 --- a/packages/gpt-runner-shared/src/common/types/config/base.config.ts +++ b/packages/gpt-runner-shared/src/common/types/config/base.config.ts @@ -3,6 +3,13 @@ import type { AnthropicModelConfig } from './anthropic.config' import type { HuggingFaceModelConfig } from './hugging-face.config' import type { OpenaiModelConfig } from './openai.config' +export interface BaseSecrets { + /** + * override api request base url + */ + basePath?: string +} + export interface BaseModelConfig { /** * mode type diff --git a/packages/gpt-runner-shared/src/common/types/config/hugging-face.config.ts b/packages/gpt-runner-shared/src/common/types/config/hugging-face.config.ts index 4eb6db6..81a8e1d 100644 --- a/packages/gpt-runner-shared/src/common/types/config/hugging-face.config.ts +++ b/packages/gpt-runner-shared/src/common/types/config/hugging-face.config.ts @@ -1,10 +1,10 @@ import type { ChatModelType } from '../enum' -import type { BaseModelConfig } from './base.config' +import type { BaseModelConfig, BaseSecrets } from './base.config' -export interface HuggingFaceSecrets { +export interface HuggingFaceSecrets extends BaseSecrets { /** - * The API key to use for Hugging Face API requests. - */ + * The API key to use for Hugging Face API requests. + */ apiKey?: string } diff --git a/packages/gpt-runner-shared/src/common/types/config/openai.config.ts b/packages/gpt-runner-shared/src/common/types/config/openai.config.ts index a3c8328..bd44249 100644 --- a/packages/gpt-runner-shared/src/common/types/config/openai.config.ts +++ b/packages/gpt-runner-shared/src/common/types/config/openai.config.ts @@ -1,7 +1,7 @@ import type { ChatModelType } from '../enum' -import type { BaseModelConfig } from './base.config' +import type { BaseModelConfig, BaseSecrets } from './base.config' -export interface OpenaiSecrets { +export interface OpenaiSecrets extends BaseSecrets { /** * The API key to use for OpenAI API requests. */ @@ -26,11 +26,6 @@ export interface OpenaiSecrets { * OpenAI access token */ accessToken?: string - - /** - * override Chatgpt base path - */ - basePath?: string } export interface OpenaiModelConfig extends BaseModelConfig { diff --git a/packages/gpt-runner-shared/src/common/types/config/user.config.ts b/packages/gpt-runner-shared/src/common/types/config/user.config.ts index 0eea9a3..c4cea76 100644 --- a/packages/gpt-runner-shared/src/common/types/config/user.config.ts +++ b/packages/gpt-runner-shared/src/common/types/config/user.config.ts @@ -29,9 +29,33 @@ export interface UserConfig { excludes?: FilterPattern /** - * @default true - */ + * @default true + */ respectGitIgnore?: boolean + + /** + * custom http request headers for specific urls + * @default {} + * + * @example + * { + * 'https://api.openai.com/*': { + * modelNames: [ + * 'gpt-3.5-turbo-16k', + * 'gpt-4', + * ], + * httpRequestHeader: { + * 'host': 'api.openai.com', + * } + * } + * } + */ + urlConfig?: { + [urlMatch: string]: { + modelNames?: string[] + httpRequestHeader?: Record + } + } } export type UserConfigForUser = Omit diff --git a/packages/gpt-runner-shared/src/common/types/server.ts b/packages/gpt-runner-shared/src/common/types/server.ts index 41ba8e2..1c3e1d2 100644 --- a/packages/gpt-runner-shared/src/common/types/server.ts +++ b/packages/gpt-runner-shared/src/common/types/server.ts @@ -58,6 +58,16 @@ export interface ChatStreamReqParams { rootPath?: string } +export interface GetModelNamesForChooseReqParams { + rootPath: string + modelType: ChatModelType + modelTypeVendorNameMap?: ModelTypeVendorNameMap +} + +export interface GetModelNamesForChooseResData { + modelNames: string[] +} + export interface GetGptFilesReqParams { rootPath: string } diff --git a/packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts b/packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts index a53a85d..5684073 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts @@ -1,11 +1,11 @@ import { z } from 'zod' import { type AnthropicModelConfig, type AnthropicSecrets, ChatModelType } from '../../types' -import { DEFAULT_ANTHROPIC_API_BASE_PATH } from '../../helpers' -import { BaseModelConfigSchema } from './base.zod' +import { DEFAULT_API_BASE_PATH } from '../../helpers' +import { BaseModelConfigSchema, BaseSecretsSchema } from './base.zod' -export const AnthropicSecretsSchema = z.object({ +export const AnthropicSecretsSchema = BaseSecretsSchema.extend({ apiKey: z.string().optional().describe('The Anthropic API key'), - basePath: z.string().optional().default(DEFAULT_ANTHROPIC_API_BASE_PATH).describe('The Anthropic base API url'), + basePath: z.string().optional().default(DEFAULT_API_BASE_PATH[ChatModelType.Anthropic]).describe('The Anthropic base API url'), }) satisfies z.ZodType export const AnthropicModelConfigSchema = BaseModelConfigSchema.extend({ diff --git a/packages/gpt-runner-shared/src/common/zod/config/base.zod.ts b/packages/gpt-runner-shared/src/common/zod/config/base.zod.ts index 86b1e25..35e4dbb 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/base.zod.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/base.zod.ts @@ -1,7 +1,11 @@ import { z } from 'zod' -import type { BaseModelConfig } from '../../types' +import type { BaseModelConfig, BaseSecrets } from '../../types' import { ChatModelTypeSchema } from '../enum.zod' +export const BaseSecretsSchema = z.object({ + basePath: z.string().optional().describe('The base API url'), +}) satisfies z.ZodType + export const BaseModelConfigSchema = z.object({ type: ChatModelTypeSchema.optional().describe('The type of the model'), modelName: z.string().optional().describe('The name of the model'), diff --git a/packages/gpt-runner-shared/src/common/zod/config/hugging-face.zod.ts b/packages/gpt-runner-shared/src/common/zod/config/hugging-face.zod.ts index 182fa88..4ef2a64 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/hugging-face.zod.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/hugging-face.zod.ts @@ -1,8 +1,8 @@ import { z } from 'zod' import { ChatModelType, type HuggingFaceModelConfig, type HuggingFaceSecrets } from '../../types' -import { BaseModelConfigSchema } from './base.zod' +import { BaseModelConfigSchema, BaseSecretsSchema } from './base.zod' -export const HuggingFaceSecretsSchema = z.object({ +export const HuggingFaceSecretsSchema = BaseSecretsSchema.extend({ apiKey: z.string().optional().describe('The HuggingFace API key'), }) satisfies z.ZodType diff --git a/packages/gpt-runner-shared/src/common/zod/config/index.ts b/packages/gpt-runner-shared/src/common/zod/config/index.ts index 0225517..43697bd 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/index.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/index.ts @@ -9,13 +9,13 @@ export * from './base.zod' export * from './openai.zod' export * from './user.config' -export function getModelConfigTypeSchema(modelType: T, schemaType: 'config' | 'secrets') { - const chatModelTypeSchemaMap: { - [key in ChatModelType]: { - config: z.ZodType> - secrets: z.ZodType> - } - } = { +interface ModelConfig { + config: z.ZodType> + secrets: z.ZodType> +} + +export function getModelConfig>(modelType: T, key: K) { + const chatModelConfigMap = ({ [ChatModelType.Anthropic]: { config: AnthropicModelConfigSchema, secrets: AnthropicSecretsSchema, @@ -28,6 +28,9 @@ export function getModelConfigTypeSchema(modelType: T, config: OpenaiModelConfigSchema, secrets: OpenaiSecretsSchema, }, + } as const) satisfies { + [Key in ChatModelType]: ModelConfig } - return chatModelTypeSchemaMap[modelType][schemaType] + + return chatModelConfigMap[modelType][key] } diff --git a/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts b/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts index d188484..5165c74 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts @@ -1,15 +1,15 @@ import { z } from 'zod' import { ChatModelType, type OpenaiModelConfig, type OpenaiSecrets } from '../../types' -import { DEFAULT_OPENAI_API_BASE_PATH } from '../../helpers' -import { BaseModelConfigSchema } from './base.zod' +import { DEFAULT_API_BASE_PATH } from '../../helpers' +import { BaseModelConfigSchema, BaseSecretsSchema } from './base.zod' -export const OpenaiSecretsSchema = z.object({ +export const OpenaiSecretsSchema = BaseSecretsSchema.extend({ apiKey: z.string().optional().describe('The OpenAI API key'), organization: z.string().optional().describe('The OpenAI organization'), // username: z.string().optional().describe('The OpenAI username'), // password: z.string().optional().describe('The OpenAI password'), accessToken: z.string().optional().describe('The OpenAI access token'), - basePath: z.string().optional().default(DEFAULT_OPENAI_API_BASE_PATH).describe('The OpenAI base API path'), + basePath: z.string().optional().default(DEFAULT_API_BASE_PATH[ChatModelType.Openai]).describe('The OpenAI base API path'), }) satisfies z.ZodType export const OpenaiModelConfigSchema = BaseModelConfigSchema.extend({ diff --git a/packages/gpt-runner-shared/src/common/zod/config/user.config.ts b/packages/gpt-runner-shared/src/common/zod/config/user.config.ts index 1f28edc..1f3aaf2 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/user.config.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/user.config.ts @@ -34,6 +34,10 @@ export const UserConfigSchema = z.object({ includes: FilterPatternSchema.optional().default(null).describe('The include patterns for filtering files'), excludes: FilterPatternSchema.optional().default(null).describe('The exclude patterns for filtering files'), respectGitIgnore: z.boolean().optional().default(true).describe('Whether to respect .gitignore rules'), + urlConfig: z.record(z.object({ + modelNames: z.array(z.string()).optional().describe('The model name that will be displayed in the model selector'), + httpRequestHeader: z.record(z.string()).optional().describe('Additional request headers are required'), + })).optional().default({}).describe('Custom http request headers and models names for specific urls'), }) satisfies z.ZodType export const UserConfigForUserSchema = UserConfigSchema.omit({ diff --git a/packages/gpt-runner-shared/src/common/zod/server.zod.ts b/packages/gpt-runner-shared/src/common/zod/server.zod.ts index c8fa0a6..2843cea 100644 --- a/packages/gpt-runner-shared/src/common/zod/server.zod.ts +++ b/packages/gpt-runner-shared/src/common/zod/server.zod.ts @@ -1,5 +1,5 @@ import { z } from 'zod' -import type { ChatStreamReqParams, CreateFilePathReqParams, DeleteFilePathReqParams, GetAppConfigReqParams, GetCommonFilesReqParams, GetFileInfoReqParams, GetGptFileInfoReqParams, GetGptFilesReqParams, GetUserConfigReqParams, InitGptFilesReqParams, MarkAsVisitedAppConfigReqParams, OpenEditorReqParams, RenameFilePathReqParams, SaveFileContentReqParams, StorageClearReqParams, StorageGetItemReqParams, StorageRemoveItemReqParams, StorageSetItemReqParams } from '../types' +import type { ChatStreamReqParams, CreateFilePathReqParams, DeleteFilePathReqParams, GetAppConfigReqParams, GetCommonFilesReqParams, GetFileInfoReqParams, GetGptFileInfoReqParams, GetGptFilesReqParams, GetModelNamesForChooseReqParams, GetUserConfigReqParams, InitGptFilesReqParams, MarkAsVisitedAppConfigReqParams, OpenEditorReqParams, RenameFilePathReqParams, SaveFileContentReqParams, StorageClearReqParams, StorageGetItemReqParams, StorageRemoveItemReqParams, StorageSetItemReqParams } from '../types' import { PartialChatModelTypeMapSchema, SingleChatMessageSchema, SingleFileConfigSchema } from './config' import { ChatModelTypeSchema, LocaleLangSchema, ServerStorageNameSchema } from './enum.zod' @@ -19,6 +19,12 @@ export const ChatStreamReqParamsSchema = z.object({ rootPath: z.string().optional(), }) satisfies z.ZodType +export const GetModelNamesForChooseReqParamsSchema = z.object({ + rootPath: z.string(), + modelType: ChatModelTypeSchema, + modelTypeVendorNameMap: z.record(z.string()).optional(), +}) satisfies z.ZodType + export const GetGptFilesReqParamsSchema = z.object({ rootPath: z.string(), }) satisfies z.ZodType diff --git a/packages/gpt-runner-vscode/package.json b/packages/gpt-runner-vscode/package.json index 52f379c..a248653 100644 --- a/packages/gpt-runner-vscode/package.json +++ b/packages/gpt-runner-vscode/package.json @@ -150,13 +150,13 @@ "@nicepkg/gpt-runner-shared": "workspace:*", "@nicepkg/gpt-runner-web": "workspace:*", "@types/vscode": "^1.71.0", - "@vscode/vsce": "^2.19.0", + "@vscode/vsce": "^2.20.0", "esno": "^0.17.0", "eventemitter3": "^5.0.1", - "execa": "^7.1.1", + "execa": "^7.2.0", "fs-extra": "^11.1.1", "jiti": "^1.19.1", "uuid": "^9.0.0", "wait-port": "^1.0.4" } -} +} \ No newline at end of file diff --git a/packages/gpt-runner-web/client/src/networks/llm.ts b/packages/gpt-runner-web/client/src/networks/llm.ts index 1ba2bcd..fa611a7 100644 --- a/packages/gpt-runner-web/client/src/networks/llm.ts +++ b/packages/gpt-runner-web/client/src/networks/llm.ts @@ -1,8 +1,10 @@ import type { EventSourceMessage } from '@microsoft/fetch-event-source' import { fetchEventSource } from '@microsoft/fetch-event-source' -import { type BaseResponse, type ChatStreamReqParams, STREAM_DONE_FLAG, getErrorMsg } from '@nicepkg/gpt-runner-shared/common' +import { STREAM_DONE_FLAG, getErrorMsg, objectToQueryString } from '@nicepkg/gpt-runner-shared/common' +import type { BaseResponse, ChatStreamReqParams, GetModelNamesForChooseReqParams, GetModelNamesForChooseResData } from '@nicepkg/gpt-runner-shared/common' import * as uuid from 'uuid' import { getGlobalConfig } from '../helpers/global-config' +import { myFetch } from '../helpers/fetch' export interface FetchChatStreamReqParams extends ChatStreamReqParams { namespace?: string @@ -99,3 +101,14 @@ export async function fetchLlmStream( onError(error) } } + +export async function getModelNamesForChoose(params: GetModelNamesForChooseReqParams): Promise> { + return await myFetch(`${getGlobalConfig().serverBaseUrl}/api/chatgpt/model-names-for-choose?${objectToQueryString({ + ...params, + })}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) +} diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/about/index.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/about/index.tsx index ad416f0..6433ecb 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/about/index.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/about/index.tsx @@ -14,7 +14,7 @@ export const About = memo(forwardRef((_props, ref) => { const version = pkg.version const githubLink = pkg.repository.url const enBuyMeACoffeeLink = 'https://bmc.link/jinmingyang' - const cnBuyMeACoffeeLink = 'https://github.com/nicepkg/gpt-runner/assets/35005637/98a4962a-8a2e-4177-8781-1e1ee886ecdc' + const cnBuyMeACoffeeLink = 'https://user-images.githubusercontent.com/35005637/255805279-da299e44-ab7a-4038-b945-86d33128a775.jpg' const buyMeACoffeeLink = langId === LocaleLang.ChineseSimplified ? cnBuyMeACoffeeLink : enBuyMeACoffeeLink const data: { title: React.ReactNode; content?: React.ReactNode }[] = [ diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx index 01d9d6f..dce5390 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx @@ -1,39 +1,29 @@ import { type AnthropicModelConfig, ChatModelType, type SingleFileConfig } from '@nicepkg/gpt-runner-shared/common' -import { memo, useState } from 'react' +import { memo } from 'react' import type { FC } from 'react' import { useTranslation } from 'react-i18next' import { HookFormInput } from '../../../../../../../components/hook-form/hook-form-input' -import { type ISelectOption, SelectOption } from '../../../../../../../components/select-option' -import { BaseModelSettings, type BaseModelSettingsFormItemConfig } from '../base-model-settings' +import { SelectOption } from '../../../../../../../components/select-option' +import { BaseModelSettings } from '../base-model-settings' +import type { BaseModelSettingsFormItemConfig, BaseModelSettingsProps } from '../base-model-settings' interface FormData extends Pick { } -export interface AnthropicModelSettingsProps { +export interface AnthropicModelSettingsProps extends Omit, 'modelType' | 'formConfig'> { singleFileConfig?: SingleFileConfig } export const AnthropicModelSettings: FC = memo((props) => { - const { singleFileConfig } = props + const { rootPath, singleFileConfig } = props const { t } = useTranslation() - const [modelTipOptions] = useState([ - { - label: 'claude-2', - value: 'claude-2', - }, - { - label: 'claude-instant-1', - value: 'claude-instant-1', - }, - ]) - const formConfig: BaseModelSettingsFormItemConfig[] = [ { name: 'modelName', - buildView: ({ buildLabel, useFormReturns: { control, formState, watch, setValue } }) => { + buildView: ({ buildLabel, modelTipOptions, useFormReturns: { control, formState, watch, setValue } }) => { return <> = memo((pro ] return = memo( return <> { buildLabel: (label: string) => ReactNode useFormReturns: UseFormReturn + modelTipOptions: ISelectOption[] } export interface BaseModelSettingsFormItemConfig { @@ -22,16 +26,17 @@ export interface BaseModelSettingsFormItemConfig { + rootPath: string modelType: ChatModelType singleFileConfig?: SingleFileConfig formConfig: BaseModelSettingsFormItemConfig[] } function BaseModelSettings_(props: BaseModelSettingsProps) { - const { modelType, singleFileConfig, formConfig } = props + const { rootPath, modelType, singleFileConfig, formConfig } = props const { t } = useTranslation() - const { overrideModelsConfig, updateOverrideModelsConfig } = useGlobalStore() + const { overrideModelsConfig, modelTypeVendorNameMap, updateOverrideModelsConfig } = useGlobalStore() const modelFromSingleFileConfig = singleFileConfig?.model as FormData | undefined const currentModelType = modelType @@ -51,9 +56,28 @@ function BaseModelSettings_(props: BaseModelSe return acc }, {} as Record)) + const { data: getModelNamesForChooseData } = useQuery({ + queryKey: ['get-model-names-for-choose', rootPath, currentModelType, modelTypeVendorNameMap], + enabled: Boolean(rootPath && currentModelType), + queryFn: () => getModelNamesForChoose({ + rootPath, + modelType: currentModelType, + modelTypeVendorNameMap, + }), + }) + + const modelTipOptions = useMemo(() => { + return getModelNamesForChooseData?.data?.modelNames.map((modelName) => { + return { + label: modelName, + value: modelName, + } + }) ?? [] + }, [getModelNamesForChooseData]) + const useFormReturns = useForm({ mode: 'onBlur', - resolver: zodResolver(getModelConfigTypeSchema(currentModelType, 'config')), + resolver: zodResolver(getModelConfig(currentModelType, 'config')), }) const { setValue, watch } = useFormReturns @@ -161,6 +185,7 @@ function BaseModelSettings_(props: BaseModelSe return buildLabel(label, formItemConfig.name) }, useFormReturns, + modelTipOptions, } return ( diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/base-secrets-settings.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/base-secrets-settings.tsx index 3b85ed8..e073315 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/base-secrets-settings.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/base-secrets-settings.tsx @@ -1,5 +1,5 @@ import type { ModelApiVendor } from '@nicepkg/gpt-runner-shared/common' -import { ChatModelType, ServerStorageName, getModelConfigTypeSchema } from '@nicepkg/gpt-runner-shared/common' +import { ChatModelType, ServerStorageName, getModelConfig } from '@nicepkg/gpt-runner-shared/common' import { memo, useEffect, useMemo } from 'react' import type { ReactNode } from 'react' import { useForm } from 'react-hook-form' @@ -97,7 +97,7 @@ function BaseSecretsSettings_({ mode: 'onBlur', - resolver: zodResolver(getModelConfigTypeSchema(currentModelType, 'secrets')), + resolver: zodResolver(getModelConfig(currentModelType, 'secrets')), defaultValues: { vendorName: modelTypeVendorNameMap[currentModelType] || '', } as any, diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx index 085efdb..85f713d 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx @@ -26,8 +26,8 @@ export interface ModelSettingsSecretsViewProps extends ModelSettingsBaseViewProp export interface ModelSettingsModelViewProps extends ModelSettingsBaseViewProps { viewType: 'model' + rootPath: string modelType?: ChatModelType - rootPath?: string singleFilePath?: string singleFileConfig?: SingleFileConfig userConfig?: UserConfig @@ -69,7 +69,7 @@ export const ModelSettings: FC = memo((props) => { const modelTypeViewMap: Record ReactNode>> = { [ChatModelType.Anthropic]: { secrets: () => , - model: () => , + model: () => , title: () => <>Anthropic, }, [ChatModelType.HuggingFace]: { @@ -79,7 +79,7 @@ export const ModelSettings: FC = memo((props) => { }, [ChatModelType.Openai]: { secrets: () => , - model: () => , + model: () => , title: () => <>OpenAI, }, } diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx index 2f4d203..9493b61 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx @@ -1,47 +1,29 @@ import { ChatModelType, type OpenaiModelConfig, type SingleFileConfig } from '@nicepkg/gpt-runner-shared/common' -import { memo, useState } from 'react' +import { memo } from 'react' import type { FC } from 'react' import { useTranslation } from 'react-i18next' import { HookFormInput } from '../../../../../../../components/hook-form/hook-form-input' -import { type ISelectOption, SelectOption } from '../../../../../../../components/select-option' -import { BaseModelSettings, type BaseModelSettingsFormItemConfig } from '../base-model-settings' +import { SelectOption } from '../../../../../../../components/select-option' +import { BaseModelSettings } from '../base-model-settings' +import type { BaseModelSettingsFormItemConfig, BaseModelSettingsProps } from '../base-model-settings' interface FormData extends Pick { } -export interface OpenaiModelSettingsProps { +export interface OpenaiModelSettingsProps extends Omit, 'modelType' | 'formConfig'> { singleFileConfig?: SingleFileConfig } export const OpenaiModelSettings: FC = memo((props) => { - const { singleFileConfig } = props + const { rootPath, singleFileConfig } = props const { t } = useTranslation() - const [modelTipOptions] = useState([ - { - label: 'gpt-3.5-turbo-16k', - value: 'gpt-3.5-turbo-16k', - }, - { - label: 'gpt-4', - value: 'gpt-4', - }, - { - label: 'gpt-4-32k', - value: 'gpt-4-32k', - }, - { - label: 'gpt-3.5-turbo', - value: 'gpt-3.5-turbo', - }, - ]) - const formConfig: BaseModelSettingsFormItemConfig[] = [ { name: 'modelName', - buildView: ({ buildLabel, useFormReturns: { control, formState, watch, setValue } }) => { + buildView: ({ buildLabel, modelTipOptions, useFormReturns: { control, formState, watch, setValue } }) => { return <> = memo((props) => ] return = memo((props return <> { + handler: async (req, res) => { const debug = new Debug('llm.controller') res.writeHead(200, { @@ -82,6 +81,23 @@ export const llmControllers: ControllerConfig = { } }, }, + { + url: '/model-names-for-choose', + method: 'get', + handler: async (req, res) => { + const query = req.query as GetModelNamesForChooseReqParams + + verifyParamsByZod(query, GetModelNamesForChooseReqParamsSchema) + + const modelNames = await LLMService.getLLMModelsNames(query) + + sendSuccessResponse(res, { + data: { + modelNames, + } satisfies GetModelNamesForChooseResData, + }) + }, + }, ], } diff --git a/packages/gpt-runner-web/server/src/services/llm.service.ts b/packages/gpt-runner-web/server/src/services/llm.service.ts index 9eabb39..b5148fc 100644 --- a/packages/gpt-runner-web/server/src/services/llm.service.ts +++ b/packages/gpt-runner-web/server/src/services/llm.service.ts @@ -1,4 +1,5 @@ -import { ChatModelType, type ChatStreamReqParams, type SingleFileConfig, toUnixPath } from '@nicepkg/gpt-runner-shared/common' +import { ChatModelType, DEFAULT_MODEL_NAMES_FOR_CHOOSE, toUnixPath } from '@nicepkg/gpt-runner-shared/common' +import type { ChatStreamReqParams, GetModelNamesForChooseReqParams, ModelTypeVendorNameMap, SingleFileConfig, UserConfig } from '@nicepkg/gpt-runner-shared/common' import type { LLMChainParams } from '@nicepkg/gpt-runner-core' import { createFileContext, getSecrets, loadUserConfig, parseGptFile } from '@nicepkg/gpt-runner-core' import { PathUtils } from '@nicepkg/gpt-runner-shared/node' @@ -6,6 +7,36 @@ import { getValidFinalPath } from '../helpers/valid-path' import { AppConfigService } from './app-config.service' export class LLMService { + static async getLLMModelsNames(params: GetModelNamesForChooseReqParams): Promise { + const { rootPath, modelType, modelTypeVendorNameMap } = params + + const finalPath = getValidFinalPath({ + path: rootPath, + assertType: 'directory', + fieldName: 'rootPath', + }) + + const { config: userConfig } = await loadUserConfig(finalPath) + + const finalSecrets = await LLMService.getSecretsFormAllWays({ + modelType, + userConfig, + modelTypeVendorNameMap, + }) + + let result: string[] = [] + + result = Object.entries(userConfig.urlConfig || {}).find(([urlMatcher]) => { + // for example: urlMatcher maybe 'https://api.openai.com/*' + return Boolean(finalSecrets.basePath?.match(urlMatcher)) + })?.[1]?.modelNames || [] + + if (!result.length) + return DEFAULT_MODEL_NAMES_FOR_CHOOSE[modelType] + + return result + } + static async getLLMChainParams(params: ChatStreamReqParams): Promise { const { messages = [], @@ -54,23 +85,12 @@ export class LLMService { ...overrideModelsConfig?.[singleFileConfig?.model?.type as ChatModelType || ''], } as SingleFileConfig['model'] - const secretFromUserConfig = userConfig.model?.type === model?.type ? userConfig.model?.secrets : undefined - let secretsFromStorage = await getSecrets(model?.type as ChatModelType || null) - // if some secret value is '' or null or undefined, should remove - secretsFromStorage = Object.fromEntries(Object.entries(secretsFromStorage || {}).filter(([_, value]) => value != null && value !== '' && value !== undefined)) - - // if user use vendor secrets - const currentVendorName = modelTypeVendorNameMap?.[model!.type] || '' - const vendorSecrets = await AppConfigService.instance.getSecretsConfig({ - modelType: model!.type, - vendorName: currentVendorName, + const finalSecrets = await LLMService.getSecretsFormAllWays({ + modelType: model?.type, + userConfig, + modelTypeVendorNameMap, }) - const finalSecrets = vendorSecrets || { - ...secretFromUserConfig, - ...secretsFromStorage, - } - const finalSystemPrompt = await LLMService.getFinalSystemPrompt({ finalPath, systemPrompt: systemPromptFromParams, @@ -88,9 +108,48 @@ export class LLMService { ...model!, secrets: finalSecrets, }, + buildRequestHeaders(url, requestHeaders) { + const requestHeadersFromUserConfig: Record = Object.entries(userConfig.urlConfig || {}).find(([urlMatcher]) => { + // for example: urlMatcher maybe 'https://api.openai.com/*' + return Boolean(url?.match(urlMatcher)) + })?.[1]?.httpRequestHeader || {} + + return { + ...requestHeaders, + ...requestHeadersFromUserConfig, + } + }, } } + static async getSecretsFormAllWays(params: { + modelType: ChatModelType | undefined + userConfig: UserConfig + modelTypeVendorNameMap: ModelTypeVendorNameMap | undefined + }) { + const { modelType = ChatModelType.Openai, userConfig, modelTypeVendorNameMap } = params + + const secretFromUserConfig = userConfig.model?.type === modelType ? userConfig.model?.secrets : undefined + let secretsFromStorage = await getSecrets(modelType || null) + + // if some secret value is '' or null or undefined, should remove + secretsFromStorage = Object.fromEntries(Object.entries(secretsFromStorage || {}).filter(([_, value]) => value != null && value !== '' && value !== undefined)) + + // if user use vendor secrets + const currentVendorName = modelTypeVendorNameMap?.[modelType] || '' + const vendorSecrets = await AppConfigService.instance.getSecretsConfig({ + modelType, + vendorName: currentVendorName, + }) + + const finalSecrets = vendorSecrets || { + ...secretFromUserConfig, + ...secretsFromStorage, + } + + return finalSecrets as typeof secretsFromStorage + } + static async getFinalSystemPrompt(params: { finalPath: string systemPrompt: string diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cfb26d8..1817fc8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: specifier: ^2.7.3 version: 2.7.3 '@types/react': - specifier: ^18.2.15 - version: 18.2.15 + specifier: ^18.2.17 + version: 18.2.17 '@vitejs/plugin-legacy': specifier: ^4.1.1 version: 4.1.1(terser@5.19.2)(vite@4.4.7) @@ -51,8 +51,8 @@ importers: specifier: ^0.17.0 version: 0.17.0 execa: - specifier: ^7.1.1 - version: 7.1.1 + specifier: ^7.2.0 + version: 7.2.0 fast-glob: specifier: ^3.3.1 version: 3.3.1 @@ -150,8 +150,8 @@ importers: specifier: ^3.2.3 version: 3.2.3 execa: - specifier: ^7.1.1 - version: 7.1.1 + specifier: ^7.2.0 + version: 7.2.0 wait-port: specifier: ^1.0.4 version: 1.0.4 @@ -165,14 +165,24 @@ importers: specifier: ^5.2.4 version: 5.2.4 langchain: - specifier: ^0.0.116 - version: 0.0.116(ignore@5.2.4) + specifier: ^0.0.118 + version: 0.0.118(ignore@5.2.4) unconfig: specifier: ^0.3.9 version: 0.3.9 + uuid: + specifier: ^9.0.0 + version: 9.0.0 zod: specifier: ^3.21.4 version: 3.21.4 + devDependencies: + '@anthropic-ai/sdk': + specifier: ^0.5.8 + version: 0.5.8 + openai: + specifier: ^3.3.0 + version: 3.3.0 packages/gpt-runner-shared: dependencies: @@ -250,8 +260,8 @@ importers: specifier: ^1.71.0 version: 1.79.1 '@vscode/vsce': - specifier: ^2.19.0 - version: 2.19.0 + specifier: ^2.20.0 + version: 2.20.0 esno: specifier: ^0.17.0 version: 0.17.0 @@ -259,8 +269,8 @@ importers: specifier: ^5.0.1 version: 5.0.1 execa: - specifier: ^7.1.1 - version: 7.1.1 + specifier: ^7.2.0 + version: 7.2.0 fs-extra: specifier: ^11.1.1 version: 11.1.1 @@ -319,8 +329,8 @@ importers: specifier: ^4.17.8 version: 4.17.8 '@types/react': - specifier: ^18.2.15 - version: 18.2.15 + specifier: ^18.2.17 + version: 18.2.17 '@types/react-dom': specifier: ^18.2.7 version: 18.2.7 @@ -361,8 +371,8 @@ importers: specifier: ^4.18.2 version: 4.18.2 framer-motion: - specifier: ^10.13.1 - version: 10.13.1(react-dom@18.2.0)(react@18.2.0) + specifier: ^10.15.0 + version: 10.15.0(react-dom@18.2.0)(react@18.2.0) fs-extra: specifier: ^11.1.1 version: 11.1.1 @@ -370,8 +380,8 @@ importers: specifier: ^3.0.0 version: 3.0.0 i18next: - specifier: ^23.2.11 - version: 23.2.11 + specifier: ^23.3.0 + version: 23.3.0 i18next-browser-languagedetector: specifier: ^7.1.0 version: 7.1.0 @@ -407,10 +417,10 @@ importers: version: 2.4.1(csstype@3.1.2)(react-dom@18.2.0)(react@18.2.0) react-i18next: specifier: ^13.0.2 - version: 13.0.2(i18next@23.2.11)(react-dom@18.2.0)(react@18.2.0) + version: 13.0.2(i18next@23.3.0)(react-dom@18.2.0)(react@18.2.0) react-markdown: specifier: ^8.0.7 - version: 8.0.7(@types/react@18.2.15)(react@18.2.0) + version: 8.0.7(@types/react@18.2.17)(react@18.2.0) react-router-dom: specifier: ^6.14.2 version: 6.14.2(react-dom@18.2.0)(react@18.2.0) @@ -482,7 +492,7 @@ importers: version: 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/preset-classic': specifier: ^2.4.1 - version: 2.4.1(@algolia/client-search@4.17.1)(@swc/core@1.3.68)(@types/react@18.2.15)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) + version: 2.4.1(@algolia/client-search@4.17.1)(@swc/core@1.3.68)(@types/react@18.2.17)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/remark-plugin-npm2yarn': specifier: ^2.4.1 version: 2.4.1 @@ -837,7 +847,6 @@ packages: transitivePeerDependencies: - encoding - supports-color - dev: false /@apideck/better-ajv-errors@0.3.6(ajv@8.12.0): resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} @@ -933,7 +942,7 @@ packages: debug: 4.3.4 gensync: 1.0.0-beta.2 json5: 2.2.3 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -1045,7 +1054,7 @@ packages: '@babel/helper-validator-option': 7.22.5 browserslist: 4.21.9 lru-cache: 5.1.1 - semver: 6.3.0 + semver: 6.3.1 /@babel/helper-compilation-targets@7.22.6(@babel/core@7.22.5): resolution: {integrity: sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==} @@ -1117,7 +1126,7 @@ packages: '@babel/helper-replace-supers': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 '@babel/helper-split-export-declaration': 7.18.6 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: false @@ -1137,7 +1146,7 @@ packages: '@babel/helper-replace-supers': 7.21.5 '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 '@babel/helper-split-export-declaration': 7.18.6 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -1209,7 +1218,7 @@ packages: '@babel/core': 7.22.5 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 - semver: 6.3.0 + semver: 6.3.1 dev: false /@babel/helper-create-regexp-features-plugin@7.21.8(@babel/core@7.22.8): @@ -1221,7 +1230,7 @@ packages: '@babel/core': 7.22.8 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 - semver: 6.3.0 + semver: 6.3.1 /@babel/helper-create-regexp-features-plugin@7.21.8(@babel/core@7.22.9): resolution: {integrity: sha512-zGuSdedkFtsFHGbexAvNuipg1hbtitDLo2XE8/uf6Y9sOQV1xsYX/2pNbtedp/X0eU1pIt+kGvaqHCowkRbS5g==} @@ -1232,7 +1241,7 @@ packages: '@babel/core': 7.22.9 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 - semver: 6.3.0 + semver: 6.3.1 dev: true /@babel/helper-create-regexp-features-plugin@7.22.5(@babel/core@7.22.5): @@ -1244,7 +1253,7 @@ packages: '@babel/core': 7.22.5 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 - semver: 6.3.0 + semver: 6.3.1 dev: false /@babel/helper-create-regexp-features-plugin@7.22.5(@babel/core@7.22.8): @@ -1256,7 +1265,7 @@ packages: '@babel/core': 7.22.8 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 - semver: 6.3.0 + semver: 6.3.1 /@babel/helper-create-regexp-features-plugin@7.22.5(@babel/core@7.22.9): resolution: {integrity: sha512-1VpEFOIbMRaXyDeUwUfmTIxExLwQ+zkW+Bh5zXpApA3oQedBx9v/updixWxnx/bZpKw7u8VxWjb/qWpIcmPq8A==} @@ -1267,7 +1276,7 @@ packages: '@babel/core': 7.22.9 '@babel/helper-annotate-as-pure': 7.22.5 regexpu-core: 5.3.2 - semver: 6.3.0 + semver: 6.3.1 dev: true /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.22.5): @@ -1281,7 +1290,7 @@ packages: debug: 4.3.4 lodash.debounce: 4.0.8 resolve: 1.22.2 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: false @@ -3860,7 +3869,7 @@ packages: babel-plugin-polyfill-corejs2: 0.4.3(@babel/core@7.22.5) babel-plugin-polyfill-corejs3: 0.8.1(@babel/core@7.22.5) babel-plugin-polyfill-regenerator: 0.5.0(@babel/core@7.22.5) - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: false @@ -4227,7 +4236,7 @@ packages: babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.22.5) babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.22.5) core-js-compat: 3.30.2 - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: false @@ -4657,7 +4666,7 @@ packages: resolution: {integrity: sha512-Hg8Xfma+rFwRi6Y/pfei4FJoQ1hdVURmmNs/XPoMTCPAImU+d5yxj+M+qdLtNjWRpfWziU4dQcqY94xgFBn2dg==} dev: false - /@docsearch/react@3.4.0(@algolia/client-search@4.17.1)(@types/react@18.2.15)(react-dom@17.0.2)(react@17.0.2): + /@docsearch/react@3.4.0(@algolia/client-search@4.17.1)(@types/react@18.2.17)(react-dom@17.0.2)(react@17.0.2): resolution: {integrity: sha512-ufrp5879XYGojgS30ZAp8H4qIMbahRHB9M85VDBP36Xgz5QjYM54i1URKj5e219F7gqTtOivfztFTij6itc0MQ==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' @@ -4674,7 +4683,7 @@ packages: '@algolia/autocomplete-core': 1.8.2 '@algolia/autocomplete-preset-algolia': 1.8.2(@algolia/client-search@4.17.1)(algoliasearch@4.17.1) '@docsearch/css': 3.4.0 - '@types/react': 18.2.15 + '@types/react': 18.2.17 algoliasearch: 4.17.1 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) @@ -4871,7 +4880,7 @@ packages: '@docusaurus/react-loadable': 5.5.2(react@17.0.2) '@docusaurus/types': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(react-dom@17.0.2)(react@17.0.2) '@types/history': 4.7.11 - '@types/react': 18.2.15 + '@types/react': 18.2.17 '@types/react-router-config': 5.0.7 '@types/react-router-dom': 5.3.3 react: 17.0.2 @@ -5043,7 +5052,7 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-debug@2.4.1(@swc/core@1.3.68)(@types/react@18.2.15)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6): + /@docusaurus/plugin-debug@2.4.1(@swc/core@1.3.68)(@types/react@18.2.17)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6): resolution: {integrity: sha512-7Yu9UPzRShlrH/G8btOpR0e6INFZr0EegWplMjOqelIwAcx3PKyR8mgPTxGTxcqiYj6hxSCRN0D8R7YrzImwNA==} engines: {node: '>=16.14'} peerDependencies: @@ -5056,7 +5065,7 @@ packages: fs-extra: 10.1.0 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - react-json-view: 1.21.3(@types/react@18.2.15)(react-dom@17.0.2)(react@17.0.2) + react-json-view: 1.21.3(@types/react@18.2.17)(react-dom@17.0.2)(react@17.0.2) tslib: 2.5.0 transitivePeerDependencies: - '@parcel/css' @@ -5296,7 +5305,7 @@ packages: - webpack-cli dev: false - /@docusaurus/preset-classic@2.4.1(@algolia/client-search@4.17.1)(@swc/core@1.3.68)(@types/react@18.2.15)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6): + /@docusaurus/preset-classic@2.4.1(@algolia/client-search@4.17.1)(@swc/core@1.3.68)(@types/react@18.2.17)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6): resolution: {integrity: sha512-P4//+I4zDqQJ+UDgoFrjIFaQ1MeS9UD1cvxVQaI6O7iBmiHQm0MGROP1TbE7HlxlDPXFJjZUK3x3cAoK63smGQ==} engines: {node: '>=16.14'} peerDependencies: @@ -5307,14 +5316,14 @@ packages: '@docusaurus/plugin-content-blog': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/plugin-content-docs': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/plugin-content-pages': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) - '@docusaurus/plugin-debug': 2.4.1(@swc/core@1.3.68)(@types/react@18.2.15)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) + '@docusaurus/plugin-debug': 2.4.1(@swc/core@1.3.68)(@types/react@18.2.17)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/plugin-google-analytics': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/plugin-google-gtag': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/plugin-google-tag-manager': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/plugin-sitemap': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/theme-classic': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/theme-common': 2.4.1(@docusaurus/types@2.4.1)(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) - '@docusaurus/theme-search-algolia': 2.4.1(@algolia/client-search@4.17.1)(@docusaurus/types@2.4.1)(@swc/core@1.3.68)(@types/react@18.2.15)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) + '@docusaurus/theme-search-algolia': 2.4.1(@algolia/client-search@4.17.1)(@docusaurus/types@2.4.1)(@swc/core@1.3.68)(@types/react@18.2.17)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/types': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(react-dom@17.0.2)(react@17.0.2) react: 17.0.2 react-dom: 17.0.2(react@17.0.2) @@ -5344,7 +5353,7 @@ packages: peerDependencies: react: '*' dependencies: - '@types/react': 18.2.15 + '@types/react': 18.2.17 prop-types: 15.8.1 react: 17.0.2 dev: false @@ -5441,7 +5450,7 @@ packages: '@docusaurus/utils': 2.4.1(@docusaurus/types@2.4.1)(@swc/core@1.3.68)(esbuild@0.15.18) '@docusaurus/utils-common': 2.4.1(@docusaurus/types@2.4.1) '@types/history': 4.7.11 - '@types/react': 18.2.15 + '@types/react': 18.2.17 '@types/react-router-config': 5.0.7 clsx: 1.2.1 parse-numeric-range: 1.3.0 @@ -5505,14 +5514,14 @@ packages: - webpack-cli dev: false - /@docusaurus/theme-search-algolia@2.4.1(@algolia/client-search@4.17.1)(@docusaurus/types@2.4.1)(@swc/core@1.3.68)(@types/react@18.2.15)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6): + /@docusaurus/theme-search-algolia@2.4.1(@algolia/client-search@4.17.1)(@docusaurus/types@2.4.1)(@swc/core@1.3.68)(@types/react@18.2.17)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6): resolution: {integrity: sha512-6BcqW2lnLhZCXuMAvPRezFs1DpmEKzXFKlYjruuas+Xy3AQeFzDJKTJFIm49N77WFCTyxff8d3E4Q9pi/+5McQ==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docsearch/react': 3.4.0(@algolia/client-search@4.17.1)(@types/react@18.2.15)(react-dom@17.0.2)(react@17.0.2) + '@docsearch/react': 3.4.0(@algolia/client-search@4.17.1)(@types/react@18.2.17)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/core': 2.4.1(@docusaurus/types@2.4.1)(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) '@docusaurus/logger': 2.4.1 '@docusaurus/plugin-content-docs': 2.4.1(@swc/core@1.3.68)(esbuild@0.15.18)(eslint@8.45.0)(react-dom@17.0.2)(react@17.0.2)(typescript@5.1.6) @@ -5566,7 +5575,7 @@ packages: react-dom: ^16.8.4 || ^17.0.0 dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.15 + '@types/react': 18.2.17 commander: 5.1.0 joi: 17.9.2 react: 17.0.2 @@ -7600,7 +7609,6 @@ packages: dependencies: '@types/node': 18.16.19 form-data: 3.0.1 - dev: false /@types/node@17.0.45: resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} @@ -7640,14 +7648,14 @@ packages: /@types/react-dom@18.2.7: resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} dependencies: - '@types/react': 18.2.15 + '@types/react': 18.2.17 dev: true /@types/react-router-config@5.0.7: resolution: {integrity: sha512-pFFVXUIydHlcJP6wJm7sDii5mD/bCmmAY0wQzq+M+uX7bqS95AQqHZWP1iNMKrWVQSuHIzj5qi9BvrtLX2/T4w==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.15 + '@types/react': 18.2.17 '@types/react-router': 5.1.20 dev: false @@ -7655,7 +7663,7 @@ packages: resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.15 + '@types/react': 18.2.17 '@types/react-router': 5.1.20 dev: false @@ -7663,17 +7671,17 @@ packages: resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.15 + '@types/react': 18.2.17 dev: false /@types/react-syntax-highlighter@15.5.7: resolution: {integrity: sha512-bo5fEO5toQeyCp0zVHBeggclqf5SQ/Z5blfFmjwO5dkMVGPgmiwZsJh9nu/Bo5L7IHTuGWrja6LxJVE2uB5ZrQ==} dependencies: - '@types/react': 18.2.15 + '@types/react': 18.2.17 dev: true - /@types/react@18.2.15: - resolution: {integrity: sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==} + /@types/react@18.2.17: + resolution: {integrity: sha512-u+e7OlgPPh+aryjOm5UJMX32OvB2E3QASOAqVMY6Ahs90djagxwv2ya0IctglNbNTexC12qCSMZG47KPfy1hAA==} dependencies: '@types/prop-types': 15.7.5 '@types/scheduler': 0.16.3 @@ -8131,8 +8139,8 @@ packages: pretty-format: 29.5.0 dev: true - /@vscode/vsce@2.19.0: - resolution: {integrity: sha512-dAlILxC5ggOutcvJY24jxz913wimGiUrHaPkk16Gm9/PGFbz1YezWtrXsTKUtJws4fIlpX2UIlVlVESWq8lkfQ==} + /@vscode/vsce@2.20.0: + resolution: {integrity: sha512-FR8Tq2WgGRi/Py5/9WUFG2DCxdqaHXyuhHXSP8hsNc1FsxNzAkqKqfvOUUGxA7gOytmc9s/000QA7wKVukMDbQ==} engines: {node: '>= 14'} hasBin: true dependencies: @@ -8149,7 +8157,7 @@ packages: minimatch: 3.1.2 parse-semver: 1.1.1 read: 1.0.7 - semver: 5.7.1 + semver: 7.5.4 tmp: 0.2.1 typed-rest-client: 1.8.9 url-join: 4.0.1 @@ -8318,7 +8326,6 @@ packages: engines: {node: '>=6.5'} dependencies: event-target-shim: 5.0.1 - dev: false /accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} @@ -8641,7 +8648,6 @@ packages: proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - dev: false /azure-devops-node-api@11.2.0: resolution: {integrity: sha512-XdiGPhrpaT5J8wdERRKs5g8E0Zy1pvOYTli7z9E8nmOn3YGp4FhtjhrOyFmX/8veWCwdI69mCHKJw6l+4J/bHA==} @@ -8695,7 +8701,7 @@ packages: '@babel/compat-data': 7.22.6 '@babel/core': 7.22.5 '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.5) - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: false @@ -8708,7 +8714,7 @@ packages: '@babel/compat-data': 7.22.6 '@babel/core': 7.22.5 '@babel/helper-define-polyfill-provider': 0.4.1(@babel/core@7.22.5) - semver: 6.3.0 + semver: 6.3.1 transitivePeerDependencies: - supports-color dev: false @@ -8841,7 +8847,6 @@ packages: /base-64@0.1.0: resolution: {integrity: sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==} - dev: false /base16@1.0.0: resolution: {integrity: sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==} @@ -9252,7 +9257,6 @@ packages: /charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} - dev: false /check-error@1.0.2: resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} @@ -9759,7 +9763,6 @@ packages: /crypt@0.0.2: resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} - dev: false /crypto-random-string@2.0.0: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} @@ -10450,7 +10453,7 @@ packages: dependencies: bundle-name: 3.0.0 default-browser-id: 3.0.0 - execa: 7.1.1 + execa: 7.2.0 titleize: 3.0.0 dev: true @@ -10600,7 +10603,6 @@ packages: dependencies: base-64: 0.1.0 md5: 2.3.0 - dev: false /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} @@ -11851,7 +11853,6 @@ packages: /event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} - dev: false /eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} @@ -11883,8 +11884,8 @@ packages: signal-exit: 3.0.7 strip-final-newline: 2.0.0 - /execa@7.1.1: - resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} + /execa@7.2.0: + resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} dependencies: cross-spawn: 7.0.3 @@ -12200,7 +12201,6 @@ packages: optional: true dependencies: debug: 4.3.4 - dev: false /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -12249,7 +12249,6 @@ packages: /form-data-encoder@1.7.2: resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} - dev: false /form-data@3.0.1: resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} @@ -12258,7 +12257,6 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: false /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} @@ -12279,7 +12277,6 @@ packages: dependencies: node-domexception: 1.0.0 web-streams-polyfill: 4.0.0-beta.3 - dev: false /forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} @@ -12289,8 +12286,8 @@ packages: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: false - /framer-motion@10.13.1(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-uiKsaLEoySeln3eOPy8wUB3FkNtRRiVga5xJOkgs7C0sHVyvpJajXJFSoabt+emBojgnMQY0epnjl0ppoYPxkQ==} + /framer-motion@10.15.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-HDjWrYWgbO5orKuhnXETLFzk7UUvwWur2HFs2elAZ8lVpI49ClHql31DNTVvVBcOrSHfAOS4eBDBedIvOx634w==} peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 @@ -13135,8 +13132,8 @@ packages: - encoding dev: true - /i18next@23.2.11: - resolution: {integrity: sha512-MA4FsxOjyCaOZtRDB4yuwjCvqYEioD4G4LlXOn7SO3rnQUlxTufyLsOqfL9MKakeLRBkefe8bqcs0D6Z/xFk1w==} + /i18next@23.3.0: + resolution: {integrity: sha512-xd/UzWT71zYudCT7qVn6tB4yUVuXAhgCorsowYgM2EOdc14WqQBp5P2wEsxgfiDgdLN5XwJvTbzxrMfoY/nxnw==} dependencies: '@babel/runtime': 7.22.5 dev: true @@ -13374,7 +13371,6 @@ packages: /is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - dev: false /is-buffer@2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} @@ -13970,8 +13966,8 @@ packages: engines: {node: '>= 8'} dev: false - /langchain@0.0.116(ignore@5.2.4): - resolution: {integrity: sha512-bFXj5MDWPKkSiQUhx//p6zDLrSo2aFZnewhmUwJYRKkSPkXE4MxTzPqxZa8E0hv9EqyOb6dA8RVcvh6xp1hUkw==} + /langchain@0.0.118(ignore@5.2.4): + resolution: {integrity: sha512-MzadedGsgvF5Rf+S94o+mY2Gkf5QEQFjLrCsaKcKeOREMJZ2GTszPlkDpwLWwe5MVugY1DhtC2c4gI13R+WtTw==} engines: {node: '>=18'} peerDependencies: '@aws-sdk/client-dynamodb': ^3.310.0 @@ -14250,7 +14246,7 @@ packages: cli-truncate: 3.1.0 commander: 10.0.1 debug: 4.3.4 - execa: 7.1.1 + execa: 7.2.0 lilconfig: 2.1.0 listr2: 5.0.8 micromatch: 4.0.5 @@ -14459,7 +14455,7 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} dependencies: - semver: 6.3.0 + semver: 6.3.1 dev: false /make-error@1.3.6: @@ -14546,7 +14542,6 @@ packages: charenc: 0.0.2 crypt: 0.0.2 is-buffer: 1.1.6 - dev: false /mdast-squeeze-paragraphs@4.0.0: resolution: {integrity: sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==} @@ -15453,7 +15448,6 @@ packages: /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} - dev: false /node-emoji@1.11.0: resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} @@ -15781,7 +15775,6 @@ packages: form-data: 4.0.0 transitivePeerDependencies: - debug - dev: false /openapi-types@12.1.3: resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} @@ -15915,7 +15908,7 @@ packages: got: 9.6.0 registry-auth-token: 4.2.2 registry-url: 5.1.0 - semver: 6.3.0 + semver: 6.3.1 dev: false /pacote@15.2.0: @@ -17035,7 +17028,6 @@ packages: /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: false /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} @@ -17264,7 +17256,7 @@ packages: - csstype dev: true - /react-i18next@13.0.2(i18next@23.2.11)(react-dom@18.2.0)(react@18.2.0): + /react-i18next@13.0.2(i18next@23.3.0)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-NEVxC32v0oR4egwYM0QM0WE93AiJG5r0NTXTL8mhQfAhsMfDS2fSO6jpluyfsfypP988KzUQrAXncspcJ7+GHA==} peerDependencies: i18next: '>= 23.2.3' @@ -17279,7 +17271,7 @@ packages: dependencies: '@babel/runtime': 7.22.5 html-parse-stringify: 3.0.1 - i18next: 23.2.11 + i18next: 23.3.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true @@ -17290,7 +17282,7 @@ packages: /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - /react-json-view@1.21.3(@types/react@18.2.15)(react-dom@17.0.2)(react@17.0.2): + /react-json-view@1.21.3(@types/react@18.2.17)(react-dom@17.0.2)(react@17.0.2): resolution: {integrity: sha512-13p8IREj9/x/Ye4WI/JpjhoIwuzEgUAtgJZNBJckfzJt1qyh24BdTm6UQNGnyTq9dapQdrqvquZTo3dz1X6Cjw==} peerDependencies: react: ^17.0.0 || ^16.3.0 || ^15.5.4 @@ -17301,7 +17293,7 @@ packages: react-base16-styling: 0.6.0 react-dom: 17.0.2(react@17.0.2) react-lifecycles-compat: 3.0.4 - react-textarea-autosize: 8.4.1(@types/react@18.2.15)(react@17.0.2) + react-textarea-autosize: 8.4.1(@types/react@18.2.17)(react@17.0.2) transitivePeerDependencies: - '@types/react' - encoding @@ -17333,7 +17325,7 @@ packages: webpack: 5.88.1(@swc/core@1.3.68)(esbuild@0.15.18) dev: false - /react-markdown@8.0.7(@types/react@18.2.15)(react@18.2.0): + /react-markdown@8.0.7(@types/react@18.2.17)(react@18.2.0): resolution: {integrity: sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==} peerDependencies: '@types/react': '>=16' @@ -17341,7 +17333,7 @@ packages: dependencies: '@types/hast': 2.3.4 '@types/prop-types': 15.7.5 - '@types/react': 18.2.15 + '@types/react': 18.2.17 '@types/unist': 2.0.6 comma-separated-tokens: 2.0.3 hast-util-whitespace: 2.0.1 @@ -17470,7 +17462,7 @@ packages: refractor: 3.6.0 dev: true - /react-textarea-autosize@8.4.1(@types/react@18.2.15)(react@17.0.2): + /react-textarea-autosize@8.4.1(@types/react@18.2.17)(react@17.0.2): resolution: {integrity: sha512-aD2C+qK6QypknC+lCMzteOdIjoMbNlgSFmJjCV+DrfTPwp59i/it9mMNf2HDzvRjQgKAyBDPyLJhcrzElf2U4Q==} engines: {node: '>=10'} peerDependencies: @@ -17479,7 +17471,7 @@ packages: '@babel/runtime': 7.22.5 react: 17.0.2 use-composed-ref: 1.3.0(react@17.0.2) - use-latest: 1.2.1(@types/react@18.2.15)(react@17.0.2) + use-latest: 1.2.1(@types/react@18.2.17)(react@17.0.2) transitivePeerDependencies: - '@types/react' dev: false @@ -18182,7 +18174,7 @@ packages: resolution: {integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==} engines: {node: '>=8'} dependencies: - semver: 6.3.0 + semver: 6.3.1 dev: false /semver@5.7.1: @@ -18196,7 +18188,6 @@ packages: /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - dev: true /semver@7.5.1: resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==} @@ -19110,7 +19101,7 @@ packages: '@antfu/ni': 0.21.4 '@npmcli/config': 6.2.1 detect-indent: 7.0.1 - execa: 7.1.1 + execa: 7.2.0 pacote: 15.2.0 prompts: 2.4.2 semver: 7.5.4 @@ -19999,7 +19990,7 @@ packages: react: 17.0.2 dev: false - /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.15)(react@17.0.2): + /use-isomorphic-layout-effect@1.1.2(@types/react@18.2.17)(react@17.0.2): resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} peerDependencies: '@types/react': '*' @@ -20008,11 +19999,11 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.15 + '@types/react': 18.2.17 react: 17.0.2 dev: false - /use-latest@1.2.1(@types/react@18.2.15)(react@17.0.2): + /use-latest@1.2.1(@types/react@18.2.17)(react@17.0.2): resolution: {integrity: sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==} peerDependencies: '@types/react': '*' @@ -20021,9 +20012,9 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.15 + '@types/react': 18.2.17 react: 17.0.2 - use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.15)(react@17.0.2) + use-isomorphic-layout-effect: 1.1.2(@types/react@18.2.17)(react@17.0.2) dev: false /use-sync-external-store@1.2.0(react@17.0.2): @@ -20449,7 +20440,6 @@ packages: /web-streams-polyfill@4.0.0-beta.3: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} - dev: false /web-worker@1.2.0: resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==}