Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
bentwnghk committed Dec 7, 2024
2 parents 7b45f8e + a1b5c26 commit e936606
Show file tree
Hide file tree
Showing 25 changed files with 1,334 additions and 6,958 deletions.
8,181 changes: 1,250 additions & 6,931 deletions changelog/v1.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@
"react-layout-kit": "^1.9.0",
"react-lazy-load": "^4.0.1",
"react-pdf": "^9.1.1",
"react-scan": "^0.0.40",
"react-virtuoso": "^4.12.0",
"react-wrap-balancer": "^1.1.1",
"remark": "^14.0.3",
Expand Down
2 changes: 1 addition & 1 deletion src/app/(backend)/middleware/auth/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ vi.mock('@/utils/server/jwt', () => ({
describe('checkAuth', () => {
const mockHandler: RequestHandler = vi.fn();
const mockRequest = new Request('https://example.com');
const mockOptions = { params: { provider: 'mock' } };
const mockOptions = { params: Promise.resolve({ provider: 'mock' }) };

beforeEach(() => {
vi.clearAllMocks();
Expand Down
5 changes: 3 additions & 2 deletions src/app/(backend)/middleware/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { getJWTPayload } from '@/utils/server/jwt';
import { checkAuthMethod } from './utils';

type CreateRuntime = (jwtPayload: JWTPayload) => AgentRuntime;
type RequestOptions = { createRuntime?: CreateRuntime; params: { provider: string } };
type RequestOptions = { createRuntime?: CreateRuntime; params: Promise<{ provider: string }> };

export type RequestHandler = (
req: Request,
Expand Down Expand Up @@ -56,7 +56,8 @@ export const checkAuth =

const error = errorContent || e;

return createErrorResponse(errorType, { error, ...res, provider: options.params?.provider });
const params = await options.params;
return createErrorResponse(errorType, { error, ...res, provider: params?.provider });
}

return handler(req, { ...options, jwtPayload });
Expand Down
6 changes: 5 additions & 1 deletion src/app/(backend)/webapi/assistant/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { AssistantStore } from '@/server/modules/AssistantStore';

export const runtime = 'edge';

export const GET = async (req: Request, { params }: { params: { id: string } }) => {
type Params = Promise<{ id: string }>;

export const GET = async (req: Request, segmentData: { params: Params }) => {
const params = await segmentData.params;

const { searchParams } = new URL(req.url);

const locale = searchParams.get('locale');
Expand Down
12 changes: 6 additions & 6 deletions src/app/(backend)/webapi/chat/[provider]/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ afterEach(() => {
describe('POST handler', () => {
describe('init chat model', () => {
it('should initialize AgentRuntime correctly with valid authorization', async () => {
const mockParams = { provider: 'test-provider' };
const mockParams = Promise.resolve({ provider: 'test-provider' });

// 设置 getJWTPayload 和 initAgentRuntimeWithUserPayload 的模拟返回值
vi.mocked(getJWTPayload).mockResolvedValueOnce({
Expand All @@ -83,7 +83,7 @@ describe('POST handler', () => {
});

it('should return Unauthorized error when LOBE_CHAT_AUTH_HEADER is missing', async () => {
const mockParams = { provider: 'test-provider' };
const mockParams = Promise.resolve({ provider: 'test-provider' });
const requestWithoutAuthHeader = new Request(new URL('https://test.com'), {
method: 'POST',
body: JSON.stringify({ model: 'test-model' }),
Expand All @@ -110,7 +110,7 @@ describe('POST handler', () => {
azureApiVersion: 'v1',
});

const mockParams = { provider: 'test-provider' };
const mockParams = Promise.resolve({ provider: 'test-provider' });
// 设置 initAgentRuntimeWithUserPayload 的模拟返回值
vi.mocked(getAuth).mockReturnValue({} as any);
vi.mocked(checkAuthMethod).mockReset();
Expand Down Expand Up @@ -141,7 +141,7 @@ describe('POST handler', () => {
});

it('should return InternalServerError error when throw a unknown error', async () => {
const mockParams = { provider: 'test-provider' };
const mockParams = Promise.resolve({ provider: 'test-provider' });
vi.mocked(getJWTPayload).mockRejectedValueOnce(new Error('unknown error'));

const response = await POST(request, { params: mockParams });
Expand All @@ -166,7 +166,7 @@ describe('POST handler', () => {
userId: 'abc',
});

const mockParams = { provider: 'test-provider' };
const mockParams = Promise.resolve({ provider: 'test-provider' });
const mockChatPayload = { message: 'Hello, world!' };
request = new Request(new URL('https://test.com'), {
headers: { [LOBE_CHAT_AUTH_HEADER]: 'Bearer some-valid-token' },
Expand All @@ -192,7 +192,7 @@ describe('POST handler', () => {
azureApiVersion: 'v1',
});

const mockParams = { provider: 'test-provider' };
const mockParams = Promise.resolve({ provider: 'test-provider' });
const mockChatPayload = { message: 'Hello, world!' };
request = new Request(new URL('https://test.com'), {
headers: { [LOBE_CHAT_AUTH_HEADER]: 'Bearer some-valid-token' },
Expand Down
2 changes: 1 addition & 1 deletion src/app/(backend)/webapi/chat/[provider]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getTracePayload } from '@/utils/trace';
export const runtime = 'edge';

export const POST = checkAuth(async (req: Request, { params, jwtPayload, createRuntime }) => {
const { provider } = params;
const { provider } = await params;

try {
// ============ 1. init chat model ============ //
Expand Down
4 changes: 3 additions & 1 deletion src/app/(backend)/webapi/chat/anthropic/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ describe('Anthropic POST function tests', () => {
it('should call UniverseRoute with correct parameters', async () => {
const mockRequest = new Request('https://example.com', { method: 'POST' });
await POST(mockRequest);
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, { params: { provider: 'anthropic' } });
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
params: Promise.resolve({ provider: 'anthropic' }),
});
});
});
2 changes: 1 addition & 1 deletion src/app/(backend)/webapi/chat/anthropic/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ export const preferredRegion = [
];

export const POST = async (req: Request) =>
UniverseRoute(req, { params: { provider: 'anthropic' } });
UniverseRoute(req, { params: Promise.resolve({ provider: 'anthropic' }) });
4 changes: 3 additions & 1 deletion src/app/(backend)/webapi/chat/google/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ describe('Google POST function tests', () => {
it('should call UniverseRoute with correct parameters', async () => {
const mockRequest = new Request('https://example.com', { method: 'POST' });
await POST(mockRequest);
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, { params: { provider: 'google' } });
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
params: Promise.resolve({ provider: 'google' }),
});
});
});
3 changes: 2 additions & 1 deletion src/app/(backend)/webapi/chat/google/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ export const preferredRegion = [
'gru1',
];

export const POST = async (req: Request) => UniverseRoute(req, { params: { provider: 'google' } });
export const POST = async (req: Request) =>
UniverseRoute(req, { params: Promise.resolve({ provider: 'google' }) });
4 changes: 3 additions & 1 deletion src/app/(backend)/webapi/chat/minimax/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ describe('Minimax POST function tests', () => {
it('should call UniverseRoute with correct parameters', async () => {
const mockRequest = new Request('https://example.com', { method: 'POST' });
await POST(mockRequest);
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, { params: { provider: 'minimax' } });
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
params: Promise.resolve({ provider: 'minimax' }),
});
});
});
3 changes: 2 additions & 1 deletion src/app/(backend)/webapi/chat/minimax/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import { POST as UniverseRoute } from '../[provider]/route';

export const runtime = 'nodejs';

export const POST = async (req: Request) => UniverseRoute(req, { params: { provider: 'minimax' } });
export const POST = async (req: Request) =>
UniverseRoute(req, { params: Promise.resolve({ provider: 'minimax' }) });
2 changes: 1 addition & 1 deletion src/app/(backend)/webapi/chat/models/[provider]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const noNeedAPIKey = (provider: string) =>
[ModelProvider.OpenRouter, ModelProvider.TogetherAI].includes(provider as any);

export const GET = checkAuth(async (req, { params, jwtPayload }) => {
const { provider } = params;
const { provider } = await params;

try {
const hasDefaultApiKey = jwtPayload.apiKey || 'dont-need-api-key-for-model-list';
Expand Down
4 changes: 3 additions & 1 deletion src/app/(backend)/webapi/chat/openai/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ describe('OpenAI POST function tests', () => {
it('should call UniverseRoute with correct parameters', async () => {
const mockRequest = new Request('https://example.com', { method: 'POST' });
await POST(mockRequest);
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, { params: { provider: 'openai' } });
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
params: Promise.resolve({ provider: 'openai' }),
});
});
});
3 changes: 2 additions & 1 deletion src/app/(backend)/webapi/chat/openai/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export const preferredRegion = [
'syd1',
];

export const POST = async (req: Request) => UniverseRoute(req, { params: { provider: 'openai' } });
export const POST = async (req: Request) =>
UniverseRoute(req, { params: Promise.resolve({ provider: 'openai' }) });
2 changes: 1 addition & 1 deletion src/app/(backend)/webapi/chat/wenxin/route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Wenxin POST function tests', () => {
await POST(mockRequest);
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
createRuntime: expect.anything(),
params: { provider: 'wenxin' },
params: Promise.resolve({ provider: 'wenxin' }),
});
});
});
2 changes: 1 addition & 1 deletion src/app/(backend)/webapi/chat/wenxin/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ export const POST = async (req: Request) =>

return new AgentRuntime(instance);
},
params: { provider: ModelProvider.Wenxin },
params: Promise.resolve({ provider: ModelProvider.Wenxin }),
});
2 changes: 1 addition & 1 deletion src/app/(backend)/webapi/text-to-image/[provider]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const preferredRegion = [
// );

export const POST = checkAuth(async (req: Request, { params, jwtPayload }) => {
const { provider } = params;
const { provider } = await params;

try {
// ============ 1. init chat model ============ //
Expand Down
11 changes: 11 additions & 0 deletions src/components/Analytics/ReactScan.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Monitoring } from 'react-scan/dist/core/monitor/params/next';

interface ReactScanProps {
apiKey: string;
}

const ReactScan = ({ apiKey }: ReactScanProps) => (
<Monitoring apiKey={apiKey} url="https://monitoring.react-scan.com/api/v1/ingest" />
);

export default ReactScan;
4 changes: 4 additions & 0 deletions src/components/Analytics/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const Plausible = dynamic(() => import('./Plausible'));
const Posthog = dynamic(() => import('./Posthog'));
const Umami = dynamic(() => import('./Umami'));
const Clarity = dynamic(() => import('./Clarity'));
const ReactScan = dynamic(() => import('./ReactScan'));

const Analytics = () => {
return (
Expand Down Expand Up @@ -37,6 +38,9 @@ const Analytics = () => {
{analyticsEnv.ENABLED_CLARITY_ANALYTICS && (
<Clarity projectId={analyticsEnv.CLARITY_PROJECT_ID} />
)}
{!!analyticsEnv.REACT_SCAN_MONITOR_API_KEY && (
<ReactScan apiKey={analyticsEnv.REACT_SCAN_MONITOR_API_KEY} />
)}
</>
);
};
Expand Down
6 changes: 6 additions & 0 deletions src/config/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export const getAnalyticsConfig = () => {

ENABLE_GOOGLE_ANALYTICS: z.boolean(),
GOOGLE_ANALYTICS_MEASUREMENT_ID: z.string().optional(),

REACT_SCAN_MONITOR_API_KEY: z.string().optional(),
},
runtimeEnv: {
// Plausible Analytics
Expand Down Expand Up @@ -55,6 +57,10 @@ export const getAnalyticsConfig = () => {
// Google Analytics
ENABLE_GOOGLE_ANALYTICS: !!process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID,
GOOGLE_ANALYTICS_MEASUREMENT_ID: process.env.GOOGLE_ANALYTICS_MEASUREMENT_ID,

// React Scan Monitor
// https://dashboard.react-scan.com
REACT_SCAN_MONITOR_API_KEY: process.env.REACT_SCAN_MONITOR_API_KEY,
},
});
};
Expand Down
4 changes: 4 additions & 0 deletions src/config/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ declare global {

NEXT_AUTH_SSO_PROVIDERS?: string;

NEXT_AUTH_DEBUG?: string;

AUTH0_CLIENT_ID?: string;
AUTH0_CLIENT_SECRET?: string;
AUTH0_ISSUER?: string;
Expand Down Expand Up @@ -156,6 +158,7 @@ export const getAuthConfig = () => {
// NEXT-AUTH
NEXT_AUTH_SECRET: z.string().optional(),
NEXT_AUTH_SSO_PROVIDERS: z.string().optional().default('auth0'),
NEXT_AUTH_DEBUG: z.boolean().optional().default(false),

// Auth0
AUTH0_CLIENT_ID: z.string().optional(),
Expand Down Expand Up @@ -217,6 +220,7 @@ export const getAuthConfig = () => {
NEXT_PUBLIC_ENABLE_NEXT_AUTH: !!process.env.NEXT_AUTH_SECRET,
NEXT_AUTH_SSO_PROVIDERS: process.env.NEXT_AUTH_SSO_PROVIDERS,
NEXT_AUTH_SECRET: process.env.NEXT_AUTH_SECRET,
NEXT_AUTH_DEBUG: !!process.env.NEXT_AUTH_DEBUG,

// Auth0
AUTH0_CLIENT_ID: process.env.AUTH0_CLIENT_ID,
Expand Down
20 changes: 18 additions & 2 deletions src/config/modelProviders/google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,26 @@ const Google: ModelProviderCard = {
chatModels: [
{
description:
'Gemini Exp 1121 是 Google 最新的实验性多模态AI模型,拥有改进的编码、推理和视觉能力。',
displayName: 'Gemini Experimental 1121',
'Gemini Exp 1206 是 Google 最新的实验性多模态AI模型,与历史版本相比有一定的质量提升。',
displayName: 'Gemini Experimental 1206',
enabled: true,
functionCall: true,
id: 'gemini-exp-1206',
maxOutput: 8192,
pricing: {
cachedInput: 0,
input: 0,
output: 0,
},
releasedAt: '2024-12-06',
tokens: 2_097_152 + 8192,
vision: true,
},
{
description:
'Gemini Exp 1121 是 Google 的实验性多模态AI模型,拥有改进的编码、推理和视觉能力。',
displayName: 'Gemini Experimental 1121',
functionCall: true,
id: 'gemini-exp-1121',
maxOutput: 8192,
pricing: {
Expand Down
3 changes: 1 addition & 2 deletions src/libs/next-auth/auth.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { NextAuthConfig } from 'next-auth';
import urlJoin from 'url-join';

import { authEnv } from '@/config/auth';

Expand Down Expand Up @@ -40,8 +39,8 @@ export default {
return session;
},
},
debug: authEnv.NEXT_AUTH_DEBUG,
providers: initSSOProviders(),
redirectProxyUrl: process.env.APP_URL ? urlJoin(process.env.APP_URL, '/api/auth') : undefined,
secret: authEnv.NEXT_AUTH_SECRET,
trustHost: process.env?.AUTH_TRUST_HOST ? process.env.AUTH_TRUST_HOST === 'true' : true,
} satisfies NextAuthConfig;

0 comments on commit e936606

Please sign in to comment.