@lobehub/lobehub 2.1.1 → 2.1.3
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/.env.example +4 -3
- package/.github/workflows/release-desktop-stable.yml +1 -1
- package/CHANGELOG.md +50 -0
- package/Dockerfile +6 -4
- package/README.md +3 -4
- package/README.zh-CN.md +3 -4
- package/apps/desktop/src/main/controllers/McpInstallCtr.ts +10 -10
- package/apps/desktop/src/main/controllers/NetworkProxyCtr.ts +6 -6
- package/apps/desktop/src/main/controllers/RemoteServerSyncCtr.ts +2 -2
- package/changelog/v2.json +14 -0
- package/docs/changelog/2025-03-02-new-models.mdx +1 -1
- package/docs/changelog/2025-03-02-new-models.zh-CN.mdx +1 -1
- package/docs/changelog/2025-04-06-exports.mdx +1 -1
- package/docs/changelog/2025-04-06-exports.zh-CN.mdx +1 -1
- package/docs/changelog/2025-05-08-desktop-app.mdx +2 -2
- package/docs/changelog/2025-05-08-desktop-app.zh-CN.mdx +2 -2
- package/docs/changelog/2025-06-08-claude-4.mdx +1 -1
- package/docs/changelog/2025-06-08-claude-4.zh-CN.mdx +1 -1
- package/docs/changelog/2025-07-08-mcp-market.mdx +1 -1
- package/docs/changelog/2025-07-08-mcp-market.zh-CN.mdx +1 -1
- package/docs/changelog/2025-08-08-image-generation.mdx +1 -1
- package/docs/changelog/2025-08-08-image-generation.zh-CN.mdx +1 -1
- package/docs/changelog/2025-09-08-gemini.mdx +1 -1
- package/docs/changelog/2025-09-08-gemini.zh-CN.mdx +1 -1
- package/docs/changelog/2025-10-08-python.mdx +1 -1
- package/docs/changelog/2025-10-08-python.zh-CN.mdx +1 -1
- package/docs/changelog/2025-11-08-comfy-ui.mdx +1 -1
- package/docs/changelog/2025-11-08-comfy-ui.zh-CN.mdx +1 -1
- package/docs/changelog/2025-12-20-mcp.mdx +1 -1
- package/docs/changelog/2025-12-20-mcp.zh-CN.mdx +1 -1
- package/docs/development/basic/add-new-authentication-providers.zh-CN.mdx +1 -1
- package/docs/development/basic/add-new-image-model.mdx +3 -3
- package/docs/development/basic/add-new-image-model.zh-CN.mdx +3 -3
- package/docs/development/basic/chat-api.mdx +10 -10
- package/docs/development/basic/chat-api.zh-CN.mdx +10 -10
- package/docs/development/basic/feature-development.mdx +4 -4
- package/docs/development/basic/feature-development.zh-CN.mdx +4 -4
- package/docs/development/basic/setup-development.mdx +4 -4
- package/docs/development/basic/setup-development.zh-CN.mdx +4 -4
- package/docs/development/internationalization/add-new-locale.mdx +1 -1
- package/docs/development/internationalization/add-new-locale.zh-CN.mdx +1 -1
- package/docs/development/internationalization/internationalization-implementation.mdx +5 -5
- package/docs/development/internationalization/internationalization-implementation.zh-CN.mdx +5 -5
- package/docs/development/others/lighthouse.mdx +8 -8
- package/docs/development/others/lighthouse.zh-CN.mdx +8 -8
- package/docs/development/start.mdx +3 -3
- package/docs/development/start.zh-CN.mdx +3 -3
- package/docs/self-hosting/advanced/feature-flags.mdx +1 -1
- package/docs/self-hosting/advanced/feature-flags.zh-CN.mdx +1 -1
- package/docs/self-hosting/advanced/knowledge-base.mdx +2 -2
- package/docs/self-hosting/advanced/knowledge-base.zh-CN.mdx +2 -2
- package/docs/self-hosting/advanced/online-search.mdx +1 -1
- package/docs/self-hosting/advanced/online-search.zh-CN.mdx +1 -1
- package/docs/self-hosting/advanced/redis/upstash.mdx +3 -3
- package/docs/self-hosting/advanced/redis/upstash.zh-CN.mdx +3 -3
- package/docs/self-hosting/advanced/redis.mdx +6 -6
- package/docs/self-hosting/advanced/redis.zh-CN.mdx +6 -6
- package/docs/self-hosting/advanced/s3/rustfs.mdx +116 -116
- package/docs/self-hosting/advanced/s3/rustfs.zh-CN.mdx +116 -117
- package/docs/self-hosting/advanced/upstream-sync.zh-CN.mdx +5 -5
- package/docs/self-hosting/auth/email.mdx +70 -0
- package/docs/self-hosting/auth/email.zh-CN.mdx +70 -0
- package/docs/self-hosting/{advanced/auth → auth}/legacy.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/legacy.zh-CN.mdx +5 -5
- package/docs/self-hosting/{advanced/auth → auth}/next-auth/casdoor.zh-CN.mdx +3 -3
- package/docs/self-hosting/{advanced/auth → auth}/next-auth/keycloak.zh-CN.mdx +2 -2
- package/docs/self-hosting/{advanced/auth → auth}/next-auth/logto.zh-CN.mdx +2 -2
- package/docs/self-hosting/{advanced/auth → auth}/providers/apple.mdx +6 -6
- package/docs/self-hosting/{advanced/auth → auth}/providers/apple.zh-CN.mdx +6 -6
- package/docs/self-hosting/{advanced/auth → auth}/providers/auth0.mdx +12 -12
- package/docs/self-hosting/{advanced/auth → auth}/providers/auth0.zh-CN.mdx +12 -12
- package/docs/self-hosting/{advanced/auth → auth}/providers/authelia.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/authelia.zh-CN.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/authentik.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/authentik.zh-CN.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/casdoor.mdx +8 -8
- package/docs/self-hosting/{advanced/auth → auth}/providers/casdoor.zh-CN.mdx +7 -7
- package/docs/self-hosting/{advanced/auth → auth}/providers/cloudflare-zero-trust.mdx +7 -7
- package/docs/self-hosting/{advanced/auth → auth}/providers/cloudflare-zero-trust.zh-CN.mdx +6 -6
- package/docs/self-hosting/{advanced/auth → auth}/providers/cognito.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/cognito.zh-CN.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/feishu.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/feishu.zh-CN.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/generic-oidc.mdx +12 -12
- package/docs/self-hosting/{advanced/auth → auth}/providers/generic-oidc.zh-CN.mdx +12 -12
- package/docs/self-hosting/{advanced/auth → auth}/providers/github.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/github.zh-CN.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/google.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/google.zh-CN.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/keycloak.mdx +11 -11
- package/docs/self-hosting/{advanced/auth → auth}/providers/keycloak.zh-CN.mdx +11 -11
- package/docs/self-hosting/{advanced/auth → auth}/providers/logto.mdx +8 -8
- package/docs/self-hosting/{advanced/auth → auth}/providers/logto.zh-CN.mdx +7 -7
- package/docs/self-hosting/{advanced/auth → auth}/providers/microsoft.mdx +11 -11
- package/docs/self-hosting/{advanced/auth → auth}/providers/microsoft.zh-CN.mdx +11 -11
- package/docs/self-hosting/{advanced/auth → auth}/providers/okta.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/okta.zh-CN.mdx +13 -13
- package/docs/self-hosting/auth/providers/password.mdx +112 -0
- package/docs/self-hosting/auth/providers/password.zh-CN.mdx +103 -0
- package/docs/self-hosting/{advanced/auth → auth}/providers/wechat.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/wechat.zh-CN.mdx +10 -10
- package/docs/self-hosting/{advanced/auth → auth}/providers/zitadel.mdx +13 -13
- package/docs/self-hosting/{advanced/auth → auth}/providers/zitadel.zh-CN.mdx +13 -13
- package/docs/self-hosting/{advanced/auth.mdx → auth.mdx} +24 -81
- package/docs/self-hosting/{advanced/auth.zh-CN.mdx → auth.zh-CN.mdx} +23 -80
- package/docs/self-hosting/environment-variables/auth.mdx +7 -0
- package/docs/self-hosting/environment-variables/auth.zh-CN.mdx +7 -0
- package/docs/self-hosting/environment-variables/basic.mdx +0 -7
- package/docs/self-hosting/environment-variables/basic.zh-CN.mdx +0 -7
- package/docs/self-hosting/environment-variables/redis.mdx +1 -1
- package/docs/self-hosting/environment-variables/redis.zh-CN.mdx +1 -1
- package/docs/self-hosting/environment-variables.mdx +1 -1
- package/docs/self-hosting/examples/azure-openai.mdx +0 -1
- package/docs/self-hosting/examples/azure-openai.zh-CN.mdx +0 -1
- package/docs/self-hosting/faq/no-v1-suffix.mdx +3 -3
- package/docs/self-hosting/faq/no-v1-suffix.zh-CN.mdx +3 -3
- package/docs/self-hosting/{advanced → migration/v2}/auth/clerk-to-betterauth.mdx +7 -7
- package/docs/self-hosting/{advanced → migration/v2}/auth/clerk-to-betterauth.zh-CN.mdx +7 -7
- package/docs/self-hosting/{advanced → migration/v2}/auth/migration-internals.mdx +2 -2
- package/docs/self-hosting/{advanced → migration/v2}/auth/migration-internals.zh-CN.mdx +2 -2
- package/docs/self-hosting/{advanced → migration/v2}/auth/nextauth-to-betterauth.mdx +11 -11
- package/docs/self-hosting/{advanced → migration/v2}/auth/nextauth-to-betterauth.zh-CN.mdx +11 -11
- package/docs/self-hosting/migration/v2/breaking-changes.mdx +1 -1
- package/docs/self-hosting/migration/v2/breaking-changes.zh-CN.mdx +1 -1
- package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +4 -4
- package/docs/self-hosting/platform/docker.mdx +5 -5
- package/docs/self-hosting/platform/docker.zh-CN.mdx +10 -10
- package/docs/self-hosting/platform/dokploy.mdx +1 -1
- package/docs/self-hosting/platform/dokploy.zh-CN.mdx +5 -5
- package/docs/self-hosting/platform/sealos.mdx +12 -12
- package/docs/self-hosting/platform/sealos.zh-CN.mdx +17 -17
- package/docs/self-hosting/platform/vercel.zh-CN.mdx +4 -4
- package/docs/self-hosting/start.mdx +3 -3
- package/docs/self-hosting/start.zh-CN.mdx +4 -4
- package/locales/en-US/auth.json +2 -1
- package/locales/en-US/authError.json +1 -0
- package/locales/en-US/metadata.json +1 -1
- package/locales/zh-CN/auth.json +1 -0
- package/locales/zh-CN/authError.json +1 -0
- package/netlify.toml +0 -1
- package/package.json +1 -1
- package/packages/types/src/serverConfig.ts +1 -0
- package/src/app/[variants]/(auth)/auth-error/page.tsx +4 -2
- package/src/app/[variants]/(auth)/signin/SignInEmailStep.tsx +57 -50
- package/src/app/[variants]/(auth)/signin/SignInPasswordStep.tsx +1 -1
- package/src/app/[variants]/(auth)/signin/page.tsx +2 -0
- package/src/app/[variants]/(auth)/signin/useSignIn.ts +2 -0
- package/src/app/[variants]/(auth)/signup/[[...signup]]/page.tsx +7 -0
- package/src/envs/app.ts +0 -2
- package/src/envs/auth.ts +3 -0
- package/src/libs/better-auth/define-config.ts +1 -1
- package/src/libs/better-auth/sso/providers/feishu.ts +15 -14
- package/src/libs/better-auth/sso/providers/wechat.ts +6 -3
- package/src/libs/next/proxy/define-config.ts +1 -1
- package/src/locales/default/auth.ts +3 -1
- package/src/locales/default/authError.ts +2 -0
- package/src/locales/default/metadata.ts +1 -1
- package/src/server/globalConfig/index.ts +1 -0
- package/src/server/ld.ts +1 -1
- package/src/store/chat/slices/topic/action.ts +1 -1
- package/src/store/electron/actions/settings.ts +7 -7
- package/src/store/electron/actions/sync.ts +11 -11
- package/src/store/global/actions/general.ts +12 -12
- package/src/store/global/initialState.ts +11 -11
- package/src/store/global/selectors/clientDB.ts +1 -1
- package/src/store/global/selectors/systemStatus.ts +1 -1
- package/src/store/image/slices/generationConfig/action.ts +12 -12
- package/src/store/image/utils/size.ts +11 -11
- package/src/store/library/slices/ragEval/actions/dataset.ts +1 -1
- package/src/store/serverConfig/selectors.ts +1 -0
- package/src/store/session/slices/session/initialState.ts +6 -6
- package/src/store/session/slices/session/reducers.ts +1 -1
- package/src/store/session/slices/sessionGroup/initialState.ts +2 -2
- package/src/store/tool/slices/customPlugin/action.ts +2 -2
- package/src/store/tool/slices/oldStore/action.ts +5 -5
- package/src/store/userMemory/slices/preference/action.ts +6 -6
- /package/docs/self-hosting/{advanced/auth → auth}/clerk.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/clerk.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/auth0.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/auth0.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/authelia.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/authelia.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/authentik.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/authentik.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/casdoor.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/cloudflare-zero-trust.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/cloudflare-zero-trust.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/github.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/github.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/google.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/google.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/keycloak.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/logto.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/microsoft-entra-id.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/microsoft-entra-id.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/okta.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/okta.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/wechat.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/wechat.zh-CN.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/zitadel.mdx +0 -0
- /package/docs/self-hosting/{advanced/auth → auth}/next-auth/zitadel.zh-CN.mdx +0 -0
|
@@ -69,7 +69,7 @@ const provider: GenericProviderDefinition<{
|
|
|
69
69
|
authorizationUrlParams: {
|
|
70
70
|
app_id: clientId,
|
|
71
71
|
response_type: 'code',
|
|
72
|
-
scope: '',
|
|
72
|
+
scope: 'contact:user.base:readonly contact:user.email:readonly',
|
|
73
73
|
},
|
|
74
74
|
clientId,
|
|
75
75
|
clientSecret,
|
|
@@ -79,8 +79,8 @@ const provider: GenericProviderDefinition<{
|
|
|
79
79
|
getToken: async ({ code, redirectURI }) => {
|
|
80
80
|
const tokenResponse = await fetch(FEISHU_TOKEN_URL, {
|
|
81
81
|
body: JSON.stringify({
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
client_id: clientId,
|
|
83
|
+
client_secret: clientSecret,
|
|
84
84
|
code,
|
|
85
85
|
grant_type: 'authorization_code',
|
|
86
86
|
redirect_uri: redirectURI,
|
|
@@ -124,16 +124,12 @@ const provider: GenericProviderDefinition<{
|
|
|
124
124
|
},
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
if (!response.ok)
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
127
|
+
if (!response.ok) return null;
|
|
130
128
|
|
|
131
129
|
const payload = (await response.json()) as unknown;
|
|
132
130
|
const profileResponse = payload as FeishuUserInfoResponse;
|
|
133
131
|
|
|
134
|
-
if (profileResponse.code && profileResponse.code !== 0)
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
132
|
+
if (profileResponse.code && profileResponse.code !== 0) return null;
|
|
137
133
|
|
|
138
134
|
const profile: FeishuUserProfile | undefined =
|
|
139
135
|
profileResponse.data ?? (isFeishuProfile(payload) ? payload : undefined);
|
|
@@ -143,11 +139,16 @@ const provider: GenericProviderDefinition<{
|
|
|
143
139
|
const unionId = profile.union_id ?? profile.open_id;
|
|
144
140
|
if (!unionId) return null;
|
|
145
141
|
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
// Always use union_id to construct email for consistency
|
|
143
|
+
// This avoids issues when:
|
|
144
|
+
// 1. Admin hasn't enabled "Allow OpenAPI to access email field" in Feishu admin console
|
|
145
|
+
// 2. User hasn't bound an email in Feishu
|
|
146
|
+
// 3. User's email changes later (which would cause account mismatch)
|
|
147
|
+
const email = profile.email || profile.enterprise_email || `${unionId}@feishu.sso`;
|
|
148
148
|
|
|
149
149
|
return {
|
|
150
|
-
|
|
150
|
+
...profile,
|
|
151
|
+
email,
|
|
151
152
|
emailVerified: false,
|
|
152
153
|
id: unionId,
|
|
153
154
|
image:
|
|
@@ -156,13 +157,13 @@ const provider: GenericProviderDefinition<{
|
|
|
156
157
|
profile.avatar_middle ??
|
|
157
158
|
profile.avatar_big,
|
|
158
159
|
name: profile.name ?? profile.en_name ?? unionId,
|
|
159
|
-
...profile,
|
|
160
160
|
};
|
|
161
161
|
},
|
|
162
162
|
pkce: false,
|
|
163
163
|
providerId: 'feishu',
|
|
164
164
|
responseMode: 'query',
|
|
165
|
-
scopes: [],
|
|
165
|
+
scopes: ['contact:user.base:readonly', 'contact:user.email:readonly'],
|
|
166
|
+
tokenUrl: FEISHU_TOKEN_URL,
|
|
166
167
|
};
|
|
167
168
|
},
|
|
168
169
|
|
|
@@ -43,7 +43,7 @@ const provider: GenericProviderDefinition<{
|
|
|
43
43
|
* and returns openid/unionid alongside tokens, so we exchange the code
|
|
44
44
|
* manually instead of proxying through a custom API route.
|
|
45
45
|
*/
|
|
46
|
-
|
|
46
|
+
getToken: async ({ code }) => {
|
|
47
47
|
const tokenUrl = new URL(WECHAT_TOKEN_URL);
|
|
48
48
|
tokenUrl.searchParams.set('appid', clientId);
|
|
49
49
|
tokenUrl.searchParams.set('secret', clientSecret);
|
|
@@ -74,10 +74,11 @@ const provider: GenericProviderDefinition<{
|
|
|
74
74
|
tokenType: data.token_type ?? 'Bearer',
|
|
75
75
|
};
|
|
76
76
|
},
|
|
77
|
+
|
|
77
78
|
/**
|
|
78
79
|
* Use openid/unionid returned in the token response; no custom scope encoding needed.
|
|
79
80
|
*/
|
|
80
|
-
|
|
81
|
+
getUserInfo: async (tokens) => {
|
|
81
82
|
const accessToken = tokens.accessToken;
|
|
82
83
|
const openId = (tokens as { raw?: WeChatTokenResponse }).raw?.openid;
|
|
83
84
|
const unionId = (tokens as { raw?: WeChatTokenResponse }).raw?.unionid;
|
|
@@ -114,7 +115,7 @@ const provider: GenericProviderDefinition<{
|
|
|
114
115
|
...profile,
|
|
115
116
|
};
|
|
116
117
|
},
|
|
117
|
-
|
|
118
|
+
|
|
118
119
|
pkce: false,
|
|
119
120
|
|
|
120
121
|
providerId: 'wechat',
|
|
@@ -122,6 +123,8 @@ const provider: GenericProviderDefinition<{
|
|
|
122
123
|
responseMode: 'query',
|
|
123
124
|
|
|
124
125
|
scopes: ['snsapi_login'],
|
|
126
|
+
|
|
127
|
+
tokenUrl: WECHAT_TOKEN_URL,
|
|
125
128
|
};
|
|
126
129
|
},
|
|
127
130
|
|
|
@@ -168,6 +168,7 @@ export function defineConfig() {
|
|
|
168
168
|
// better auth
|
|
169
169
|
'/signin',
|
|
170
170
|
'/signup',
|
|
171
|
+
'/auth-error',
|
|
171
172
|
'/verify-email',
|
|
172
173
|
'/reset-password',
|
|
173
174
|
// oauth
|
|
@@ -227,7 +228,6 @@ export function defineConfig() {
|
|
|
227
228
|
};
|
|
228
229
|
|
|
229
230
|
logDefault('Middleware configuration: %O', {
|
|
230
|
-
enableAuthProtection: appEnv.ENABLE_AUTH_PROTECTION,
|
|
231
231
|
enableOIDC: authEnv.ENABLE_OIDC,
|
|
232
232
|
});
|
|
233
233
|
|
|
@@ -102,6 +102,8 @@ export default {
|
|
|
102
102
|
'betterAuth.signin.socialError': 'Social sign in failed, please try again',
|
|
103
103
|
'betterAuth.signin.socialOnlyHint':
|
|
104
104
|
'This email was registered via a third-party social account. Sign in with that provider, or',
|
|
105
|
+
'betterAuth.signin.ssoOnlyNoProviders':
|
|
106
|
+
'Email registration is disabled and no SSO providers are configured. Please contact your administrator.',
|
|
105
107
|
'betterAuth.signin.submit': 'Sign In',
|
|
106
108
|
'betterAuth.signup.confirmPasswordPlaceholder': 'Confirm your password',
|
|
107
109
|
'betterAuth.signup.emailPlaceholder': 'Enter your email address',
|
|
@@ -201,7 +203,7 @@ export default {
|
|
|
201
203
|
'profile.usernameRule': 'Username can only contain letters, numbers, or underscores',
|
|
202
204
|
'profile.usernameUpdateFailed': 'Failed to update username, please try again later',
|
|
203
205
|
'signin.subtitle': 'Sign up or log in to your {{appName}} account',
|
|
204
|
-
'signin.title': 'Agent
|
|
206
|
+
'signin.title': 'Agent teammates that grow with you',
|
|
205
207
|
'signout': 'Log Out',
|
|
206
208
|
'signup': 'Sign Up',
|
|
207
209
|
'stats.aiheatmaps': 'Activity Index',
|
|
@@ -10,6 +10,8 @@ export default {
|
|
|
10
10
|
'This email has been associated with a deleted account and cannot be used for registration',
|
|
11
11
|
'codes.EMAIL_CAN_NOT_BE_UPDATED': 'Email cannot be updated for this account',
|
|
12
12
|
'codes.EMAIL_NOT_ALLOWED': 'Email not allowed for registration',
|
|
13
|
+
'codes.EMAIL_NOT_FOUND':
|
|
14
|
+
'No email associated with this account. Please check if your account has an email bound.',
|
|
13
15
|
'codes.EMAIL_NOT_VERIFIED': 'Please verify your email first',
|
|
14
16
|
'codes.FAILED_TO_CREATE_SESSION': 'Failed to create session',
|
|
15
17
|
'codes.FAILED_TO_CREATE_USER': 'Failed to create user',
|
|
@@ -3,7 +3,7 @@ export default {
|
|
|
3
3
|
'changelog.title': 'Changelog',
|
|
4
4
|
'chat.description':
|
|
5
5
|
'{{appName}} is a work-and-lifestyle space to find, build, and collaborate with agent teams that grow with you.',
|
|
6
|
-
'chat.title': '{{appName}} · Agent
|
|
6
|
+
'chat.title': '{{appName}} · Agent teammates that grow with you',
|
|
7
7
|
'discover.assistants.description':
|
|
8
8
|
'Content, Q&A, images, video, voice, workflows—browse and add Agents from the Community.',
|
|
9
9
|
'discover.assistants.title': 'Agent Community',
|
|
@@ -74,6 +74,7 @@ export const getServerGlobalConfig = async () => {
|
|
|
74
74
|
defaultAgent: {
|
|
75
75
|
config: parseAgentConfig(DEFAULT_AGENT_CONFIG),
|
|
76
76
|
},
|
|
77
|
+
disableEmailPassword: authEnv.AUTH_DISABLE_EMAIL_PASSWORD,
|
|
77
78
|
enableBusinessFeatures: ENABLE_BUSINESS_FEATURES,
|
|
78
79
|
enableEmailVerification: authEnv.AUTH_EMAIL_VERIFICATION,
|
|
79
80
|
enableKlavis: !!klavisEnv.KLAVIS_API_KEY,
|
package/src/server/ld.ts
CHANGED
|
@@ -94,7 +94,7 @@ export class Ld {
|
|
|
94
94
|
'email': BRANDING_EMAIL.support,
|
|
95
95
|
},
|
|
96
96
|
'description':
|
|
97
|
-
'Agent
|
|
97
|
+
'Agent teammates that grow with you\n' +
|
|
98
98
|
'LobeHub is a work-and-lifestyle space to find, build, and collaborate with agent teams that grow with you.',
|
|
99
99
|
'email': BRANDING_EMAIL.business,
|
|
100
100
|
'founders': [this.getAuthors(['arvinxx']), this.getAuthors(['canisminor'])],
|
|
@@ -9,7 +9,7 @@ import { desktopSettingsService } from '@/services/electron/settings';
|
|
|
9
9
|
import type { ElectronStore } from '../store';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Settings actions
|
|
13
13
|
*/
|
|
14
14
|
export interface ElectronSettingsAction {
|
|
15
15
|
refreshDesktopHotkeys: () => Promise<void>;
|
|
@@ -39,29 +39,29 @@ export const settingsSlice: StateCreator<
|
|
|
39
39
|
|
|
40
40
|
setProxySettings: async (values) => {
|
|
41
41
|
try {
|
|
42
|
-
//
|
|
42
|
+
// Update settings
|
|
43
43
|
await desktopSettingsService.setSettings(values);
|
|
44
44
|
|
|
45
|
-
//
|
|
45
|
+
// Refresh state
|
|
46
46
|
await get().refreshProxySettings();
|
|
47
47
|
} catch (error) {
|
|
48
|
-
console.error('
|
|
48
|
+
console.error('Proxy settings update failed:', error);
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
updateDesktopHotkey: async (id, accelerator) => {
|
|
53
53
|
try {
|
|
54
|
-
//
|
|
54
|
+
// Update hotkey configuration
|
|
55
55
|
const result = await desktopSettingsService.updateDesktopHotkey(id, accelerator);
|
|
56
56
|
|
|
57
|
-
//
|
|
57
|
+
// If update successful, refresh state
|
|
58
58
|
if (result.success) {
|
|
59
59
|
await get().refreshDesktopHotkeys();
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
return result;
|
|
63
63
|
} catch (error) {
|
|
64
|
-
console.error('
|
|
64
|
+
console.error('Desktop hotkey update failed:', error);
|
|
65
65
|
return {
|
|
66
66
|
errorType: 'UNKNOWN' as const,
|
|
67
67
|
success: false,
|
|
@@ -10,7 +10,7 @@ import { initialState } from '../initialState';
|
|
|
10
10
|
import type { ElectronStore } from '../store';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
13
|
+
* Remote server actions
|
|
14
14
|
*/
|
|
15
15
|
export interface ElectronRemoteServerAction {
|
|
16
16
|
clearRemoteServerSyncError: () => void;
|
|
@@ -39,28 +39,28 @@ export const remoteSyncSlice: StateCreator<
|
|
|
39
39
|
set({ isConnectingServer: true });
|
|
40
40
|
get().clearRemoteServerSyncError();
|
|
41
41
|
try {
|
|
42
|
-
//
|
|
42
|
+
// Get current configuration
|
|
43
43
|
const config = await remoteServerService.getRemoteServerConfig();
|
|
44
44
|
|
|
45
|
-
//
|
|
45
|
+
// If already active, need to clear first
|
|
46
46
|
if (!isEqual(config, values)) {
|
|
47
47
|
await remoteServerService.setRemoteServerConfig({ ...values, active: false });
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
//
|
|
50
|
+
// Request authorization
|
|
51
51
|
const result = await remoteServerService.requestAuthorization(values);
|
|
52
52
|
|
|
53
53
|
if (!result.success) {
|
|
54
|
-
console.error('
|
|
54
|
+
console.error('Authorization request failed:', result.error);
|
|
55
55
|
|
|
56
56
|
set({
|
|
57
57
|
remoteServerSyncError: { message: result.error, type: 'AUTH_ERROR' },
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
-
//
|
|
60
|
+
// Refresh state
|
|
61
61
|
await get().refreshServerConfig();
|
|
62
62
|
} catch (error) {
|
|
63
|
-
console.error('
|
|
63
|
+
console.error('Remote server configuration error:', error);
|
|
64
64
|
set({
|
|
65
65
|
remoteServerSyncError: { message: (error as Error).message, type: 'CONFIG_ERROR' },
|
|
66
66
|
});
|
|
@@ -74,12 +74,12 @@ export const remoteSyncSlice: StateCreator<
|
|
|
74
74
|
get().clearRemoteServerSyncError();
|
|
75
75
|
try {
|
|
76
76
|
await remoteServerService.setRemoteServerConfig({ active: false, storageMode: 'cloud' });
|
|
77
|
-
//
|
|
77
|
+
// Update form URL to empty
|
|
78
78
|
set({ dataSyncConfig: initialState.dataSyncConfig });
|
|
79
|
-
//
|
|
79
|
+
// Refresh state
|
|
80
80
|
await get().refreshServerConfig();
|
|
81
81
|
} catch (error) {
|
|
82
|
-
console.error('
|
|
82
|
+
console.error('Disconnect failed:', error);
|
|
83
83
|
set({
|
|
84
84
|
remoteServerSyncError: { message: (error as Error).message, type: 'DISCONNECT_ERROR' },
|
|
85
85
|
});
|
|
@@ -110,7 +110,7 @@ export const remoteSyncSlice: StateCreator<
|
|
|
110
110
|
try {
|
|
111
111
|
return await remoteServerService.getRemoteServerConfig();
|
|
112
112
|
} catch (error) {
|
|
113
|
-
console.error('
|
|
113
|
+
console.error('Failed to get remote server configuration:', error);
|
|
114
114
|
throw error;
|
|
115
115
|
}
|
|
116
116
|
},
|
|
@@ -188,18 +188,18 @@ export const generalActionSlice: StateCreator<
|
|
|
188
188
|
if (!clientVersion || !serverVersion) return;
|
|
189
189
|
|
|
190
190
|
const DIFF_THRESHOLD = 5;
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
// │
|
|
194
|
-
//
|
|
195
|
-
// │ 1.0.5 → 1.0.0 │ 5 │ ⚠️
|
|
196
|
-
//
|
|
197
|
-
// │ 1.1.0 → 1.0.5 │ 5 │ ⚠️
|
|
198
|
-
//
|
|
199
|
-
// │ 2.0.0 → 1.9.9 │ 91 │ ⚠️
|
|
200
|
-
//
|
|
201
|
-
// │ 1.0.4 → 1.0.0 │ 4 │ ✅
|
|
202
|
-
//
|
|
191
|
+
// Version difference calculation rules
|
|
192
|
+
// ┌─────────────────┬────────┬───────────┐
|
|
193
|
+
// │ Client → Server │ Diff │ Result │
|
|
194
|
+
// ├─────────────────┼────────┼───────────┤
|
|
195
|
+
// │ 1.0.5 → 1.0.0 │ 5 │ ⚠️ Too old│
|
|
196
|
+
// ├─────────────────┼────────┼───────────┤
|
|
197
|
+
// │ 1.1.0 → 1.0.5 │ 5 │ ⚠️ Too old│
|
|
198
|
+
// ├─────────────────┼────────┼───────────┤
|
|
199
|
+
// │ 2.0.0 → 1.9.9 │ 91 │ ⚠️ Too old│
|
|
200
|
+
// ├─────────────────┼────────┼───────────┤
|
|
201
|
+
// │ 1.0.4 → 1.0.0 │ 4 │ ✅ Normal │
|
|
202
|
+
// └─────────────────┴────────┴───────────┘
|
|
203
203
|
const versionDiff =
|
|
204
204
|
(clientVersion.major - serverVersion.major) * 100 +
|
|
205
205
|
(clientVersion.minor - serverVersion.minor) * 10 +
|
|
@@ -105,18 +105,18 @@ export interface SystemStatus {
|
|
|
105
105
|
imagePanelWidth: number;
|
|
106
106
|
imageTopicPanelWidth?: number;
|
|
107
107
|
/**
|
|
108
|
-
*
|
|
108
|
+
* Do not enable PGLite on app initialization, only enable when user manually turns it on
|
|
109
109
|
*/
|
|
110
110
|
isEnablePglite?: boolean;
|
|
111
111
|
isShowCredit?: boolean;
|
|
112
112
|
knowledgeBaseModalViewMode?: 'list' | 'masonry';
|
|
113
113
|
language?: LocaleMode;
|
|
114
114
|
/**
|
|
115
|
-
*
|
|
115
|
+
* Remember user's last selected image generation model
|
|
116
116
|
*/
|
|
117
117
|
lastSelectedImageModel?: string;
|
|
118
118
|
/**
|
|
119
|
-
*
|
|
119
|
+
* Remember user's last selected image generation provider
|
|
120
120
|
*/
|
|
121
121
|
lastSelectedImageProvider?: string;
|
|
122
122
|
latestChangelogId?: string;
|
|
@@ -124,11 +124,11 @@ export interface SystemStatus {
|
|
|
124
124
|
mobileShowPortal?: boolean;
|
|
125
125
|
mobileShowTopic?: boolean;
|
|
126
126
|
/**
|
|
127
|
-
* ModelSwitchPanel
|
|
127
|
+
* ModelSwitchPanel grouping mode
|
|
128
128
|
*/
|
|
129
129
|
modelSwitchPanelGroupMode?: 'byModel' | 'byProvider';
|
|
130
130
|
/**
|
|
131
|
-
* ModelSwitchPanel
|
|
131
|
+
* ModelSwitchPanel width
|
|
132
132
|
*/
|
|
133
133
|
modelSwitchPanelWidth?: number;
|
|
134
134
|
noWideScreen?: boolean;
|
|
@@ -157,7 +157,7 @@ export interface SystemStatus {
|
|
|
157
157
|
showSystemRole?: boolean;
|
|
158
158
|
systemRoleExpandedMap: Record<string, boolean>;
|
|
159
159
|
/**
|
|
160
|
-
*
|
|
160
|
+
* Whether to display tokens in short format
|
|
161
161
|
*/
|
|
162
162
|
tokenDisplayFormatShort?: boolean;
|
|
163
163
|
/**
|
|
@@ -177,21 +177,21 @@ export interface GlobalState {
|
|
|
177
177
|
|
|
178
178
|
initClientDBProcess?: { costTime?: number; phase: 'wasm' | 'dependencies'; progress: number };
|
|
179
179
|
/**
|
|
180
|
-
*
|
|
181
|
-
*
|
|
180
|
+
* Client database initialization state
|
|
181
|
+
* Idle on startup, Ready when complete, Error on failure
|
|
182
182
|
*/
|
|
183
183
|
initClientDBStage: DatabaseLoadingState;
|
|
184
184
|
isMobile?: boolean;
|
|
185
185
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
186
|
+
* Server version is too old, does not support /api/version endpoint
|
|
187
|
+
* Need to prompt user to update server
|
|
188
188
|
*/
|
|
189
189
|
isServerVersionOutdated?: boolean;
|
|
190
190
|
isStatusInit?: boolean;
|
|
191
191
|
latestVersion?: string;
|
|
192
192
|
navigate?: NavigateFunction;
|
|
193
193
|
/**
|
|
194
|
-
*
|
|
194
|
+
* Server version number, used to detect client-server version consistency
|
|
195
195
|
*/
|
|
196
196
|
serverVersion?: string;
|
|
197
197
|
sidebarKey: SidebarTabKey;
|
|
@@ -51,7 +51,7 @@ const getAgentSystemRoleExpanded =
|
|
|
51
51
|
(agentId: string) =>
|
|
52
52
|
(s: GlobalState): boolean => {
|
|
53
53
|
const map = s.status.systemRoleExpandedMap || {};
|
|
54
|
-
return map[agentId] === true; //
|
|
54
|
+
return map[agentId] === true; // System role is collapsed by default
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
const disabledModelProvidersSortType = (s: GlobalState) =>
|
|
@@ -40,7 +40,7 @@ export interface GenerationConfigAction {
|
|
|
40
40
|
toggleAspectRatioLock(): void;
|
|
41
41
|
setAspectRatio(aspectRatio: string): void;
|
|
42
42
|
|
|
43
|
-
//
|
|
43
|
+
// Initialization related methods
|
|
44
44
|
_initializeDefaultImageConfig(): void;
|
|
45
45
|
initializeImageConfig(
|
|
46
46
|
isLogin?: boolean,
|
|
@@ -185,12 +185,12 @@ export const createGenerationConfigSlice: StateCreator<
|
|
|
185
185
|
} = state;
|
|
186
186
|
const newLockState = !isAspectRatioLocked;
|
|
187
187
|
|
|
188
|
-
//
|
|
188
|
+
// If transitioning from unlocked to locked and there's an active aspect ratio, adjust dimensions immediately
|
|
189
189
|
if (newLockState && activeAspectRatio && parameters && parametersSchema) {
|
|
190
190
|
const currentWidth = parameters.width;
|
|
191
191
|
const currentHeight = parameters.height;
|
|
192
192
|
|
|
193
|
-
//
|
|
193
|
+
// Only adjust when both width and height exist
|
|
194
194
|
if (
|
|
195
195
|
typeof currentWidth === 'number' &&
|
|
196
196
|
typeof currentHeight === 'number' &&
|
|
@@ -200,9 +200,9 @@ export const createGenerationConfigSlice: StateCreator<
|
|
|
200
200
|
const targetRatio = parseRatio(activeAspectRatio);
|
|
201
201
|
const currentRatio = currentWidth / currentHeight;
|
|
202
202
|
|
|
203
|
-
//
|
|
203
|
+
// If current ratio doesn't match target ratio, adjustment is needed
|
|
204
204
|
if (Math.abs(currentRatio - targetRatio) > 0.01) {
|
|
205
|
-
//
|
|
205
|
+
// Allow small margin of error
|
|
206
206
|
const widthSchema = parametersSchema.width;
|
|
207
207
|
const heightSchema = parametersSchema.height;
|
|
208
208
|
|
|
@@ -214,19 +214,19 @@ export const createGenerationConfigSlice: StateCreator<
|
|
|
214
214
|
typeof heightSchema.max === 'number' &&
|
|
215
215
|
typeof heightSchema.min === 'number'
|
|
216
216
|
) {
|
|
217
|
-
//
|
|
217
|
+
// Prioritize keeping width, adjust height
|
|
218
218
|
let newWidth = currentWidth;
|
|
219
219
|
let newHeight = Math.round(currentWidth / targetRatio);
|
|
220
220
|
|
|
221
|
-
//
|
|
221
|
+
// If calculated height is out of range, switch to keeping height and adjust width
|
|
222
222
|
if (newHeight > heightSchema.max || newHeight < heightSchema.min) {
|
|
223
223
|
newHeight = currentHeight;
|
|
224
224
|
newWidth = Math.round(currentHeight * targetRatio);
|
|
225
225
|
|
|
226
|
-
//
|
|
226
|
+
// Ensure width is also within range
|
|
227
227
|
newWidth = Math.max(Math.min(newWidth, widthSchema.max), widthSchema.min);
|
|
228
228
|
} else {
|
|
229
|
-
//
|
|
229
|
+
// Ensure height is within range
|
|
230
230
|
newHeight = Math.max(Math.min(newHeight, heightSchema.max), heightSchema.min);
|
|
231
231
|
}
|
|
232
232
|
|
|
@@ -253,7 +253,7 @@ export const createGenerationConfigSlice: StateCreator<
|
|
|
253
253
|
const defaultValues = extractDefaultValues(parametersSchema);
|
|
254
254
|
const newParams = { ...parameters };
|
|
255
255
|
|
|
256
|
-
//
|
|
256
|
+
// If model supports width/height, calculate new dimensions
|
|
257
257
|
if (
|
|
258
258
|
parametersSchema?.width &&
|
|
259
259
|
parametersSchema?.height &&
|
|
@@ -266,7 +266,7 @@ export const createGenerationConfigSlice: StateCreator<
|
|
|
266
266
|
newParams.height = height;
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
//
|
|
269
|
+
// If model itself supports aspectRatio, update it
|
|
270
270
|
if (parametersSchema?.aspectRatio) {
|
|
271
271
|
newParams.aspectRatio = aspectRatio;
|
|
272
272
|
}
|
|
@@ -297,7 +297,7 @@ export const createGenerationConfigSlice: StateCreator<
|
|
|
297
297
|
`setModelAndProviderOnSelect/${model}/${provider}`,
|
|
298
298
|
);
|
|
299
299
|
|
|
300
|
-
//
|
|
300
|
+
// Only remember last selection for logged-in users, consistent with recovery strategy
|
|
301
301
|
const isLogin = authSelectors.isLogin(useUserStore.getState());
|
|
302
302
|
if (isLogin) {
|
|
303
303
|
useGlobalStore.getState().updateSystemStatus({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @param ratio -
|
|
4
|
-
* @returns
|
|
2
|
+
* Parse ratio string, e.g., "16:9" -> 1.777
|
|
3
|
+
* @param ratio - Ratio string in "width:height" format
|
|
4
|
+
* @returns Ratio value, returns 1:1 ratio on error
|
|
5
5
|
*/
|
|
6
6
|
export function parseRatio(ratio: string): number {
|
|
7
7
|
if (!ratio || typeof ratio !== 'string') return 1;
|
|
@@ -21,14 +21,14 @@ export function parseRatio(ratio: string): number {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
25
|
-
* @param ratio -
|
|
26
|
-
* @param defaultWidth -
|
|
27
|
-
* @param defaultHeight -
|
|
28
|
-
* @returns
|
|
24
|
+
* Calculate the most appropriate size based on target ratio and default dimensions
|
|
25
|
+
* @param ratio - Target aspect ratio
|
|
26
|
+
* @param defaultWidth - Default width
|
|
27
|
+
* @param defaultHeight - Default height
|
|
28
|
+
* @returns Calculated size object
|
|
29
29
|
*/
|
|
30
30
|
export function adaptSizeToRatio(ratio: number, defaultWidth: number, defaultHeight: number) {
|
|
31
|
-
//
|
|
31
|
+
// Validate input parameters
|
|
32
32
|
if (!Number.isFinite(ratio) || ratio <= 0) {
|
|
33
33
|
throw new Error('Invalid ratio: must be a positive finite number');
|
|
34
34
|
}
|
|
@@ -42,10 +42,10 @@ export function adaptSizeToRatio(ratio: number, defaultWidth: number, defaultHei
|
|
|
42
42
|
const currentRatio = defaultWidth / defaultHeight;
|
|
43
43
|
|
|
44
44
|
if (ratio > currentRatio) {
|
|
45
|
-
//
|
|
45
|
+
// Target ratio is wider, keep width and adjust height
|
|
46
46
|
return { width: defaultWidth, height: Math.round(defaultWidth / ratio) };
|
|
47
47
|
} else {
|
|
48
|
-
//
|
|
48
|
+
// Target ratio is taller, keep height and adjust width
|
|
49
49
|
return { width: Math.round(defaultHeight * ratio), height: defaultHeight };
|
|
50
50
|
}
|
|
51
51
|
}
|
|
@@ -42,7 +42,7 @@ export const createRagEvalDatasetSlice: StateCreator<
|
|
|
42
42
|
const fileType = file.name.split('.').pop();
|
|
43
43
|
|
|
44
44
|
if (fileType === 'jsonl') {
|
|
45
|
-
// jsonl
|
|
45
|
+
// jsonl file needs to be split into individual entries, then validated one by one
|
|
46
46
|
const jsonl = await file.text();
|
|
47
47
|
const { default: JSONL } = await import('jsonl-parse-stringify');
|
|
48
48
|
|
|
@@ -3,6 +3,7 @@ import { type ServerConfigStore } from './store';
|
|
|
3
3
|
export const featureFlagsSelectors = (s: ServerConfigStore) => s.featureFlags;
|
|
4
4
|
|
|
5
5
|
export const serverConfigSelectors = {
|
|
6
|
+
disableEmailPassword: (s: ServerConfigStore) => s.serverConfig.disableEmailPassword || false,
|
|
6
7
|
enableBusinessFeatures: (s: ServerConfigStore) => s.serverConfig.enableBusinessFeatures || false,
|
|
7
8
|
enableEmailVerification: (s: ServerConfigStore) =>
|
|
8
9
|
s.serverConfig.enableEmailVerification || false,
|
|
@@ -3,8 +3,8 @@ import { type LobeSessions } from '@/types/session';
|
|
|
3
3
|
export interface SessionState {
|
|
4
4
|
activeAgentId?: string;
|
|
5
5
|
/**
|
|
6
|
-
* @title
|
|
7
|
-
* @description
|
|
6
|
+
* @title Current active session
|
|
7
|
+
* @description The session currently being edited or viewed
|
|
8
8
|
*/
|
|
9
9
|
activeId: string;
|
|
10
10
|
/**
|
|
@@ -22,14 +22,14 @@ export interface SessionState {
|
|
|
22
22
|
pinnedSessions: LobeSessions;
|
|
23
23
|
searchKeywords: string;
|
|
24
24
|
/**
|
|
25
|
-
* @title
|
|
26
|
-
* @description
|
|
25
|
+
* @title Session ID being renamed
|
|
26
|
+
* @description Used to control the display state of the session rename modal
|
|
27
27
|
*/
|
|
28
28
|
sessionRenamingId: string | null;
|
|
29
29
|
sessionSearchKeywords?: string;
|
|
30
30
|
/**
|
|
31
|
-
* @title
|
|
32
|
-
* @description
|
|
31
|
+
* @title Session ID being updated
|
|
32
|
+
* @description Used to display loading state when session is being updated
|
|
33
33
|
*/
|
|
34
34
|
sessionUpdatingId: string | null;
|
|
35
35
|
/**
|
|
@@ -27,7 +27,7 @@ export const sessionsReducer = (state: LobeSessions, payload: SessionDispatch):
|
|
|
27
27
|
const { session } = payload;
|
|
28
28
|
if (!session) return;
|
|
29
29
|
|
|
30
|
-
// TODO:
|
|
30
|
+
// TODO: Migrate Date type in the future to remove this ignore
|
|
31
31
|
// @ts-ignore
|
|
32
32
|
draft.unshift({ ...session, createdAt: new Date(), updatedAt: new Date() });
|
|
33
33
|
});
|
|
@@ -4,8 +4,8 @@ export interface SessionGroupState {
|
|
|
4
4
|
customSessionGroups: CustomSessionGroup[];
|
|
5
5
|
sessionGroupRenamingId: string | null;
|
|
6
6
|
/**
|
|
7
|
-
* @title
|
|
8
|
-
* @description
|
|
7
|
+
* @title Group ID being updated
|
|
8
|
+
* @description Used to display loading state when group is being updated
|
|
9
9
|
*/
|
|
10
10
|
sessionGroupUpdatingId: string | null;
|
|
11
11
|
sessionGroups: LobeSessionGroups;
|