@lobehub/lobehub 2.0.0-next.312 → 2.0.0-next.313
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 +26 -0
- package/apps/desktop/src/main/controllers/AuthCtr.ts +75 -7
- package/changelog/v1.json +9 -0
- package/docs/usage/providers/internlm.mdx +2 -2
- package/docs/usage/providers/internlm.zh-CN.mdx +3 -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/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/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/features/LoginStep.tsx +84 -26
- package/src/app/[variants]/(main)/_layout/DesktopAutoOidcOnFirstOpen.tsx +4 -0
- 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/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/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 +7 -0
- package/src/server/services/sandbox/index.ts +120 -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 +31 -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/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
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// ==================== File Operations Params ====================
|
|
2
|
+
|
|
3
|
+
export interface ListLocalFilesParams {
|
|
4
|
+
directoryPath: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface ReadLocalFileParams {
|
|
8
|
+
endLine?: number;
|
|
9
|
+
path: string;
|
|
10
|
+
startLine?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface WriteLocalFileParams {
|
|
14
|
+
content: string;
|
|
15
|
+
createDirectories?: boolean;
|
|
16
|
+
path: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface EditLocalFileParams {
|
|
20
|
+
all?: boolean;
|
|
21
|
+
path: string;
|
|
22
|
+
replace: string;
|
|
23
|
+
search: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SearchLocalFilesParams {
|
|
27
|
+
directory: string;
|
|
28
|
+
fileType?: string;
|
|
29
|
+
keyword?: string;
|
|
30
|
+
modifiedAfter?: string;
|
|
31
|
+
modifiedBefore?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface MoveLocalFilesParams {
|
|
35
|
+
operations: Array<{
|
|
36
|
+
destination: string;
|
|
37
|
+
source: string;
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface RenameLocalFileParams {
|
|
42
|
+
newName: string;
|
|
43
|
+
oldPath: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface GlobLocalFilesParams {
|
|
47
|
+
directory?: string;
|
|
48
|
+
pattern: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface ExportFileParams {
|
|
52
|
+
path: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ==================== Code Execution Params ====================
|
|
56
|
+
|
|
57
|
+
export interface ExecuteCodeParams {
|
|
58
|
+
code: string;
|
|
59
|
+
language?: 'javascript' | 'python' | 'typescript';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ==================== Shell Command Params ====================
|
|
63
|
+
|
|
64
|
+
export interface RunCommandParams {
|
|
65
|
+
background?: boolean;
|
|
66
|
+
command: string;
|
|
67
|
+
timeout?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface GetCommandOutputParams {
|
|
71
|
+
commandId: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface KillCommandParams {
|
|
75
|
+
commandId: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ==================== Search & Find Params ====================
|
|
79
|
+
|
|
80
|
+
export interface GrepContentParams {
|
|
81
|
+
directory: string;
|
|
82
|
+
filePattern?: string;
|
|
83
|
+
pattern: string;
|
|
84
|
+
recursive?: boolean;
|
|
85
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// ==================== Sandbox Service Interface ====================
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Result of calling a sandbox tool
|
|
5
|
+
*/
|
|
6
|
+
export interface SandboxCallToolResult {
|
|
7
|
+
error?: { message: string; name?: string };
|
|
8
|
+
result: any;
|
|
9
|
+
sessionExpiredAndRecreated?: boolean;
|
|
10
|
+
success: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Result of exporting and uploading a file from sandbox
|
|
15
|
+
*/
|
|
16
|
+
export interface SandboxExportFileResult {
|
|
17
|
+
error?: { message: string };
|
|
18
|
+
fileId?: string;
|
|
19
|
+
filename: string;
|
|
20
|
+
mimeType?: string;
|
|
21
|
+
size?: number;
|
|
22
|
+
success: boolean;
|
|
23
|
+
url?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Sandbox Service Interface - for dependency injection
|
|
28
|
+
*
|
|
29
|
+
* Context (topicId, userId) is bound at service creation time, not passed per-call.
|
|
30
|
+
* This allows CloudSandboxExecutionRuntime to work on both client and server:
|
|
31
|
+
* - Client: Implemented via tRPC client (codeInterpreterService)
|
|
32
|
+
* - Server: Implemented via MarketSDK directly (ServerSandboxService)
|
|
33
|
+
*/
|
|
34
|
+
export interface ISandboxService {
|
|
35
|
+
/**
|
|
36
|
+
* Call a sandbox tool
|
|
37
|
+
* @param toolName - The name of the tool to call (e.g., 'runCommand', 'writeLocalFile')
|
|
38
|
+
* @param params - The parameters for the tool
|
|
39
|
+
*/
|
|
40
|
+
callTool(toolName: string, params: Record<string, any>): Promise<SandboxCallToolResult>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Export a file from sandbox and upload to cloud storage
|
|
44
|
+
* @param path - The file path in the sandbox
|
|
45
|
+
* @param filename - The name of the file to export
|
|
46
|
+
*/
|
|
47
|
+
exportAndUploadFile(path: string, filename: string): Promise<SandboxExportFileResult>;
|
|
48
|
+
}
|
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API names for Cloud Sandbox tool
|
|
3
|
-
*/
|
|
4
|
-
export const CloudSandboxApiName = {
|
|
5
|
-
editLocalFile: 'editLocalFile',
|
|
6
|
-
executeCode: 'executeCode',
|
|
7
|
-
exportFile: 'exportFile',
|
|
8
|
-
getCommandOutput: 'getCommandOutput',
|
|
9
|
-
globLocalFiles: 'globLocalFiles',
|
|
10
|
-
grepContent: 'grepContent',
|
|
11
|
-
killCommand: 'killCommand',
|
|
12
|
-
listLocalFiles: 'listLocalFiles',
|
|
13
|
-
moveLocalFiles: 'moveLocalFiles',
|
|
14
|
-
readLocalFile: 'readLocalFile',
|
|
15
|
-
renameLocalFile: 'renameLocalFile',
|
|
16
|
-
runCommand: 'runCommand',
|
|
17
|
-
searchLocalFiles: 'searchLocalFiles',
|
|
18
|
-
writeLocalFile: 'writeLocalFile',
|
|
19
|
-
} as const;
|
|
20
|
-
|
|
21
|
-
export type CloudSandboxApiNameType =
|
|
22
|
-
(typeof CloudSandboxApiName)[keyof typeof CloudSandboxApiName];
|
|
23
|
-
|
|
24
1
|
// ==================== File Operations ====================
|
|
25
2
|
|
|
26
3
|
export interface ListLocalFilesState {
|
|
@@ -278,16 +278,16 @@ export const MemoryManifest: BuiltinToolManifest = {
|
|
|
278
278
|
},
|
|
279
279
|
},
|
|
280
280
|
required: [
|
|
281
|
+
'situation',
|
|
282
|
+
'reasoning',
|
|
281
283
|
'action',
|
|
284
|
+
'possibleOutcome',
|
|
282
285
|
'keyLearning',
|
|
283
|
-
'
|
|
286
|
+
'type',
|
|
284
287
|
'labels',
|
|
285
|
-
'possibleOutcome',
|
|
286
288
|
'problemSolvingScore',
|
|
287
|
-
'reasoning',
|
|
288
289
|
'scoreConfidence',
|
|
289
|
-
'
|
|
290
|
-
'type',
|
|
290
|
+
'knowledgeValueScore',
|
|
291
291
|
],
|
|
292
292
|
type: 'object',
|
|
293
293
|
},
|
|
@@ -21,7 +21,7 @@ describe('EditorRuntime - Real Cases', () => {
|
|
|
21
21
|
let mockTitleGetter: ReturnType<typeof vi.fn>;
|
|
22
22
|
|
|
23
23
|
beforeEach(() => {
|
|
24
|
-
editor = new Kernel();
|
|
24
|
+
editor = new Kernel() as unknown as IEditor;
|
|
25
25
|
editor.registerPlugins([CommonPlugin, MarkdownPlugin, ListPlugin, LitexmlPlugin]);
|
|
26
26
|
editor.initNodeEditor();
|
|
27
27
|
|
|
@@ -22,5 +22,9 @@ export type MainBroadcastParams<T extends MainBroadcastEventKey> = Parameters<
|
|
|
22
22
|
MainBroadcastEvents[T]
|
|
23
23
|
>[0];
|
|
24
24
|
|
|
25
|
-
export type {
|
|
25
|
+
export type {
|
|
26
|
+
AuthorizationPhase,
|
|
27
|
+
AuthorizationProgress,
|
|
28
|
+
MarketAuthorizationParams,
|
|
29
|
+
} from './remoteServer';
|
|
26
30
|
export type { OpenSettingsWindowOptions } from './windows';
|
|
@@ -2,11 +2,34 @@ export interface MarketAuthorizationParams {
|
|
|
2
2
|
authUrl: string;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Authorization phase for progress tracking
|
|
7
|
+
*/
|
|
8
|
+
export type AuthorizationPhase =
|
|
9
|
+
| 'browser_opened' // Browser has been opened for authorization
|
|
10
|
+
| 'waiting_for_auth' // Waiting for user to complete browser login
|
|
11
|
+
| 'verifying' // Received credentials, verifying with server
|
|
12
|
+
| 'cancelled'; // Authorization was cancelled by user
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Authorization progress info for UI updates
|
|
16
|
+
*/
|
|
17
|
+
export interface AuthorizationProgress {
|
|
18
|
+
/** Elapsed time in milliseconds since authorization started */
|
|
19
|
+
elapsed: number;
|
|
20
|
+
/** Maximum polling time in milliseconds */
|
|
21
|
+
maxPollTime: number;
|
|
22
|
+
/** Current authorization phase */
|
|
23
|
+
phase: AuthorizationPhase;
|
|
24
|
+
}
|
|
25
|
+
|
|
5
26
|
/**
|
|
6
27
|
* 从主进程广播的远程服务器相关事件
|
|
7
28
|
*/
|
|
8
29
|
export interface RemoteServerBroadcastEvents {
|
|
9
30
|
authorizationFailed: (params: { error: string }) => void;
|
|
31
|
+
/** Broadcast authorization progress for UI updates */
|
|
32
|
+
authorizationProgress: (params: AuthorizationProgress) => void;
|
|
10
33
|
authorizationRequired: (params: void) => void;
|
|
11
34
|
authorizationSuccessful: (params: void) => void;
|
|
12
35
|
remoteServerConfigUpdated: (params: void) => void;
|
|
@@ -14,7 +14,7 @@ const InternLM: ModelProviderCard = {
|
|
|
14
14
|
settings: {
|
|
15
15
|
disableBrowserRequest: true,
|
|
16
16
|
proxyUrl: {
|
|
17
|
-
placeholder: 'https://
|
|
17
|
+
placeholder: 'https://chat.intern-ai.org.cn/api/v1',
|
|
18
18
|
},
|
|
19
19
|
sdkType: 'openai',
|
|
20
20
|
showModelFetcher: true,
|
|
@@ -133,14 +133,6 @@ export interface CreateRouterRuntimeOptions<T extends Record<string, any> = any>
|
|
|
133
133
|
routers: Routers;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
const formatErrorMessage = (error: unknown): string => {
|
|
137
|
-
if (error instanceof Error) {
|
|
138
|
-
return error.name ? `${error.name}: ${error.message}` : error.message;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return String(error);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
136
|
export const createRouterRuntime = ({
|
|
145
137
|
id,
|
|
146
138
|
routers,
|
|
@@ -310,30 +302,28 @@ export const createRouterRuntime = ({
|
|
|
310
302
|
} catch (error) {
|
|
311
303
|
lastError = error;
|
|
312
304
|
|
|
313
|
-
const message = formatErrorMessage(error);
|
|
314
305
|
if (attempt < totalOptions) {
|
|
315
306
|
log(
|
|
316
|
-
'attempt failed
|
|
317
|
-
model,
|
|
307
|
+
'attempt %d/%d failed (model=%s apiType=%s channelId=%s remark=%s), trying next',
|
|
318
308
|
attempt,
|
|
319
309
|
totalOptions,
|
|
310
|
+
model,
|
|
320
311
|
resolvedApiType,
|
|
321
312
|
channelId ?? '',
|
|
322
313
|
remark ?? '',
|
|
323
|
-
message,
|
|
324
314
|
);
|
|
325
315
|
} else {
|
|
326
316
|
log(
|
|
327
|
-
'attempt failed
|
|
328
|
-
model,
|
|
317
|
+
'attempt %d/%d failed (model=%s apiType=%s channelId=%s remark=%s), no more fallbacks',
|
|
329
318
|
attempt,
|
|
330
319
|
totalOptions,
|
|
320
|
+
model,
|
|
331
321
|
resolvedApiType,
|
|
332
322
|
channelId ?? '',
|
|
333
323
|
remark ?? '',
|
|
334
|
-
message,
|
|
335
324
|
);
|
|
336
325
|
}
|
|
326
|
+
console.error(error);
|
|
337
327
|
}
|
|
338
328
|
}
|
|
339
329
|
|
|
@@ -9,7 +9,7 @@ import { LobeInternLMAI, params } from './index';
|
|
|
9
9
|
testProvider({
|
|
10
10
|
Runtime: LobeInternLMAI,
|
|
11
11
|
provider: ModelProvider.InternLM,
|
|
12
|
-
defaultBaseURL: 'https://
|
|
12
|
+
defaultBaseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
13
13
|
chatDebugEnv: 'DEBUG_INTERNLM_CHAT_COMPLETION',
|
|
14
14
|
chatModel: 'internlm2_5-7b-chat',
|
|
15
15
|
test: {
|
|
@@ -30,7 +30,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
30
30
|
|
|
31
31
|
describe('params object', () => {
|
|
32
32
|
it('should export params with correct baseURL', () => {
|
|
33
|
-
expect(params.baseURL).toBe('https://
|
|
33
|
+
expect(params.baseURL).toBe('https://chat.intern-ai.org.cn/api/v1');
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
it('should have correct provider', () => {
|
|
@@ -116,7 +116,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
116
116
|
describe('models', () => {
|
|
117
117
|
it('should fetch and process models', async () => {
|
|
118
118
|
const mockClient = {
|
|
119
|
-
baseURL: 'https://
|
|
119
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
120
120
|
apiKey: 'test',
|
|
121
121
|
models: {
|
|
122
122
|
list: vi.fn().mockResolvedValue({
|
|
@@ -137,7 +137,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
137
137
|
|
|
138
138
|
it('should detect function call capability from model name', async () => {
|
|
139
139
|
const mockClient = {
|
|
140
|
-
baseURL: 'https://
|
|
140
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
141
141
|
apiKey: 'test',
|
|
142
142
|
models: {
|
|
143
143
|
list: vi.fn().mockResolvedValue({
|
|
@@ -156,7 +156,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
156
156
|
|
|
157
157
|
it('should detect vision capability from model name', async () => {
|
|
158
158
|
const mockClient = {
|
|
159
|
-
baseURL: 'https://
|
|
159
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
160
160
|
apiKey: 'test',
|
|
161
161
|
models: {
|
|
162
162
|
list: vi.fn().mockResolvedValue({
|
|
@@ -175,7 +175,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
175
175
|
|
|
176
176
|
it('should handle case-insensitive keyword matching', async () => {
|
|
177
177
|
const mockClient = {
|
|
178
|
-
baseURL: 'https://
|
|
178
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
179
179
|
apiKey: 'test',
|
|
180
180
|
models: {
|
|
181
181
|
list: vi.fn().mockResolvedValue({
|
|
@@ -194,7 +194,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
194
194
|
|
|
195
195
|
it('should merge with known model data from model-bank', async () => {
|
|
196
196
|
const mockClient = {
|
|
197
|
-
baseURL: 'https://
|
|
197
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
198
198
|
apiKey: 'test',
|
|
199
199
|
models: {
|
|
200
200
|
list: vi.fn().mockResolvedValue({
|
|
@@ -215,7 +215,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
215
215
|
|
|
216
216
|
it('should handle models not in model-bank', async () => {
|
|
217
217
|
const mockClient = {
|
|
218
|
-
baseURL: 'https://
|
|
218
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
219
219
|
apiKey: 'test',
|
|
220
220
|
models: {
|
|
221
221
|
list: vi.fn().mockResolvedValue({
|
|
@@ -238,7 +238,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
238
238
|
|
|
239
239
|
it('should set enabled flag from known model', async () => {
|
|
240
240
|
const mockClient = {
|
|
241
|
-
baseURL: 'https://
|
|
241
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
242
242
|
apiKey: 'test',
|
|
243
243
|
models: {
|
|
244
244
|
list: vi.fn().mockResolvedValue({
|
|
@@ -255,7 +255,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
255
255
|
|
|
256
256
|
it('should inherit abilities from known model', async () => {
|
|
257
257
|
const mockClient = {
|
|
258
|
-
baseURL: 'https://
|
|
258
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
259
259
|
apiKey: 'test',
|
|
260
260
|
models: {
|
|
261
261
|
list: vi.fn().mockResolvedValue({
|
|
@@ -291,7 +291,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
291
291
|
|
|
292
292
|
it('should handle empty model list', async () => {
|
|
293
293
|
const mockClient = {
|
|
294
|
-
baseURL: 'https://
|
|
294
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
295
295
|
apiKey: 'test',
|
|
296
296
|
models: {
|
|
297
297
|
list: vi.fn().mockResolvedValue({
|
|
@@ -306,7 +306,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
306
306
|
|
|
307
307
|
it('should filter out null/undefined models', async () => {
|
|
308
308
|
const mockClient = {
|
|
309
|
-
baseURL: 'https://
|
|
309
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
310
310
|
apiKey: 'test',
|
|
311
311
|
models: {
|
|
312
312
|
list: vi.fn().mockResolvedValue({
|
|
@@ -322,7 +322,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
322
322
|
|
|
323
323
|
it('should set contextWindowTokens from known model', async () => {
|
|
324
324
|
const mockClient = {
|
|
325
|
-
baseURL: 'https://
|
|
325
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
326
326
|
apiKey: 'test',
|
|
327
327
|
models: {
|
|
328
328
|
list: vi.fn().mockResolvedValue({
|
|
@@ -340,7 +340,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
340
340
|
|
|
341
341
|
it('should set displayName from known model', async () => {
|
|
342
342
|
const mockClient = {
|
|
343
|
-
baseURL: 'https://
|
|
343
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
344
344
|
apiKey: 'test',
|
|
345
345
|
models: {
|
|
346
346
|
list: vi.fn().mockResolvedValue({
|
|
@@ -358,7 +358,7 @@ describe('LobeInternLMAI - custom features', () => {
|
|
|
358
358
|
|
|
359
359
|
it('should combine keyword detection with known model abilities', async () => {
|
|
360
360
|
const mockClient = {
|
|
361
|
-
baseURL: 'https://
|
|
361
|
+
baseURL: 'https://chat.intern-ai.org.cn/api/v1',
|
|
362
362
|
apiKey: 'test',
|
|
363
363
|
models: {
|
|
364
364
|
list: vi.fn().mockResolvedValue({
|
|
@@ -138,13 +138,15 @@ export interface UserInterventionConfig {
|
|
|
138
138
|
* - auto-run: Automatically approve all tools without user consent
|
|
139
139
|
* - allow-list: Only approve tools in the allow list
|
|
140
140
|
* - manual: Use tool's own humanIntervention config (default)
|
|
141
|
+
* - headless: Fully automated mode for async tasks - all tools execute automatically,
|
|
142
|
+
* security blacklist tools are skipped (not blocked)
|
|
141
143
|
*/
|
|
142
|
-
approvalMode: 'auto-run' | 'allow-list' | 'manual';
|
|
144
|
+
approvalMode: 'auto-run' | 'allow-list' | 'manual' | 'headless';
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
export const UserInterventionConfigSchema = z.object({
|
|
146
148
|
allowList: z.array(z.string()).optional(),
|
|
147
|
-
approvalMode: z.enum(['auto-run', 'allow-list', 'manual']),
|
|
149
|
+
approvalMode: z.enum(['auto-run', 'allow-list', 'manual', 'headless']),
|
|
148
150
|
});
|
|
149
151
|
|
|
150
152
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useWatchBroadcast } from '@lobechat/electron-client-ipc';
|
|
3
|
+
import { AuthorizationProgress, useWatchBroadcast } from '@lobechat/electron-client-ipc';
|
|
4
4
|
import { Alert, Button, Center, Flexbox, Icon, Input, Text } from '@lobehub/ui';
|
|
5
5
|
import { Divider } from 'antd';
|
|
6
6
|
import { cssVar } from 'antd-style';
|
|
@@ -9,6 +9,7 @@ import { memo, useEffect, useState } from 'react';
|
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
|
|
11
11
|
import { isDesktop } from '@/const/version';
|
|
12
|
+
import { remoteServerService } from '@/services/electron/remoteServer';
|
|
12
13
|
import { useElectronStore } from '@/store/electron';
|
|
13
14
|
import { setDesktopAutoOidcFirstOpenHandled } from '@/utils/electron/autoOidc';
|
|
14
15
|
|
|
@@ -44,6 +45,7 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
|
|
44
45
|
const { t } = useTranslation('desktop-onboarding');
|
|
45
46
|
const [endpoint, setEndpoint] = useState('');
|
|
46
47
|
const [cloudLoginStatus, setCloudLoginStatus] = useState<LoginStatus>('idle');
|
|
48
|
+
const [authProgress, setAuthProgress] = useState<AuthorizationProgress | null>(null);
|
|
47
49
|
const [selfhostLoginStatus, setSelfhostLoginStatus] = useState<LoginStatus>('idle');
|
|
48
50
|
const [remoteError, setRemoteError] = useState<string | null>(null);
|
|
49
51
|
const [isSigningOut, setIsSigningOut] = useState(false);
|
|
@@ -164,29 +166,53 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
|
|
164
166
|
useWatchBroadcast('authorizationSuccessful', async () => {
|
|
165
167
|
setRemoteError(null);
|
|
166
168
|
clearRemoteServerSyncError();
|
|
169
|
+
setAuthProgress(null);
|
|
167
170
|
await refreshServerConfig();
|
|
168
171
|
});
|
|
169
172
|
|
|
170
173
|
useWatchBroadcast('authorizationFailed', ({ error }) => {
|
|
171
174
|
setRemoteError(error);
|
|
175
|
+
setAuthProgress(null);
|
|
172
176
|
if (cloudLoginStatus === 'loading') setCloudLoginStatus('error');
|
|
173
177
|
if (selfhostLoginStatus === 'loading') setSelfhostLoginStatus('error');
|
|
174
178
|
});
|
|
175
179
|
|
|
180
|
+
useWatchBroadcast('authorizationProgress', (progress) => {
|
|
181
|
+
setAuthProgress(progress);
|
|
182
|
+
if (progress.phase === 'cancelled') {
|
|
183
|
+
setCloudLoginStatus('idle');
|
|
184
|
+
setAuthProgress(null);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const handleCancelAuth = async () => {
|
|
189
|
+
await remoteServerService.cancelAuthorization();
|
|
190
|
+
setCloudLoginStatus('idle');
|
|
191
|
+
setAuthProgress(null);
|
|
192
|
+
};
|
|
193
|
+
|
|
176
194
|
// 渲染 Cloud 登录内容
|
|
177
195
|
const renderCloudContent = () => {
|
|
178
196
|
if (cloudLoginStatus === 'success') {
|
|
179
197
|
return (
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
198
|
+
<Flexbox gap={12} style={{ width: '100%' }}>
|
|
199
|
+
<Alert
|
|
200
|
+
description={t('authResult.success.desc')}
|
|
201
|
+
style={{ width: '100%' }}
|
|
202
|
+
title={t('authResult.success.title')}
|
|
203
|
+
type={'success'}
|
|
204
|
+
/>
|
|
205
|
+
<Button
|
|
206
|
+
block
|
|
207
|
+
disabled={isSigningOut || isConnectingServer}
|
|
208
|
+
icon={Cloud}
|
|
209
|
+
onClick={handleSignOut}
|
|
210
|
+
size={'large'}
|
|
211
|
+
type={'default'}
|
|
212
|
+
>
|
|
213
|
+
{isSigningOut ? t('screen5.actions.signingOut') : t('screen5.actions.signOut')}
|
|
214
|
+
</Button>
|
|
215
|
+
</Flexbox>
|
|
190
216
|
);
|
|
191
217
|
}
|
|
192
218
|
|
|
@@ -212,19 +238,43 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
|
|
212
238
|
);
|
|
213
239
|
}
|
|
214
240
|
|
|
241
|
+
if (cloudLoginStatus === 'loading') {
|
|
242
|
+
return (
|
|
243
|
+
<Flexbox gap={8} style={{ width: '100%' }}>
|
|
244
|
+
<Button block disabled={true} icon={Cloud} loading={true} size={'large'} type={'primary'}>
|
|
245
|
+
{authProgress
|
|
246
|
+
? t(`screen5.auth.phase.${authProgress.phase}`, {
|
|
247
|
+
defaultValue: t('screen5.actions.signingIn'),
|
|
248
|
+
})
|
|
249
|
+
: t('screen5.actions.signingIn')}
|
|
250
|
+
</Button>
|
|
251
|
+
{authProgress && (
|
|
252
|
+
<Flexbox align={'center'} horizontal justify={'space-between'}>
|
|
253
|
+
<Text style={{ color: cssVar.colorTextDescription }} type={'secondary'}>
|
|
254
|
+
{t('screen5.auth.remaining', {
|
|
255
|
+
time: Math.round((authProgress.maxPollTime - authProgress.elapsed) / 1000),
|
|
256
|
+
})}
|
|
257
|
+
</Text>
|
|
258
|
+
<Button onClick={handleCancelAuth} size={'small'} type={'text'}>
|
|
259
|
+
{t('screen5.actions.cancel')}
|
|
260
|
+
</Button>
|
|
261
|
+
</Flexbox>
|
|
262
|
+
)}
|
|
263
|
+
</Flexbox>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
215
267
|
return (
|
|
216
268
|
<Button
|
|
217
269
|
block
|
|
218
|
-
disabled={
|
|
270
|
+
disabled={isConnectingServer}
|
|
219
271
|
icon={Cloud}
|
|
220
|
-
loading={
|
|
272
|
+
loading={false}
|
|
221
273
|
onClick={handleCloudLogin}
|
|
222
274
|
size={'large'}
|
|
223
275
|
type={'primary'}
|
|
224
276
|
>
|
|
225
|
-
{
|
|
226
|
-
? t('screen5.actions.signingIn')
|
|
227
|
-
: t('screen5.actions.signInCloud')}
|
|
277
|
+
{t('screen5.actions.signInCloud')}
|
|
228
278
|
</Button>
|
|
229
279
|
);
|
|
230
280
|
};
|
|
@@ -233,16 +283,24 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
|
|
233
283
|
const renderSelfhostContent = () => {
|
|
234
284
|
if (selfhostLoginStatus === 'success') {
|
|
235
285
|
return (
|
|
236
|
-
<
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
286
|
+
<Flexbox gap={12} style={{ width: '100%' }}>
|
|
287
|
+
<Alert
|
|
288
|
+
description={t('authResult.success.desc')}
|
|
289
|
+
style={{ width: '100%' }}
|
|
290
|
+
title={t('authResult.success.title')}
|
|
291
|
+
type={'success'}
|
|
292
|
+
/>
|
|
293
|
+
<Button
|
|
294
|
+
block
|
|
295
|
+
disabled={isSigningOut || isConnectingServer}
|
|
296
|
+
icon={Server}
|
|
297
|
+
onClick={handleSignOut}
|
|
298
|
+
size={'large'}
|
|
299
|
+
type={'default'}
|
|
300
|
+
>
|
|
301
|
+
{isSigningOut ? t('screen5.actions.signingOut') : t('screen5.actions.signOut')}
|
|
302
|
+
</Button>
|
|
303
|
+
</Flexbox>
|
|
246
304
|
);
|
|
247
305
|
}
|
|
248
306
|
|