From b956755f12b1cb45ffba5f52c1ccf1b84f8e5c79 Mon Sep 17 00:00:00 2001 From: Cai Yao <67412196+cy948@users.noreply.github.com> Date: Thu, 12 Sep 2024 21:35:33 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20Support?= =?UTF-8?q?=20Environment=20Variable=20Inference=20For=20NextAuth=20(#3701?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :recycle: refactor: `AUTH_SECRET`&`AUTH_TRUST_HOST` * :arrow_up: chore: update nextauth & @auth/core version * :recycle: refactor: env infer for `auth0` * :arrow_up: chore: always use latest `next-auth` & `@auth/core` * :recycle: refactor: align `authelia` * :recycle: refactor: align `authentik` * :recycle: align `github` * :recycle: refactor: align `azure_ad` * :recycle: refactor: align `cloudflare zero trust` * :recycle: refactor: align `generic-oidc` * :recycle: refactor: align `logto` * :recycle: refactor: align `zitadel` * :recycle: refactor: add deprecate tips * :recycle: refactor: add warning for `azure_ad` * :lipstick: style: reformat codes * :bug: fix: azure warning * :bug: fix: warning for cloudfalre zero turst * :bug: fix: warning for generic oidc * :rewind: revert: revert changes to `NEXT_AUTH_SECRET` * :recycle: refactor: add redirectProxy url * :rewind: revert: unmodify ENABLE_NEXT_AUTH * :test_tube: test: should show env warning --- package.json | 4 +- src/config/__tests__/auth.test.ts | 200 ++++++++++++++++++ src/config/auth.ts | 99 ++++++++- src/libs/next-auth/auth.config.ts | 4 +- src/libs/next-auth/sso-providers/auth0.ts | 8 +- src/libs/next-auth/sso-providers/authelia.ts | 12 +- src/libs/next-auth/sso-providers/authentik.ts | 8 +- src/libs/next-auth/sso-providers/azure-ad.ts | 8 +- .../sso-providers/cloudflare-zero-trust.ts | 7 +- .../next-auth/sso-providers/generic-oidc.ts | 6 +- src/libs/next-auth/sso-providers/github.ts | 6 +- src/libs/next-auth/sso-providers/logto.ts | 6 +- src/libs/next-auth/sso-providers/zitadel.ts | 8 +- 13 files changed, 342 insertions(+), 34 deletions(-) create mode 100644 src/config/__tests__/auth.test.ts diff --git a/package.json b/package.json index 975edfa7c342..a668231cdbcf 100644 --- a/package.json +++ b/package.json @@ -102,7 +102,7 @@ "@ant-design/icons": "^5.4.0", "@ant-design/pro-components": "^2.7.10", "@anthropic-ai/sdk": "^0.27.0", - "@auth/core": "0.28.0", + "@auth/core": "^0.34.2", "@aws-sdk/client-bedrock-runtime": "^3.637.0", "@aws-sdk/client-s3": "^3.637.0", "@aws-sdk/s3-request-presigner": "^3.637.0", @@ -169,7 +169,7 @@ "modern-screenshot": "^4.4.39", "nanoid": "^5.0.7", "next": "14.2.8", - "next-auth": "5.0.0-beta.15", + "next-auth": "beta", "next-sitemap": "^4.2.3", "numeral": "^2.0.6", "nuqs": "^1.17.8", diff --git a/src/config/__tests__/auth.test.ts b/src/config/__tests__/auth.test.ts new file mode 100644 index 000000000000..632393f2496f --- /dev/null +++ b/src/config/__tests__/auth.test.ts @@ -0,0 +1,200 @@ +// @vitest-environment node +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +import { getAuthConfig } from '../auth'; + +// Stub the global process object to safely mock environment variables +vi.stubGlobal('process', { + ...process, // Preserve the original process object + env: { ...process.env }, // Clone the environment variables object for modification +}); + +const spyConsoleWarn = vi.spyOn(console, 'warn'); + +describe('getAuthConfig', () => { + beforeEach(() => { + // Clear all environment variables before each test + // @ts-expect-error + process.env = {}; + }); + + // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end + describe('should warn about deprecated environment variables', () => { + it('should warn about Auth0 deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.AUTH0_CLIENT_ID = 'auth0_client_id'; + process.env.AUTH0_CLIENT_SECRET = 'auth0_client_secret'; + process.env.AUTH0_ISSUER = 'auth0_issuer'; + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + // Example: A warning meassage should incloud: ` .* ` + // And the regex should match the warning message: `AUTH0_CLIENT_ID.*AUTH_AUTH0_ID` + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTH0_CLIENT_ID.*AUTH_AUTH0_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTH0_CLIENT_SECRET.*AUTH_AUTH0_SECRET/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTH0_ISSUER.*AUTH_AUTH0_ISSUER/), + ); + }); + it('should warn about Authentik deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.AUTHENTIK_CLIENT_ID = 'authentik_client_id'; + process.env.AUTHENTIK_CLIENT_SECRET = 'authentik_client_secret'; + process.env.AUTHENTIK_ISSUER = 'authentik_issuer'; + + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTHENTIK_CLIENT_ID.*AUTH_AUTHENTIK_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTHENTIK_CLIENT_SECRET.*AUTH_AUTHENTIK_SECRET/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTHENTIK_ISSUER.*AUTH_AUTHENTIK_ISSUER/), + ); + }); + it('should warn about Authelia deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.AUTHELIA_CLIENT_ID = 'authelia_client_id'; + process.env.AUTHELIA_CLIENT_SECRET = 'authelia_client_secret'; + process.env.AUTHELIA_ISSUER = 'authelia_issuer'; + + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTHELIA_CLIENT_ID.*AUTH_AUTHELIA_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTHELIA_CLIENT_SECRET.*AUTH_AUTHELIA_SECRET/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AUTHELIA_ISSUER.*AUTH_AUTHELIA_ISSUER/), + ); + }); + it('should warn about AzureAD deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.AZURE_AD_CLIENT_ID = 'azure_ad_client_id'; + process.env.AZURE_AD_CLIENT_SECRET = 'azure_ad_client_secret'; + process.env.AZURE_AD_TENANT_ID = 'azure_ad_tenant_id'; + + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AZURE_AD_CLIENT_ID.*AUTH_AZURE_AD_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AZURE_AD_CLIENT_SECRET.*AUTH_AZURE_AD_SECRET/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/AZURE_AD_TENANT_ID.*AUTH_AZURE_AD_TENANT_ID/), + ); + }); + it('should warn about Cloudflare Zero Trust deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.CLOUDFLARE_ZERO_TRUST_CLIENT_ID = 'cloudflare_zero_trust_client_id'; + process.env.CLOUDFLARE_ZERO_TRUST_CLIENT_SECRET = 'cloudflare_zero_trust_client_secret'; + process.env.CLOUDFLARE_ZERO_TRUST_ISSUER = 'cloudflare_zero_trust_issuer'; + + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/CLOUDFLARE_ZERO_TRUST_CLIENT_ID.*AUTH_CLOUDFLARE_ZERO_TRUST_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching( + /CLOUDFLARE_ZERO_TRUST_CLIENT_SECRET.*AUTH_CLOUDFLARE_ZERO_TRUST_SECRET/, + ), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/CLOUDFLARE_ZERO_TRUST_ISSUER.*AUTH_CLOUDFLARE_ZERO_TRUST_ISSUER/), + ); + }); + it('should warn about Generic OIDC deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.GENERIC_OIDC_CLIENT_ID = 'generic_oidc_client_id'; + process.env.GENERIC_OIDC_CLIENT_SECRET = 'generic_oidc_client_secret'; + process.env.GENERIC_OIDC_ISSUER = 'generic_oidc_issuer'; + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/GENERIC_OIDC_CLIENT_ID.*AUTH_GENERIC_OIDC_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/GENERIC_OIDC_CLIENT_SECRET.*AUTH_GENERIC_OIDC_SECRET/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/GENERIC_OIDC_ISSUER.*AUTH_GENERIC_OIDC_ISSUER/), + ); + }); + it('should warn about GitHub deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.GITHUB_CLIENT_ID = 'github_client_id'; + process.env.GITHUB_CLIENT_SECRET = 'github_client_secret'; + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/GITHUB_CLIENT_ID.*AUTH_GITHUB_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/GITHUB_CLIENT_SECRET.*AUTH_GITHUB_SECRET/), + ); + }); + it('should warn about Logto deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.LOGTO_CLIENT_ID = 'logto_client_id'; + process.env.LOGTO_CLIENT_SECRET = 'logto_client_secret'; + process.env.LOGTO_ISSUER = 'logto_issuer'; + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/LOGTO_CLIENT_ID.*AUTH_LOGTO_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/LOGTO_CLIENT_SECRET.*AUTH_LOGTO_SECRET/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/LOGTO_ISSUER.*AUTH_LOGTO_ISSUER/), + ); + }); + it('should warn about Zitadel deprecated environment variables', () => { + // Set all deprecated environment variables + process.env.ZITADEL_CLIENT_ID = 'zitadel_client_id'; + process.env.ZITADEL_CLIENT_SECRET = 'zitadel_client_secret'; + process.env.ZITADEL_ISSUER = 'zitadel_issuer'; + // Call the function + getAuthConfig(); + + // Check that the spyConsoleWarn function was called for each deprecated environment variable + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/ZITADEL_CLIENT_ID.*AUTH_ZITADEL_ID/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/ZITADEL_CLIENT_SECRET.*AUTH_ZITADEL_SECRET/), + ); + expect(spyConsoleWarn).toHaveBeenCalledWith( + expect.stringMatching(/ZITADEL_ISSUER.*AUTH_ZITADEL_ISSUER/), + ); + }); + }); + // Remove end +}); diff --git a/src/config/auth.ts b/src/config/auth.ts index fa28c94e9a0e..d15cddd8724d 100644 --- a/src/config/auth.ts +++ b/src/config/auth.ts @@ -42,7 +42,102 @@ declare global { } } +// TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end +const removeTipsTemplate = (willBeRemoved: string, replaceOne: string) => + `${willBeRemoved} will be removed in the future. Please set ${replaceOne} instead.`; +// End + export const getAuthConfig = () => { + // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end + if (process.env.AUTH0_CLIENT_ID) { + console.warn(removeTipsTemplate('AUTH0_CLIENT_ID', 'AUTH_AUTH0_ID')); + } + if (process.env.AUTH0_CLIENT_SECRET) { + console.warn(removeTipsTemplate('AUTH0_CLIENT_SECRET', 'AUTH_AUTH0_SECRET')); + } + if (process.env.AUTH0_ISSUER) { + console.warn(removeTipsTemplate('AUTH0_ISSUER', 'AUTH_AUTH0_ISSUER')); + } + if (process.env.AUTHENTIK_CLIENT_ID) { + console.warn(removeTipsTemplate('AUTHENTIK_CLIENT_ID', 'AUTH_AUTHENTIK_ID')); + } + if (process.env.AUTHENTIK_CLIENT_SECRET) { + console.warn(removeTipsTemplate('AUTHENTIK_CLIENT_SECRET', 'AUTH_AUTHENTIK_SECRET')); + } + if (process.env.AUTHENTIK_ISSUER) { + console.warn(removeTipsTemplate('AUTHENTIK_ISSUER', 'AUTH_AUTHENTIK_ISSUER')); + } + if (process.env.AUTHELIA_CLIENT_ID) { + console.warn(removeTipsTemplate('AUTHELIA_CLIENT_ID', 'AUTH_AUTHELIA_ID')); + } + if (process.env.AUTHELIA_CLIENT_SECRET) { + console.warn(removeTipsTemplate('AUTHELIA_CLIENT_SECRET', 'AUTH_AUTHELIA_SECRET')); + } + if (process.env.AUTHELIA_ISSUER) { + console.warn(removeTipsTemplate('AUTHELIA_ISSUER', 'AUTH_AUTHELIA_ISSUER')); + } + if (process.env.AZURE_AD_CLIENT_ID) { + console.warn(removeTipsTemplate('AZURE_AD_CLIENT_ID', 'AUTH_AZURE_AD_ID')); + } + if (process.env.AZURE_AD_CLIENT_SECRET) { + console.warn(removeTipsTemplate('AZURE_AD_CLIENT_SECRET', 'AUTH_AZURE_AD_SECRET')); + } + if (process.env.AZURE_AD_TENANT_ID) { + console.warn(removeTipsTemplate('AZURE_AD_TENANT_ID', 'AUTH_AZURE_AD_TENANT_ID')); + } + if (process.env.CLOUDFLARE_ZERO_TRUST_CLIENT_ID) { + console.warn( + removeTipsTemplate('CLOUDFLARE_ZERO_TRUST_CLIENT_ID', 'AUTH_CLOUDFLARE_ZERO_TRUST_ID'), + ); + } + if (process.env.CLOUDFLARE_ZERO_TRUST_CLIENT_SECRET) { + console.warn( + removeTipsTemplate( + 'CLOUDFLARE_ZERO_TRUST_CLIENT_SECRET', + 'AUTH_CLOUDFLARE_ZERO_TRUST_SECRET', + ), + ); + } + if (process.env.CLOUDFLARE_ZERO_TRUST_ISSUER) { + console.warn( + removeTipsTemplate('CLOUDFLARE_ZERO_TRUST_ISSUER', 'AUTH_CLOUDFLARE_ZERO_TRUST_ISSUER'), + ); + } + if (process.env.GENERIC_OIDC_CLIENT_ID) { + console.warn(removeTipsTemplate('GENERIC_OIDC_CLIENT_ID', 'AUTH_GENERIC_OIDC_ID')); + } + if (process.env.GENERIC_OIDC_CLIENT_SECRET) { + console.warn(removeTipsTemplate('GENERIC_OIDC_CLIENT_SECRET', 'AUTH_GENERIC_OIDC_SECRET')); + } + if (process.env.GENERIC_OIDC_ISSUER) { + console.warn(removeTipsTemplate('GENERIC_OIDC_ISSUER', 'AUTH_GENERIC_OIDC_ISSUER')); + } + if (process.env.GITHUB_CLIENT_ID) { + console.warn(removeTipsTemplate('GITHUB_CLIENT_ID', 'AUTH_GITHUB_ID')); + } + if (process.env.GITHUB_CLIENT_SECRET) { + console.warn(removeTipsTemplate('GITHUB_CLIENT_SECRET', 'AUTH_GITHUB_SECRET')); + } + if (process.env.LOGTO_CLIENT_ID) { + console.warn(removeTipsTemplate('LOGTO_CLIENT_ID', 'AUTH_LOGTO_ID')); + } + if (process.env.LOGTO_CLIENT_SECRET) { + console.warn(removeTipsTemplate('LOGTO_CLIENT_SECRET', 'AUTH_LOGTO_SECRET')); + } + if (process.env.LOGTO_ISSUER) { + console.warn(removeTipsTemplate('LOGTO_ISSUER', 'AUTH_LOGTO_ISSUER')); + } + if (process.env.ZITADEL_CLIENT_ID) { + console.warn(removeTipsTemplate('ZITADEL_CLIENT_ID', 'AUTH_ZITADEL_ID')); + } + if (process.env.ZITADEL_CLIENT_SECRET) { + console.warn(removeTipsTemplate('ZITADEL_CLIENT_SECRET', 'AUTH_ZITADEL_SECRET')); + } + if (process.env.ZITADEL_ISSUER) { + console.warn(removeTipsTemplate('ZITADEL_ISSUER', 'AUTH_ZITADEL_ISSUER')); + } + // End + return createEnv({ client: { NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().optional(), @@ -95,7 +190,7 @@ export const getAuthConfig = () => { GENERIC_OIDC_CLIENT_ID: z.string().optional(), GENERIC_OIDC_CLIENT_SECRET: z.string().optional(), GENERIC_OIDC_ISSUER: z.string().optional(), - + // ZITADEL ZITADEL_CLIENT_ID: z.string().optional(), ZITADEL_CLIENT_SECRET: z.string().optional(), @@ -152,7 +247,7 @@ export const getAuthConfig = () => { GENERIC_OIDC_CLIENT_ID: process.env.GENERIC_OIDC_CLIENT_ID, GENERIC_OIDC_CLIENT_SECRET: process.env.GENERIC_OIDC_CLIENT_SECRET, GENERIC_OIDC_ISSUER: process.env.GENERIC_OIDC_ISSUER, - + // ZITADEL ZITADEL_CLIENT_ID: process.env.ZITADEL_CLIENT_ID, ZITADEL_CLIENT_SECRET: process.env.ZITADEL_CLIENT_SECRET, diff --git a/src/libs/next-auth/auth.config.ts b/src/libs/next-auth/auth.config.ts index 2ad9f7e8e1aa..afb11a8ef462 100644 --- a/src/libs/next-auth/auth.config.ts +++ b/src/libs/next-auth/auth.config.ts @@ -1,4 +1,5 @@ import type { NextAuthConfig } from 'next-auth'; +import urlJoin from 'url-join'; import { authEnv } from '@/config/auth'; @@ -40,6 +41,7 @@ export default { }, }, providers: initSSOProviders(), + redirectProxyUrl: process.env.APP_URL ? urlJoin(process.env.APP_URL, '/api/auth') : undefined, secret: authEnv.NEXT_AUTH_SECRET, - trustHost: true, + trustHost: process.env?.AUTH_TRUST_HOST ? process.env.AUTH_TRUST_HOST === 'true' : true, } satisfies NextAuthConfig; diff --git a/src/libs/next-auth/sso-providers/auth0.ts b/src/libs/next-auth/sso-providers/auth0.ts index 1bfe62fb19ad..4ca84f32e0f7 100644 --- a/src/libs/next-auth/sso-providers/auth0.ts +++ b/src/libs/next-auth/sso-providers/auth0.ts @@ -11,9 +11,11 @@ const provider = { // Specify auth scope, at least include 'openid email' // all scopes in Auth0 ref: https://auth0.com/docs/get-started/apis/scopes/openid-connect-scopes#standard-claims authorization: { params: { scope: 'openid email profile' } }, - clientId: authEnv.AUTH0_CLIENT_ID, - clientSecret: authEnv.AUTH0_CLIENT_SECRET, - issuer: authEnv.AUTH0_ISSUER, + // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end + clientId: authEnv.AUTH0_CLIENT_ID ?? process.env.AUTH_AUTH0_ID, + clientSecret: authEnv.AUTH0_CLIENT_SECRET ?? process.env.AUTH_AUTH0_SECRET, + issuer: authEnv.AUTH0_ISSUER ?? process.env.AUTH_AUTH0_ISSUER, + // Remove End profile(profile) { return { email: profile.email, diff --git a/src/libs/next-auth/sso-providers/authelia.ts b/src/libs/next-auth/sso-providers/authelia.ts index 748f8d42f5fe..9ac77a0ef67c 100644 --- a/src/libs/next-auth/sso-providers/authelia.ts +++ b/src/libs/next-auth/sso-providers/authelia.ts @@ -6,11 +6,11 @@ import { CommonProviderConfig } from './sso.config'; export type AutheliaProfile = { // The users display name - email: string; + email: string; // The users email - groups: string[]; + groups: string[]; // The username the user used to login with - name: string; + name: string; preferred_username: string; // The users groups sub: string; // The users id }; @@ -21,10 +21,10 @@ const provider = { ...CommonProviderConfig, authorization: { params: { scope: 'openid email profile' } }, checks: ['state', 'pkce'], - clientId: authEnv.AUTHELIA_CLIENT_ID, - clientSecret: authEnv.AUTHELIA_CLIENT_SECRET, + clientId: authEnv.AUTHELIA_CLIENT_ID ?? process.env.AUTH_AUTHELIA_ID, + clientSecret: authEnv.AUTHELIA_CLIENT_SECRET ?? process.env.AUTH_AUTHELIA_SECRET, id: 'authelia', - issuer: authEnv.AUTHELIA_ISSUER, + issuer: authEnv.AUTHELIA_ISSUER ?? process.env.AUTH_AUTHELIA_ISSUER, name: 'Authelia', profile(profile) { return { diff --git a/src/libs/next-auth/sso-providers/authentik.ts b/src/libs/next-auth/sso-providers/authentik.ts index bb8f007840e1..3b13902269f0 100644 --- a/src/libs/next-auth/sso-providers/authentik.ts +++ b/src/libs/next-auth/sso-providers/authentik.ts @@ -11,9 +11,11 @@ const provider = { // Specify auth scope, at least include 'openid email' // all scopes in Authentik ref: https://goauthentik.io/docs/providers/oauth2 authorization: { params: { scope: 'openid email profile' } }, - clientId: authEnv.AUTHENTIK_CLIENT_ID, - clientSecret: authEnv.AUTHENTIK_CLIENT_SECRET, - issuer: authEnv.AUTHENTIK_ISSUER, + // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end + clientId: authEnv.AUTHENTIK_CLIENT_ID ?? process.env.AUTH_AUTHENTIK_ID, + clientSecret: authEnv.AUTHENTIK_CLIENT_SECRET ?? process.env.AUTH_AUTHENTIK_SECRET, + issuer: authEnv.AUTHENTIK_ISSUER ?? process.env.AUTH_AUTHENTIK_ISSUER, + // Remove end // TODO(NextAuth): map unique user id to `providerAccountId` field // profile(profile) { // return { diff --git a/src/libs/next-auth/sso-providers/azure-ad.ts b/src/libs/next-auth/sso-providers/azure-ad.ts index ec615dd8bea1..9aab77da32fd 100644 --- a/src/libs/next-auth/sso-providers/azure-ad.ts +++ b/src/libs/next-auth/sso-providers/azure-ad.ts @@ -11,9 +11,11 @@ const provider = { // Specify auth scope, at least include 'openid email' // all scopes in Azure AD ref: https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc#openid-connect-scopes authorization: { params: { scope: 'openid email profile' } }, - clientId: authEnv.AZURE_AD_CLIENT_ID, - clientSecret: authEnv.AZURE_AD_CLIENT_SECRET, - tenantId: authEnv.AZURE_AD_TENANT_ID, + // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end + clientId: authEnv.AZURE_AD_CLIENT_ID ?? process.env.AUTH_AZURE_AD_ID, + clientSecret: authEnv.AZURE_AD_CLIENT_SECRET ?? process.env.AUTH_AZURE_AD_SECRET, + tenantId: authEnv.AZURE_AD_TENANT_ID ?? process.env.AUTH_AZURE_AD_TENANT_ID, + // Remove end // TODO(NextAuth): map unique user id to `providerAccountId` field // profile(profile) { // return { diff --git a/src/libs/next-auth/sso-providers/cloudflare-zero-trust.ts b/src/libs/next-auth/sso-providers/cloudflare-zero-trust.ts index 0c03c770d385..bd9ba2f13ae4 100644 --- a/src/libs/next-auth/sso-providers/cloudflare-zero-trust.ts +++ b/src/libs/next-auth/sso-providers/cloudflare-zero-trust.ts @@ -16,10 +16,11 @@ const provider = { ...CommonProviderConfig, authorization: { params: { scope: 'openid email profile' } }, checks: ['state', 'pkce'], - clientId: authEnv.CLOUDFLARE_ZERO_TRUST_CLIENT_ID, - clientSecret: authEnv.CLOUDFLARE_ZERO_TRUST_CLIENT_SECRET, + clientId: authEnv.CLOUDFLARE_ZERO_TRUST_CLIENT_ID ?? process.env.AUTH_CLOUDFLARE_ZERO_TRUST_ID, + clientSecret: + authEnv.CLOUDFLARE_ZERO_TRUST_CLIENT_SECRET ?? process.env.AUTH_CLOUDFLARE_ZERO_TRUST_SECRET, id: 'cloudflare-zero-trust', - issuer: authEnv.CLOUDFLARE_ZERO_TRUST_ISSUER, + issuer: authEnv.CLOUDFLARE_ZERO_TRUST_ISSUER ?? process.env.AUTH_CLOUDFLARE_ZERO_TRUST_ISSUER, name: 'Cloudflare Zero Trust', profile(profile) { return { diff --git a/src/libs/next-auth/sso-providers/generic-oidc.ts b/src/libs/next-auth/sso-providers/generic-oidc.ts index 3390c592d0db..61736a5367a7 100644 --- a/src/libs/next-auth/sso-providers/generic-oidc.ts +++ b/src/libs/next-auth/sso-providers/generic-oidc.ts @@ -19,10 +19,10 @@ const provider = { ...CommonProviderConfig, authorization: { params: { scope: 'email openid profile' } }, checks: ['state', 'pkce'], - clientId: authEnv.GENERIC_OIDC_CLIENT_ID, - clientSecret: authEnv.GENERIC_OIDC_CLIENT_SECRET, + clientId: authEnv.GENERIC_OIDC_CLIENT_ID ?? process.env.AUTH_GENERIC_OIDC_ID, + clientSecret: authEnv.GENERIC_OIDC_CLIENT_SECRET ?? process.env.AUTH_GENERIC_OIDC_SECRET, id: 'generic-oidc', - issuer: authEnv.GENERIC_OIDC_ISSUER, + issuer: authEnv.GENERIC_OIDC_ISSUER ?? process.env.AUTH_GENERIC_OIDC_ISSUER, name: 'Generic OIDC', profile(profile) { return { diff --git a/src/libs/next-auth/sso-providers/github.ts b/src/libs/next-auth/sso-providers/github.ts index cabae5ff16ab..53514fe3cbd1 100644 --- a/src/libs/next-auth/sso-providers/github.ts +++ b/src/libs/next-auth/sso-providers/github.ts @@ -10,8 +10,10 @@ const provider = { ...CommonProviderConfig, // Specify auth scope, at least include 'openid email' authorization: { params: { scope: 'read:user user:email' } }, - clientId: authEnv.GITHUB_CLIENT_ID, - clientSecret: authEnv.GITHUB_CLIENT_SECRET, + // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end + clientId: authEnv.GITHUB_CLIENT_ID ?? process.env.AUTH_GITHUB_ID, + clientSecret: authEnv.GITHUB_CLIENT_SECRET ?? process.env.AUTH_GITHUB_SECRET, + // Remove end profile: (profile) => { return { email: profile.email, diff --git a/src/libs/next-auth/sso-providers/logto.ts b/src/libs/next-auth/sso-providers/logto.ts index c2e4fde062d2..2195ab0ef446 100644 --- a/src/libs/next-auth/sso-providers/logto.ts +++ b/src/libs/next-auth/sso-providers/logto.ts @@ -41,9 +41,9 @@ const provider = { }, // You can get the issuer value from the Logto Application Details page, // in the field "Issuer endpoint" - clientId: authEnv.LOGTO_CLIENT_ID, - clientSecret: authEnv.LOGTO_CLIENT_SECRET, - issuer: authEnv.LOGTO_ISSUER, + clientId: authEnv.LOGTO_CLIENT_ID ?? process.env.AUTH_LOGTO_ID, + clientSecret: authEnv.LOGTO_CLIENT_SECRET ?? process.env.AUTH_LOGTO_SECRET, + issuer: authEnv.LOGTO_ISSUER ?? process.env.AUTH_LOGTO_ISSUER, }), }; diff --git a/src/libs/next-auth/sso-providers/zitadel.ts b/src/libs/next-auth/sso-providers/zitadel.ts index 506ad50ed5cd..97e29f7771ab 100644 --- a/src/libs/next-auth/sso-providers/zitadel.ts +++ b/src/libs/next-auth/sso-providers/zitadel.ts @@ -7,9 +7,11 @@ const provider = { provider: Zitadel({ // Available scopes in ZITADEL: https://zitadel.com/docs/apis/openidoauth/scopes authorization: { params: { scope: 'openid email profile' } }, - clientId: authEnv.ZITADEL_CLIENT_ID, - clientSecret: authEnv.ZITADEL_CLIENT_SECRET, - issuer: authEnv.ZITADEL_ISSUER, + // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end + clientId: authEnv.ZITADEL_CLIENT_ID ?? process.env.AUTH_ZITADEL_ID, + clientSecret: authEnv.ZITADEL_CLIENT_SECRET ?? process.env.AUTH_ZITADEL_SECRET, + issuer: authEnv.ZITADEL_ISSUER ?? process.env.AUTH_ZITADEL_ISSUER, + // Remove end // TODO(NextAuth): map unique user id to `providerAccountId` field // profile(profile) { // return { From c9f00e540e835c8ea497720f2b0fafc0f2fdb4f5 Mon Sep 17 00:00:00 2001 From: sxjeru Date: Thu, 12 Sep 2024 21:36:25 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=90=9B=20fix:=20Qwen=20model=20para?= =?UTF-8?q?m=20error=20(#3902)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update index.ts * Update index.test.ts * Update index.test.ts * Update index.test.ts --- src/libs/agent-runtime/qwen/index.test.ts | 24 +++++++++++++++++++---- src/libs/agent-runtime/qwen/index.ts | 2 +- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/libs/agent-runtime/qwen/index.test.ts b/src/libs/agent-runtime/qwen/index.test.ts index 797c42e908b8..35845391a12c 100644 --- a/src/libs/agent-runtime/qwen/index.test.ts +++ b/src/libs/agent-runtime/qwen/index.test.ts @@ -161,13 +161,11 @@ describe('LobeQwenAI', () => { vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue( new ReadableStream() as any, ); - await instance.chat({ messages: [{ content: 'Hello', role: 'user' }], model: 'qwen-turbo', temperature: temp, }); - expect(instance['client'].chat.completions.create).toHaveBeenCalledWith( expect.objectContaining({ messages: expect.any(Array), @@ -183,13 +181,11 @@ describe('LobeQwenAI', () => { vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue( new ReadableStream() as any, ); - await instance.chat({ messages: [{ content: 'Hello', role: 'user' }], model: 'qwen-turbo', temperature: 1.5, }); - expect(instance['client'].chat.completions.create).toHaveBeenCalledWith( expect.objectContaining({ messages: expect.any(Array), @@ -199,6 +195,26 @@ describe('LobeQwenAI', () => { expect.any(Object), ); }); + + it('should set temperature to Float', async () => { + const createMock = vi.fn().mockResolvedValue(new ReadableStream() as any); + vi.spyOn(instance['client'].chat.completions, 'create').mockImplementation(createMock); + await instance.chat({ + messages: [{ content: 'Hello', role: 'user' }], + model: 'qwen-turbo', + temperature: 1, + }); + expect(instance['client'].chat.completions.create).toHaveBeenCalledWith( + expect.objectContaining({ + messages: expect.any(Array), + model: 'qwen-turbo', + temperature: expect.any(Number), + }), + expect.any(Object), + ); + const callArgs = createMock.mock.calls[0][0]; + expect(Number.isInteger(callArgs.temperature)).toBe(false); // Temperature is always not an integer + }); }); describe('Error', () => { diff --git a/src/libs/agent-runtime/qwen/index.ts b/src/libs/agent-runtime/qwen/index.ts index 5657c46f2c60..a3dded74e519 100644 --- a/src/libs/agent-runtime/qwen/index.ts +++ b/src/libs/agent-runtime/qwen/index.ts @@ -111,7 +111,7 @@ export class LobeQwenAI implements LobeRuntimeAI { temperature: temperature === 0 || temperature >= 2 ? undefined - : temperature, + : (temperature === 1 ? 0.999 : temperature), // 'temperature' must be Float top_p: top_p && top_p >= 1 ? 0.999 : top_p, }; From 32ab090ac6e626c2a97a0d9dd1986c21165b1b3c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 12 Sep 2024 13:43:22 +0000 Subject: [PATCH 03/10] :bookmark: chore(release): v1.16.10 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### [Version 1.16.10](https://github.com/lobehub/lobe-chat/compare/v1.16.9...v1.16.10) Released on **2024-09-12** #### ♻ Code Refactoring - **misc**: Support Environment Variable Inference For NextAuth. #### 🐛 Bug Fixes - **misc**: Qwen model param error.
Improvements and Fixes #### Code refactoring * **misc**: Support Environment Variable Inference For NextAuth, closes [#3701](https://github.com/lobehub/lobe-chat/issues/3701) ([b956755](https://github.com/lobehub/lobe-chat/commit/b956755)) #### What's fixed * **misc**: Qwen model param error, closes [#3902](https://github.com/lobehub/lobe-chat/issues/3902) ([c9f00e5](https://github.com/lobehub/lobe-chat/commit/c9f00e5))
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
--- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4623522b362..2c3d665e37da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,39 @@ # Changelog +### [Version 1.16.10](https://github.com/lobehub/lobe-chat/compare/v1.16.9...v1.16.10) + +Released on **2024-09-12** + +#### ♻ Code Refactoring + +- **misc**: Support Environment Variable Inference For NextAuth. + +#### 🐛 Bug Fixes + +- **misc**: Qwen model param error. + +
+ +
+Improvements and Fixes + +#### Code refactoring + +- **misc**: Support Environment Variable Inference For NextAuth, closes [#3701](https://github.com/lobehub/lobe-chat/issues/3701) ([b956755](https://github.com/lobehub/lobe-chat/commit/b956755)) + +#### What's fixed + +- **misc**: Qwen model param error, closes [#3902](https://github.com/lobehub/lobe-chat/issues/3902) ([c9f00e5](https://github.com/lobehub/lobe-chat/commit/c9f00e5)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ ### [Version 1.16.9](https://github.com/lobehub/lobe-chat/compare/v1.16.8...v1.16.9) Released on **2024-09-12** diff --git a/package.json b/package.json index a668231cdbcf..3028aea08044 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lobehub/chat", - "version": "1.16.9", + "version": "1.16.10", "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.", "keywords": [ "framework", From 278a5bfc83cf75c01ac62be6fddb079b9deea544 Mon Sep 17 00:00:00 2001 From: Chung1912 <38153111+chung1912@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:10:55 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=F0=9F=93=9D=20docs:=20Minio=20uses=20a?= =?UTF-8?q?=20non-443=20port=20for=20reverse=20proxy,=20and=20the=20Host?= =?UTF-8?q?=20needs=20to=20be=20set=20to=20$http=5Fhost=20(#3925)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update docker-compose.zh-CN.mdx * Update docker-compose.mdx --- docs/self-hosting/server-database/docker-compose.mdx | 1 + docs/self-hosting/server-database/docker-compose.zh-CN.mdx | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/self-hosting/server-database/docker-compose.mdx b/docs/self-hosting/server-database/docker-compose.mdx index 623fb2f49a09..55eaace8e94c 100644 --- a/docs/self-hosting/server-database/docker-compose.mdx +++ b/docs/self-hosting/server-database/docker-compose.mdx @@ -186,6 +186,7 @@ And the service port without reverse proxy: Please note that CORS cross-origin is configured internally in MinIO / Logto service, do not configure CORS additionally in your reverse proxy, as this will cause errors. + For minio ports other than 443, Host must be $http_host (with port number), otherwise a 403 error will occur: proxy_set_header Host $http_host. If you need to configure SSL certificates, please configure them uniformly in the outer Nginx reverse proxy, rather than in MinIO. diff --git a/docs/self-hosting/server-database/docker-compose.zh-CN.mdx b/docs/self-hosting/server-database/docker-compose.zh-CN.mdx index 9f0faa6728b2..8952ed47686a 100644 --- a/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +++ b/docs/self-hosting/server-database/docker-compose.zh-CN.mdx @@ -185,6 +185,7 @@ docker compose up -d 请务必注意,CORS 跨域是在 MinIO / Logto 服务端内部配置的,请勿在你的反向代理中额外配置 CORS,这会导致错误。 + 对于minio非443端口时,Host必须是$http_host(带端口号),否则会403错误:proxy_set_header Host $http_host。 如果你需要配置 SSL 证书,请统一在外层的 Nginx 反向代理中配置,而不是在 MinIO 中配置。 From bdbc64780b9832a19cc55b3f842f8edb9e920115 Mon Sep 17 00:00:00 2001 From: LovelyGuYiMeng <76251800+LovelyGuYiMeng@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:17:57 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=F0=9F=92=84=20style:=20default=20disable?= =?UTF-8?q?=20mistral=20provider=20useless=20models=20(#3922)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update mistral.ts * Update bedrock.ts * Update mistral.ts * Update mistral.ts --- src/config/modelProviders/bedrock.ts | 28 ++++++++++++++-------------- src/config/modelProviders/mistral.ts | 3 --- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/config/modelProviders/bedrock.ts b/src/config/modelProviders/bedrock.ts index 892df8d143b7..32052eefd97d 100644 --- a/src/config/modelProviders/bedrock.ts +++ b/src/config/modelProviders/bedrock.ts @@ -40,6 +40,20 @@ const Bedrock: ModelProviderCard = { tokens: 200_000, vision: true, }, + { + description: + 'Claude 3 Haiku 是 Anthropic 最快、最紧凑的模型,提供近乎即时的响应速度。它可以快速回答简单的查询和请求。客户将能够构建模仿人类互动的无缝 AI 体验。Claude 3 Haiku 可以处理图像并返回文本输出,具有 200K 的上下文窗口。', + displayName: 'Claude 3 Haiku', + enabled: true, + functionCall: true, + id: 'anthropic.claude-3-haiku-20240307-v1:0', + pricing: { + input: 0.25, + output: 1.25, + }, + tokens: 200_000, + vision: true, + }, { description: 'Anthropic 的 Claude 3 Sonnet 在智能和速度之间达到了理想的平衡——特别适合企业工作负载。它以低于竞争对手的价格提供最大的效用,并被设计成为可靠的、高耐用的主力机,适用于规模化的 AI 部署。Claude 3 Sonnet 可以处理图像并返回文本输出,具有 200K 的上下文窗口。', @@ -68,20 +82,6 @@ const Bedrock: ModelProviderCard = { tokens: 200_000, vision: true, }, - { - description: - 'Claude 3 Haiku 是 Anthropic 最快、最紧凑的模型,提供近乎即时的响应速度。它可以快速回答简单的查询和请求。客户将能够构建模仿人类互动的无缝 AI 体验。Claude 3 Haiku 可以处理图像并返回文本输出,具有 200K 的上下文窗口。', - displayName: 'Claude 3 Haiku', - enabled: true, - functionCall: true, - id: 'anthropic.claude-3-haiku-20240307-v1:0', - pricing: { - input: 0.25, - output: 1.25, - }, - tokens: 200_000, - vision: true, - }, { description: 'Claude 2 的更新版,具有双倍的上下文窗口,以及在长文档和 RAG 上下文中的可靠性、幻觉率和基于证据的准确性的改进。', diff --git a/src/config/modelProviders/mistral.ts b/src/config/modelProviders/mistral.ts index 2f772ff90796..b8111c2a6feb 100644 --- a/src/config/modelProviders/mistral.ts +++ b/src/config/modelProviders/mistral.ts @@ -8,7 +8,6 @@ const Mistral: ModelProviderCard = { description: 'Mistral 7B是一款紧凑但高性能的模型,擅长批量处理和简单任务,如分类和文本生成,具有良好的推理能力。', displayName: 'Mistral 7B', - enabled: true, id: 'open-mistral-7b', tokens: 32_768, }, @@ -16,7 +15,6 @@ const Mistral: ModelProviderCard = { description: 'Mixtral 8x7B是一个稀疏专家模型,利用多个参数提高推理速度,适合处理多语言和代码生成任务。', displayName: 'Mixtral 8x7B', - enabled: true, id: 'open-mixtral-8x7b', tokens: 32_768, }, @@ -57,7 +55,6 @@ const Mistral: ModelProviderCard = { description: 'Codestral Mamba是专注于代码生成的Mamba 2语言模型,为先进的代码和推理任务提供强力支持。', displayName: 'Codestral Mamba', - enabled: true, id: 'open-codestral-mamba', tokens: 256_000, }, From 0cfee6b744853965a3808f25eeb54682e911e67e Mon Sep 17 00:00:00 2001 From: Cai Yao <67412196+cy948@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:19:57 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=F0=9F=90=9B=20fix:=20support=20webhooks?= =?UTF-8?q?=20for=20logto=20(#3774)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :sparkles: feat: support webhooks for logto * :sparles: feat: update more info * :recycle: refactor: allow edit more info by webhook * :recycle: refactor: rename `nextauthUser` to `nextAuthUser` * :test_tube: test: + webhooks trigger --------- Co-authored-by: Arvin Xu --- .../webhooks/logto/__tests__/route.test.ts | 92 +++++++++++++++++++ src/app/api/webhooks/logto/route.ts | 40 ++++++++ src/app/api/webhooks/logto/validateRequest.ts | 50 ++++++++++ src/config/auth.ts | 2 + src/server/services/nextAuthUser/index.ts | 42 +++++++++ 5 files changed, 226 insertions(+) create mode 100644 src/app/api/webhooks/logto/__tests__/route.test.ts create mode 100644 src/app/api/webhooks/logto/route.ts create mode 100644 src/app/api/webhooks/logto/validateRequest.ts create mode 100644 src/server/services/nextAuthUser/index.ts diff --git a/src/app/api/webhooks/logto/__tests__/route.test.ts b/src/app/api/webhooks/logto/__tests__/route.test.ts new file mode 100644 index 000000000000..8c1fe7c52537 --- /dev/null +++ b/src/app/api/webhooks/logto/__tests__/route.test.ts @@ -0,0 +1,92 @@ +import { createHmac } from 'node:crypto'; +import { describe, expect, it } from 'vitest'; + +interface UserDataUpdatedEvent { + event: string; + createdAt: string; + userAgent: string; + ip: string; + path: string; + method: string; + status: number; + params: { + userId: string; + }; + matchedRoute: string; + data: { + id: string; + username: string; + primaryEmail: string; + primaryPhone: string | null; + name: string; + avatar: string | null; + customData: Record; + identities: Record; + lastSignInAt: number; + createdAt: number; + updatedAt: number; + profile: Record; + applicationId: string; + isSuspended: boolean; + }; + hookId: string; +} + +const userDataUpdatedEvent: UserDataUpdatedEvent = { + event: 'User.Data.Updated', + createdAt: '2024-09-07T08:29:09.381Z', + userAgent: + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0', + ip: '223.104.76.217', + path: '/users/rra41h9vmpnd', + method: 'PATCH', + status: 200, + params: { + userId: 'rra41h9vmpnd', + }, + matchedRoute: '/users/:userId', + data: { + id: 'uid', + username: 'test', + primaryEmail: 'user@example.com', + primaryPhone: null, + name: 'test', + avatar: null, + customData: {}, + identities: {}, + lastSignInAt: 1725446291545, + createdAt: 1725440405556, + updatedAt: 1725697749337, + profile: {}, + applicationId: 'appid', + isSuspended: false, + }, + hookId: 'hookId', +}; + +const LOGTO_WEBHOOK_SIGNING_KEY = 'logto-signing-key'; + +// Test Logto Webhooks in Local dev, here is some tips: +// - Replace the var `LOGTO_WEBHOOK_SIGNING_KEY` with the actual value in your `.env` file +// - Start web request: If you want to run the test, replace `describe.skip` with `describe` below + +describe.skip('Test Logto Webhooks in Local dev', () => { + // describe('Test Logto Webhooks in Local dev', () => { + it('should send a POST request with logto headers', async () => { + const url = 'http://localhost:3010/api/webhooks/logto'; // 替换为目标URL + const data = userDataUpdatedEvent; + // Generate data signature + const hmac = createHmac('sha256', LOGTO_WEBHOOK_SIGNING_KEY!); + hmac.update(JSON.stringify(data)); + const signature = hmac.digest('hex'); + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'logto-signature-sha-256': signature, + }, + body: JSON.stringify(data), + }); + expect(response.status).toBe(200); // 检查响应状态 + }); +}); diff --git a/src/app/api/webhooks/logto/route.ts b/src/app/api/webhooks/logto/route.ts new file mode 100644 index 000000000000..d1b67b0ec78f --- /dev/null +++ b/src/app/api/webhooks/logto/route.ts @@ -0,0 +1,40 @@ +import { NextResponse } from 'next/server'; + +import { authEnv } from '@/config/auth'; +import { pino } from '@/libs/logger'; +import { NextAuthUserService } from '@/server/services/nextAuthUser'; + +import { validateRequest } from './validateRequest'; + +export const POST = async (req: Request): Promise => { + const payload = await validateRequest(req, authEnv.LOGTO_WEBHOOK_SIGNING_KEY!); + + if (!payload) { + return NextResponse.json( + { error: 'webhook verification failed or payload was malformed' }, + { status: 400 }, + ); + } + + const { event, data } = payload; + + pino.trace(`logto webhook payload: ${{ data, event }}`); + + const nextAuthUserService = new NextAuthUserService(); + switch (event) { + case 'User.Data.Updated': { + return nextAuthUserService.safeUpdateUser(data.id, { + avatar: data?.avatar, + email: data?.primaryEmail, + fullName: data?.name, + }); + } + + default: { + pino.warn( + `${req.url} received event type "${event}", but no handler is defined for this type`, + ); + return NextResponse.json({ error: `unrecognised payload type: ${event}` }, { status: 400 }); + } + } +}; diff --git a/src/app/api/webhooks/logto/validateRequest.ts b/src/app/api/webhooks/logto/validateRequest.ts new file mode 100644 index 000000000000..0a1fa48a063f --- /dev/null +++ b/src/app/api/webhooks/logto/validateRequest.ts @@ -0,0 +1,50 @@ +import { headers } from 'next/headers'; +import { createHmac } from 'node:crypto'; + +import { authEnv } from '@/config/auth'; + +export type LogtToUserEntity = { + applicationId?: string; + avatar?: string; + createdAt?: string; + customData?: object; + id: string; + identities?: object; + isSuspended?: boolean; + lastSignInAt?: string; + name?: string; + primaryEmail?: string; + primaryPhone?: string; + username?: string; +}; + +interface LogtoWebhookPayload { + // Only support user event currently + data: LogtToUserEntity; + event: string; +} + +export const validateRequest = async (request: Request, signingKey: string) => { + const payloadString = await request.text(); + const headerPayload = headers(); + const logtoHeaderSignature = headerPayload.get('logto-signature-sha-256')!; + try { + const hmac = createHmac('sha256', signingKey); + hmac.update(payloadString); + const signature = hmac.digest('hex'); + if (signature === logtoHeaderSignature) { + return JSON.parse(payloadString) as LogtoWebhookPayload; + } else { + console.warn( + '[logto]: signature verify failed, please check your logto signature in `LOGTO_WEBHOOK_SIGNING_KEY`', + ); + return; + } + } catch (e) { + if (!authEnv.LOGTO_WEBHOOK_SIGNING_KEY) { + throw new Error('`LOGTO_WEBHOOK_SIGNING_KEY` environment variable is missing.'); + } + console.error('[logto]: incoming webhook failed in verification.\n', e); + return; + } +}; diff --git a/src/config/auth.ts b/src/config/auth.ts index d15cddd8724d..3859b8f88045 100644 --- a/src/config/auth.ts +++ b/src/config/auth.ts @@ -200,6 +200,7 @@ export const getAuthConfig = () => { LOGTO_CLIENT_ID: z.string().optional(), LOGTO_CLIENT_SECRET: z.string().optional(), LOGTO_ISSUER: z.string().optional(), + LOGTO_WEBHOOK_SIGNING_KEY: z.string().optional(), }, runtimeEnv: { @@ -257,6 +258,7 @@ export const getAuthConfig = () => { LOGTO_CLIENT_ID: process.env.LOGTO_CLIENT_ID, LOGTO_CLIENT_SECRET: process.env.LOGTO_CLIENT_SECRET, LOGTO_ISSUER: process.env.LOGTO_ISSUER, + LOGTO_WEBHOOK_SIGNING_KEY: process.env.LOGTO_WEBHOOK_SIGNING_KEY, }, }); }; diff --git a/src/server/services/nextAuthUser/index.ts b/src/server/services/nextAuthUser/index.ts new file mode 100644 index 000000000000..73889f2b9929 --- /dev/null +++ b/src/server/services/nextAuthUser/index.ts @@ -0,0 +1,42 @@ +import { NextResponse } from 'next/server'; + +import { serverDB } from '@/database/server'; +import { UserModel } from '@/database/server/models/user'; +import { UserItem } from '@/database/server/schemas/lobechat'; +import { pino } from '@/libs/logger'; +import { LobeNextAuthDbAdapter } from '@/libs/next-auth/adapter'; + +export class NextAuthUserService { + userModel; + adapter; + + constructor() { + this.userModel = new UserModel(); + this.adapter = LobeNextAuthDbAdapter(serverDB); + } + + safeUpdateUser = async (providerAccountId: string, data: Partial) => { + pino.info('updating user due to webhook'); + // 1. Find User by account + // @ts-expect-error: Already impl in `LobeNextauthDbAdapter` + const user = await this.adapter.getUserByAccount({ + provider: 'logto', + providerAccountId, + }); + + // 2. If found, Update user data from provider + if (user?.id) { + // Perform update + await this.userModel.updateUser(user.id, { + avatar: data?.avatar, + email: data?.email, + fullName: data?.fullName, + }); + } else { + pino.warn( + `[logto]: Webhooks handler user update for "${JSON.stringify(data)}", but no user was found by the providerAccountId.`, + ); + } + return NextResponse.json({ message: 'user updated', success: true }, { status: 200 }); + }; +} From ecf084b4b05ca607ddef66d80e2f8bdb3c8ad2cd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 12 Sep 2024 14:27:02 +0000 Subject: [PATCH 07/10] :bookmark: chore(release): v1.16.11 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### [Version 1.16.11](https://github.com/lobehub/lobe-chat/compare/v1.16.10...v1.16.11) Released on **2024-09-12** #### 🐛 Bug Fixes - **misc**: Support webhooks for logto. #### 💄 Styles - **misc**: Default disable mistral provider useless models.
Improvements and Fixes #### What's fixed * **misc**: Support webhooks for logto, closes [#3774](https://github.com/lobehub/lobe-chat/issues/3774) ([0cfee6b](https://github.com/lobehub/lobe-chat/commit/0cfee6b)) #### Styles * **misc**: Default disable mistral provider useless models, closes [#3922](https://github.com/lobehub/lobe-chat/issues/3922) ([bdbc647](https://github.com/lobehub/lobe-chat/commit/bdbc647))
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
--- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c3d665e37da..6cd4b225a109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,39 @@ # Changelog +### [Version 1.16.11](https://github.com/lobehub/lobe-chat/compare/v1.16.10...v1.16.11) + +Released on **2024-09-12** + +#### 🐛 Bug Fixes + +- **misc**: Support webhooks for logto. + +#### 💄 Styles + +- **misc**: Default disable mistral provider useless models. + +
+ +
+Improvements and Fixes + +#### What's fixed + +- **misc**: Support webhooks for logto, closes [#3774](https://github.com/lobehub/lobe-chat/issues/3774) ([0cfee6b](https://github.com/lobehub/lobe-chat/commit/0cfee6b)) + +#### Styles + +- **misc**: Default disable mistral provider useless models, closes [#3922](https://github.com/lobehub/lobe-chat/issues/3922) ([bdbc647](https://github.com/lobehub/lobe-chat/commit/bdbc647)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ ### [Version 1.16.10](https://github.com/lobehub/lobe-chat/compare/v1.16.9...v1.16.10) Released on **2024-09-12** diff --git a/package.json b/package.json index 3028aea08044..6ba2e9c639e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lobehub/chat", - "version": "1.16.10", + "version": "1.16.11", "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.", "keywords": [ "framework", From cc97ff6e4b251d6f6beac9a1a36c4424790285e4 Mon Sep 17 00:00:00 2001 From: Bui Trong Khanh Duy <57395332+khanhduyvt0101@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:16:59 +0700 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=92=84=20style:=20Add=20sessionToke?= =?UTF-8?q?n=20input=20for=20bedrock=20model=20=20(#3854)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add sessionToken for bedrock model * Support google model list * update relate sessionToken info * update description and revert gg model list * update description * change session token is a custom field --- .../advanced/auth/next-auth/logto.zh-CN.mdx | 2 +- locales/ar/modelProvider.json | 6 ++++ locales/bg-BG/modelProvider.json | 6 ++++ locales/de-DE/modelProvider.json | 6 ++++ locales/en-US/modelProvider.json | 6 ++++ locales/es-ES/modelProvider.json | 6 ++++ locales/fr-FR/modelProvider.json | 6 ++++ locales/it-IT/modelProvider.json | 6 ++++ locales/ja-JP/modelProvider.json | 6 ++++ locales/ko-KR/modelProvider.json | 6 ++++ locales/nl-NL/modelProvider.json | 6 ++++ locales/pl-PL/modelProvider.json | 6 ++++ locales/pt-BR/modelProvider.json | 6 ++++ locales/ru-RU/modelProvider.json | 6 ++++ locales/tr-TR/modelProvider.json | 6 ++++ locales/vi-VN/modelProvider.json | 6 ++++ locales/zh-CN/modelProvider.json | 6 ++++ locales/zh-TW/modelProvider.json | 6 ++++ .../llm/ProviderList/Bedrock/index.tsx | 11 ++++++++ src/app/api/chat/agentRuntime.test.ts | 1 + src/app/api/chat/agentRuntime.ts | 7 +++-- src/config/llm.ts | 2 ++ src/const/auth.ts | 1 + .../Conversation/Error/APIKeyForm/Bedrock.tsx | 28 +++++++++++++++++-- src/libs/agent-runtime/AgentRuntime.ts | 8 +++--- src/libs/agent-runtime/baichuan/index.ts | 9 ++---- src/libs/agent-runtime/bedrock/index.ts | 4 ++- src/libs/agent-runtime/qwen/index.test.ts | 2 +- src/libs/agent-runtime/qwen/index.ts | 6 ++-- .../utils/openaiCompatibleFactory/index.ts | 2 +- src/locales/default/modelProvider.ts | 6 ++++ src/server/globalConfig/index.ts | 12 ++++---- src/services/_auth.ts | 13 ++++++--- src/services/chat.ts | 1 + src/types/user/settings/keyVaults.ts | 1 + src/utils/format.ts | 2 +- 36 files changed, 187 insertions(+), 33 deletions(-) diff --git a/docs/self-hosting/advanced/auth/next-auth/logto.zh-CN.mdx b/docs/self-hosting/advanced/auth/next-auth/logto.zh-CN.mdx index dc35714ceff0..632e2bc9a70b 100644 --- a/docs/self-hosting/advanced/auth/next-auth/logto.zh-CN.mdx +++ b/docs/self-hosting/advanced/auth/next-auth/logto.zh-CN.mdx @@ -75,4 +75,4 @@ tags:
-部署成功后,用户将可以通过 Logto 身份认证并使用 LobeChat。 \ No newline at end of file +部署成功后,用户将可以通过 Logto 身份认证并使用 LobeChat。 diff --git a/locales/ar/modelProvider.json b/locales/ar/modelProvider.json index 5946f1052522..b25fd23ecfe5 100644 --- a/locales/ar/modelProvider.json +++ b/locales/ar/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "إذا كنت تستخدم AWS SSO/STS، يرجى إدخال رمز جلسة AWS الخاص بك", + "placeholder": "رمز جلسة AWS", + "title": "رمز جلسة AWS (اختياري)" + }, "title": "Bedrock", "unlock": { "customRegion": "منطقة خدمة مخصصة", + "customSessionToken": "رمز الجلسة المخصص", "description": "أدخل معرف الوصول / مفتاح الوصول السري الخاص بك في AWS لبدء الجلسة. لن يتم تسجيل تكوين المصادقة الخاص بك من قبل التطبيق", "title": "استخدام معلومات المصادقة الخاصة بـ Bedrock المخصصة" } diff --git a/locales/bg-BG/modelProvider.json b/locales/bg-BG/modelProvider.json index 6db4aa96d7d6..9ca9aababefe 100644 --- a/locales/bg-BG/modelProvider.json +++ b/locales/bg-BG/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Ако използвате AWS SSO/STS, моля, въведете вашия AWS Session Token", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (по избор)" + }, "title": "Bedrock", "unlock": { "customRegion": "Персонализиран регион за услуги", + "customSessionToken": "Персонализиран токен за сесия", "description": "Въведете вашия AWS AccessKeyId / SecretAccessKey, за да започнете сесия. Приложението няма да запази вашата удостоверителна конфигурация", "title": "Използване на персонализирана информация за удостоверяване на Bedrock" } diff --git a/locales/de-DE/modelProvider.json b/locales/de-DE/modelProvider.json index 1984d79d96f1..9d118f9efc9f 100644 --- a/locales/de-DE/modelProvider.json +++ b/locales/de-DE/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Wenn Sie AWS SSO/STS verwenden, geben Sie Ihr AWS Session Token ein", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (optional)" + }, "title": "Bedrock", "unlock": { "customRegion": "Benutzerdefinierter Regionsservice", + "customSessionToken": "Benutzerdefiniertes Sitzungstoken", "description": "Geben Sie Ihren AWS AccessKeyId / SecretAccessKey ein, um das Gespräch zu beginnen. Die App speichert Ihre Authentifizierungsinformationen nicht.", "title": "Verwenden Sie benutzerdefinierte Bedrock-Authentifizierungsinformationen" } diff --git a/locales/en-US/modelProvider.json b/locales/en-US/modelProvider.json index 0dca43e992ca..c96a74c0314a 100644 --- a/locales/en-US/modelProvider.json +++ b/locales/en-US/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "If you are using AWS SSO/STS, please enter your AWS Session Token", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (optional)" + }, "title": "Bedrock", "unlock": { "customRegion": "Custom Service Region", + "customSessionToken": "Custom Session Token", "description": "Enter your AWS AccessKeyId / SecretAccessKey to start the session. The app will not store your authentication configuration", "title": "Use Custom Bedrock Authentication Information" } diff --git a/locales/es-ES/modelProvider.json b/locales/es-ES/modelProvider.json index 3f8252390ba2..ce77c262d696 100644 --- a/locales/es-ES/modelProvider.json +++ b/locales/es-ES/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Si estás utilizando AWS SSO/STS, introduce tu Token de Sesión de AWS", + "placeholder": "Token de Sesión de AWS", + "title": "Token de Sesión de AWS (opcional)" + }, "title": "Bedrock", "unlock": { "customRegion": "Región de servicio personalizada", + "customSessionToken": "Token de sesión personalizado", "description": "Introduce tu AWS AccessKeyId / SecretAccessKey para comenzar la sesión. La aplicación no guardará tu configuración de autenticación.", "title": "Usar información de autenticación de Bedrock personalizada" } diff --git a/locales/fr-FR/modelProvider.json b/locales/fr-FR/modelProvider.json index 196204d65b7b..02950fe4c131 100644 --- a/locales/fr-FR/modelProvider.json +++ b/locales/fr-FR/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "Clé d'accès secrète AWS", "title": "Clé d'accès secrète AWS" }, + "sessionToken": { + "desc": "Si vous utilisez AWS SSO/STS, veuillez entrer votre jeton de session AWS", + "placeholder": "Jeton de session AWS", + "title": "Jeton de session AWS (facultatif)" + }, "title": "Bedrock", "unlock": { "customRegion": "Région de service personnalisée", + "customSessionToken": "Jeton de session personnalisé", "description": "Entrez votre ID de clé d'accès AWS / SecretAccessKey pour commencer la session. L'application ne stockera pas votre configuration d'authentification.", "title": "Utiliser des informations d'authentification Bedrock personnalisées" } diff --git a/locales/it-IT/modelProvider.json b/locales/it-IT/modelProvider.json index 07810bf158db..8fb0dedf4493 100644 --- a/locales/it-IT/modelProvider.json +++ b/locales/it-IT/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "Chiave di accesso segreta AWS", "title": "Chiave di accesso segreta AWS" }, + "sessionToken": { + "desc": "Se stai utilizzando AWS SSO/STS, inserisci il tuo AWS Session Token", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (opzionale)" + }, "title": "Bedrock", "unlock": { "customRegion": "Regione del servizio personalizzata", + "customSessionToken": "Token di sessione personalizzato", "description": "Inserisci la tua chiave di accesso AWS AccessKeyId / SecretAccessKey per avviare la sessione. L'applicazione non memorizzerà la tua configurazione di autenticazione", "title": "Usa le informazioni di autenticazione Bedrock personalizzate" } diff --git a/locales/ja-JP/modelProvider.json b/locales/ja-JP/modelProvider.json index 0db2e820c69c..8875b339ae07 100644 --- a/locales/ja-JP/modelProvider.json +++ b/locales/ja-JP/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "AWS SSO/STSを使用している場合は、AWSセッショントークンを入力してください。", + "placeholder": "AWSセッショントークン", + "title": "AWSセッショントークン(オプション)" + }, "title": "Bedrock", "unlock": { "customRegion": "カスタムサービスリージョン", + "customSessionToken": "カスタムセッショントークン", "description": "AWS AccessKeyId / SecretAccessKey を入力するとセッションを開始できます。アプリは認証情報を記録しません", "title": "使用カスタム Bedrock 認証情報" } diff --git a/locales/ko-KR/modelProvider.json b/locales/ko-KR/modelProvider.json index c1b96eee6ea7..8d9e4ab0a1f8 100644 --- a/locales/ko-KR/modelProvider.json +++ b/locales/ko-KR/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS 비밀 액세스 키", "title": "AWS 비밀 액세스 키" }, + "sessionToken": { + "desc": "AWS SSO/STS를 사용 중이라면 AWS 세션 토큰을 입력하세요.", + "placeholder": "AWS 세션 토큰", + "title": "AWS 세션 토큰 (선택 사항)" + }, "title": "Bedrock", "unlock": { "customRegion": "사용자 정의 서비스 지역", + "customSessionToken": "사용자 정의 세션 토큰", "description": "AWS AccessKeyId / SecretAccessKey를 입력하면 세션이 시작됩니다. 애플리케이션은 인증 구성을 기록하지 않습니다.", "title": "사용자 정의 Bedrock 인증 정보 사용" } diff --git a/locales/nl-NL/modelProvider.json b/locales/nl-NL/modelProvider.json index f1047716d0e3..10e2d82d0c2c 100644 --- a/locales/nl-NL/modelProvider.json +++ b/locales/nl-NL/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Als je AWS SSO/STS gebruikt, voer dan je AWS Sessie Token in", + "placeholder": "AWS Sessie Token", + "title": "AWS Sessie Token (optioneel)" + }, "title": "Bedrock", "unlock": { "customRegion": "Aangepaste regio", + "customSessionToken": "Aangepaste sessietoken", "description": "Voer uw AWS AccessKeyId / SecretAccessKey in om een sessie te starten. De app zal uw verificatiegegevens niet opslaan", "title": "Gebruik aangepaste Bedrock-verificatiegegevens" } diff --git a/locales/pl-PL/modelProvider.json b/locales/pl-PL/modelProvider.json index c7ddabd1ee84..7074b5b85118 100644 --- a/locales/pl-PL/modelProvider.json +++ b/locales/pl-PL/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Jeśli korzystasz z AWS SSO/STS, wprowadź swój token sesji AWS", + "placeholder": "Token sesji AWS", + "title": "Token sesji AWS (opcjonalnie)" + }, "title": "Bedrock", "unlock": { "customRegion": "Niestandardowy region usługi", + "customSessionToken": "Niestandardowy token sesji", "description": "Wprowadź swój AWS AccessKeyId / SecretAccessKey, aby rozpocząć sesję. Aplikacja nie będzie przechowywać Twojej konfiguracji uwierzytelniania", "title": "Użyj niestandardowych informacji uwierzytelniających Bedrock" } diff --git a/locales/pt-BR/modelProvider.json b/locales/pt-BR/modelProvider.json index 1521fb28dd6b..a01fcc3de95e 100644 --- a/locales/pt-BR/modelProvider.json +++ b/locales/pt-BR/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Se você estiver usando AWS SSO/STS, insira seu Token de Sessão da AWS", + "placeholder": "Token de Sessão da AWS", + "title": "Token de Sessão da AWS (opcional)" + }, "title": "Bedrock", "unlock": { "customRegion": "Região de serviço personalizada", + "customSessionToken": "Token de Sessão Personalizado", "description": "Digite sua AWS AccessKeyId / SecretAccessKey para iniciar a sessão. O aplicativo não irá armazenar suas configurações de autenticação", "title": "Usar informações de autenticação Bedrock personalizadas" } diff --git a/locales/ru-RU/modelProvider.json b/locales/ru-RU/modelProvider.json index d4ee8caa89e2..66009ef7fa12 100644 --- a/locales/ru-RU/modelProvider.json +++ b/locales/ru-RU/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Если вы используете AWS SSO/STS, введите ваш AWS Session Token", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (необязательно)" + }, "title": "Bedrock", "unlock": { "customRegion": "Пользовательский регион обслуживания", + "customSessionToken": "Пользовательский токен сессии", "description": "Введите свой ключ доступа AWS AccessKeyId / SecretAccessKey, чтобы начать сеанс. Приложение не будет сохранять вашу конфигурацию аутентификации", "title": "Использовать пользовательскую информацию аутентификации Bedrock" } diff --git a/locales/tr-TR/modelProvider.json b/locales/tr-TR/modelProvider.json index ff9e277d0f8c..8c5e3301e0b0 100644 --- a/locales/tr-TR/modelProvider.json +++ b/locales/tr-TR/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "AWS SSO/STS kullanıyorsanız, lütfen AWS Oturum Tokeninizi girin", + "placeholder": "AWS Oturum Tokeni", + "title": "AWS Oturum Tokeni (isteğe bağlı)" + }, "title": "Bedrock", "unlock": { "customRegion": "Özel Bölge", + "customSessionToken": "Özel Oturum Tokeni", "description": "AWS AccessKeyId / SecretAccessKey bilgilerinizi girerek oturumu başlatabilirsiniz. Uygulama kimlik doğrulama bilgilerinizi kaydetmez.", "title": "Özel Bedrock Kimlik Bilgilerini Kullan" } diff --git a/locales/vi-VN/modelProvider.json b/locales/vi-VN/modelProvider.json index 890169ab2623..481b1e2b76d0 100644 --- a/locales/vi-VN/modelProvider.json +++ b/locales/vi-VN/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "Nếu bạn đang sử dụng AWS SSO/STS, hãy nhập AWS Session Token của bạn", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (tùy chọn)" + }, "title": "Bedrock", "unlock": { "customRegion": "Vùng Dịch vụ Tùy chỉnh", + "customSessionToken": "Mã thông báo phiên tùy chỉnh", "description": "Nhập AWS AccessKeyId / SecretAccessKey của bạn để bắt đầu phiên làm việc. Ứng dụng sẽ không lưu trữ cấu hình xác thực của bạn", "title": "Sử dụng Thông tin Xác thực Bedrock tùy chỉnh" } diff --git a/locales/zh-CN/modelProvider.json b/locales/zh-CN/modelProvider.json index 4bbe0586e1d6..aec88fcf9cf0 100644 --- a/locales/zh-CN/modelProvider.json +++ b/locales/zh-CN/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "如果你正在使用 AWS SSO/STS,请输入你的 AWS Session Token", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (可选)" + }, "title": "Bedrock", "unlock": { "customRegion": "自定义服务区域", + "customSessionToken": "自定义 Session Token", "description": "输入你的 AWS AccessKeyId / SecretAccessKey 即可开始会话。应用不会记录你的鉴权配置", "title": "使用自定义 Bedrock 鉴权信息" } diff --git a/locales/zh-TW/modelProvider.json b/locales/zh-TW/modelProvider.json index cf7015220eb2..e7424f3263b0 100644 --- a/locales/zh-TW/modelProvider.json +++ b/locales/zh-TW/modelProvider.json @@ -38,9 +38,15 @@ "placeholder": "AWS Secret Access Key", "title": "AWS Secret Access Key" }, + "sessionToken": { + "desc": "如果你正在使用 AWS SSO/STS,請輸入你的 AWS Session Token", + "placeholder": "AWS Session Token", + "title": "AWS Session Token (可選)" + }, "title": "Bedrock", "unlock": { "customRegion": "自定義服務區域", + "customSessionToken": "自訂 Session Token", "description": "輸入你的 AWS AccessKeyId / SecretAccessKey 即可開始會話。應用程式不會記錄你的驗證配置", "title": "使用自定義 Bedrock 驗證資訊" } diff --git a/src/app/(main)/settings/llm/ProviderList/Bedrock/index.tsx b/src/app/(main)/settings/llm/ProviderList/Bedrock/index.tsx index a44527de74b1..946b4d58a58f 100644 --- a/src/app/(main)/settings/llm/ProviderList/Bedrock/index.tsx +++ b/src/app/(main)/settings/llm/ProviderList/Bedrock/index.tsx @@ -39,6 +39,17 @@ export const useBedrockProvider = (): ProviderItem => { label: t(`${providerKey}.secretAccessKey.title`), name: [KeyVaultsConfigKey, providerKey, 'secretAccessKey'], }, + { + children: ( + + ), + desc: t(`${providerKey}.sessionToken.desc`), + label: t(`${providerKey}.sessionToken.title`), + name: [KeyVaultsConfigKey, providerKey, 'sessionToken'], + }, { children: ( { diff --git a/src/libs/agent-runtime/AgentRuntime.ts b/src/libs/agent-runtime/AgentRuntime.ts index 7c04d4cb7e8c..ebc514bec892 100644 --- a/src/libs/agent-runtime/AgentRuntime.ts +++ b/src/libs/agent-runtime/AgentRuntime.ts @@ -26,7 +26,6 @@ import { LobeSparkAI } from './spark'; import { LobeStepfunAI } from './stepfun'; import { LobeTaichuAI } from './taichu'; import { LobeTogetherAI } from './togetherai'; -import { LobeUpstageAI } from './upstage'; import { ChatCompetitionOptions, ChatStreamPayload, @@ -35,6 +34,7 @@ import { ModelProvider, TextToImagePayload, } from './types'; +import { LobeUpstageAI } from './upstage'; import { LobeZeroOneAI } from './zeroone'; import { LobeZhipuAI } from './zhipu'; @@ -230,7 +230,7 @@ class AgentRuntime { case ModelProvider.FireworksAI: { runtimeModel = new LobeFireworksAI(params.fireworksai); - break + break; } case ModelProvider.ZeroOne: { @@ -275,12 +275,12 @@ class AgentRuntime { case ModelProvider.Upstage: { runtimeModel = new LobeUpstageAI(params.upstage); - break + break; } case ModelProvider.Spark: { runtimeModel = new LobeSparkAI(params.spark); - break + break; } } diff --git a/src/libs/agent-runtime/baichuan/index.ts b/src/libs/agent-runtime/baichuan/index.ts index 3b03186c89b8..3178977af4ac 100644 --- a/src/libs/agent-runtime/baichuan/index.ts +++ b/src/libs/agent-runtime/baichuan/index.ts @@ -9,14 +9,11 @@ export const LobeBaichuanAI = LobeOpenAICompatibleFactory({ handlePayload: (payload: ChatStreamPayload) => { const { temperature, ...rest } = payload; - return { - ...rest, + return { + ...rest, // [baichuan] frequency_penalty must be between 1 and 2. frequency_penalty: undefined, - temperature: - temperature !== undefined - ? temperature / 2 - : undefined, + temperature: temperature !== undefined ? temperature / 2 : undefined, } as OpenAI.ChatCompletionCreateParamsStreaming; }, }, diff --git a/src/libs/agent-runtime/bedrock/index.ts b/src/libs/agent-runtime/bedrock/index.ts index 9b24ff71cf9d..a0668e273cc0 100644 --- a/src/libs/agent-runtime/bedrock/index.ts +++ b/src/libs/agent-runtime/bedrock/index.ts @@ -21,6 +21,7 @@ export interface LobeBedrockAIParams { accessKeyId?: string; accessKeySecret?: string; region?: string; + sessionToken?: string; } export class LobeBedrockAI implements LobeRuntimeAI { @@ -28,7 +29,7 @@ export class LobeBedrockAI implements LobeRuntimeAI { region: string; - constructor({ region, accessKeyId, accessKeySecret }: LobeBedrockAIParams = {}) { + constructor({ region, accessKeyId, accessKeySecret, sessionToken }: LobeBedrockAIParams = {}) { if (!(accessKeyId && accessKeySecret)) throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidBedrockCredentials); @@ -38,6 +39,7 @@ export class LobeBedrockAI implements LobeRuntimeAI { credentials: { accessKeyId: accessKeyId, secretAccessKey: accessKeySecret, + sessionToken: sessionToken, }, region: this.region, }); diff --git a/src/libs/agent-runtime/qwen/index.test.ts b/src/libs/agent-runtime/qwen/index.test.ts index 35845391a12c..819a30a5175d 100644 --- a/src/libs/agent-runtime/qwen/index.test.ts +++ b/src/libs/agent-runtime/qwen/index.test.ts @@ -213,7 +213,7 @@ describe('LobeQwenAI', () => { expect.any(Object), ); const callArgs = createMock.mock.calls[0][0]; - expect(Number.isInteger(callArgs.temperature)).toBe(false); // Temperature is always not an integer + expect(Number.isInteger(callArgs.temperature)).toBe(false); // Temperature is always not an integer }); }); diff --git a/src/libs/agent-runtime/qwen/index.ts b/src/libs/agent-runtime/qwen/index.ts index a3dded74e519..0bfee54edd10 100644 --- a/src/libs/agent-runtime/qwen/index.ts +++ b/src/libs/agent-runtime/qwen/index.ts @@ -108,10 +108,8 @@ export class LobeQwenAI implements LobeRuntimeAI { messages, result_format: 'message', stream: !!tools?.length ? false : (stream ?? true), - temperature: - temperature === 0 || temperature >= 2 - ? undefined - : (temperature === 1 ? 0.999 : temperature), // 'temperature' must be Float + temperature: + temperature === 0 || temperature >= 2 ? undefined : temperature === 1 ? 0.999 : temperature, // 'temperature' must be Float top_p: top_p && top_p >= 1 ? 0.999 : top_p, }; diff --git a/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts b/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts index df0311c1b9e6..f324b9c68f38 100644 --- a/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts +++ b/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts @@ -18,9 +18,9 @@ import { AgentRuntimeError } from '../createError'; import { debugResponse, debugStream } from '../debugStream'; import { desensitizeUrl } from '../desensitizeUrl'; import { handleOpenAIError } from '../handleOpenAIError'; +import { convertOpenAIMessages } from '../openaiHelpers'; import { StreamingResponse } from '../response'; import { OpenAIStream } from '../streams'; -import { convertOpenAIMessages } from '../openaiHelpers'; // the model contains the following keywords is not a chat model, so we should filter them out const CHAT_MODELS_BLOCK_LIST = [ diff --git a/src/locales/default/modelProvider.ts b/src/locales/default/modelProvider.ts index 69d010023338..bc28461ab04d 100644 --- a/src/locales/default/modelProvider.ts +++ b/src/locales/default/modelProvider.ts @@ -38,9 +38,15 @@ export default { placeholder: 'AWS Secret Access Key', title: 'AWS Secret Access Key', }, + sessionToken: { + desc: '如果你正在使用 AWS SSO/STS,请输入你的 AWS Session Token', + placeholder: 'AWS Session Token', + title: 'AWS Session Token (可选)', + }, title: 'Bedrock', unlock: { customRegion: '自定义服务区域', + customSessionToken: '自定义 Session Token', description: '输入你的 AWS AccessKeyId / SecretAccessKey 即可开始会话。应用不会记录你的鉴权配置', title: '使用自定义 Bedrock 鉴权信息', diff --git a/src/server/globalConfig/index.ts b/src/server/globalConfig/index.ts index d33b911e098c..82d8a9e6d620 100644 --- a/src/server/globalConfig/index.ts +++ b/src/server/globalConfig/index.ts @@ -211,12 +211,12 @@ export const getServerGlobalConfig = () => { modelString: ZEROONE_MODEL_LIST, }), }, - zhipu: { - enabled: ENABLED_ZHIPU, - enabledModels: extractEnabledModels(ZHIPU_MODEL_LIST), - serverModelCards: transformToChatModelCards({ - defaultChatModels: ZhiPuProviderCard.chatModels, - modelString: ZHIPU_MODEL_LIST + zhipu: { + enabled: ENABLED_ZHIPU, + enabledModels: extractEnabledModels(ZHIPU_MODEL_LIST), + serverModelCards: transformToChatModelCards({ + defaultChatModels: ZhiPuProviderCard.chatModels, + modelString: ZHIPU_MODEL_LIST, }), }, }, diff --git a/src/services/_auth.ts b/src/services/_auth.ts index 6e8c98b04d9f..3eacfa4603f0 100644 --- a/src/services/_auth.ts +++ b/src/services/_auth.ts @@ -8,16 +8,21 @@ import { createJWT } from '@/utils/jwt'; export const getProviderAuthPayload = (provider: string) => { switch (provider) { case ModelProvider.Bedrock: { - const { accessKeyId, region, secretAccessKey } = keyVaultsConfigSelectors.bedrockConfig( - useUserStore.getState(), - ); + const { accessKeyId, region, secretAccessKey, sessionToken } = + keyVaultsConfigSelectors.bedrockConfig(useUserStore.getState()); const awsSecretAccessKey = secretAccessKey; const awsAccessKeyId = accessKeyId; const apiKey = (awsSecretAccessKey || '') + (awsAccessKeyId || ''); - return { apiKey, awsAccessKeyId, awsRegion: region, awsSecretAccessKey }; + return { + apiKey, + awsAccessKeyId, + awsRegion: region, + awsSecretAccessKey, + awsSessionToken: sessionToken, + }; } case ModelProvider.Azure: { diff --git a/src/services/chat.ts b/src/services/chat.ts index 787f7bd04657..8e5e63b3b785 100644 --- a/src/services/chat.ts +++ b/src/services/chat.ts @@ -114,6 +114,7 @@ export function initializeWithClientStore(provider: string, payload: any) { accessKeyId: providerAuthPayload?.awsAccessKeyId, accessKeySecret: providerAuthPayload?.awsSecretAccessKey, region: providerAuthPayload?.awsRegion, + sessionToken: providerAuthPayload?.awsSessionToken, }; } break; diff --git a/src/types/user/settings/keyVaults.ts b/src/types/user/settings/keyVaults.ts index 048c5f1af0cb..b188652cc5b8 100644 --- a/src/types/user/settings/keyVaults.ts +++ b/src/types/user/settings/keyVaults.ts @@ -13,6 +13,7 @@ export interface AWSBedrockKeyVault { accessKeyId?: string; region?: string; secretAccessKey?: string; + sessionToken?: string; } export interface UserKeyVaults { diff --git a/src/utils/format.ts b/src/utils/format.ts index b3bd551dc0a9..5e2ae46796de 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -59,7 +59,7 @@ export const formatTokenNumber = (num: number): string => { if (num > 0 && num < 1024) return '1K'; let kiloToken = Math.floor(num / 1024); - if (num >= 1024 && num < 1024 * 41 || num >= 128_000) { + if ((num >= 1024 && num < 1024 * 41) || num >= 128_000) { kiloToken = Math.floor(num / 1000); } if (num === 131_072) return '128K'; From 2a937bc8fd9c1a6327591a10b23160544732628b Mon Sep 17 00:00:00 2001 From: LovelyGuYiMeng <76251800+LovelyGuYiMeng@users.noreply.github.com> Date: Fri, 13 Sep 2024 00:17:24 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=F0=9F=92=84=20style:=20Remove=20brackets?= =?UTF-8?q?=20from=20model=20names=20with=20dates=20in=20OpenAI=20(#3927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update openai.ts * Update index.test.ts.snap * Update index.test.ts.snap --- src/config/modelProviders/openai.ts | 20 +++++++++---------- .../openai/__snapshots__/index.test.ts.snap | 12 +++++------ .../config/__snapshots__/index.test.ts.snap | 6 +++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/config/modelProviders/openai.ts b/src/config/modelProviders/openai.ts index 3021fce7b4c9..f3bc737c86d3 100644 --- a/src/config/modelProviders/openai.ts +++ b/src/config/modelProviders/openai.ts @@ -35,7 +35,7 @@ const OpenAI: ModelProviderCard = { { description: 'ChatGPT-4o 是一款动态模型,实时更新以保持当前最新版本。它结合了强大的语言理解与生成能力,适合于大规模应用场景,包括客户服务、教育和技术支持。', - displayName: 'GPT-4o (240806)', + displayName: 'GPT-4o 0806', enabled: true, functionCall: true, id: 'gpt-4o-2024-08-06', @@ -49,7 +49,7 @@ const OpenAI: ModelProviderCard = { { description: 'ChatGPT-4o 是一款动态模型,实时更新以保持当前最新版本。它结合了强大的语言理解与生成能力,适合于大规模应用场景,包括客户服务、教育和技术支持。', - displayName: 'GPT-4o (240513)', + displayName: 'GPT-4o 0513', functionCall: true, id: 'gpt-4o-2024-05-13', pricing: { @@ -88,7 +88,7 @@ const OpenAI: ModelProviderCard = { { description: '最新的 GPT-4 Turbo 模型具备视觉功能。现在,视觉请求可以使用 JSON 模式和函数调用。 GPT-4 Turbo 是一个增强版本,为多模态任务提供成本效益高的支持。它在准确性和效率之间找到平衡,适合需要进行实时交互的应用程序场景。', - displayName: 'GPT-4 Turbo Vision (240409)', + displayName: 'GPT-4 Turbo Vision 0409', functionCall: true, id: 'gpt-4-turbo-2024-04-09', pricing: { @@ -113,7 +113,7 @@ const OpenAI: ModelProviderCard = { { description: '最新的 GPT-4 Turbo 模型具备视觉功能。现在,视觉请求可以使用 JSON 模式和函数调用。 GPT-4 Turbo 是一个增强版本,为多模态任务提供成本效益高的支持。它在准确性和效率之间找到平衡,适合需要进行实时交互的应用程序场景。', - displayName: 'GPT-4 Turbo Preview (0125)', + displayName: 'GPT-4 Turbo Preview 0125', functionCall: true, id: 'gpt-4-0125-preview', pricing: { @@ -148,7 +148,7 @@ const OpenAI: ModelProviderCard = { { description: '最新的 GPT-4 Turbo 模型具备视觉功能。现在,视觉请求可以使用 JSON 模式和函数调用。 GPT-4 Turbo 是一个增强版本,为多模态任务提供成本效益高的支持。它在准确性和效率之间找到平衡,适合需要进行实时交互的应用程序场景。', - displayName: 'GPT-4 Turbo Preview (1106)', + displayName: 'GPT-4 Turbo Preview 1106', functionCall: true, id: 'gpt-4-1106-preview', pricing: { @@ -172,7 +172,7 @@ const OpenAI: ModelProviderCard = { { description: 'GPT-4 提供了一个更大的上下文窗口,能够处理更长的文本输入,适用于需要广泛信息整合和数据分析的场景。', - displayName: 'GPT-4 (0613)', + displayName: 'GPT-4 0613', functionCall: true, id: 'gpt-4-0613', pricing: { @@ -197,7 +197,7 @@ const OpenAI: ModelProviderCard = { // Will be discontinued on June 6, 2025 description: 'GPT-4 提供了一个更大的上下文窗口,能够处理更长的文本输入,适用于需要广泛信息整合和数据分析的场景。', - displayName: 'GPT-4 32K (0613)', + displayName: 'GPT-4 32K 0613', functionCall: true, id: 'gpt-4-32k-0613', pricing: { @@ -221,7 +221,7 @@ const OpenAI: ModelProviderCard = { { description: 'GPT 3.5 Turbo,适用于各种文本生成和理解任务,Currently points to gpt-3.5-turbo-0125', - displayName: 'GPT-3.5 Turbo (0125)', + displayName: 'GPT-3.5 Turbo 0125', functionCall: true, id: 'gpt-3.5-turbo-0125', pricing: { @@ -233,7 +233,7 @@ const OpenAI: ModelProviderCard = { { description: 'GPT 3.5 Turbo,适用于各种文本生成和理解任务,Currently points to gpt-3.5-turbo-0125', - displayName: 'GPT-3.5 Turbo (1106)', + displayName: 'GPT-3.5 Turbo 1106', functionCall: true, id: 'gpt-3.5-turbo-1106', pricing: { @@ -269,7 +269,7 @@ const OpenAI: ModelProviderCard = { { description: 'GPT-3.5 Turbo 是 OpenAI 的一款基础模型,结合了高效性和经济性,广泛用于文本生成、理解和分析,专为指导性提示进行调整,去除了与聊天相关的优化。', - displayName: 'GPT-3.5 Turbo (0613)', + displayName: 'GPT-3.5 Turbo 0613', // Will be discontinued on September 13, 2024 id: 'gpt-3.5-turbo-0613', legacy: true, diff --git a/src/libs/agent-runtime/openai/__snapshots__/index.test.ts.snap b/src/libs/agent-runtime/openai/__snapshots__/index.test.ts.snap index 81287865943e..40284cef6ce9 100644 --- a/src/libs/agent-runtime/openai/__snapshots__/index.test.ts.snap +++ b/src/libs/agent-runtime/openai/__snapshots__/index.test.ts.snap @@ -49,7 +49,7 @@ exports[`LobeOpenAI > models > should get models 1`] = ` }, { "description": "最新的 GPT-4 Turbo 模型具备视觉功能。现在,视觉请求可以使用 JSON 模式和函数调用。 GPT-4 Turbo 是一个增强版本,为多模态任务提供成本效益高的支持。它在准确性和效率之间找到平衡,适合需要进行实时交互的应用程序场景。", - "displayName": "GPT-4 Turbo Preview (0125)", + "displayName": "GPT-4 Turbo Preview 0125", "functionCall": true, "id": "gpt-4-0125-preview", "pricing": { @@ -84,7 +84,7 @@ exports[`LobeOpenAI > models > should get models 1`] = ` }, { "description": "GPT-3.5 Turbo 是 OpenAI 的一款基础模型,结合了高效性和经济性,广泛用于文本生成、理解和分析,专为指导性提示进行调整,去除了与聊天相关的优化。", - "displayName": "GPT-3.5 Turbo (0613)", + "displayName": "GPT-3.5 Turbo 0613", "id": "gpt-3.5-turbo-0613", "legacy": true, "pricing": { @@ -95,7 +95,7 @@ exports[`LobeOpenAI > models > should get models 1`] = ` }, { "description": "GPT 3.5 Turbo,适用于各种文本生成和理解任务,Currently points to gpt-3.5-turbo-0125", - "displayName": "GPT-3.5 Turbo (1106)", + "displayName": "GPT-3.5 Turbo 1106", "functionCall": true, "id": "gpt-3.5-turbo-1106", "pricing": { @@ -106,7 +106,7 @@ exports[`LobeOpenAI > models > should get models 1`] = ` }, { "description": "最新的 GPT-4 Turbo 模型具备视觉功能。现在,视觉请求可以使用 JSON 模式和函数调用。 GPT-4 Turbo 是一个增强版本,为多模态任务提供成本效益高的支持。它在准确性和效率之间找到平衡,适合需要进行实时交互的应用程序场景。", - "displayName": "GPT-4 Turbo Preview (1106)", + "displayName": "GPT-4 Turbo Preview 1106", "functionCall": true, "id": "gpt-4-1106-preview", "pricing": { @@ -139,7 +139,7 @@ exports[`LobeOpenAI > models > should get models 1`] = ` }, { "description": "GPT 3.5 Turbo,适用于各种文本生成和理解任务,Currently points to gpt-3.5-turbo-0125", - "displayName": "GPT-3.5 Turbo (0125)", + "displayName": "GPT-3.5 Turbo 0125", "functionCall": true, "id": "gpt-3.5-turbo-0125", "pricing": { @@ -150,7 +150,7 @@ exports[`LobeOpenAI > models > should get models 1`] = ` }, { "description": "GPT-4 提供了一个更大的上下文窗口,能够处理更长的文本输入,适用于需要广泛信息整合和数据分析的场景。", - "displayName": "GPT-4 (0613)", + "displayName": "GPT-4 0613", "functionCall": true, "id": "gpt-4-0613", "pricing": { diff --git a/src/server/routers/edge/config/__snapshots__/index.test.ts.snap b/src/server/routers/edge/config/__snapshots__/index.test.ts.snap index 1931595af8e8..baeadb695787 100644 --- a/src/server/routers/edge/config/__snapshots__/index.test.ts.snap +++ b/src/server/routers/edge/config/__snapshots__/index.test.ts.snap @@ -39,7 +39,7 @@ exports[`configRouter > getGlobalConfig > Model Provider env > OPENAI_MODEL_LIST [ { "description": "GPT 3.5 Turbo,适用于各种文本生成和理解任务,Currently points to gpt-3.5-turbo-0125", - "displayName": "GPT-3.5 Turbo (1106)", + "displayName": "GPT-3.5 Turbo 1106", "enabled": true, "functionCall": true, "id": "gpt-3.5-turbo-1106", @@ -99,7 +99,7 @@ exports[`configRouter > getGlobalConfig > Model Provider env > OPENAI_MODEL_LIST }, { "description": "最新的 GPT-4 Turbo 模型具备视觉功能。现在,视觉请求可以使用 JSON 模式和函数调用。 GPT-4 Turbo 是一个增强版本,为多模态任务提供成本效益高的支持。它在准确性和效率之间找到平衡,适合需要进行实时交互的应用程序场景。", - "displayName": "GPT-4 Turbo Preview (1106)", + "displayName": "GPT-4 Turbo Preview 1106", "enabled": true, "functionCall": true, "id": "gpt-4-1106-preview", @@ -127,7 +127,7 @@ exports[`configRouter > getGlobalConfig > Model Provider env > OPENAI_MODEL_LIST exports[`configRouter > getGlobalConfig > Model Provider env > OPENAI_MODEL_LIST > show the hidden model 1`] = ` { "description": "最新的 GPT-4 Turbo 模型具备视觉功能。现在,视觉请求可以使用 JSON 模式和函数调用。 GPT-4 Turbo 是一个增强版本,为多模态任务提供成本效益高的支持。它在准确性和效率之间找到平衡,适合需要进行实时交互的应用程序场景。", - "displayName": "GPT-4 Turbo Preview (1106)", + "displayName": "GPT-4 Turbo Preview 1106", "enabled": true, "functionCall": true, "id": "gpt-4-1106-preview", From a8ba75b647384c7420712d2b5b4a7ab5ee74a9a5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 12 Sep 2024 16:24:15 +0000 Subject: [PATCH 10/10] :bookmark: chore(release): v1.16.12 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### [Version 1.16.12](https://github.com/lobehub/lobe-chat/compare/v1.16.11...v1.16.12) Released on **2024-09-12** #### 💄 Styles - **misc**: Remove brackets from model names with dates in OpenAI.
Improvements and Fixes #### Styles * **misc**: Remove brackets from model names with dates in OpenAI, closes [#3927](https://github.com/lobehub/lobe-chat/issues/3927) ([2a937bc](https://github.com/lobehub/lobe-chat/commit/2a937bc))
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
--- CHANGELOG.md | 25 +++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cd4b225a109..36c71f6cc6e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,31 @@ # Changelog +### [Version 1.16.12](https://github.com/lobehub/lobe-chat/compare/v1.16.11...v1.16.12) + +Released on **2024-09-12** + +#### 💄 Styles + +- **misc**: Remove brackets from model names with dates in OpenAI. + +
+ +
+Improvements and Fixes + +#### Styles + +- **misc**: Remove brackets from model names with dates in OpenAI, closes [#3927](https://github.com/lobehub/lobe-chat/issues/3927) ([2a937bc](https://github.com/lobehub/lobe-chat/commit/2a937bc)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ ### [Version 1.16.11](https://github.com/lobehub/lobe-chat/compare/v1.16.10...v1.16.11) Released on **2024-09-12** diff --git a/package.json b/package.json index 6ba2e9c639e5..23537154b079 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lobehub/chat", - "version": "1.16.11", + "version": "1.16.12", "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.", "keywords": [ "framework",