@lobehub/lobehub 2.0.0-next.312 → 2.0.0-next.314
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 +51 -0
- package/apps/desktop/src/main/appBrowsers.ts +4 -1
- package/apps/desktop/src/main/controllers/AuthCtr.ts +75 -7
- package/apps/desktop/src/main/controllers/BrowserWindowsCtr.ts +15 -3
- package/apps/desktop/src/main/core/browser/Browser.ts +14 -4
- package/apps/desktop/src/main/core/browser/BrowserManager.ts +7 -2
- package/changelog/v1.json +18 -0
- package/docs/usage/providers/internlm.mdx +2 -2
- package/docs/usage/providers/internlm.zh-CN.mdx +3 -3
- package/e2e/src/steps/community/detail-pages.steps.ts +2 -2
- package/e2e/src/steps/community/interactions.steps.ts +6 -6
- package/e2e/src/steps/hooks.ts +19 -3
- package/locales/en-US/error.json +10 -1
- package/locales/en-US/subscription.json +1 -1
- package/locales/zh-CN/desktop-onboarding.json +5 -0
- package/locales/zh-CN/error.json +10 -1
- package/locales/zh-CN/subscription.json +1 -1
- package/package.json +1 -1
- package/packages/agent-runtime/src/agents/GeneralChatAgent.ts +14 -2
- package/packages/agent-runtime/src/agents/__tests__/GeneralChatAgent.test.ts +275 -1
- package/packages/builtin-tool-cloud-sandbox/package.json +1 -0
- package/packages/builtin-tool-cloud-sandbox/src/ExecutionRuntime/index.ts +105 -134
- package/packages/builtin-tool-cloud-sandbox/src/executor/index.ts +254 -0
- package/packages/builtin-tool-cloud-sandbox/src/index.ts +1 -0
- package/packages/builtin-tool-cloud-sandbox/src/types/api.ts +22 -0
- package/packages/builtin-tool-cloud-sandbox/src/types/index.ts +4 -0
- package/packages/builtin-tool-cloud-sandbox/src/types/params.ts +85 -0
- package/packages/builtin-tool-cloud-sandbox/src/types/service.ts +48 -0
- package/packages/builtin-tool-cloud-sandbox/src/{types.ts → types/state.ts} +0 -23
- package/packages/builtin-tool-memory/src/manifest.ts +5 -5
- package/packages/desktop-bridge/src/index.ts +5 -0
- package/packages/editor-runtime/src/__tests__/EditorRuntime.real.test.ts +1 -1
- package/packages/editor-runtime/src/__tests__/EditorRuntime.test.ts +1 -1
- package/packages/electron-client-ipc/src/events/index.ts +5 -1
- package/packages/electron-client-ipc/src/events/remoteServer.ts +23 -0
- package/packages/electron-client-ipc/src/types/window.ts +3 -2
- package/packages/memory-user-memory/src/schemas/index.ts +0 -1
- package/packages/model-bank/src/modelProviders/internlm.ts +1 -1
- package/packages/model-runtime/src/core/RouterRuntime/createRuntime.ts +5 -15
- package/packages/model-runtime/src/providers/internlm/index.test.ts +15 -15
- package/packages/model-runtime/src/providers/internlm/index.ts +1 -1
- package/packages/types/src/tool/intervention.ts +4 -2
- package/packages/types/src/user/preference.ts +1 -0
- package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +6 -3
- package/src/app/[variants]/(desktop)/desktop-onboarding/components/OnboardingFooterActions.tsx +38 -0
- package/src/app/[variants]/(desktop)/desktop-onboarding/features/DataModeStep.tsx +19 -14
- package/src/app/[variants]/(desktop)/desktop-onboarding/features/LoginStep.tsx +121 -29
- package/src/app/[variants]/(desktop)/desktop-onboarding/features/PermissionsStep.tsx +19 -14
- package/src/app/[variants]/(desktop)/desktop-onboarding/index.tsx +8 -7
- package/src/app/[variants]/(main)/_layout/DesktopAutoOidcOnFirstOpen.tsx +4 -0
- package/src/app/manifest.ts +1 -1
- package/src/business/server/user.ts +4 -0
- package/src/features/Conversation/Messages/Task/Actions/index.tsx +0 -2
- package/src/features/Conversation/Messages/Task/index.tsx +1 -1
- package/src/features/Conversation/Messages/Tasks/shared/ProcessingState.tsx +0 -2
- package/src/features/Electron/titlebar/NavigationBar.tsx +1 -2
- package/src/features/NavPanel/components/NavPanelDraggable.tsx +0 -14
- package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +4 -3
- package/src/features/SharePopover/index.tsx +5 -3
- package/src/hooks/useAppOrigin.ts +16 -0
- package/src/layout/GlobalProvider/useUserStateRedirect.ts +37 -24
- package/src/libs/trusted-client/index.ts +2 -5
- package/src/locales/default/desktop-onboarding.ts +5 -0
- package/src/locales/default/error.ts +11 -0
- package/src/locales/default/subscription.ts +1 -1
- package/src/server/manifest.ts +2 -2
- package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +2 -0
- package/src/server/routers/lambda/user.ts +24 -10
- package/src/server/services/agentRuntime/AgentRuntimeService.test.ts +3 -0
- package/src/server/services/agentRuntime/AgentRuntimeService.ts +8 -5
- package/src/server/services/agentRuntime/types.ts +7 -0
- package/src/server/services/aiAgent/__tests__/execGroupSubAgentTask.test.ts +3 -0
- package/src/server/services/aiAgent/index.ts +10 -4
- package/src/server/services/market/index.ts +20 -0
- package/src/server/services/sandbox/index.ts +186 -0
- package/src/server/services/toolExecution/builtin.ts +12 -18
- package/src/server/services/toolExecution/index.ts +1 -1
- package/src/server/services/toolExecution/serverRuntimes/cloudSandbox.ts +38 -0
- package/src/server/services/toolExecution/serverRuntimes/index.ts +55 -0
- package/src/server/services/toolExecution/serverRuntimes/types.ts +14 -0
- package/src/server/services/toolExecution/serverRuntimes/webBrowsing.ts +20 -0
- package/src/server/services/toolExecution/types.ts +2 -0
- package/src/services/{codeInterpreter.ts → cloudSandbox.ts} +3 -3
- package/src/services/electron/remoteServer.ts +8 -0
- package/src/services/electron/system.ts +5 -5
- package/src/store/chat/agents/GroupOrchestration/__tests__/batch-exec-async-tasks.test.ts +626 -0
- package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +294 -0
- package/src/store/chat/slices/plugin/action.test.ts +0 -48
- package/src/store/chat/slices/plugin/actions/pluginTypes.ts +0 -131
- package/src/store/tool/slices/builtin/executors/index.ts +2 -0
- package/src/store/user/slices/settings/selectors/toolIntervention.test.ts +143 -0
- package/src/store/user/slices/settings/selectors/toolIntervention.ts +11 -2
- package/packages/memory-user-memory/src/schemas/jsonSchemas.ts +0 -37
|
@@ -13,6 +13,10 @@ export async function getIsInWaitList(userId: string): Promise<boolean> {
|
|
|
13
13
|
return false;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export async function getIsInviteCodeRequired(userId: string): Promise<boolean> {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
export async function initNewUserForBusiness(
|
|
17
21
|
userId: string,
|
|
18
22
|
createdAt: Date | null | undefined,
|
|
@@ -43,7 +43,7 @@ const TaskMessage = memo<TaskMessageProps>(({ id, index, disableEditing, isLates
|
|
|
43
43
|
const editing = useConversationStore(messageStateSelectors.isMessageEditing(id));
|
|
44
44
|
const generating = useConversationStore(messageStateSelectors.isMessageGenerating(id));
|
|
45
45
|
const creating = useConversationStore(messageStateSelectors.isMessageCreating(id));
|
|
46
|
-
const newScreen = useNewScreen({ creating, isLatestItem });
|
|
46
|
+
const newScreen = useNewScreen({ creating: generating || creating, isLatestItem });
|
|
47
47
|
|
|
48
48
|
const errorContent = useErrorContent(error);
|
|
49
49
|
|
|
@@ -53,13 +53,12 @@ const NavigationBar = memo(() => {
|
|
|
53
53
|
return (
|
|
54
54
|
<Flexbox
|
|
55
55
|
align="center"
|
|
56
|
-
className={electronStylish.nodrag}
|
|
57
56
|
data-width={leftPanelWidth}
|
|
58
57
|
horizontal
|
|
59
58
|
justify="end"
|
|
60
59
|
style={{ width: `${leftPanelWidth - 12}px` }}
|
|
61
60
|
>
|
|
62
|
-
<Flexbox align="center" gap={2} horizontal>
|
|
61
|
+
<Flexbox align="center" className={electronStylish.nodrag} gap={2} horizontal>
|
|
63
62
|
<ActionIcon disabled={!canGoBack} icon={ArrowLeft} onClick={goBack} size="small" />
|
|
64
63
|
<ActionIcon disabled={!canGoForward} icon={ArrowRight} onClick={goForward} size="small" />
|
|
65
64
|
<Popover
|
|
@@ -13,7 +13,6 @@ import { systemStatusSelectors } from '@/store/global/selectors';
|
|
|
13
13
|
import { isMacOS } from '@/utils/platform';
|
|
14
14
|
|
|
15
15
|
import { useNavPanelSizeChangeHandler } from '../hooks/useNavPanel';
|
|
16
|
-
import { BACK_BUTTON_ID } from './BackButton';
|
|
17
16
|
|
|
18
17
|
const motionVariants = {
|
|
19
18
|
animate: { opacity: 1, x: 0 },
|
|
@@ -78,12 +77,6 @@ const draggableStyles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
78
77
|
width 0.2s ${cssVar.motionEaseOut};
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
#${BACK_BUTTON_ID} {
|
|
82
|
-
width: 0 !important;
|
|
83
|
-
opacity: 0;
|
|
84
|
-
transition: all 0.2s ${cssVar.motionEaseOut};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
80
|
&:hover {
|
|
88
81
|
#${TOGGLE_BUTTON_ID} {
|
|
89
82
|
width: 32px !important;
|
|
@@ -94,13 +87,6 @@ const draggableStyles = createStaticStyles(({ css, cssVar }) => ({
|
|
|
94
87
|
width: 14px !important;
|
|
95
88
|
opacity: 1;
|
|
96
89
|
}
|
|
97
|
-
|
|
98
|
-
&:hover {
|
|
99
|
-
#${BACK_BUTTON_ID} {
|
|
100
|
-
width: 24px !important;
|
|
101
|
-
opacity: 1;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
90
|
}
|
|
105
91
|
`,
|
|
106
92
|
}));
|
package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import { shallow } from 'zustand/shallow';
|
|
|
17
17
|
import RepoIcon from '@/components/LibIcon';
|
|
18
18
|
import { clearTreeFolderCache } from '@/features/ResourceManager/components/LibraryHierarchy';
|
|
19
19
|
import { PAGE_FILE_TYPE } from '@/features/ResourceManager/constants';
|
|
20
|
+
import { useAppOrigin } from '@/hooks/useAppOrigin';
|
|
20
21
|
import { documentService } from '@/services/document';
|
|
21
22
|
import { useFileStore } from '@/store/file';
|
|
22
23
|
import { useKnowledgeBaseStore } from '@/store/library';
|
|
@@ -53,6 +54,7 @@ export const useFileItemDropdown = ({
|
|
|
53
54
|
}: UseFileItemDropdownParams): UseFileItemDropdownReturn => {
|
|
54
55
|
const { t } = useTranslation(['components', 'common', 'knowledgeBase']);
|
|
55
56
|
const { message, modal } = App.useApp();
|
|
57
|
+
const appOrigin = useAppOrigin();
|
|
56
58
|
|
|
57
59
|
const { deleteResource, refreshFileList } = useFileStore(
|
|
58
60
|
(s) => ({
|
|
@@ -184,11 +186,10 @@ export const useFileItemDropdown = ({
|
|
|
184
186
|
// For pages, use the route path instead of the storage URL
|
|
185
187
|
let urlToCopy = url;
|
|
186
188
|
if (isPage) {
|
|
187
|
-
const baseUrl = window.location.origin;
|
|
188
189
|
if (libraryId) {
|
|
189
|
-
urlToCopy = `${
|
|
190
|
+
urlToCopy = `${appOrigin}/resource/library/${libraryId}?file=${id}`;
|
|
190
191
|
} else {
|
|
191
|
-
urlToCopy = `${
|
|
192
|
+
urlToCopy = `${appOrigin}/resource?file=${id}`;
|
|
192
193
|
}
|
|
193
194
|
}
|
|
194
195
|
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import { Button, Flexbox, Popover, copyToClipboard, usePopoverContext } from '@lobehub/ui';
|
|
4
4
|
import { App, Divider, Select, Skeleton, Typography } from 'antd';
|
|
5
|
-
import {
|
|
5
|
+
import { ExternalLinkIcon, LinkIcon, LockIcon } from 'lucide-react';
|
|
6
6
|
import { type ReactNode, memo, useCallback, useEffect, useRef, useState } from 'react';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import useSWR from 'swr';
|
|
9
9
|
|
|
10
|
+
import { useAppOrigin } from '@/hooks/useAppOrigin';
|
|
10
11
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
|
11
12
|
import { topicService } from '@/services/topic';
|
|
12
13
|
import { useChatStore } from '@/store/chat';
|
|
@@ -26,6 +27,7 @@ const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) =>
|
|
|
26
27
|
const [updating, setUpdating] = useState(false);
|
|
27
28
|
const { close } = usePopoverContext();
|
|
28
29
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
30
|
+
const appOrigin = useAppOrigin();
|
|
29
31
|
|
|
30
32
|
const activeTopicId = useChatStore((s) => s.activeTopicId);
|
|
31
33
|
|
|
@@ -46,7 +48,7 @@ const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) =>
|
|
|
46
48
|
}
|
|
47
49
|
}, [isLoading, shareInfo, activeTopicId, mutate]);
|
|
48
50
|
|
|
49
|
-
const shareUrl = shareInfo?.id ? `${
|
|
51
|
+
const shareUrl = shareInfo?.id ? `${appOrigin}/share/t/${shareInfo.id}` : '';
|
|
50
52
|
const currentVisibility = (shareInfo?.visibility as Visibility) || 'private';
|
|
51
53
|
|
|
52
54
|
const updateVisibility = useCallback(
|
|
@@ -178,7 +180,7 @@ const SharePopoverContent = memo<SharePopoverContentProps>(({ onOpenModal }) =>
|
|
|
178
180
|
>
|
|
179
181
|
{t('shareModal.popover.moreOptions')}
|
|
180
182
|
</Button>
|
|
181
|
-
<Button icon={
|
|
183
|
+
<Button icon={LinkIcon} onClick={handleCopyLink} size="small" type="primary">
|
|
182
184
|
{t('shareModal.copyLink')}
|
|
183
185
|
</Button>
|
|
184
186
|
</Flexbox>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { isDesktop } from '@lobechat/const';
|
|
4
|
+
|
|
5
|
+
import { useElectronStore } from '@/store/electron';
|
|
6
|
+
import { electronSyncSelectors } from '@/store/electron/selectors';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns the correct app origin URL for sharing/linking.
|
|
10
|
+
* - Web: uses window.location.origin
|
|
11
|
+
* - Desktop: uses remoteServerUrl from electron store
|
|
12
|
+
*/
|
|
13
|
+
export const useAppOrigin = () => {
|
|
14
|
+
const remoteServerUrl = useElectronStore(electronSyncSelectors.remoteServerUrl);
|
|
15
|
+
return isDesktop ? remoteServerUrl : window.location.origin;
|
|
16
|
+
};
|
|
@@ -20,43 +20,51 @@ export const useDesktopUserStateRedirect = () => {
|
|
|
20
20
|
const dataSyncConfig = useElectronStore((s) => s.dataSyncConfig);
|
|
21
21
|
const logout = useUserStore((s) => s.logout);
|
|
22
22
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
const openExternalAndLogout = useCallback(
|
|
24
|
+
async (path: string) => {
|
|
25
|
+
const baseUrl = dataSyncConfig.remoteServerUrl || OFFICIAL_URL;
|
|
26
|
+
let targetUrl = baseUrl;
|
|
27
|
+
try {
|
|
28
|
+
targetUrl = new URL(path, baseUrl).toString();
|
|
29
|
+
} catch {
|
|
30
|
+
// Ignore: keep fallback URL for external open attempt.
|
|
31
|
+
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
try {
|
|
34
|
+
const { electronSystemService } = await import('@/services/electron/system');
|
|
35
|
+
await electronSystemService.openExternalLink(targetUrl);
|
|
36
|
+
} catch {
|
|
37
|
+
// Ignore: fallback to logout flow even if IPC is unavailable.
|
|
38
|
+
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
try {
|
|
41
|
+
const { remoteServerService } = await import('@/services/electron/remoteServer');
|
|
42
|
+
await remoteServerService.clearRemoteServerConfig();
|
|
43
|
+
} catch {
|
|
44
|
+
// Ignore: fallback to logout flow even if IPC is unavailable.
|
|
45
|
+
}
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
await logout();
|
|
48
|
+
},
|
|
49
|
+
[dataSyncConfig.remoteServerUrl, logout],
|
|
50
|
+
);
|
|
48
51
|
|
|
49
52
|
return useCallback(
|
|
50
53
|
(state: UserInitializationState) => {
|
|
51
54
|
if (state.isInWaitList === true) {
|
|
52
|
-
void
|
|
55
|
+
void openExternalAndLogout('/waitlist');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (state.isInviteCodeRequired === true) {
|
|
60
|
+
void openExternalAndLogout('/invite-code');
|
|
53
61
|
return;
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
if (!getDesktopOnboardingCompleted()) return;
|
|
57
65
|
// Desktop onboarding is handled by desktop-only flow.
|
|
58
66
|
},
|
|
59
|
-
[
|
|
67
|
+
[openExternalAndLogout],
|
|
60
68
|
);
|
|
61
69
|
};
|
|
62
70
|
|
|
@@ -68,6 +76,11 @@ export const useWebUserStateRedirect = () =>
|
|
|
68
76
|
return;
|
|
69
77
|
}
|
|
70
78
|
|
|
79
|
+
if (state.isInviteCodeRequired === true) {
|
|
80
|
+
redirectIfNotOn(pathname, '/invite-code');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
71
84
|
if (!onboardingSelectors.needsOnboarding(state)) return;
|
|
72
85
|
|
|
73
86
|
redirectIfNotOn(pathname, '/onboarding');
|
|
@@ -31,14 +31,11 @@ export const generateTrustedClientToken = (userInfo: TrustedClientUserInfo): str
|
|
|
31
31
|
return undefined;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
if (!userInfo.email) {
|
|
35
|
-
return undefined;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
34
|
try {
|
|
39
35
|
const payload = buildTrustedClientPayload({
|
|
40
36
|
clientId: MARKET_TRUSTED_CLIENT_ID,
|
|
41
|
-
|
|
37
|
+
// TODO: remove '' when sdk update
|
|
38
|
+
email: userInfo.email || '',
|
|
42
39
|
name: userInfo.name,
|
|
43
40
|
userId: userInfo.userId,
|
|
44
41
|
});
|
|
@@ -73,6 +73,7 @@ export default {
|
|
|
73
73
|
'screen4.title2': 'Your choice helps us improve',
|
|
74
74
|
'screen4.title3': 'You can change this anytime in settings',
|
|
75
75
|
|
|
76
|
+
'screen5.actions.cancel': 'Cancel',
|
|
76
77
|
'screen5.actions.connectToServer': 'Connect to Server',
|
|
77
78
|
'screen5.actions.connecting': 'Connecting...',
|
|
78
79
|
'screen5.actions.signInCloud': 'Sign in to LobeHub Cloud',
|
|
@@ -80,6 +81,10 @@ export default {
|
|
|
80
81
|
'screen5.actions.signingIn': 'Signing in...',
|
|
81
82
|
'screen5.actions.signingOut': 'Signing out...',
|
|
82
83
|
'screen5.actions.tryAgain': 'Try Again',
|
|
84
|
+
'screen5.auth.phase.browserOpened': 'Browser opened, please sign in...',
|
|
85
|
+
'screen5.auth.phase.verifying': 'Verifying credentials...',
|
|
86
|
+
'screen5.auth.phase.waitingForAuth': 'Waiting for authorization...',
|
|
87
|
+
'screen5.auth.remaining': 'Remaining: {{time}}s',
|
|
83
88
|
'screen5.badge': 'Sign in',
|
|
84
89
|
'screen5.description':
|
|
85
90
|
'Sign in to sync Agents, Groups, settings, and Context across all devices.',
|
|
@@ -16,6 +16,12 @@ export default {
|
|
|
16
16
|
'import.incompatible.description':
|
|
17
17
|
'This file was exported from a higher version. Please try upgrading to the latest version and then re-importing.',
|
|
18
18
|
'import.incompatible.title': 'Current application does not support importing this file',
|
|
19
|
+
'inviteCode.currentEmail': 'Current account: {{email}}',
|
|
20
|
+
'inviteCode.desc':
|
|
21
|
+
'An invite code is required to access LobeHub. Please enter a valid invite code to continue.',
|
|
22
|
+
'inviteCode.friends': 'Friends',
|
|
23
|
+
'inviteCode.getCodeHint': 'Get an invite code from:',
|
|
24
|
+
'inviteCode.title': 'Invite Code Required',
|
|
19
25
|
'loginRequired.desc': 'You will be redirected to the login page shortly',
|
|
20
26
|
'loginRequired.title': 'Please log in to use this feature',
|
|
21
27
|
'notFound.backHome': 'Back to Home',
|
|
@@ -238,5 +244,10 @@ export default {
|
|
|
238
244
|
'upload.title': 'File upload failed. Please check your network connection or try again later',
|
|
239
245
|
'upload.unknownError': 'Error reason: {{reason}}',
|
|
240
246
|
'upload.uploadFailed': 'File upload failed.',
|
|
247
|
+
'waitlist.currentEmail': 'Current account: {{email}}',
|
|
248
|
+
'waitlist.desc':
|
|
249
|
+
'Your account is not on the whitelist. Please contact the administrator to request access.',
|
|
250
|
+
'waitlist.switchAccount': 'Switch Account',
|
|
251
|
+
'waitlist.title': 'Access Restricted',
|
|
241
252
|
...businessErrorsLocales,
|
|
242
253
|
};
|
|
@@ -328,7 +328,7 @@ export default {
|
|
|
328
328
|
'referral.rules.backfill.expiredTip':
|
|
329
329
|
'Backfill period has expired. Cannot backfill after 3 days of registration',
|
|
330
330
|
'referral.rules.backfill.link': 'Backfill Invite Code',
|
|
331
|
-
'referral.rules.backfill.placeholder': 'Enter invite code',
|
|
331
|
+
'referral.rules.backfill.placeholder': 'Enter invite code or link',
|
|
332
332
|
'referral.rules.backfill.submit': 'Confirm Binding',
|
|
333
333
|
'referral.rules.backfill.success': 'Invite code bound successfully',
|
|
334
334
|
'referral.rules.backfill.title': 'Backfill Invite Code',
|
package/src/server/manifest.ts
CHANGED
|
@@ -63,10 +63,10 @@ export class Manifest {
|
|
|
63
63
|
screenshots: screenshots.map((item) => this._getScreenshot(item)),
|
|
64
64
|
short_name: name,
|
|
65
65
|
splash_pages: null,
|
|
66
|
-
start_url: '/
|
|
66
|
+
start_url: '/',
|
|
67
67
|
tab_strip: {
|
|
68
68
|
new_tab_button: {
|
|
69
|
-
url: '/
|
|
69
|
+
url: '/',
|
|
70
70
|
},
|
|
71
71
|
},
|
|
72
72
|
theme_color: color,
|
|
@@ -36,6 +36,7 @@ export interface RuntimeExecutorContext {
|
|
|
36
36
|
stepIndex: number;
|
|
37
37
|
streamManager: IStreamEventManager;
|
|
38
38
|
toolExecutionService: ToolExecutionService;
|
|
39
|
+
topicId?: string;
|
|
39
40
|
userId?: string;
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -475,6 +476,7 @@ export const createRuntimeExecutors = (
|
|
|
475
476
|
const executionResult = await toolExecutionService.executeTool(chatToolPayload, {
|
|
476
477
|
serverDB: ctx.serverDB,
|
|
477
478
|
toolManifestMap: state.toolManifestMap,
|
|
479
|
+
topicId: ctx.topicId,
|
|
478
480
|
userId: ctx.userId,
|
|
479
481
|
});
|
|
480
482
|
|
|
@@ -16,7 +16,12 @@ import { after } from 'next/server';
|
|
|
16
16
|
import { v4 as uuidv4 } from 'uuid';
|
|
17
17
|
import { z } from 'zod';
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
getIsInviteCodeRequired,
|
|
21
|
+
getIsInWaitList,
|
|
22
|
+
getReferralStatus,
|
|
23
|
+
getSubscriptionPlan,
|
|
24
|
+
} from '@/business/server/user';
|
|
20
25
|
import { MessageModel } from '@/database/models/message';
|
|
21
26
|
import { SessionModel } from '@/database/models/session';
|
|
22
27
|
import { UserModel, UserNotFoundError } from '@/database/models/user';
|
|
@@ -129,15 +134,23 @@ export const userRouter = router({
|
|
|
129
134
|
};
|
|
130
135
|
|
|
131
136
|
// Run user state fetch and count queries in parallel
|
|
132
|
-
const [
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
const [
|
|
138
|
+
state,
|
|
139
|
+
messageCount,
|
|
140
|
+
hasExtraSession,
|
|
141
|
+
referralStatus,
|
|
142
|
+
subscriptionPlan,
|
|
143
|
+
isInWaitList,
|
|
144
|
+
isInviteCodeRequired,
|
|
145
|
+
] = await Promise.all([
|
|
146
|
+
getOrCreateUserState(),
|
|
147
|
+
ctx.messageModel.countUpTo(5),
|
|
148
|
+
ctx.sessionModel.hasMoreThanN(1),
|
|
149
|
+
getReferralStatus(ctx.userId),
|
|
150
|
+
getSubscriptionPlan(ctx.userId),
|
|
151
|
+
getIsInWaitList(ctx.userId),
|
|
152
|
+
getIsInviteCodeRequired(ctx.userId),
|
|
153
|
+
]);
|
|
141
154
|
|
|
142
155
|
const hasMoreThan4Messages = messageCount > 4;
|
|
143
156
|
const hasAnyMessages = messageCount > 0;
|
|
@@ -168,6 +181,7 @@ export const userRouter = router({
|
|
|
168
181
|
referralStatus,
|
|
169
182
|
subscriptionPlan,
|
|
170
183
|
isInWaitList,
|
|
184
|
+
isInviteCodeRequired,
|
|
171
185
|
isFreePlan: !subscriptionPlan || subscriptionPlan === Plans.Free,
|
|
172
186
|
} satisfies UserInitializationState;
|
|
173
187
|
/* eslint-enable sort-keys-fix/sort-keys-fix */
|
|
@@ -40,6 +40,9 @@ vi.mock('@/server/modules/ModelRuntime', () => ({
|
|
|
40
40
|
|
|
41
41
|
// Mock search service to avoid server-side env access
|
|
42
42
|
vi.mock('@/server/services/search', () => ({
|
|
43
|
+
SearchService: vi.fn().mockImplementation(() => ({
|
|
44
|
+
search: vi.fn(),
|
|
45
|
+
})),
|
|
43
46
|
searchService: {
|
|
44
47
|
search: vi.fn(),
|
|
45
48
|
},
|
|
@@ -233,6 +233,7 @@ export class AgentRuntimeService {
|
|
|
233
233
|
toolManifestMap,
|
|
234
234
|
toolSourceMap,
|
|
235
235
|
stepCallbacks,
|
|
236
|
+
userInterventionConfig,
|
|
236
237
|
} = params;
|
|
237
238
|
|
|
238
239
|
try {
|
|
@@ -261,6 +262,8 @@ export class AgentRuntimeService {
|
|
|
261
262
|
toolManifestMap,
|
|
262
263
|
toolSourceMap,
|
|
263
264
|
tools,
|
|
265
|
+
// User intervention config for headless mode in async tasks
|
|
266
|
+
userInterventionConfig,
|
|
264
267
|
} as Partial<AgentState>;
|
|
265
268
|
|
|
266
269
|
// Use coordinator to create operation, automatically sends initialization event
|
|
@@ -329,10 +332,7 @@ export class AgentRuntimeService {
|
|
|
329
332
|
});
|
|
330
333
|
|
|
331
334
|
// Get operation state and metadata
|
|
332
|
-
const
|
|
333
|
-
this.coordinator.loadAgentState(operationId),
|
|
334
|
-
this.coordinator.getOperationMetadata(operationId),
|
|
335
|
-
]);
|
|
335
|
+
const agentState = await this.coordinator.loadAgentState(operationId);
|
|
336
336
|
|
|
337
337
|
if (!agentState) {
|
|
338
338
|
throw new Error(`Agent state not found for operation ${operationId}`);
|
|
@@ -353,8 +353,10 @@ export class AgentRuntimeService {
|
|
|
353
353
|
}
|
|
354
354
|
|
|
355
355
|
// Create Agent and Runtime instances
|
|
356
|
+
// Use agentState.metadata which contains the full app context (topicId, agentId, etc.)
|
|
357
|
+
// operationMetadata only contains basic fields (agentConfig, modelRuntimeConfig, userId)
|
|
356
358
|
const { runtime } = await this.createAgentRuntime({
|
|
357
|
-
metadata:
|
|
359
|
+
metadata: agentState?.metadata,
|
|
358
360
|
operationId,
|
|
359
361
|
stepIndex,
|
|
360
362
|
});
|
|
@@ -850,6 +852,7 @@ export class AgentRuntimeService {
|
|
|
850
852
|
stepIndex,
|
|
851
853
|
streamManager: this.streamManager,
|
|
852
854
|
toolExecutionService: this.toolExecutionService,
|
|
855
|
+
topicId: metadata?.topicId,
|
|
853
856
|
userId: metadata?.userId,
|
|
854
857
|
};
|
|
855
858
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type AgentRuntimeContext, type AgentState } from '@lobechat/agent-runtime';
|
|
2
2
|
import { type LobeToolManifest } from '@lobechat/context-engine';
|
|
3
|
+
import type { UserInterventionConfig } from '@lobechat/types';
|
|
3
4
|
|
|
4
5
|
// ==================== Step Lifecycle Callbacks ====================
|
|
5
6
|
|
|
@@ -90,6 +91,12 @@ export interface OperationCreationParams {
|
|
|
90
91
|
toolSourceMap?: Record<string, 'builtin' | 'plugin' | 'mcp' | 'klavis' | 'lobehubSkill'>;
|
|
91
92
|
tools?: any[];
|
|
92
93
|
userId?: string;
|
|
94
|
+
/**
|
|
95
|
+
* User intervention configuration
|
|
96
|
+
* Controls how tools requiring approval are handled
|
|
97
|
+
* Use { approvalMode: 'headless' } for async tasks that should never wait for human approval
|
|
98
|
+
*/
|
|
99
|
+
userInterventionConfig?: UserInterventionConfig;
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
export interface OperationCreationResult {
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
ExecGroupAgentResult,
|
|
9
9
|
ExecSubAgentTaskParams,
|
|
10
10
|
ExecSubAgentTaskResult,
|
|
11
|
+
UserInterventionConfig,
|
|
11
12
|
} from '@lobechat/types';
|
|
12
13
|
import { ThreadStatus, ThreadType } from '@lobechat/types';
|
|
13
14
|
import { nanoid } from '@lobechat/utils';
|
|
@@ -66,6 +67,11 @@ interface InternalExecAgentParams extends ExecAgentParams {
|
|
|
66
67
|
stepCallbacks?: StepLifecycleCallbacks;
|
|
67
68
|
/** Topic creation trigger source ('cron' | 'chat' | 'api') */
|
|
68
69
|
trigger?: string;
|
|
70
|
+
/**
|
|
71
|
+
* User intervention configuration
|
|
72
|
+
* Use { approvalMode: 'headless' } for async tasks that should never wait for human approval
|
|
73
|
+
*/
|
|
74
|
+
userInterventionConfig?: UserInterventionConfig;
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
/**
|
|
@@ -125,6 +131,7 @@ export class AiAgentService {
|
|
|
125
131
|
stepCallbacks,
|
|
126
132
|
trigger,
|
|
127
133
|
cronJobId,
|
|
134
|
+
userInterventionConfig,
|
|
128
135
|
} = params;
|
|
129
136
|
|
|
130
137
|
// Validate that either agentId or slug is provided
|
|
@@ -231,10 +238,6 @@ export class AiAgentService {
|
|
|
231
238
|
|
|
232
239
|
const tools = toolsResult.tools;
|
|
233
240
|
|
|
234
|
-
// Log detailed tools generation result
|
|
235
|
-
if (toolsResult.filteredTools && toolsResult.filteredTools.length > 0) {
|
|
236
|
-
log('execAgent: filtered tools: %O', toolsResult.filteredTools);
|
|
237
|
-
}
|
|
238
241
|
log('execAgent: enabled tool ids: %O', toolsResult.enabledToolIds);
|
|
239
242
|
|
|
240
243
|
// Get manifest map and convert from Map to Record
|
|
@@ -396,6 +399,7 @@ export class AiAgentService {
|
|
|
396
399
|
toolSourceMap,
|
|
397
400
|
tools,
|
|
398
401
|
userId: this.userId,
|
|
402
|
+
userInterventionConfig,
|
|
399
403
|
});
|
|
400
404
|
|
|
401
405
|
log('execAgent: created operation %s (autoStarted: %s)', operationId, result.autoStarted);
|
|
@@ -572,12 +576,14 @@ export class AiAgentService {
|
|
|
572
576
|
|
|
573
577
|
// 4. Delegate to execAgent with threadId in appContext and callbacks
|
|
574
578
|
// The instruction will be created as user message in the Thread
|
|
579
|
+
// Use headless mode to skip human approval in async task execution
|
|
575
580
|
const result = await this.execAgent({
|
|
576
581
|
agentId,
|
|
577
582
|
appContext: { groupId, threadId: thread.id, topicId },
|
|
578
583
|
autoStart: true,
|
|
579
584
|
prompt: instruction,
|
|
580
585
|
stepCallbacks,
|
|
586
|
+
userInterventionConfig: { approvalMode: 'headless' },
|
|
581
587
|
});
|
|
582
588
|
|
|
583
589
|
log(
|
|
@@ -280,6 +280,19 @@ export class MarketService {
|
|
|
280
280
|
return this.market.plugins.callCloudGateway(params, options);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Export file from sandbox to upload URL
|
|
285
|
+
*/
|
|
286
|
+
async exportFile(params: { path: string; topicId: string; uploadUrl: string; userId: string }) {
|
|
287
|
+
const { path, uploadUrl, topicId, userId } = params;
|
|
288
|
+
|
|
289
|
+
return this.market.plugins.runBuildInTool(
|
|
290
|
+
'exportFile',
|
|
291
|
+
{ path, uploadUrl },
|
|
292
|
+
{ topicId, userId },
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
283
296
|
/**
|
|
284
297
|
* Get plugin manifest
|
|
285
298
|
*/
|
|
@@ -368,6 +381,13 @@ export class MarketService {
|
|
|
368
381
|
return this.market.user.getUserInfo(username, options);
|
|
369
382
|
}
|
|
370
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Register user on market and optionally follow another user
|
|
386
|
+
*/
|
|
387
|
+
async registerUser(params: { followUserId?: string; registerUserId: string }): Promise<void> {
|
|
388
|
+
await this.market.user.register(params);
|
|
389
|
+
}
|
|
390
|
+
|
|
371
391
|
// ============================== Skills Methods ==============================
|
|
372
392
|
|
|
373
393
|
/**
|