@lobehub/lobehub 2.0.0-next.237 → 2.0.0-next.239
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/CHANGELOG.md +58 -0
- package/changelog/v1.json +21 -0
- package/locales/en-US/oauth.json +1 -0
- package/locales/zh-CN/oauth.json +1 -0
- package/package.json +1 -1
- package/packages/const/src/klavis.ts +1 -7
- package/packages/const/src/lobehubSkill.ts +7 -1
- package/src/app/[variants]/(auth)/oauth/callback/success/page.tsx +44 -2
- package/src/app/[variants]/(main)/chat/_layout/Sidebar/Topic/List/Item/Editing.tsx +18 -9
- package/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx +42 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.239](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.238...v2.0.0-next.239)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2026-01-08**</sup>
|
|
8
|
+
|
|
9
|
+
#### ✨ Features
|
|
10
|
+
|
|
11
|
+
- **misc**: Add the twitter lobehub skill.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's improved
|
|
19
|
+
|
|
20
|
+
- **misc**: Add the twitter lobehub skill, closes [#11342](https://github.com/lobehub/lobe-chat/issues/11342) ([503acb3](https://github.com/lobehub/lobe-chat/commit/503acb3))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 2.0.0-next.238](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.237...v2.0.0-next.238)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2026-01-08**</sup>
|
|
33
|
+
|
|
34
|
+
#### ✨ Features
|
|
35
|
+
|
|
36
|
+
- **misc**: Change the klavis Linear to LobeHub oauth Linear.
|
|
37
|
+
|
|
38
|
+
#### 🐛 Bug Fixes
|
|
39
|
+
|
|
40
|
+
- **misc**: Topic renaming input focus issue in context menu.
|
|
41
|
+
|
|
42
|
+
<br/>
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
46
|
+
|
|
47
|
+
#### What's improved
|
|
48
|
+
|
|
49
|
+
- **misc**: Change the klavis Linear to LobeHub oauth Linear, closes [#11339](https://github.com/lobehub/lobe-chat/issues/11339) ([ec8ff26](https://github.com/lobehub/lobe-chat/commit/ec8ff26))
|
|
50
|
+
|
|
51
|
+
#### What's fixed
|
|
52
|
+
|
|
53
|
+
- **misc**: Topic renaming input focus issue in context menu, closes [#11323](https://github.com/lobehub/lobe-chat/issues/11323) ([dd065fc](https://github.com/lobehub/lobe-chat/commit/dd065fc))
|
|
54
|
+
|
|
55
|
+
</details>
|
|
56
|
+
|
|
57
|
+
<div align="right">
|
|
58
|
+
|
|
59
|
+
[](#readme-top)
|
|
60
|
+
|
|
61
|
+
</div>
|
|
62
|
+
|
|
5
63
|
## [Version 2.0.0-next.237](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.236...v2.0.0-next.237)
|
|
6
64
|
|
|
7
65
|
<sup>Released on **2026-01-08**</sup>
|
package/changelog/v1.json
CHANGED
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"features": [
|
|
5
|
+
"Add the twitter lobehub skill."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2026-01-08",
|
|
9
|
+
"version": "2.0.0-next.239"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"features": [
|
|
14
|
+
"Change the klavis Linear to LobeHub oauth Linear."
|
|
15
|
+
],
|
|
16
|
+
"fixes": [
|
|
17
|
+
"Topic renaming input focus issue in context menu."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"date": "2026-01-08",
|
|
21
|
+
"version": "2.0.0-next.238"
|
|
22
|
+
},
|
|
2
23
|
{
|
|
3
24
|
"children": {},
|
|
4
25
|
"date": "2026-01-08",
|
package/locales/en-US/oauth.json
CHANGED
|
@@ -32,5 +32,6 @@
|
|
|
32
32
|
"login.title": "Login to {{clientName}}",
|
|
33
33
|
"login.userWelcome": "Welcome back, ",
|
|
34
34
|
"success.subTitle": "You have successfully authorized the application to access your account. You may now close this page.",
|
|
35
|
+
"success.subTitleWithCountdown": "Authorization successful. Auto-closing in {{countdown}}s...",
|
|
35
36
|
"success.title": "Authorization Successful"
|
|
36
37
|
}
|
package/locales/zh-CN/oauth.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.239",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IconType, SiCaldotcom, SiGithub
|
|
1
|
+
import { IconType, SiCaldotcom, SiGithub } from '@icons-pack/react-simple-icons';
|
|
2
2
|
import { Klavis } from 'klavis';
|
|
3
3
|
|
|
4
4
|
export interface KlavisServerType {
|
|
@@ -40,12 +40,6 @@ export const KLAVIS_SERVER_TYPES: KlavisServerType[] = [
|
|
|
40
40
|
label: 'Airtable',
|
|
41
41
|
serverName: Klavis.McpServerName.Airtable,
|
|
42
42
|
},
|
|
43
|
-
{
|
|
44
|
-
icon: SiLinear,
|
|
45
|
-
identifier: 'linear',
|
|
46
|
-
label: 'Linear',
|
|
47
|
-
serverName: Klavis.McpServerName.Linear,
|
|
48
|
-
},
|
|
49
43
|
{
|
|
50
44
|
icon: 'https://hub-apac-1.lobeobjects.space/assets/logos/googlesheets.svg',
|
|
51
45
|
identifier: 'google-sheets',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IconType, SiLinear } from '@icons-pack/react-simple-icons';
|
|
1
|
+
import { type IconType, SiLinear, SiX } from '@icons-pack/react-simple-icons';
|
|
2
2
|
|
|
3
3
|
export interface LobehubSkillProviderType {
|
|
4
4
|
/**
|
|
@@ -40,6 +40,12 @@ export const LOBEHUB_SKILL_PROVIDERS: LobehubSkillProviderType[] = [
|
|
|
40
40
|
id: 'microsoft',
|
|
41
41
|
label: 'Outlook Calendar',
|
|
42
42
|
},
|
|
43
|
+
{
|
|
44
|
+
defaultVisible: true,
|
|
45
|
+
icon: SiX,
|
|
46
|
+
id: 'twitter',
|
|
47
|
+
label: 'X (Twitter)',
|
|
48
|
+
},
|
|
43
49
|
];
|
|
44
50
|
|
|
45
51
|
/**
|
|
@@ -2,11 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
import { FluentEmoji, Text } from '@lobehub/ui';
|
|
4
4
|
import { Result } from 'antd';
|
|
5
|
-
import
|
|
5
|
+
import { useSearchParams } from 'next/navigation';
|
|
6
|
+
import React, { memo, useEffect, useState } from 'react';
|
|
6
7
|
import { useTranslation } from 'react-i18next';
|
|
7
8
|
|
|
8
9
|
const SuccessPage = memo(() => {
|
|
9
10
|
const { t } = useTranslation('oauth');
|
|
11
|
+
const searchParams = useSearchParams();
|
|
12
|
+
const [countdown, setCountdown] = useState(3);
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
// Check if this is a LobeHub Skill OAuth callback
|
|
16
|
+
const provider = searchParams.get('provider');
|
|
17
|
+
|
|
18
|
+
if (provider && window.opener) {
|
|
19
|
+
// Notify parent window about successful OAuth
|
|
20
|
+
window.opener.postMessage(
|
|
21
|
+
{
|
|
22
|
+
provider,
|
|
23
|
+
type: 'LOBEHUB_SKILL_AUTH_SUCCESS',
|
|
24
|
+
},
|
|
25
|
+
window.location.origin,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Start countdown and close window after 3 seconds
|
|
29
|
+
let timeLeft = 3;
|
|
30
|
+
setCountdown(timeLeft);
|
|
31
|
+
|
|
32
|
+
const countdownTimer = setInterval(() => {
|
|
33
|
+
timeLeft -= 1;
|
|
34
|
+
setCountdown(timeLeft);
|
|
35
|
+
|
|
36
|
+
if (timeLeft <= 0) {
|
|
37
|
+
clearInterval(countdownTimer);
|
|
38
|
+
window.close();
|
|
39
|
+
}
|
|
40
|
+
}, 1000);
|
|
41
|
+
|
|
42
|
+
return () => clearInterval(countdownTimer);
|
|
43
|
+
}
|
|
44
|
+
}, [searchParams]);
|
|
45
|
+
|
|
46
|
+
const provider = searchParams.get('provider');
|
|
10
47
|
|
|
11
48
|
return (
|
|
12
49
|
<Result
|
|
@@ -14,7 +51,12 @@ const SuccessPage = memo(() => {
|
|
|
14
51
|
status="success"
|
|
15
52
|
subTitle={
|
|
16
53
|
<Text fontSize={16} type="secondary">
|
|
17
|
-
{
|
|
54
|
+
{provider
|
|
55
|
+
? t('success.subTitleWithCountdown', {
|
|
56
|
+
countdown,
|
|
57
|
+
defaultValue: `You may close this page. Auto-closing in ${countdown}s...`,
|
|
58
|
+
})
|
|
59
|
+
: t('success.subTitle')}
|
|
18
60
|
</Text>
|
|
19
61
|
}
|
|
20
62
|
title={
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Input, Popover } from '@lobehub/ui';
|
|
2
|
-
import {
|
|
1
|
+
import { Input, type InputProps, Popover } from '@lobehub/ui';
|
|
2
|
+
import type { InputRef } from 'antd';
|
|
3
|
+
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
3
4
|
|
|
4
5
|
import { useChatStore } from '@/store/chat';
|
|
5
6
|
|
|
@@ -9,6 +10,18 @@ interface EditingProps {
|
|
|
9
10
|
toggleEditing: (visible?: boolean) => void;
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
function FocusableInput({ ...props }: InputProps) {
|
|
14
|
+
const ref = useRef<InputRef>(null);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
queueMicrotask(() => {
|
|
17
|
+
if (ref.current) {
|
|
18
|
+
ref.current.input?.focus();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}, []);
|
|
22
|
+
return <Input {...props} ref={ref} />;
|
|
23
|
+
}
|
|
24
|
+
|
|
12
25
|
const Editing = memo<EditingProps>(({ id, title, toggleEditing }) => {
|
|
13
26
|
const [newTitle, setNewTitle] = useState(title);
|
|
14
27
|
const [editing, updateTopicTitle] = useChatStore((s) => [
|
|
@@ -41,19 +54,14 @@ const Editing = memo<EditingProps>(({ id, title, toggleEditing }) => {
|
|
|
41
54
|
);
|
|
42
55
|
}
|
|
43
56
|
}
|
|
44
|
-
toggleEditing(false);
|
|
45
57
|
}, [newTitle, title, id, updateTopicTitle, toggleEditing]);
|
|
46
58
|
|
|
47
59
|
return (
|
|
48
60
|
<Popover
|
|
49
61
|
content={
|
|
50
|
-
<
|
|
51
|
-
autoFocus
|
|
62
|
+
<FocusableInput
|
|
52
63
|
defaultValue={title}
|
|
53
|
-
onBlur={
|
|
54
|
-
handleUpdate();
|
|
55
|
-
toggleEditing(false);
|
|
56
|
-
}}
|
|
64
|
+
onBlur={handleUpdate}
|
|
57
65
|
onChange={(e) => setNewTitle(e.target.value)}
|
|
58
66
|
onClick={(e) => e.stopPropagation()}
|
|
59
67
|
onPressEnter={() => {
|
|
@@ -64,6 +72,7 @@ const Editing = memo<EditingProps>(({ id, title, toggleEditing }) => {
|
|
|
64
72
|
}
|
|
65
73
|
onOpenChange={(open) => {
|
|
66
74
|
if (!open) handleUpdate();
|
|
75
|
+
|
|
67
76
|
toggleEditing(open);
|
|
68
77
|
}}
|
|
69
78
|
open={editing}
|
|
@@ -135,13 +135,52 @@ const LobehubSkillServerItem = memo<LobehubSkillServerItemProps>(({ provider, la
|
|
|
135
135
|
s.togglePlugin,
|
|
136
136
|
]);
|
|
137
137
|
|
|
138
|
+
// Listen for OAuth success message from popup window
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
const handleMessage = async (event: MessageEvent) => {
|
|
141
|
+
// Verify origin for security
|
|
142
|
+
if (event.origin !== window.location.origin) return;
|
|
143
|
+
|
|
144
|
+
if (event.data?.type === 'LOBEHUB_SKILL_AUTH_SUCCESS' && event.data?.provider === provider) {
|
|
145
|
+
console.log('[LobehubSkill] OAuth success message received for provider:', provider);
|
|
146
|
+
|
|
147
|
+
// Cleanup polling/window monitoring
|
|
148
|
+
cleanup();
|
|
149
|
+
|
|
150
|
+
// Refresh status to get the connected state
|
|
151
|
+
await checkStatus(provider);
|
|
152
|
+
|
|
153
|
+
// Auto-enable the plugin after successful OAuth
|
|
154
|
+
// Need to get the latest server state after checkStatus
|
|
155
|
+
const latestServer = useToolStore
|
|
156
|
+
.getState()
|
|
157
|
+
.lobehubSkillServers?.find((s) => s.identifier === provider);
|
|
158
|
+
if (latestServer?.status === LobehubSkillStatus.CONNECTED) {
|
|
159
|
+
const newPluginId = latestServer.identifier;
|
|
160
|
+
const isAlreadyEnabled = agentSelectors
|
|
161
|
+
.currentAgentPlugins(useAgentStore.getState())
|
|
162
|
+
.includes(newPluginId);
|
|
163
|
+
if (!isAlreadyEnabled) {
|
|
164
|
+
console.log('[LobehubSkill] Auto-enabling plugin:', newPluginId);
|
|
165
|
+
togglePlugin(newPluginId);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
window.addEventListener('message', handleMessage);
|
|
172
|
+
return () => window.removeEventListener('message', handleMessage);
|
|
173
|
+
}, [provider, cleanup, checkStatus, togglePlugin]);
|
|
174
|
+
|
|
138
175
|
const handleConnect = async () => {
|
|
139
176
|
// 只有已连接状态才阻止重新连接
|
|
140
177
|
if (server?.isConnected) return;
|
|
141
178
|
|
|
142
179
|
setIsConnecting(true);
|
|
143
180
|
try {
|
|
144
|
-
|
|
181
|
+
// Use /oauth/callback/success as redirect URI with provider param for auto-enable
|
|
182
|
+
const redirectUri = `${window.location.origin}/oauth/callback/success?provider=${encodeURIComponent(provider)}`;
|
|
183
|
+
const { authorizeUrl } = await getAuthorizeUrl(provider, { redirectUri });
|
|
145
184
|
openOAuthWindow(authorizeUrl);
|
|
146
185
|
} catch (error) {
|
|
147
186
|
console.error('[LobehubSkill] Failed to get authorize URL:', error);
|
|
@@ -236,7 +275,8 @@ const LobehubSkillServerItem = memo<LobehubSkillServerItemProps>(({ provider, la
|
|
|
236
275
|
onClick={async (e) => {
|
|
237
276
|
e.stopPropagation();
|
|
238
277
|
try {
|
|
239
|
-
const
|
|
278
|
+
const redirectUri = `${window.location.origin}/oauth/callback/success?provider=${encodeURIComponent(provider)}`;
|
|
279
|
+
const { authorizeUrl } = await getAuthorizeUrl(provider, { redirectUri });
|
|
240
280
|
openOAuthWindow(authorizeUrl);
|
|
241
281
|
} catch (error) {
|
|
242
282
|
console.error('[LobehubSkill] Failed to get authorize URL:', error);
|