diff --git a/package-lock.json b/package-lock.json index 60f264a8fc2..1360ef9e5c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "chat-ui", - "version": "0.20.0", + "version": "0.20.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "chat-ui", - "version": "0.20.0", + "version": "0.20.4", "dependencies": { "@aws-sdk/credential-providers": "^3.925.0", "@elysiajs/swagger": "^1.3.0", @@ -681,7 +681,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.927.0.tgz", "integrity": "sha512-CasoHKKE/K+6YcVqjE+v5dVyKqKBtfzZyvGi669HvJ1f4EPHbVRPPLIb0eAYd/aEmwHsB/nn9VnyN9Wq5OppUQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@aws-sdk/client-cognito-identity": "3.927.0", "@aws-sdk/core": "3.927.0", @@ -958,6 +957,7 @@ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", + "peer": true, "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", @@ -972,6 +972,7 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "license": "MIT", + "peer": true, "engines": { "node": ">=6.9.0" } @@ -1073,7 +1074,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -1097,7 +1097,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -3250,8 +3249,7 @@ "version": "0.34.41", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@smithy/abort-controller": { "version": "4.2.4", @@ -3864,7 +3862,6 @@ "integrity": "sha512-EMYTY4+rNa7TaRZYzCqhQslEkACEZzWc363jOYuc90oJrgvlWTcgqTxcGSIJim48hPaXwYlHyatRnnMmTFf5tA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", @@ -3897,7 +3894,6 @@ "integrity": "sha512-wojIS/7GYnJDYIg1higWj2ROA6sSRWvcR1PO/bqEyFr/5UZah26c8Cz4u0NaqjPeVltzsVpt2Tm8d2io0V+4Tw==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", "debug": "^4.4.1", @@ -3937,6 +3933,7 @@ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.8.0" } @@ -3982,6 +3979,7 @@ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", "license": "MIT", + "peer": true, "engines": { "node": ">=12", "npm": ">=6" @@ -4027,7 +4025,8 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/chai": { "version": "5.2.2", @@ -4256,7 +4255,6 @@ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", @@ -4655,7 +4653,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4839,6 +4836,7 @@ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "license": "Apache-2.0", + "peer": true, "dependencies": { "dequal": "^2.0.3" } @@ -5104,7 +5102,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001718", "electron-to-chromium": "^1.5.160", @@ -5774,7 +5771,8 @@ "version": "0.5.16", "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/dom-serializer": { "version": "2.0.0", @@ -5915,7 +5913,6 @@ "resolved": "https://registry.npmjs.org/elysia/-/elysia-1.3.4.tgz", "integrity": "sha512-kAfM3Zwovy3z255IZgTKVxBw91HbgKhYl3TqrGRdZqqr+Fd+4eKOfvxgaKij22+MZLczPzIHtscAmvfpI3+q/A==", "license": "MIT", - "peer": true, "dependencies": { "cookie": "^1.0.2", "exact-mirror": "0.1.2", @@ -6116,7 +6113,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -6754,7 +6750,6 @@ "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", "license": "MIT", - "peer": true, "dependencies": { "@tokenizer/inflate": "^0.2.7", "strtok3": "^10.2.2", @@ -7259,10 +7254,9 @@ } }, "node_modules/hono": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.3.tgz", - "integrity": "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==", - "license": "MIT", + "version": "4.11.7", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz", + "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==", "peer": true, "engines": { "node": ">=16.9.0" @@ -7914,7 +7908,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/js-yaml": { "version": "4.1.0", @@ -9692,7 +9687,6 @@ "integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "playwright-core": "1.55.1" }, @@ -9738,7 +9732,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -9970,7 +9963,6 @@ "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -9987,7 +9979,6 @@ "integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" @@ -10077,6 +10068,7 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "license": "MIT", + "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -10091,6 +10083,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -10299,7 +10292,8 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/read-cache": { "version": "1.0.0", @@ -10463,7 +10457,6 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.7" }, @@ -11382,7 +11375,6 @@ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.14.tgz", "integrity": "sha512-kRlbhIlMTijbFmVDQFDeKXPLlX1/ovXwV0I162wRqQhRcygaqDIcu1d/Ese3H2uI+yt3uT8E7ndgDthQv5v5BA==", "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.3.0", "@jridgewell/sourcemap-codec": "^1.5.0", @@ -11522,7 +11514,6 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", "license": "MIT", - "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -11980,7 +11971,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12216,7 +12206,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -12352,7 +12341,6 @@ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.2.tgz", "integrity": "sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==", "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.2", @@ -12675,7 +12663,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -12798,7 +12785,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.55.tgz", "integrity": "sha512-219huNnkSLQnLsQ3uaRjXsxMrVm5C9W3OOpEVt2k5tvMKuA8nBSu38e0B//a+he9Iq2dvmk2VyYVlHqiHa4YBA==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/src/lib/server/config.ts b/src/lib/server/config.ts index 8d9f0c29461..8372713fa6b 100644 --- a/src/lib/server/config.ts +++ b/src/lib/server/config.ts @@ -159,7 +159,8 @@ type ExtraConfigKeys = | "METRICS_PORT" | "MCP_SERVERS" | "MCP_FORWARD_HF_USER_TOKEN" - | "EXA_API_KEY"; + | "EXA_API_KEY" + | "DEFAULT_MAX_TOKENS"; type ConfigProxy = ConfigManager & { [K in ConfigKey | ExtraConfigKeys]: string }; diff --git a/src/lib/server/endpoints/openai/endpointOai.ts b/src/lib/server/endpoints/openai/endpointOai.ts index 47ae66fde10..751d486713e 100644 --- a/src/lib/server/endpoints/openai/endpointOai.ts +++ b/src/lib/server/endpoints/openai/endpointOai.ts @@ -130,11 +130,14 @@ export async function endpointOai( }); const parameters = { ...model.parameters, ...generateSettings }; + const defaultMaxTokens = config.DEFAULT_MAX_TOKENS + ? parseInt(config.DEFAULT_MAX_TOKENS) + : undefined; const body: CompletionCreateParamsStreaming = { model: model.id ?? model.name, prompt, stream: true, - max_tokens: parameters?.max_tokens, + max_tokens: parameters?.max_tokens ?? defaultMaxTokens, stop: parameters?.stop, temperature: parameters?.temperature, top_p: parameters?.top_p, @@ -197,14 +200,18 @@ export async function endpointOai( // Combine model defaults with request-specific parameters const parameters = { ...model.parameters, ...generateSettings }; + const defaultMaxTokens = config.DEFAULT_MAX_TOKENS + ? parseInt(config.DEFAULT_MAX_TOKENS) + : undefined; + const effectiveMaxTokens = parameters?.max_tokens ?? defaultMaxTokens; const body = { model: model.id ?? model.name, messages: messagesOpenAI, stream: streamingSupported, // Support two different ways of specifying token limits depending on the model ...(useCompletionTokens - ? { max_completion_tokens: parameters?.max_tokens } - : { max_tokens: parameters?.max_tokens }), + ? { max_completion_tokens: effectiveMaxTokens } + : { max_tokens: effectiveMaxTokens }), stop: parameters?.stop, temperature: parameters?.temperature, top_p: parameters?.top_p, diff --git a/src/lib/server/models.ts b/src/lib/server/models.ts index 5459f6202cc..efdb66c472a 100644 --- a/src/lib/server/models.ts +++ b/src/lib/server/models.ts @@ -378,10 +378,17 @@ const buildModels = async (): Promise => { } } + // Track which overrides matched existing models + const matchedOverrideKeys = new Set(); + modelsRaw = modelsRaw.map((model) => { const override = overrideMap.get(model.id ?? "") ?? overrideMap.get(model.name ?? ""); if (!override) return model; + // Mark this override as matched + if (model.id) matchedOverrideKeys.add(model.id); + if (model.name) matchedOverrideKeys.add(model.name); + const { id, name, ...rest } = override; void id; void name; @@ -391,6 +398,39 @@ const buildModels = async (): Promise => { ...rest, }; }); + + // Add models from MODELS that didn't match any discovered model (new models) + for (const override of overrides) { + const overrideId = override.id?.trim() || override.name?.trim(); + if (!overrideId) continue; + + // Skip if this override already matched an existing model + if (matchedOverrideKeys.has(overrideId)) continue; + if (override.id && matchedOverrideKeys.has(override.id)) continue; + if (override.name && matchedOverrideKeys.has(override.name)) continue; + + // This is a new model - add it + // Ensure it has required fields and endpoints + if (override.endpoints && override.endpoints.length > 0) { + const newModel: ModelConfig = { + id: override.id || override.name || overrideId, + name: override.name || override.id || overrideId, + displayName: override.displayName, + description: override.description, + logoUrl: override.logoUrl, + endpoints: override.endpoints, + parameters: override.parameters, + multimodal: override.multimodal ?? false, + multimodalAcceptedMimetypes: override.multimodalAcceptedMimetypes, + supportsTools: override.supportsTools ?? false, + unlisted: override.unlisted ?? false, + preprompt: override.preprompt ?? "", + systemRoleSupported: override.systemRoleSupported ?? true, + }; + modelsRaw.push(newModel); + logger.info({ modelId: newModel.id }, "[models] Added new model from MODELS env"); + } + } } const builtModels = await Promise.all(