@lobehub/lobehub 2.0.0-next.51 → 2.0.0-next.52
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 +25 -0
- package/apps/desktop/src/main/controllers/LocalFileCtr.ts +25 -5
- package/apps/desktop/src/main/controllers/__tests__/LocalFileCtr.test.ts +4 -1
- package/apps/desktop/src/main/modules/fileSearch/__tests__/macOS.integration.test.ts +357 -0
- package/apps/desktop/src/main/modules/fileSearch/impl/macOS.ts +30 -22
- package/changelog/v1.json +9 -0
- package/locales/ar/models.json +119 -126
- package/locales/ar/plugin.json +1 -1
- package/locales/bg-BG/models.json +104 -132
- package/locales/bg-BG/plugin.json +1 -1
- package/locales/de-DE/models.json +119 -126
- package/locales/de-DE/plugin.json +1 -1
- package/locales/en-US/models.json +167 -126
- package/locales/en-US/plugin.json +1 -1
- package/locales/es-ES/models.json +119 -126
- package/locales/es-ES/plugin.json +1 -1
- package/locales/fa-IR/models.json +119 -126
- package/locales/fa-IR/plugin.json +1 -1
- package/locales/fr-FR/models.json +119 -126
- package/locales/fr-FR/plugin.json +1 -1
- package/locales/it-IT/models.json +119 -126
- package/locales/it-IT/plugin.json +1 -1
- package/locales/ja-JP/models.json +119 -126
- package/locales/ja-JP/plugin.json +1 -1
- package/locales/ko-KR/models.json +119 -126
- package/locales/ko-KR/plugin.json +1 -1
- package/locales/nl-NL/models.json +119 -126
- package/locales/nl-NL/plugin.json +1 -1
- package/locales/pl-PL/models.json +119 -126
- package/locales/pl-PL/plugin.json +1 -1
- package/locales/pt-BR/models.json +119 -126
- package/locales/pt-BR/plugin.json +1 -1
- package/locales/ru-RU/models.json +119 -126
- package/locales/ru-RU/plugin.json +1 -1
- package/locales/tr-TR/models.json +119 -126
- package/locales/tr-TR/plugin.json +1 -1
- package/locales/vi-VN/models.json +119 -126
- package/locales/vi-VN/plugin.json +1 -1
- package/locales/zh-CN/models.json +173 -80
- package/locales/zh-CN/plugin.json +1 -1
- package/locales/zh-TW/models.json +119 -126
- package/locales/zh-TW/plugin.json +1 -1
- package/package.json +1 -1
- package/packages/electron-client-ipc/src/types/localSystem.ts +26 -2
- package/packages/model-runtime/src/core/contextBuilders/openai.test.ts +58 -0
- package/packages/model-runtime/src/core/contextBuilders/openai.ts +24 -10
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +3 -2
- package/packages/model-runtime/src/providers/openai/index.test.ts +44 -0
- package/packages/types/src/tool/builtin.ts +6 -4
- package/src/features/Conversation/Messages/Assistant/Tool/Render/LoadingPlaceholder/index.tsx +3 -3
- package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/index.tsx +2 -2
- package/src/features/Conversation/Messages/Group/Tool/Render/LoadingPlaceholder/index.tsx +3 -3
- package/src/features/PluginsUI/Render/BuiltinType/index.test.tsx +10 -4
- package/src/features/PluginsUI/Render/BuiltinType/index.tsx +2 -2
- package/src/locales/default/plugin.ts +1 -1
- package/src/services/chat/chat.test.ts +1 -0
- package/src/store/aiInfra/slices/aiProvider/__tests__/selectors.test.ts +62 -0
- package/src/store/aiInfra/slices/aiProvider/selectors.ts +1 -1
- package/src/tools/code-interpreter/Render/index.tsx +1 -1
- package/src/tools/interventions.ts +28 -4
- package/src/tools/local-system/Placeholder/ListFiles.tsx +3 -5
- package/src/tools/local-system/Placeholder/SearchFiles.tsx +2 -5
- package/src/tools/local-system/Render/ListFiles/index.tsx +16 -21
- package/src/tools/local-system/Render/RenameLocalFile/index.tsx +15 -20
- package/src/tools/local-system/Render/RunCommand/index.tsx +67 -70
- package/src/tools/local-system/Render/SearchFiles/SearchQuery/index.tsx +0 -1
- package/src/tools/local-system/Render/SearchFiles/index.tsx +15 -20
- package/src/tools/local-system/Render/WriteFile/index.tsx +2 -8
- package/src/tools/local-system/index.ts +4 -4
- package/src/tools/local-system/systemRole.ts +1 -1
- package/src/tools/placeholders.ts +39 -8
- package/src/tools/renders.ts +56 -9
- package/src/tools/web-browsing/Placeholder/{PageContent.tsx → CrawlMultiPages.tsx} +4 -1
- package/src/tools/web-browsing/Placeholder/CrawlSinglePage.tsx +12 -0
- package/src/tools/web-browsing/Placeholder/Search.tsx +4 -4
- package/src/tools/web-browsing/Render/CrawlMultiPages.tsx +15 -0
- package/src/tools/web-browsing/Render/CrawlSinglePage.tsx +15 -0
- package/src/tools/web-browsing/Render/Search/index.tsx +39 -44
- package/packages/database/migrations/0044_add_tool_intervention.sql +0 -1
- package/src/tools/local-system/Intervention/index.tsx +0 -17
- package/src/tools/local-system/Placeholder/index.tsx +0 -25
- package/src/tools/local-system/Render/index.tsx +0 -42
- package/src/tools/web-browsing/Placeholder/index.tsx +0 -40
- package/src/tools/web-browsing/Render/index.tsx +0 -57
|
@@ -409,6 +409,50 @@ describe('LobeOpenAI', () => {
|
|
|
409
409
|
const createCall = (instance['client'].responses.create as Mock).mock.calls[0][0];
|
|
410
410
|
expect(createCall.reasoning).toEqual({ effort: 'high', summary: 'auto' });
|
|
411
411
|
});
|
|
412
|
+
|
|
413
|
+
it('should convert max_tokens to max_output_tokens for responses API', async () => {
|
|
414
|
+
const payload = {
|
|
415
|
+
max_tokens: 2048,
|
|
416
|
+
messages: [{ content: 'Hello', role: 'user' as const }],
|
|
417
|
+
model: 'o1-pro',
|
|
418
|
+
temperature: 0.7,
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
await instance.chat(payload);
|
|
422
|
+
|
|
423
|
+
const createCall = (instance['client'].responses.create as Mock).mock.calls[0][0];
|
|
424
|
+
expect(createCall.max_output_tokens).toBe(2048);
|
|
425
|
+
expect(createCall.max_tokens).toBeUndefined();
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('should not include max_output_tokens when max_tokens is undefined', async () => {
|
|
429
|
+
const payload = {
|
|
430
|
+
messages: [{ content: 'Hello', role: 'user' as const }],
|
|
431
|
+
model: 'o1-pro',
|
|
432
|
+
temperature: 0.7,
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
await instance.chat(payload);
|
|
436
|
+
|
|
437
|
+
const createCall = (instance['client'].responses.create as Mock).mock.calls[0][0];
|
|
438
|
+
expect(createCall.max_output_tokens).toBeUndefined();
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it('should convert max_tokens to max_output_tokens for search-enabled models', async () => {
|
|
442
|
+
const payload = {
|
|
443
|
+
enabledSearch: true,
|
|
444
|
+
max_tokens: 4096,
|
|
445
|
+
messages: [{ content: 'Hello', role: 'user' as const }],
|
|
446
|
+
model: 'gpt-4o',
|
|
447
|
+
temperature: 0.7,
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
await instance.chat(payload);
|
|
451
|
+
|
|
452
|
+
const createCall = (instance['client'].responses.create as Mock).mock.calls[0][0];
|
|
453
|
+
expect(createCall.max_output_tokens).toBe(4096);
|
|
454
|
+
expect(createCall.max_tokens).toBeUndefined();
|
|
455
|
+
});
|
|
412
456
|
});
|
|
413
457
|
|
|
414
458
|
describe('supportsFlexTier', () => {
|
|
@@ -115,7 +115,7 @@ export const LobeBuiltinToolSchema = z.object({
|
|
|
115
115
|
type: z.literal('builtin'),
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
export interface BuiltinRenderProps<
|
|
118
|
+
export interface BuiltinRenderProps<Arguments = any, State = any, Content = any> {
|
|
119
119
|
apiName?: string;
|
|
120
120
|
args: Arguments;
|
|
121
121
|
content: Content;
|
|
@@ -125,7 +125,9 @@ export interface BuiltinRenderProps<Content = any, Arguments = any, State = any>
|
|
|
125
125
|
pluginState?: State;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
export type BuiltinRender = <
|
|
128
|
+
export type BuiltinRender = <A = any, S = any, C = any>(
|
|
129
|
+
props: BuiltinRenderProps<A, S, C>,
|
|
130
|
+
) => ReactNode;
|
|
129
131
|
|
|
130
132
|
export interface BuiltinPortalProps<Arguments = Record<string, any>, State = any> {
|
|
131
133
|
apiName?: string;
|
|
@@ -137,9 +139,9 @@ export interface BuiltinPortalProps<Arguments = Record<string, any>, State = any
|
|
|
137
139
|
|
|
138
140
|
export type BuiltinPortal = <T = any>(props: BuiltinPortalProps<T>) => ReactNode;
|
|
139
141
|
|
|
140
|
-
export interface BuiltinPlaceholderProps {
|
|
142
|
+
export interface BuiltinPlaceholderProps<T extends Record<string, any> = any> {
|
|
141
143
|
apiName: string;
|
|
142
|
-
args?:
|
|
144
|
+
args?: T;
|
|
143
145
|
identifier: string;
|
|
144
146
|
}
|
|
145
147
|
|
package/src/features/Conversation/Messages/Assistant/Tool/Render/LoadingPlaceholder/index.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { safeParseJSON } from '@lobechat/utils';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getBuiltinPlaceholder } from '@/tools/placeholders';
|
|
5
5
|
|
|
6
6
|
import Arguments from '../Arguments';
|
|
7
7
|
|
|
@@ -14,9 +14,9 @@ interface LoadingPlaceholderProps {
|
|
|
14
14
|
|
|
15
15
|
const LoadingPlaceholder = memo<LoadingPlaceholderProps>(
|
|
16
16
|
({ identifier, requestArgs, apiName, loading }) => {
|
|
17
|
-
const Render =
|
|
17
|
+
const Render = getBuiltinPlaceholder(identifier, apiName);
|
|
18
18
|
|
|
19
|
-
if (
|
|
19
|
+
if (Render) {
|
|
20
20
|
return (
|
|
21
21
|
<Render apiName={apiName} args={safeParseJSON(requestArgs) || {}} identifier={identifier} />
|
|
22
22
|
);
|
|
@@ -5,7 +5,7 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
5
5
|
import { useChatStore } from '@/store/chat';
|
|
6
6
|
import { useUserStore } from '@/store/user';
|
|
7
7
|
import { toolInterventionSelectors } from '@/store/user/selectors';
|
|
8
|
-
import {
|
|
8
|
+
import { getBuiltinIntervention } from '@/tools/interventions';
|
|
9
9
|
|
|
10
10
|
import Arguments from '../Arguments';
|
|
11
11
|
import ApprovalActions from './ApprovalActions';
|
|
@@ -52,7 +52,7 @@ const Intervention = memo<InterventionProps>(
|
|
|
52
52
|
},
|
|
53
53
|
[requestArgs, id],
|
|
54
54
|
);
|
|
55
|
-
const BuiltinToolInterventionRender =
|
|
55
|
+
const BuiltinToolInterventionRender = getBuiltinIntervention(identifier, apiName);
|
|
56
56
|
|
|
57
57
|
if (BuiltinToolInterventionRender) {
|
|
58
58
|
if (isEditing)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { safeParseJSON } from '@lobechat/utils';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getBuiltinPlaceholder } from '@/tools/placeholders';
|
|
5
5
|
|
|
6
6
|
import Arguments from '../Arguments';
|
|
7
7
|
|
|
@@ -14,9 +14,9 @@ interface LoadingPlaceholderProps {
|
|
|
14
14
|
|
|
15
15
|
const LoadingPlaceholder = memo<LoadingPlaceholderProps>(
|
|
16
16
|
({ identifier, requestArgs, apiName, loading }) => {
|
|
17
|
-
const Render =
|
|
17
|
+
const Render = getBuiltinPlaceholder(identifier, apiName);
|
|
18
18
|
|
|
19
|
-
if (
|
|
19
|
+
if (Render) {
|
|
20
20
|
return (
|
|
21
21
|
<Render apiName={apiName} args={safeParseJSON(requestArgs) || {}} identifier={identifier} />
|
|
22
22
|
);
|
|
@@ -4,11 +4,17 @@ import { describe, expect, it, vi } from 'vitest';
|
|
|
4
4
|
import BuiltinType from './index';
|
|
5
5
|
|
|
6
6
|
// Mock renders module
|
|
7
|
+
const mockWebBrowsingRender = vi.fn(({ content }) => <div>WebBrowsingRender: {content}</div>);
|
|
8
|
+
const mockCodeInterpreterRender = vi.fn(({ content }) => (
|
|
9
|
+
<div>CodeInterpreterRender: {content}</div>
|
|
10
|
+
));
|
|
11
|
+
|
|
7
12
|
vi.mock('@/tools/renders', () => ({
|
|
8
|
-
|
|
9
|
-
'lobe-web-browsing'
|
|
10
|
-
'lobe-code-interpreter'
|
|
11
|
-
|
|
13
|
+
getBuiltinRender: vi.fn((identifier, apiName) => {
|
|
14
|
+
if (identifier === 'lobe-web-browsing') return mockWebBrowsingRender;
|
|
15
|
+
if (identifier === 'lobe-code-interpreter') return mockCodeInterpreterRender;
|
|
16
|
+
return undefined;
|
|
17
|
+
}),
|
|
12
18
|
}));
|
|
13
19
|
|
|
14
20
|
// Mock useParseContent hook
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { safeParseJSON } from '@lobechat/utils';
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getBuiltinRender } from '@/tools/renders';
|
|
5
5
|
|
|
6
6
|
import { useParseContent } from '../useParseContent';
|
|
7
7
|
|
|
@@ -28,7 +28,7 @@ const BuiltinType = memo<BuiltinTypeProps>(
|
|
|
28
28
|
}) => {
|
|
29
29
|
const { data } = useParseContent(content);
|
|
30
30
|
|
|
31
|
-
const Render =
|
|
31
|
+
const Render = getBuiltinRender(identifier, apiName);
|
|
32
32
|
|
|
33
33
|
if (!Render) return;
|
|
34
34
|
|
|
@@ -246,4 +246,66 @@ describe('aiProviderSelectors', () => {
|
|
|
246
246
|
);
|
|
247
247
|
});
|
|
248
248
|
});
|
|
249
|
+
|
|
250
|
+
describe('isProviderEnableResponseApi', () => {
|
|
251
|
+
it('should return true when config explicitly sets enableResponseApi to true', () => {
|
|
252
|
+
const state = {
|
|
253
|
+
...mockState,
|
|
254
|
+
aiProviderRuntimeConfig: {
|
|
255
|
+
test: {
|
|
256
|
+
config: { enableResponseApi: true },
|
|
257
|
+
keyVaults: {},
|
|
258
|
+
settings: {},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('test')(state)).toBe(true);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should return false when config explicitly sets enableResponseApi to false', () => {
|
|
266
|
+
const state = {
|
|
267
|
+
...mockState,
|
|
268
|
+
aiProviderRuntimeConfig: {
|
|
269
|
+
test: {
|
|
270
|
+
config: { enableResponseApi: false },
|
|
271
|
+
keyVaults: {},
|
|
272
|
+
settings: {},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('test')(state)).toBe(false);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('should return true by default for openai provider', () => {
|
|
280
|
+
const state = {
|
|
281
|
+
...mockState,
|
|
282
|
+
aiProviderRuntimeConfig: {
|
|
283
|
+
openai: {
|
|
284
|
+
keyVaults: {},
|
|
285
|
+
settings: {},
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('openai')(state)).toBe(true);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
it('should return false by default for non-openai provider', () => {
|
|
293
|
+
const state = {
|
|
294
|
+
...mockState,
|
|
295
|
+
aiProviderRuntimeConfig: {
|
|
296
|
+
anthropic: {
|
|
297
|
+
keyVaults: {},
|
|
298
|
+
settings: {},
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('anthropic')(state)).toBe(false);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should return false for provider without config', () => {
|
|
306
|
+
expect(aiProviderSelectors.isProviderEnableResponseApi('non-existing')(mockState)).toBe(
|
|
307
|
+
false,
|
|
308
|
+
);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
249
311
|
});
|
|
@@ -108,7 +108,7 @@ const isProviderEnableResponseApi = (id: string) => (s: AIProviderStoreState) =>
|
|
|
108
108
|
|
|
109
109
|
if (typeof enableResponseApi === 'boolean') return enableResponseApi;
|
|
110
110
|
|
|
111
|
-
return
|
|
111
|
+
return id === 'openai';
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
const isInitAiProviderRuntimeState = (s: AIProviderStoreState) => !!s.isInitAiProviderRuntimeState;
|
|
@@ -17,7 +17,7 @@ import { chatToolSelectors } from '@/store/chat/slices/builtinTool/selectors';
|
|
|
17
17
|
import ResultFileGallery from './components/ResultFileGallery';
|
|
18
18
|
|
|
19
19
|
const CodeInterpreter = memo<
|
|
20
|
-
BuiltinRenderProps<
|
|
20
|
+
BuiltinRenderProps<CodeInterpreterParams, CodeInterpreterState, CodeInterpreterResponse>
|
|
21
21
|
>(({ content, args, pluginState, messageId, apiName }) => {
|
|
22
22
|
const { t } = useTranslation('tool');
|
|
23
23
|
const theme = useTheme();
|
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
import { BuiltinIntervention } from '@lobechat/types';
|
|
2
2
|
|
|
3
|
-
import { LocalSystemManifest } from './local-system';
|
|
4
|
-
import
|
|
3
|
+
import { LocalSystemApiName, LocalSystemManifest } from './local-system';
|
|
4
|
+
import RunCommand from './local-system/Intervention/RunCommand';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Builtin tools interventions registry
|
|
8
|
+
* Organized by toolset (identifier) -> API name
|
|
9
|
+
* Only register APIs that have custom intervention UI
|
|
10
|
+
*/
|
|
11
|
+
export const BuiltinToolInterventions: Record<string, Record<string, any>> = {
|
|
12
|
+
[LocalSystemManifest.identifier]: {
|
|
13
|
+
[LocalSystemApiName.runCommand]: RunCommand,
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Get builtin intervention component for a specific API
|
|
19
|
+
* @param identifier - Tool identifier (e.g., 'lobe-local-system')
|
|
20
|
+
* @param apiName - API name (e.g., 'runCommand')
|
|
21
|
+
*/
|
|
22
|
+
export const getBuiltinIntervention = (
|
|
23
|
+
identifier?: string,
|
|
24
|
+
apiName?: string,
|
|
25
|
+
): BuiltinIntervention | undefined => {
|
|
26
|
+
if (!identifier || !apiName) return undefined;
|
|
27
|
+
|
|
28
|
+
const toolset = BuiltinToolInterventions[identifier];
|
|
29
|
+
if (!toolset) return undefined;
|
|
30
|
+
|
|
31
|
+
return toolset[apiName];
|
|
8
32
|
};
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { ListLocalFileParams } from '@lobechat/electron-client-ipc';
|
|
2
|
+
import { BuiltinPlaceholderProps } from '@lobechat/types';
|
|
2
3
|
import { Skeleton } from 'antd';
|
|
3
4
|
import React, { memo } from 'react';
|
|
4
5
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
5
6
|
|
|
6
7
|
import { LocalFolder } from '@/features/LocalFile';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
args: ListLocalFileParams;
|
|
10
|
-
}
|
|
11
|
-
export const ListFiles = memo<ListFilesProps>(({ args }) => {
|
|
9
|
+
export const ListFiles = memo<BuiltinPlaceholderProps<ListLocalFileParams>>(({ args }) => {
|
|
12
10
|
return (
|
|
13
11
|
<Flexbox gap={12}>
|
|
14
|
-
<LocalFolder path={args.path} />
|
|
12
|
+
{args?.path && <LocalFolder path={args.path} />}
|
|
15
13
|
<Center height={140}>
|
|
16
14
|
<Flexbox gap={4} width={'90%'}>
|
|
17
15
|
<Skeleton.Button active block style={{ height: 16 }} />
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LocalSearchFilesParams } from '@lobechat/electron-client-ipc';
|
|
2
|
+
import { BuiltinPlaceholderProps } from '@lobechat/types';
|
|
2
3
|
import { Icon } from '@lobehub/ui';
|
|
3
4
|
import { Skeleton } from 'antd';
|
|
4
5
|
import { createStyles } from 'antd-style';
|
|
@@ -21,11 +22,7 @@ const useStyles = createStyles(({ css, token, cx }) => ({
|
|
|
21
22
|
`),
|
|
22
23
|
}));
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
args: LocalSearchFilesParams;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const SearchFiles = memo<SearchFilesProps>(({ args }) => {
|
|
25
|
+
const SearchFiles = memo<BuiltinPlaceholderProps<LocalSearchFilesParams>>(({ args = {} }) => {
|
|
29
26
|
const { styles } = useStyles();
|
|
30
27
|
|
|
31
28
|
return (
|
|
@@ -1,31 +1,26 @@
|
|
|
1
1
|
import { ListLocalFileParams } from '@lobechat/electron-client-ipc';
|
|
2
|
-
import {
|
|
2
|
+
import { BuiltinRenderProps } from '@lobechat/types';
|
|
3
3
|
import React, { memo } from 'react';
|
|
4
4
|
|
|
5
5
|
import { LocalFolder } from '@/features/LocalFile';
|
|
6
|
-
import { LocalFileListState } from '@/tools/local-system/type';
|
|
7
6
|
|
|
7
|
+
import { LocalFileListState } from '../../type';
|
|
8
8
|
import SearchResult from './Result';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
args
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
pluginError={pluginError}
|
|
25
|
-
/>
|
|
26
|
-
</>
|
|
27
|
-
);
|
|
28
|
-
});
|
|
10
|
+
const ListFiles = memo<BuiltinRenderProps<ListLocalFileParams, LocalFileListState>>(
|
|
11
|
+
({ messageId, pluginError, args, pluginState }) => {
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<LocalFolder path={args.path} />
|
|
15
|
+
<SearchResult
|
|
16
|
+
listResults={pluginState?.listResults}
|
|
17
|
+
messageId={messageId}
|
|
18
|
+
pluginError={pluginError}
|
|
19
|
+
/>
|
|
20
|
+
</>
|
|
21
|
+
);
|
|
22
|
+
},
|
|
23
|
+
);
|
|
29
24
|
|
|
30
25
|
ListFiles.displayName = 'ListFiles';
|
|
31
26
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RenameLocalFileParams } from '@lobechat/electron-client-ipc';
|
|
2
|
-
import {
|
|
2
|
+
import { BuiltinRenderProps } from '@lobechat/types';
|
|
3
3
|
import { Icon } from '@lobehub/ui';
|
|
4
4
|
import { createStyles } from 'antd-style';
|
|
5
5
|
import { ArrowRightIcon } from 'lucide-react';
|
|
@@ -19,27 +19,22 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
19
19
|
`,
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
args
|
|
24
|
-
|
|
25
|
-
pluginError: ChatMessagePluginError;
|
|
26
|
-
pluginState: LocalReadFileState;
|
|
27
|
-
}
|
|
22
|
+
const RenameLocalFile = memo<BuiltinRenderProps<RenameLocalFileParams, LocalReadFileState>>(
|
|
23
|
+
({ args }) => {
|
|
24
|
+
const { styles } = useStyles();
|
|
28
25
|
|
|
29
|
-
const
|
|
30
|
-
const { styles } = useStyles();
|
|
26
|
+
const { base: oldFileName, dir } = path.parse(args.path);
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<
|
|
28
|
+
return (
|
|
29
|
+
<Flexbox align={'center'} className={styles.container} gap={8} horizontal paddingInline={12}>
|
|
30
|
+
<Flexbox>{oldFileName}</Flexbox>
|
|
31
|
+
<Flexbox>
|
|
32
|
+
<Icon icon={ArrowRightIcon} />
|
|
33
|
+
</Flexbox>
|
|
34
|
+
<LocalFile name={args.newName} path={path.join(dir, args.newName)} />
|
|
39
35
|
</Flexbox>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
);
|
|
44
39
|
|
|
45
40
|
export default RenameLocalFile;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons';
|
|
2
2
|
import { RunCommandParams, RunCommandResult } from '@lobechat/electron-client-ipc';
|
|
3
|
-
import {
|
|
3
|
+
import { BuiltinRenderProps } from '@lobechat/types';
|
|
4
4
|
import { ActionIcon, Block, Highlighter, Text } from '@lobehub/ui';
|
|
5
5
|
import { createStyles } from 'antd-style';
|
|
6
6
|
import { ChevronDown, ChevronUp } from 'lucide-react';
|
|
@@ -33,82 +33,79 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
33
33
|
`,
|
|
34
34
|
}));
|
|
35
35
|
|
|
36
|
-
interface
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
pluginError: ChatMessagePluginError;
|
|
40
|
-
pluginState: {
|
|
41
|
-
message: string;
|
|
42
|
-
result: RunCommandResult;
|
|
43
|
-
};
|
|
36
|
+
interface RunCommandState {
|
|
37
|
+
message: string;
|
|
38
|
+
result: RunCommandResult;
|
|
44
39
|
}
|
|
45
40
|
|
|
46
|
-
const RunCommand = memo<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
const RunCommand = memo<BuiltinRenderProps<RunCommandParams, RunCommandState>>(
|
|
42
|
+
({ args, pluginState }) => {
|
|
43
|
+
const { styles, theme } = useStyles();
|
|
44
|
+
const { result, message } = pluginState || {};
|
|
45
|
+
const isSuccess = result?.success;
|
|
46
|
+
const [expanded, setExpanded] = useState(false);
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
48
|
+
return (
|
|
49
|
+
<Flexbox className={styles.container} gap={8}>
|
|
50
|
+
{/* Header: Description + Status */}
|
|
51
|
+
<Flexbox align={'center'} className={styles.header} horizontal justify={'space-between'}>
|
|
52
|
+
<Flexbox gap={8} horizontal>
|
|
53
|
+
<Flexbox gap={4} horizontal>
|
|
54
|
+
{!result ? null : isSuccess ? (
|
|
55
|
+
<CheckCircleFilled
|
|
56
|
+
className={styles.statusIcon}
|
|
57
|
+
style={{ color: theme.colorSuccess }}
|
|
58
|
+
/>
|
|
59
|
+
) : (
|
|
60
|
+
<CloseCircleFilled
|
|
61
|
+
className={styles.statusIcon}
|
|
62
|
+
style={{ color: theme.colorError }}
|
|
63
|
+
/>
|
|
64
|
+
)}
|
|
65
|
+
{args.description && <Text className={styles.head}>{args.description}</Text>}
|
|
66
|
+
</Flexbox>
|
|
67
|
+
{message && (
|
|
68
|
+
<Flexbox align={'center'} gap={4} horizontal>
|
|
69
|
+
<Text className={styles.head} type={'secondary'}>
|
|
70
|
+
{message}
|
|
71
|
+
</Text>
|
|
72
|
+
</Flexbox>
|
|
68
73
|
)}
|
|
69
|
-
{args.description && <Text className={styles.head}>{args.description}</Text>}
|
|
70
74
|
</Flexbox>
|
|
71
|
-
{
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
className={`action-icon`}
|
|
82
|
-
icon={expanded ? ChevronUp : ChevronDown}
|
|
83
|
-
onClick={() => setExpanded(!expanded)}
|
|
84
|
-
size={'small'}
|
|
85
|
-
style={{ opacity: expanded ? 1 : undefined }}
|
|
86
|
-
title={expanded ? 'Collapse' : 'Expand'}
|
|
87
|
-
/>
|
|
75
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
76
|
+
<ActionIcon
|
|
77
|
+
className={`action-icon`}
|
|
78
|
+
icon={expanded ? ChevronUp : ChevronDown}
|
|
79
|
+
onClick={() => setExpanded(!expanded)}
|
|
80
|
+
size={'small'}
|
|
81
|
+
style={{ opacity: expanded ? 1 : undefined }}
|
|
82
|
+
title={expanded ? 'Collapse' : 'Expand'}
|
|
83
|
+
/>
|
|
84
|
+
</Flexbox>
|
|
88
85
|
</Flexbox>
|
|
89
|
-
</Flexbox>
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
</Highlighter>
|
|
103
|
-
{result?.output && (
|
|
104
|
-
<Highlighter language={'text'} showLanguage={false} variant={'filled'} wrap>
|
|
105
|
-
{result.output}
|
|
87
|
+
{/* Command & Output */}
|
|
88
|
+
{expanded && (
|
|
89
|
+
<Block gap={8} padding={8} variant={'outlined'}>
|
|
90
|
+
<Highlighter
|
|
91
|
+
language={'sh'}
|
|
92
|
+
showLanguage={false}
|
|
93
|
+
style={{ paddingInline: 8 }}
|
|
94
|
+
variant={'borderless'}
|
|
95
|
+
wrap
|
|
96
|
+
>
|
|
97
|
+
{args.command}
|
|
106
98
|
</Highlighter>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
{result?.output && (
|
|
100
|
+
<Highlighter language={'text'} showLanguage={false} variant={'filled'} wrap>
|
|
101
|
+
{result.output}
|
|
102
|
+
</Highlighter>
|
|
103
|
+
)}
|
|
104
|
+
</Block>
|
|
105
|
+
)}
|
|
106
|
+
</Flexbox>
|
|
107
|
+
);
|
|
108
|
+
},
|
|
109
|
+
);
|
|
113
110
|
|
|
114
111
|
export default RunCommand;
|