@lobehub/chat 1.79.8 → 1.79.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -0
- package/CHANGELOG.md +58 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/models.json +9 -0
- package/locales/ar/oauth.json +7 -6
- package/locales/bg-BG/models.json +9 -0
- package/locales/bg-BG/oauth.json +7 -6
- package/locales/de-DE/models.json +9 -0
- package/locales/de-DE/oauth.json +7 -6
- package/locales/en-US/models.json +9 -0
- package/locales/en-US/oauth.json +7 -6
- package/locales/es-ES/models.json +9 -0
- package/locales/es-ES/oauth.json +7 -6
- package/locales/fa-IR/models.json +9 -0
- package/locales/fa-IR/oauth.json +7 -6
- package/locales/fr-FR/models.json +9 -0
- package/locales/fr-FR/oauth.json +7 -6
- package/locales/it-IT/models.json +9 -0
- package/locales/it-IT/oauth.json +7 -6
- package/locales/ja-JP/models.json +9 -0
- package/locales/ja-JP/oauth.json +7 -6
- package/locales/ko-KR/models.json +9 -0
- package/locales/ko-KR/oauth.json +7 -6
- package/locales/nl-NL/models.json +9 -0
- package/locales/nl-NL/oauth.json +7 -6
- package/locales/pl-PL/models.json +9 -0
- package/locales/pl-PL/oauth.json +7 -6
- package/locales/pt-BR/models.json +9 -0
- package/locales/pt-BR/oauth.json +7 -6
- package/locales/ru-RU/models.json +9 -0
- package/locales/ru-RU/oauth.json +7 -6
- package/locales/tr-TR/models.json +9 -0
- package/locales/tr-TR/oauth.json +7 -6
- package/locales/vi-VN/models.json +9 -0
- package/locales/vi-VN/oauth.json +7 -6
- package/locales/zh-CN/models.json +9 -0
- package/locales/zh-CN/oauth.json +7 -6
- package/locales/zh-TW/models.json +9 -0
- package/locales/zh-TW/oauth.json +7 -6
- package/package.json +1 -1
- package/src/app/(backend)/oidc/[...oidc]/route.ts +27 -201
- package/src/app/(backend)/oidc/consent/route.ts +58 -24
- package/src/app/(backend)/trpc/async/[trpc]/route.ts +1 -1
- package/src/app/(backend)/trpc/edge/[trpc]/route.ts +2 -2
- package/src/app/(backend)/trpc/lambda/[trpc]/route.ts +2 -2
- package/src/app/(backend)/trpc/tools/[trpc]/route.ts +2 -2
- package/src/app/[variants]/(main)/files/[id]/page.tsx +1 -1
- package/src/app/[variants]/oauth/consent/[uid]/Client.tsx +184 -57
- package/src/app/[variants]/oauth/consent/[uid]/ClientError.tsx +46 -0
- package/src/app/[variants]/oauth/consent/[uid]/page.tsx +19 -21
- package/src/components/Branding/ProductLogo/index.tsx +6 -1
- package/src/config/aiModels/openai.ts +63 -41
- package/src/config/modelProviders/openai.ts +17 -0
- package/src/const/settings/llm.ts +1 -1
- package/src/database/server/models/__tests__/adapter.test.ts +1 -5
- package/src/libs/oidc-provider/adapter.ts +47 -0
- package/src/libs/oidc-provider/config.ts +4 -5
- package/src/libs/oidc-provider/http-adapter.ts +60 -28
- package/src/libs/oidc-provider/provider.ts +41 -13
- package/src/libs/trpc/async/init.ts +1 -1
- package/src/{server → libs/trpc/edge}/context.ts +2 -2
- package/src/libs/trpc/{index.ts → edge/index.ts} +8 -8
- package/src/libs/trpc/{init.ts → edge/init.ts} +2 -2
- package/src/libs/trpc/{middleware → edge/middleware}/jwtPayload.test.ts +3 -3
- package/src/libs/trpc/{middleware → edge/middleware}/jwtPayload.ts +3 -2
- package/src/libs/trpc/lambda/context.ts +70 -0
- package/src/libs/trpc/lambda/index.ts +39 -1
- package/src/libs/trpc/lambda/init.ts +26 -0
- package/src/libs/trpc/lambda/middleware/index.ts +2 -0
- package/src/libs/trpc/{middleware → lambda/middleware}/keyVaults.ts +2 -1
- package/src/libs/trpc/lambda/{serverDatabase.ts → middleware/serverDatabase.ts} +2 -1
- package/src/libs/trpc/middleware/userAuth.test.ts +3 -3
- package/src/libs/trpc/middleware/userAuth.ts +1 -1
- package/src/libs/trpc/mock.ts +7 -0
- package/src/locales/default/oauth.ts +8 -6
- package/src/server/routers/edge/appStatus.ts +1 -1
- package/src/server/routers/edge/config/index.test.ts +2 -3
- package/src/server/routers/edge/config/index.ts +1 -1
- package/src/server/routers/edge/index.ts +1 -1
- package/src/server/routers/edge/upload.ts +1 -1
- package/src/server/routers/lambda/_template.ts +2 -2
- package/src/server/routers/lambda/agent.ts +2 -2
- package/src/server/routers/lambda/aiModel.ts +2 -2
- package/src/server/routers/lambda/aiProvider.ts +2 -2
- package/src/server/routers/lambda/chunk.ts +2 -3
- package/src/server/routers/lambda/exporter.ts +2 -2
- package/src/server/routers/lambda/file.ts +2 -2
- package/src/server/routers/lambda/importer.ts +2 -2
- package/src/server/routers/lambda/index.ts +1 -1
- package/src/server/routers/lambda/knowledgeBase.ts +2 -2
- package/src/server/routers/lambda/message.ts +2 -2
- package/src/server/routers/lambda/plugin.ts +2 -2
- package/src/server/routers/lambda/ragEval.ts +2 -3
- package/src/server/routers/lambda/session.ts +2 -2
- package/src/server/routers/lambda/sessionGroup.ts +2 -2
- package/src/server/routers/lambda/thread.ts +2 -2
- package/src/server/routers/lambda/topic.ts +2 -2
- package/src/server/routers/lambda/user.ts +2 -2
- package/src/server/routers/tools/__tests__/search.test.ts +2 -2
- package/src/server/routers/tools/index.ts +1 -1
- package/src/server/routers/tools/search.ts +3 -1
- package/src/server/services/oidc/index.ts +36 -1
- package/src/server/services/oidc/oidcProvider.ts +1 -3
- package/src/services/chat.ts +1 -0
- package/src/store/agent/slices/chat/selectors/__snapshots__/agent.test.ts.snap +1 -1
- package/src/store/user/slices/modelList/selectors/modelProvider.test.ts +1 -0
- package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +8 -8
- package/src/server/mock.ts +0 -8
- /package/src/{server/asyncContext.ts → libs/trpc/async/context.ts} +0 -0
@@ -1,36 +1,114 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
|
-
import {
|
3
|
+
import { Icon } from '@lobehub/ui';
|
4
|
+
import { Button, Card, Divider, Typography } from 'antd';
|
4
5
|
import { createStyles } from 'antd-style';
|
6
|
+
import { Link2Icon, ServerIcon } from 'lucide-react';
|
7
|
+
import Image from 'next/image';
|
5
8
|
import React, { memo } from 'react';
|
6
9
|
import { useTranslation } from 'react-i18next';
|
7
10
|
import { Center, Flexbox } from 'react-layout-kit';
|
8
11
|
|
9
|
-
|
12
|
+
import { ProductLogo } from '@/components/Branding';
|
13
|
+
|
14
|
+
interface ClientProps {
|
10
15
|
clientId: string;
|
11
|
-
|
12
|
-
|
13
|
-
|
16
|
+
clientMetadata: {
|
17
|
+
clientName?: string;
|
18
|
+
logo?: string;
|
14
19
|
};
|
20
|
+
|
21
|
+
redirectUri?: string;
|
15
22
|
scopes: string[];
|
16
23
|
uid: string;
|
17
|
-
}
|
24
|
+
}
|
18
25
|
|
19
26
|
const { Title, Text, Paragraph } = Typography;
|
20
27
|
|
21
28
|
const useStyles = createStyles(({ css, token }) => ({
|
22
|
-
|
23
|
-
|
29
|
+
authButton: css`
|
30
|
+
width: 100%;
|
31
|
+
height: 40px;
|
32
|
+
border-radius: ${token.borderRadius}px;
|
33
|
+
font-weight: 500;
|
34
|
+
`,
|
35
|
+
cancelButton: css`
|
36
|
+
width: 100%;
|
37
|
+
height: 40px;
|
38
|
+
border-color: ${token.colorBorderSecondary};
|
39
|
+
border-radius: ${token.borderRadius}px;
|
40
|
+
|
41
|
+
font-weight: 500;
|
42
|
+
color: ${token.colorTextBase};
|
43
|
+
|
44
|
+
background-color: transparent;
|
45
|
+
`,
|
46
|
+
card: css`
|
47
|
+
width: 100%;
|
48
|
+
max-width: 500px;
|
49
|
+
border-color: ${token.colorBorderSecondary};
|
50
|
+
border-radius: 12px;
|
51
|
+
|
52
|
+
background-color: ${token.colorBgContainer};
|
53
|
+
`,
|
54
|
+
connector: css`
|
55
|
+
width: 40px;
|
56
|
+
height: 40px;
|
57
|
+
`,
|
58
|
+
connectorLine: css`
|
59
|
+
width: 32px;
|
60
|
+
height: 1px;
|
61
|
+
background-color: ${token.colorBorderSecondary};
|
62
|
+
`,
|
63
|
+
container: css`
|
64
|
+
width: 100%;
|
65
|
+
min-height: 100vh;
|
66
|
+
color: ${token.colorTextBase};
|
67
|
+
background-color: ${token.colorBgLayout};
|
68
|
+
`,
|
69
|
+
icon: css`
|
70
|
+
overflow: hidden;
|
71
|
+
display: flex;
|
72
|
+
align-items: center;
|
73
|
+
justify-content: center;
|
74
|
+
|
75
|
+
width: 64px;
|
76
|
+
height: 64px;
|
77
|
+
border: 1px solid ${token.colorBorderSecondary};
|
78
|
+
border-radius: 16px;
|
79
|
+
|
80
|
+
background-color: ${token.colorBgElevated};
|
81
|
+
`,
|
82
|
+
iconContainer: css`
|
83
|
+
display: flex;
|
84
|
+
align-items: center;
|
85
|
+
justify-content: center;
|
86
|
+
`,
|
87
|
+
lobeIcon: css`
|
88
|
+
overflow: hidden;
|
89
|
+
display: flex;
|
90
|
+
align-items: center;
|
91
|
+
justify-content: center;
|
92
|
+
|
93
|
+
width: 64px;
|
94
|
+
height: 64px;
|
95
|
+
border-radius: 50%;
|
96
|
+
|
97
|
+
background-color: ${token.colorBgElevated};
|
24
98
|
`,
|
25
99
|
scope: css`
|
26
100
|
margin-block: 8px;
|
27
101
|
padding: 12px;
|
28
|
-
border-radius:
|
29
|
-
background: ${token.
|
102
|
+
border-radius: 6px;
|
103
|
+
background: ${token.colorFillQuaternary};
|
30
104
|
`,
|
31
105
|
scopes: css`
|
32
106
|
width: 100%;
|
33
|
-
|
107
|
+
`,
|
108
|
+
title: css`
|
109
|
+
margin-block-end: ${token.marginLG}px;
|
110
|
+
color: ${token.colorTextBase};
|
111
|
+
text-align: center;
|
34
112
|
`,
|
35
113
|
}));
|
36
114
|
|
@@ -38,60 +116,109 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
38
116
|
* 获取 Scope 的描述
|
39
117
|
*/
|
40
118
|
function getScopeDescription(scope: string, t: any): string {
|
41
|
-
return t(`consent.scope.${scope}`, scope);
|
119
|
+
return t(`consent.scope.${scope.replace(':', '-')}`, scope);
|
42
120
|
}
|
43
121
|
|
44
|
-
const ConsentClient = memo(
|
45
|
-
|
46
|
-
|
122
|
+
const ConsentClient = memo<ClientProps>(
|
123
|
+
({ uid, clientId, scopes, clientMetadata, redirectUri }) => {
|
124
|
+
const { styles, theme } = useStyles();
|
125
|
+
const { t } = useTranslation('oauth');
|
47
126
|
|
48
|
-
|
49
|
-
if (error) {
|
127
|
+
const clientDisplayName = clientMetadata?.clientName || clientId;
|
50
128
|
return (
|
51
|
-
<Center
|
52
|
-
<
|
53
|
-
<
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
129
|
+
<Center className={styles.container} gap={16}>
|
130
|
+
<Flexbox gap={40}>
|
131
|
+
<Flexbox align={'center'} gap={12} horizontal justify={'center'}>
|
132
|
+
<div className={styles.icon}>
|
133
|
+
{clientMetadata?.logo ? (
|
134
|
+
<Image
|
135
|
+
alt={clientDisplayName}
|
136
|
+
height={56}
|
137
|
+
src={clientMetadata?.logo}
|
138
|
+
unoptimized
|
139
|
+
width={56}
|
140
|
+
/>
|
141
|
+
) : (
|
142
|
+
<Icon icon={ServerIcon} />
|
143
|
+
)}
|
144
|
+
</div>
|
145
|
+
<div className={styles.connectorLine} />
|
146
|
+
<Center className={styles.connector}>
|
147
|
+
<Icon icon={Link2Icon} style={{ color: theme.colorTextSecondary, fontSize: 20 }} />
|
148
|
+
</Center>
|
149
|
+
<div className={styles.connectorLine} />
|
150
|
+
<div className={styles.lobeIcon}>
|
151
|
+
<ProductLogo height={48} style={{ objectFit: 'cover' }} width={48} />
|
152
|
+
</div>
|
153
|
+
</Flexbox>
|
154
|
+
|
155
|
+
<Title className={styles.title} level={3}>
|
156
|
+
{t('consent.title', { clientName: clientDisplayName })}
|
66
157
|
</Title>
|
67
|
-
|
158
|
+
</Flexbox>
|
159
|
+
<Card className={styles.card}>
|
160
|
+
<Flexbox gap={8}>
|
161
|
+
<Flexbox gap={12}>
|
162
|
+
<Paragraph>{t('consent.description', { clientName: clientDisplayName })}</Paragraph>
|
68
163
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
164
|
+
<div className={styles.scopes}>
|
165
|
+
<Paragraph type={'secondary'}>{t('consent.permissionsTitle')}</Paragraph>
|
166
|
+
{scopes.map((scope) => (
|
167
|
+
<div className={styles.scope} key={scope}>
|
168
|
+
<Text>{getScopeDescription(scope, t)}</Text>
|
169
|
+
</div>
|
170
|
+
))}
|
74
171
|
</div>
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
172
|
+
|
173
|
+
<Divider dashed />
|
174
|
+
<Flexbox gap={16}>
|
175
|
+
<form action="/oidc/consent" method="post" style={{ width: '100%' }}>
|
176
|
+
<input name="uid" type="hidden" value={uid} />
|
177
|
+
<Flexbox gap={12} horizontal>
|
178
|
+
<Button
|
179
|
+
className={styles.cancelButton}
|
180
|
+
htmlType="submit"
|
181
|
+
name="consent"
|
182
|
+
value="deny"
|
183
|
+
>
|
184
|
+
{t('consent.buttons.deny')}
|
185
|
+
</Button>
|
186
|
+
<Button
|
187
|
+
className={styles.authButton}
|
188
|
+
htmlType="submit"
|
189
|
+
name="consent"
|
190
|
+
type="primary"
|
191
|
+
value="accept"
|
192
|
+
>
|
193
|
+
{t('consent.buttons.accept')}
|
194
|
+
</Button>
|
195
|
+
</Flexbox>
|
196
|
+
</form>
|
197
|
+
<Center>
|
198
|
+
<div style={{ color: theme.colorTextTertiary, fontSize: 12, height: '18px' }}>
|
199
|
+
{t('consent.redirectUri')}
|
200
|
+
</div>
|
201
|
+
<div>
|
202
|
+
<div
|
203
|
+
style={{
|
204
|
+
color: theme.colorTextSecondary,
|
205
|
+
fontSize: 12,
|
206
|
+
height: '18px',
|
207
|
+
}}
|
208
|
+
>
|
209
|
+
{redirectUri}
|
210
|
+
</div>
|
211
|
+
</div>
|
212
|
+
</Center>
|
213
|
+
</Flexbox>
|
87
214
|
</Flexbox>
|
88
|
-
</
|
89
|
-
</
|
90
|
-
</
|
91
|
-
|
92
|
-
|
93
|
-
|
215
|
+
</Flexbox>
|
216
|
+
</Card>
|
217
|
+
</Center>
|
218
|
+
);
|
219
|
+
},
|
220
|
+
);
|
94
221
|
|
95
222
|
ConsentClient.displayName = 'ConsentClient';
|
96
223
|
|
97
|
-
export
|
224
|
+
export default ConsentClient;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { Typography } from 'antd';
|
4
|
+
import { createStyles } from 'antd-style';
|
5
|
+
import React, { memo } from 'react';
|
6
|
+
import { Center } from 'react-layout-kit';
|
7
|
+
|
8
|
+
interface ClientProps {
|
9
|
+
error: {
|
10
|
+
message: string;
|
11
|
+
title: string;
|
12
|
+
};
|
13
|
+
}
|
14
|
+
|
15
|
+
const { Title, Paragraph } = Typography;
|
16
|
+
|
17
|
+
const useStyles = createStyles(({ css, token }) => ({
|
18
|
+
container: css`
|
19
|
+
width: 100%;
|
20
|
+
min-height: 100vh;
|
21
|
+
color: ${token.colorTextBase};
|
22
|
+
background-color: ${token.colorBgLayout};
|
23
|
+
`,
|
24
|
+
error: css`
|
25
|
+
text-align: center;
|
26
|
+
`,
|
27
|
+
}));
|
28
|
+
|
29
|
+
const ConsentClientError = memo<ClientProps>(({ error }) => {
|
30
|
+
const { styles } = useStyles();
|
31
|
+
|
32
|
+
return (
|
33
|
+
<Center className={styles.container}>
|
34
|
+
<div className={styles.error}>
|
35
|
+
<Title level={2} style={{ color: 'inherit' }}>
|
36
|
+
{error.title}
|
37
|
+
</Title>
|
38
|
+
<Paragraph style={{ color: 'inherit' }}>{error.message}</Paragraph>
|
39
|
+
</div>
|
40
|
+
</Center>
|
41
|
+
);
|
42
|
+
});
|
43
|
+
|
44
|
+
ConsentClientError.displayName = 'ConsentClientError';
|
45
|
+
|
46
|
+
export default ConsentClientError;
|
@@ -3,11 +3,9 @@ import { notFound } from 'next/navigation';
|
|
3
3
|
import { oidcEnv } from '@/envs/oidc';
|
4
4
|
import { OIDCService } from '@/server/services/oidc';
|
5
5
|
|
6
|
-
import
|
6
|
+
import ConsentClient from './Client';
|
7
|
+
import ConsentClientError from './ClientError';
|
7
8
|
|
8
|
-
/**
|
9
|
-
* Consent 授权页面
|
10
|
-
*/
|
11
9
|
const InteractionPage = async (props: { params: Promise<{ uid: string }> }) => {
|
12
10
|
if (!oidcEnv.ENABLE_OIDC) return notFound();
|
13
11
|
|
@@ -23,14 +21,11 @@ const InteractionPage = async (props: { params: Promise<{ uid: string }> }) => {
|
|
23
21
|
// 支持 login 和 consent 类型的交互
|
24
22
|
if (details.prompt.name !== 'consent' && details.prompt.name !== 'login') {
|
25
23
|
return (
|
26
|
-
<
|
27
|
-
clientId=""
|
24
|
+
<ConsentClientError
|
28
25
|
error={{
|
29
26
|
message: `不支持的交互类型: ${details.prompt.name}`,
|
30
27
|
title: '不支持的交互类型',
|
31
28
|
}}
|
32
|
-
scopes={[]}
|
33
|
-
uid={params.uid}
|
34
29
|
/>
|
35
30
|
);
|
36
31
|
}
|
@@ -39,8 +34,21 @@ const InteractionPage = async (props: { params: Promise<{ uid: string }> }) => {
|
|
39
34
|
const clientId = (details.params.client_id as string) || 'unknown';
|
40
35
|
const scopes = (details.params.scope as string)?.split(' ') || [];
|
41
36
|
|
37
|
+
const clientDetail = await oidcService.getClientMetadata(clientId);
|
38
|
+
|
42
39
|
// 渲染客户端组件,无论是 login 还是 consent 类型
|
43
|
-
return
|
40
|
+
return (
|
41
|
+
<ConsentClient
|
42
|
+
clientId={clientId}
|
43
|
+
clientMetadata={{
|
44
|
+
clientName: clientDetail?.client_name,
|
45
|
+
logo: clientDetail?.logo_uri,
|
46
|
+
}}
|
47
|
+
redirectUri={details.params.redirect_uri as string}
|
48
|
+
scopes={scopes}
|
49
|
+
uid={params.uid}
|
50
|
+
/>
|
51
|
+
);
|
44
52
|
} catch (error) {
|
45
53
|
console.error('Error handling OIDC interaction:', error);
|
46
54
|
// 确保错误处理能正确显示
|
@@ -48,23 +56,13 @@ const InteractionPage = async (props: { params: Promise<{ uid: string }> }) => {
|
|
48
56
|
// 检查是否是 'interaction session not found' 错误,可以给用户更友好的提示
|
49
57
|
if (errorMessage.includes('interaction session not found')) {
|
50
58
|
return (
|
51
|
-
<
|
52
|
-
clientId=""
|
59
|
+
<ConsentClientError
|
53
60
|
error={{ message: '授权会话已过期或无效,请重新发起授权流程。', title: '授权会话无效' }}
|
54
|
-
scopes={[]}
|
55
|
-
uid={params.uid} // uid 可能已失效,但仍传递给 Client
|
56
61
|
/>
|
57
62
|
);
|
58
63
|
}
|
59
64
|
|
60
|
-
return
|
61
|
-
<ConsentClient
|
62
|
-
clientId=""
|
63
|
-
error={{ message: errorMessage, title: '发生错误' }}
|
64
|
-
scopes={[]}
|
65
|
-
uid={params.uid}
|
66
|
-
/>
|
67
|
-
);
|
65
|
+
return <ConsentClientError error={{ message: errorMessage, title: '发生错误' }} />;
|
68
66
|
}
|
69
67
|
};
|
70
68
|
|
@@ -5,7 +5,12 @@ import { isCustomBranding } from '@/const/version';
|
|
5
5
|
|
6
6
|
import CustomLogo from './Custom';
|
7
7
|
|
8
|
-
|
8
|
+
interface ProductLogoProps extends LobeHubProps {
|
9
|
+
height?: number;
|
10
|
+
width?: number;
|
11
|
+
}
|
12
|
+
|
13
|
+
export const ProductLogo = memo<ProductLogoProps>((props) => {
|
9
14
|
if (isCustomBranding) {
|
10
15
|
return <CustomLogo {...props} />;
|
11
16
|
}
|
@@ -8,6 +8,66 @@ import {
|
|
8
8
|
} from '@/types/aiModel';
|
9
9
|
|
10
10
|
export const openaiChatModels: AIChatModelCard[] = [
|
11
|
+
{
|
12
|
+
abilities: {
|
13
|
+
functionCall: true,
|
14
|
+
vision: true,
|
15
|
+
},
|
16
|
+
contextWindowTokens: 1_047_576,
|
17
|
+
description:
|
18
|
+
'GPT-4.1 是我们用于复杂任务的旗舰模型。它非常适合跨领域解决问题。',
|
19
|
+
displayName: 'GPT-4.1',
|
20
|
+
enabled: true,
|
21
|
+
id: 'gpt-4.1',
|
22
|
+
maxOutput: 32_768,
|
23
|
+
pricing: {
|
24
|
+
cachedInput: 0.5,
|
25
|
+
input: 2,
|
26
|
+
output: 8,
|
27
|
+
},
|
28
|
+
releasedAt: '2025-04-14',
|
29
|
+
type: 'chat',
|
30
|
+
},
|
31
|
+
{
|
32
|
+
abilities: {
|
33
|
+
functionCall: true,
|
34
|
+
vision: true,
|
35
|
+
},
|
36
|
+
contextWindowTokens: 1_047_576,
|
37
|
+
description:
|
38
|
+
'GPT-4.1 mini 提供了智能、速度和成本之间的平衡,使其成为许多用例中有吸引力的模型。',
|
39
|
+
displayName: 'GPT-4.1 mini',
|
40
|
+
enabled: true,
|
41
|
+
id: 'gpt-4.1-mini',
|
42
|
+
maxOutput: 32_768,
|
43
|
+
pricing: {
|
44
|
+
cachedInput: 0.1,
|
45
|
+
input: 0.4,
|
46
|
+
output: 1.6,
|
47
|
+
},
|
48
|
+
releasedAt: '2025-04-14',
|
49
|
+
type: 'chat',
|
50
|
+
},
|
51
|
+
{
|
52
|
+
abilities: {
|
53
|
+
functionCall: true,
|
54
|
+
vision: true,
|
55
|
+
},
|
56
|
+
contextWindowTokens: 1_047_576,
|
57
|
+
description:
|
58
|
+
'GPT-4.1 mini 提供了智能、速度和成本之间的平衡,使其成为许多用例中有吸引力的模型。',
|
59
|
+
displayName: 'GPT-4.1 nano',
|
60
|
+
enabled: true,
|
61
|
+
id: 'gpt-4.1-nano',
|
62
|
+
maxOutput: 32_768,
|
63
|
+
pricing: {
|
64
|
+
cachedInput: 0.025,
|
65
|
+
input: 0.1,
|
66
|
+
output: 0.4,
|
67
|
+
},
|
68
|
+
releasedAt: '2025-04-14',
|
69
|
+
type: 'chat',
|
70
|
+
},
|
11
71
|
{
|
12
72
|
abilities: {
|
13
73
|
functionCall: true,
|
@@ -36,7 +96,6 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
36
96
|
description:
|
37
97
|
'o1-mini是一款针对编程、数学和科学应用场景而设计的快速、经济高效的推理模型。该模型具有128K上下文和2023年10月的知识截止日期。',
|
38
98
|
displayName: 'OpenAI o1-mini',
|
39
|
-
enabled: true,
|
40
99
|
id: 'o1-mini',
|
41
100
|
maxOutput: 65_536,
|
42
101
|
pricing: {
|
@@ -75,7 +134,6 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
75
134
|
description:
|
76
135
|
'o1是OpenAI新的推理模型,适用于需要广泛通用知识的复杂任务。该模型具有128K上下文和2023年10月的知识截止日期。',
|
77
136
|
displayName: 'OpenAI o1-preview',
|
78
|
-
enabled: true,
|
79
137
|
id: 'o1-preview',
|
80
138
|
maxOutput: 32_768,
|
81
139
|
pricing: {
|
@@ -94,8 +152,7 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
94
152
|
description:
|
95
153
|
'GPT-4.5 的研究预览版,它是我们迄今为止最大、最强大的 GPT 模型。它拥有广泛的世界知识,并能更好地理解用户意图,使其在创造性任务和自主规划方面表现出色。GPT-4.5 可接受文本和图像输入,并生成文本输出(包括结构化输出)。支持关键的开发者功能,如函数调用、批量 API 和流式输出。在需要创造性、开放式思考和对话的任务(如写作、学习或探索新想法)中,GPT-4.5 表现尤为出色。知识截止日期为 2023 年 10 月。',
|
96
154
|
displayName: 'GPT-4.5 Preview',
|
97
|
-
|
98
|
-
id: 'gpt-4.5-preview',
|
155
|
+
id: 'gpt-4.5-preview', // deprecated on 2025-07-14
|
99
156
|
maxOutput: 16_384,
|
100
157
|
pricing: {
|
101
158
|
cachedInput: 37.5,
|
@@ -114,7 +171,6 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
114
171
|
description:
|
115
172
|
'GPT-4o mini是OpenAI在GPT-4 Omni之后推出的最新模型,支持图文输入并输出文本。作为他们最先进的小型模型,它比其他近期的前沿模型便宜很多,并且比GPT-3.5 Turbo便宜超过60%。它保持了最先进的智能,同时具有显著的性价比。GPT-4o mini在MMLU测试中获得了 82% 的得分,目前在聊天偏好上排名高于 GPT-4。',
|
116
173
|
displayName: 'GPT-4o mini',
|
117
|
-
enabled: true,
|
118
174
|
id: 'gpt-4o-mini',
|
119
175
|
maxOutput: 16_384,
|
120
176
|
pricing: {
|
@@ -136,6 +192,7 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
136
192
|
displayName: 'GPT-4o 1120',
|
137
193
|
id: 'gpt-4o-2024-11-20',
|
138
194
|
pricing: {
|
195
|
+
cachedInput: 1.25,
|
139
196
|
input: 2.5,
|
140
197
|
output: 10,
|
141
198
|
},
|
@@ -151,7 +208,6 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
151
208
|
description:
|
152
209
|
'ChatGPT-4o 是一款动态模型,实时更新以保持当前最新版本。它结合了强大的语言理解与生成能力,适合于大规模应用场景,包括客户服务、教育和技术支持。',
|
153
210
|
displayName: 'GPT-4o',
|
154
|
-
enabled: true,
|
155
211
|
id: 'gpt-4o',
|
156
212
|
pricing: {
|
157
213
|
cachedInput: 1.25,
|
@@ -161,23 +217,6 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
161
217
|
releasedAt: '2024-05-13',
|
162
218
|
type: 'chat',
|
163
219
|
},
|
164
|
-
{
|
165
|
-
abilities: {
|
166
|
-
functionCall: true,
|
167
|
-
vision: true,
|
168
|
-
},
|
169
|
-
contextWindowTokens: 128_000,
|
170
|
-
description:
|
171
|
-
'ChatGPT-4o 是一款动态模型,实时更新以保持当前最新版本。它结合了强大的语言理解与生成能力,适合于大规模应用场景,包括客户服务、教育和技术支持。',
|
172
|
-
displayName: 'GPT-4o 0806',
|
173
|
-
id: 'gpt-4o-2024-08-06',
|
174
|
-
pricing: {
|
175
|
-
input: 2.5,
|
176
|
-
output: 10,
|
177
|
-
},
|
178
|
-
releasedAt: '2024-08-06',
|
179
|
-
type: 'chat',
|
180
|
-
},
|
181
220
|
{
|
182
221
|
abilities: {
|
183
222
|
functionCall: true,
|
@@ -345,8 +384,7 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
345
384
|
description:
|
346
385
|
'GPT-4 提供了一个更大的上下文窗口,能够处理更长的文本输入,适用于需要广泛信息整合和数据分析的场景。',
|
347
386
|
displayName: 'GPT-4 32K',
|
348
|
-
id: 'gpt-4-32k',
|
349
|
-
// Will be discontinued on June 6, 2025
|
387
|
+
id: 'gpt-4-32k', // deprecated on 2025-06-06
|
350
388
|
legacy: true,
|
351
389
|
pricing: {
|
352
390
|
input: 60,
|
@@ -354,22 +392,6 @@ export const openaiChatModels: AIChatModelCard[] = [
|
|
354
392
|
},
|
355
393
|
type: 'chat',
|
356
394
|
},
|
357
|
-
{
|
358
|
-
abilities: {
|
359
|
-
functionCall: true,
|
360
|
-
},
|
361
|
-
contextWindowTokens: 32_768,
|
362
|
-
description:
|
363
|
-
'GPT-4 提供了一个更大的上下文窗口,能够处理更长的文本输入,适用于需要广泛信息整合和数据分析的场景。',
|
364
|
-
displayName: 'GPT-4 32K 0613',
|
365
|
-
id: 'gpt-4-32k-0613',
|
366
|
-
pricing: {
|
367
|
-
input: 60,
|
368
|
-
output: 120,
|
369
|
-
},
|
370
|
-
releasedAt: '2023-06-13',
|
371
|
-
type: 'chat',
|
372
|
-
},
|
373
395
|
{
|
374
396
|
abilities: {
|
375
397
|
functionCall: true,
|
@@ -3,6 +3,23 @@ import { ModelProviderCard } from '@/types/llm';
|
|
3
3
|
// ref: https://platform.openai.com/docs/deprecations
|
4
4
|
const OpenAI: ModelProviderCard = {
|
5
5
|
chatModels: [
|
6
|
+
{
|
7
|
+
contextWindowTokens: 1_047_576,
|
8
|
+
description:
|
9
|
+
'GPT-4.1 mini 提供了智能、速度和成本之间的平衡,使其成为许多用例中有吸引力的模型。',
|
10
|
+
displayName: 'GPT-4.1 mini',
|
11
|
+
enabled: true,
|
12
|
+
functionCall: true,
|
13
|
+
id: 'gpt-4.1-mini',
|
14
|
+
maxOutput: 32_768,
|
15
|
+
pricing: {
|
16
|
+
cachedInput: 0.1,
|
17
|
+
input: 0.4,
|
18
|
+
output: 1.6,
|
19
|
+
},
|
20
|
+
releasedAt: '2025-04-14',
|
21
|
+
vision: true,
|
22
|
+
},
|
6
23
|
{
|
7
24
|
contextWindowTokens: 128_000,
|
8
25
|
description:
|
@@ -14,7 +14,7 @@ export const DEFAULT_LLM_CONFIG = genUserLLMConfig({
|
|
14
14
|
},
|
15
15
|
});
|
16
16
|
|
17
|
-
export const DEFAULT_MODEL = 'gpt-
|
17
|
+
export const DEFAULT_MODEL = 'gpt-4.1-mini';
|
18
18
|
|
19
19
|
export const DEFAULT_EMBEDDING_MODEL = 'text-embedding-3-small';
|
20
20
|
export const DEFAULT_EMBEDDING_PROVIDER = ModelProvider.OpenAI;
|
@@ -1,20 +1,16 @@
|
|
1
|
-
import type { AdapterUser } from '@auth/core/adapters';
|
2
1
|
import { eq } from 'drizzle-orm/expressions';
|
3
|
-
import {
|
2
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
4
3
|
|
5
4
|
import { getTestDBInstance } from '@/database/core/dbForTest';
|
6
5
|
import { users } from '@/database/schemas';
|
7
6
|
import {
|
8
7
|
oidcAccessTokens,
|
9
|
-
oidcAuthorizationCodes,
|
10
8
|
oidcClients,
|
11
9
|
oidcDeviceCodes,
|
12
|
-
oidcGrants,
|
13
10
|
oidcInteractions,
|
14
11
|
oidcRefreshTokens,
|
15
12
|
oidcSessions,
|
16
13
|
} from '@/database/schemas/oidc';
|
17
|
-
import { LobeChatDatabase } from '@/database/type';
|
18
14
|
import { DrizzleAdapter } from '@/libs/oidc-provider/adapter';
|
19
15
|
|
20
16
|
let serverDB = await getTestDBInstance();
|