@lobehub/lobehub 2.0.0-next.295 → 2.0.0-next.297

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/locales/en-US/plugin.json +4 -0
  4. package/locales/zh-CN/plugin.json +4 -0
  5. package/package.json +2 -2
  6. package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +5 -5
  7. package/packages/agent-runtime/src/utils/stepContextComputer.test.ts +5 -5
  8. package/packages/builtin-tool-gtd/src/client/Inspector/index.ts +0 -4
  9. package/packages/builtin-tool-gtd/src/client/Intervention/AddTodo.tsx +1 -1
  10. package/packages/builtin-tool-gtd/src/client/Render/TodoList/index.tsx +39 -10
  11. package/packages/builtin-tool-gtd/src/client/Render/index.ts +0 -2
  12. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/TodoItemRow.tsx +26 -12
  13. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/actions.ts +5 -5
  14. package/packages/builtin-tool-gtd/src/client/components/SortableTodoList/store/store.test.ts +14 -8
  15. package/packages/builtin-tool-gtd/src/executor/index.test.ts +48 -227
  16. package/packages/builtin-tool-gtd/src/executor/index.ts +15 -158
  17. package/packages/builtin-tool-gtd/src/manifest.ts +12 -42
  18. package/packages/builtin-tool-gtd/src/systemRole.ts +14 -8
  19. package/packages/builtin-tool-gtd/src/types.ts +47 -41
  20. package/packages/builtin-tool-memory/package.json +8 -0
  21. package/packages/builtin-tool-memory/src/client/Inspector/AddContextMemory/index.tsx +60 -0
  22. package/packages/builtin-tool-memory/src/client/Inspector/AddExperienceMemory/index.tsx +60 -0
  23. package/packages/builtin-tool-memory/src/client/Inspector/AddIdentityMemory/index.tsx +60 -0
  24. package/packages/builtin-tool-memory/src/client/Inspector/AddPreferenceMemory/index.tsx +60 -0
  25. package/packages/builtin-tool-memory/src/client/Inspector/RemoveIdentityMemory/index.tsx +60 -0
  26. package/packages/builtin-tool-memory/src/client/Inspector/SearchUserMemory/index.tsx +67 -0
  27. package/packages/builtin-tool-memory/src/client/Inspector/UpdateIdentityMemory/index.tsx +60 -0
  28. package/packages/builtin-tool-memory/src/client/Inspector/index.ts +35 -0
  29. package/packages/builtin-tool-memory/src/client/Intervention/AddExperienceMemory/index.tsx +17 -0
  30. package/packages/builtin-tool-memory/src/client/Intervention/index.ts +13 -0
  31. package/packages/builtin-tool-memory/src/client/Render/AddExperienceMemory/index.tsx +17 -0
  32. package/packages/builtin-tool-memory/src/client/Render/SearchUserMemory/index.tsx +217 -0
  33. package/packages/builtin-tool-memory/src/client/Render/index.ts +15 -0
  34. package/packages/builtin-tool-memory/src/client/Streaming/AddExperienceMemory/index.tsx +17 -0
  35. package/packages/builtin-tool-memory/src/client/Streaming/index.ts +18 -0
  36. package/packages/builtin-tool-memory/src/client/components/ExperienceMemoryCard.tsx +231 -0
  37. package/packages/builtin-tool-memory/src/client/components/index.ts +1 -0
  38. package/packages/builtin-tool-memory/src/client/index.ts +27 -0
  39. package/packages/builtin-tool-memory/src/executor/index.ts +9 -1
  40. package/packages/builtin-tool-memory/src/types.ts +61 -0
  41. package/packages/context-engine/src/providers/GTDTodoInjector.ts +15 -7
  42. package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistantGroup/tools-with-branches.json +4 -0
  43. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +1 -0
  44. package/packages/prompts/src/prompts/gtd/index.test.ts +32 -16
  45. package/packages/prompts/src/prompts/gtd/index.ts +9 -5
  46. package/packages/types/package.json +1 -1
  47. package/packages/types/src/discover/assistants.ts +4 -0
  48. package/packages/types/src/discover/groupAgents.ts +196 -0
  49. package/packages/types/src/discover/index.ts +5 -1
  50. package/packages/types/src/stepContext.ts +4 -1
  51. package/src/app/[variants]/(main)/community/(detail)/assistant/features/Details/Versions/index.tsx +2 -2
  52. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/DetailProvider.tsx +19 -0
  53. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Members/index.tsx +137 -0
  54. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Nav.tsx +88 -0
  55. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Overview/index.tsx +213 -0
  56. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Related/index.tsx +85 -0
  57. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/TagList.tsx +20 -0
  58. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/SystemRole/index.tsx +71 -0
  59. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/Versions/index.tsx +119 -0
  60. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Details/index.tsx +51 -0
  61. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Header.tsx +253 -0
  62. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/AddGroupAgent.tsx +222 -0
  63. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/ActionButton/index.tsx +34 -0
  64. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/Summary/index.tsx +42 -0
  65. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/Sidebar/index.tsx +41 -0
  66. package/src/app/[variants]/(main)/community/(detail)/group_agent/features/StatusPage/index.tsx +104 -0
  67. package/src/app/[variants]/(main)/community/(detail)/group_agent/index.tsx +103 -0
  68. package/src/app/[variants]/(main)/community/(detail)/group_agent/loading.tsx +1 -0
  69. package/src/app/[variants]/(main)/community/(detail)/user/features/DetailProvider.tsx +7 -1
  70. package/src/app/[variants]/(main)/community/(detail)/user/features/UserContent.tsx +2 -0
  71. package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupCard.tsx +186 -0
  72. package/src/app/[variants]/(main)/community/(detail)/user/features/UserGroupList.tsx +59 -0
  73. package/src/app/[variants]/(main)/community/(detail)/user/index.tsx +3 -1
  74. package/src/app/[variants]/(main)/community/(list)/assistant/features/List/Item.tsx +26 -8
  75. package/src/app/[variants]/(main)/community/(list)/assistant/index.tsx +1 -0
  76. package/src/app/[variants]/(main)/community/features/Search.tsx +1 -1
  77. package/src/app/[variants]/(main)/group/profile/features/GroupProfile/index.tsx +2 -0
  78. package/src/app/[variants]/(main)/group/profile/features/Header/AgentPublishButton/PublishResultModal.tsx +2 -1
  79. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupForkConfirmModal.tsx +60 -0
  80. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/GroupPublishResultModal.tsx +62 -0
  81. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/PublishButton.tsx +122 -0
  82. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/index.tsx +46 -0
  83. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/types.ts +12 -0
  84. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/useMarketGroupPublish.ts +211 -0
  85. package/src/app/[variants]/(main)/group/profile/features/Header/GroupPublishButton/utils.ts +22 -0
  86. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +4 -2
  87. package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +30 -35
  88. package/src/app/[variants]/(main)/resource/library/_layout/Header/index.tsx +9 -11
  89. package/src/app/[variants]/router/desktopRouter.config.tsx +7 -0
  90. package/src/features/Conversation/Messages/AssistantGroup/Tool/Actions/index.tsx +11 -17
  91. package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/LoadingPlaceholder/index.tsx +13 -3
  92. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/CustomRender.tsx +43 -0
  93. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/FallbacktArgumentRender.tsx +59 -0
  94. package/src/features/Conversation/Messages/AssistantGroup/Tool/Detail/Render/index.tsx +46 -0
  95. package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/index.tsx +13 -19
  96. package/src/features/Conversation/Messages/AssistantGroup/Tool/index.tsx +17 -17
  97. package/src/features/Conversation/Messages/Tool/Tool/index.tsx +10 -9
  98. package/src/features/Conversation/TodoProgress/index.tsx +56 -23
  99. package/src/features/PluginsUI/Render/MCPType/index.tsx +1 -1
  100. package/src/features/ResourceManager/components/Explorer/Header/index.tsx +57 -4
  101. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +6 -4
  102. package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +16 -5
  103. package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +5 -4
  104. package/src/hooks/useActiveTabKey.ts +1 -2
  105. package/src/locales/default/plugin.ts +1 -0
  106. package/src/locales/default/setting.ts +12 -0
  107. package/src/server/routers/lambda/market/agentGroup.ts +296 -0
  108. package/src/server/routers/lambda/market/index.ts +134 -4
  109. package/src/server/services/discover/index.ts +123 -7
  110. package/src/services/discover.ts +55 -0
  111. package/src/store/chat/slices/message/selectors/dbMessage.test.ts +11 -11
  112. package/src/store/discover/slices/groupAgent/action.ts +80 -0
  113. package/src/store/discover/store.ts +3 -0
  114. package/src/store/file/slices/resource/action.ts +4 -2
  115. package/src/tools/inspectors.ts +2 -0
  116. package/src/tools/interventions.ts +2 -0
  117. package/src/tools/renders.ts +3 -1
  118. package/src/tools/streamings.ts +2 -0
  119. package/packages/builtin-tool-gtd/src/client/Inspector/CompleteTodos/index.tsx +0 -52
  120. package/packages/builtin-tool-gtd/src/client/Inspector/RemoveTodos/index.tsx +0 -52
  121. package/src/features/Conversation/Messages/AssistantGroup/Tool/Render/CustomRender.tsx +0 -113
  122. package/src/features/Conversation/Messages/Tool/Tool/Render.tsx +0 -47
  123. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/AbortResponse.tsx +0 -0
  124. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Arguments/index.tsx +0 -0
  125. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/ErrorResponse.tsx +0 -0
  126. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ApprovalActions.tsx +0 -0
  127. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/Fallback.tsx +0 -0
  128. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/KeyValueEditor.tsx +0 -0
  129. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/ModeSelector.tsx +0 -0
  130. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/Intervention/index.tsx +0 -0
  131. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/PluginSettings.tsx +0 -0
  132. /package/src/features/Conversation/Messages/AssistantGroup/Tool/{Render → Detail}/RejectedResponse.tsx +0 -0
@@ -1,8 +1,16 @@
1
1
  'use client';
2
2
 
3
- import { Center, type DropdownItem, DropdownMenu, Flexbox, Skeleton, Text } from '@lobehub/ui';
3
+ import {
4
+ ActionIcon,
5
+ Block,
6
+ Center,
7
+ type DropdownItem,
8
+ DropdownMenu,
9
+ Skeleton,
10
+ Text,
11
+ } from '@lobehub/ui';
4
12
  import { createStaticStyles, cx } from 'antd-style';
5
- import { ChevronsUpDown } from 'lucide-react';
13
+ import { ChevronsUpDownIcon } from 'lucide-react';
6
14
  import { type DragEvent, memo, useCallback, useMemo, useState } from 'react';
7
15
  import { useNavigate } from 'react-router-dom';
8
16
 
@@ -12,15 +20,6 @@ import RepoIcon from '@/components/LibIcon';
12
20
  import { knowledgeBaseSelectors, useKnowledgeBaseStore } from '@/store/library';
13
21
 
14
22
  const styles = createStaticStyles(({ css, cssVar }) => ({
15
- clickableHeader: css`
16
- cursor: pointer;
17
- border-radius: ${cssVar.borderRadius}px;
18
- transition: all 0.2s;
19
-
20
- &:hover {
21
- background-color: ${cssVar.colorFillTertiary};
22
- }
23
- `,
24
23
  dropZoneActive: css`
25
24
  color: ${cssVar.colorBgElevated} !important;
26
25
  background-color: ${cssVar.colorText} !important;
@@ -29,14 +28,6 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
29
28
  color: ${cssVar.colorBgElevated} !important;
30
29
  }
31
30
  `,
32
- icon: css`
33
- color: ${cssVar.colorTextSecondary};
34
- transition: all 0.2s;
35
-
36
- &:hover {
37
- color: ${cssVar.colorText};
38
- }
39
- `,
40
31
  menuIcon: css`
41
32
  color: ${cssVar.colorTextTertiary};
42
33
  `,
@@ -101,43 +92,47 @@ const Head = memo<{ id: string }>(({ id }) => {
101
92
  }, [libraries, handleLibrarySwitch, id, styles.menuIcon]);
102
93
 
103
94
  return (
104
- <Flexbox
95
+ <Block
105
96
  align={'center'}
106
- className={cx(styles.clickableHeader, isDropZoneActive && styles.dropZoneActive)}
97
+ className={cx(isDropZoneActive && styles.dropZoneActive)}
98
+ clickable
107
99
  data-drop-target-id="root"
108
100
  data-is-folder="true"
109
101
  data-root-drop="true"
110
102
  gap={8}
111
103
  horizontal
104
+ onClick={handleClick}
112
105
  onDragLeave={handleDragLeave}
113
106
  onDragOver={handleDragOver}
114
107
  onDrop={handleDrop}
115
- paddingBlock={6}
116
- paddingInline={'12px 14px'}
108
+ padding={2}
109
+ style={{ minWidth: 32, overflow: 'hidden' }}
110
+ variant={'borderless'}
117
111
  >
118
- <Center style={{ minWidth: 24 }} width={24}>
119
- <RepoIcon />
112
+ <Center style={{ minWidth: 32 }} width={32}>
113
+ <RepoIcon size={18} />
120
114
  </Center>
121
115
  {!name ? (
122
116
  <Skeleton active paragraph={false} title={{ style: { marginBottom: 0 }, width: 80 }} />
123
117
  ) : (
124
- <Flexbox align={'center'} flex={1} gap={4} horizontal onClick={handleClick}>
125
- <Text ellipsis strong style={{ flex: 1, fontSize: 16 }}>
126
- {name}
127
- </Text>
128
- </Flexbox>
118
+ <Text ellipsis style={{ flex: 1 }} weight={500}>
119
+ {name}
120
+ </Text>
129
121
  )}
130
122
  {name && (
131
123
  <DropdownMenu items={menuItems} placement="bottomRight">
132
- <ChevronsUpDown
133
- className={styles.icon}
124
+ <ActionIcon
125
+ icon={ChevronsUpDownIcon}
134
126
  onClick={(e) => e.stopPropagation()}
135
- size={16}
136
- style={{ cursor: 'pointer', flex: 'none' }}
127
+ size={{
128
+ blockSize: 28,
129
+ size: 16,
130
+ }}
131
+ style={{ width: 24 }}
137
132
  />
138
133
  </DropdownMenu>
139
134
  )}
140
- </Flexbox>
135
+ </Block>
141
136
  );
142
137
  });
143
138
 
@@ -12,17 +12,15 @@ const Header = memo(() => {
12
12
  const { id } = useParams<{ id: string }>();
13
13
  const { t } = useTranslation('common');
14
14
  return (
15
- <>
16
- <SideBarHeaderLayout
17
- breadcrumb={[
18
- {
19
- href: '/resource',
20
- title: t('tab.resource'),
21
- },
22
- ]}
23
- />
24
- <LibraryHead id={id || ''} />
25
- </>
15
+ <SideBarHeaderLayout
16
+ breadcrumb={[
17
+ {
18
+ href: '/resource',
19
+ title: t('tab.resource'),
20
+ },
21
+ ]}
22
+ left={<LibraryHead id={id || ''} />}
23
+ />
26
24
  );
27
25
  });
28
26
 
@@ -168,6 +168,13 @@ export const desktopRoutes: RouteConfig[] = [
168
168
  ),
169
169
  path: 'assistant/:slug',
170
170
  },
171
+ {
172
+ element: dynamicElement(
173
+ () => import('../(main)/community/(detail)/group_agent'),
174
+ 'Desktop > Discover > Detail > Group Agent',
175
+ ),
176
+ path: 'group_agent/:slug',
177
+ },
171
178
  {
172
179
  element: dynamicElement(
173
180
  () => import('../(main)/community/(detail)/model'),
@@ -8,49 +8,43 @@ import Settings from './Settings';
8
8
 
9
9
  interface ActionsProps {
10
10
  assistantMessageId: string;
11
- handleExpand?: (expand?: boolean) => void;
11
+ canToggleCustomToolRender?: boolean;
12
12
  identifier: string;
13
+ setShowCustomToolRender?: (show: boolean) => void;
13
14
  setShowDebug?: (show: boolean) => void;
14
- setShowPluginRender: (show: boolean) => void;
15
- showCustomPluginRender: boolean;
15
+ showCustomToolRender?: boolean;
16
16
  showDebug?: boolean;
17
- showPluginRender: boolean;
18
17
  }
19
18
 
20
19
  const Actions = memo<ActionsProps>(
21
20
  ({
22
21
  assistantMessageId,
22
+ canToggleCustomToolRender,
23
23
  identifier,
24
+ setShowCustomToolRender,
24
25
  setShowDebug,
25
- setShowPluginRender,
26
- showCustomPluginRender,
26
+ showCustomToolRender,
27
27
  showDebug,
28
- showPluginRender,
29
- handleExpand,
30
28
  }) => {
31
29
  const { t } = useTranslation('plugin');
32
30
  const deleteAssistantMessage = useConversationStore((s) => s.deleteAssistantMessage);
33
31
 
34
32
  return (
35
33
  <>
36
- {showCustomPluginRender && (
34
+ {canToggleCustomToolRender && (
37
35
  <ActionIcon
38
- icon={showPluginRender ? LogsIcon : LayoutPanelTop}
36
+ icon={showCustomToolRender ? LogsIcon : LayoutPanelTop}
39
37
  onClick={() => {
40
- setShowPluginRender(!showPluginRender);
41
- handleExpand?.(true);
38
+ setShowCustomToolRender?.(!showCustomToolRender);
42
39
  }}
43
40
  size={'small'}
44
- title={showPluginRender ? t('inspector.args') : t('inspector.pluginRender')}
41
+ title={showCustomToolRender ? t('inspector.args') : t('inspector.pluginRender')}
45
42
  />
46
43
  )}
47
44
  <ActionIcon
48
45
  active={showDebug}
49
46
  icon={showDebug ? LucideBugOff : LucideBug}
50
- onClick={() => {
51
- setShowDebug?.(!showDebug);
52
- handleExpand?.(true);
53
- }}
47
+ onClick={() => setShowDebug?.(!showDebug)}
54
48
  size={'small'}
55
49
  title={t(showDebug ? 'debug.off' : 'debug.on')}
56
50
  />
@@ -2,6 +2,7 @@ import { safeParseJSON } from '@lobechat/utils';
2
2
  import { memo } from 'react';
3
3
 
4
4
  import { getBuiltinPlaceholder } from '@/tools/placeholders';
5
+ import { getBuiltinStreaming } from '@/tools/streamings';
5
6
 
6
7
  import Arguments from '../Arguments';
7
8
 
@@ -9,16 +10,25 @@ interface LoadingPlaceholderProps {
9
10
  apiName: string;
10
11
  identifier: string;
11
12
  loading?: boolean;
13
+ messageId: string;
12
14
  requestArgs?: string;
15
+ toolCallId: string;
13
16
  }
14
17
 
15
18
  const LoadingPlaceholder = memo<LoadingPlaceholderProps>(
16
- ({ identifier, requestArgs, apiName, loading }) => {
17
- const Render = getBuiltinPlaceholder(identifier, apiName);
19
+ ({ identifier, requestArgs, apiName, loading, toolCallId, messageId }) => {
20
+ const Render =
21
+ getBuiltinPlaceholder(identifier, apiName) || getBuiltinStreaming(identifier, apiName);
18
22
 
19
23
  if (Render) {
20
24
  return (
21
- <Render apiName={apiName} args={safeParseJSON(requestArgs) || {}} identifier={identifier} />
25
+ <Render
26
+ apiName={apiName}
27
+ args={safeParseJSON(requestArgs) || {}}
28
+ identifier={identifier}
29
+ messageId={messageId}
30
+ toolCallId={toolCallId}
31
+ />
22
32
  );
23
33
  }
24
34
 
@@ -0,0 +1,43 @@
1
+ import { type ChatPluginPayload } from '@/types/index';
2
+ import { Flexbox } from '@lobehub/ui';
3
+ import { memo } from 'react';
4
+
5
+ import PluginRender from '@/features/PluginsUI/Render';
6
+
7
+ interface CustomRenderProps {
8
+ content: string;
9
+ /**
10
+ * The real message ID (tool message ID)
11
+ */
12
+ messageId?: string;
13
+ plugin?: ChatPluginPayload;
14
+ pluginState?: any;
15
+ /**
16
+ * The tool call ID from the assistant message
17
+ */
18
+ toolCallId: string;
19
+ }
20
+
21
+ const CustomRender = memo<CustomRenderProps>(
22
+ ({ toolCallId, messageId, content, pluginState, plugin }) => {
23
+ return (
24
+ <Flexbox gap={12} id={toolCallId} width={'100%'}>
25
+ <PluginRender
26
+ arguments={plugin?.arguments}
27
+ content={content}
28
+ identifier={plugin?.identifier}
29
+ loading={false}
30
+ messageId={messageId}
31
+ payload={plugin}
32
+ pluginState={pluginState}
33
+ toolCallId={toolCallId}
34
+ type={plugin?.type}
35
+ />
36
+ </Flexbox>
37
+ );
38
+ },
39
+ );
40
+
41
+ CustomRender.displayName = 'GroupCustomRender';
42
+
43
+ export default CustomRender;
@@ -0,0 +1,59 @@
1
+ import { Block, Flexbox, Highlighter, Text } from '@lobehub/ui';
2
+ import { Divider } from 'antd';
3
+ import { memo, useMemo } from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+
6
+ import Arguments from '../Arguments';
7
+
8
+ interface FallbackArgumentRenderProps {
9
+ content: string;
10
+ requestArgs?: string;
11
+ toolCallId: string;
12
+ }
13
+
14
+ export const FallbackArgumentRender = memo<FallbackArgumentRenderProps>(
15
+ ({ toolCallId, content, requestArgs }) => {
16
+ const { t } = useTranslation('plugin');
17
+
18
+ // Parse and display result content
19
+ const { data, language } = useMemo(() => {
20
+ try {
21
+ const parsed = JSON.parse(content || '');
22
+ // If parsed result is a string, return it directly
23
+ if (typeof parsed === 'string') {
24
+ return { data: parsed, language: 'plaintext' };
25
+ }
26
+ return { data: JSON.stringify(parsed, null, 2), language: 'json' };
27
+ } catch {
28
+ return { data: content || '', language: 'plaintext' };
29
+ }
30
+ }, [content]);
31
+
32
+ // Default render: show arguments and result
33
+ return (
34
+ <Block id={toolCallId} variant={'outlined'} width={'100%'}>
35
+ <Arguments arguments={requestArgs} />
36
+ {content && (
37
+ <>
38
+ <Divider style={{ marginBlock: 0 }} />
39
+ <Flexbox paddingBlock={'8px 0'} paddingInline={16}>
40
+ <Text>{t('debug.response')}</Text>
41
+ </Flexbox>
42
+ <Highlighter
43
+ language={language}
44
+ style={{
45
+ background: 'transparent',
46
+ borderRadius: 0,
47
+ maxHeight: 300,
48
+ overflow: 'auto',
49
+ }}
50
+ variant={'filled'}
51
+ >
52
+ {data}
53
+ </Highlighter>
54
+ </>
55
+ )}
56
+ </Block>
57
+ );
58
+ },
59
+ );
@@ -0,0 +1,46 @@
1
+ import { type ChatPluginPayload } from '@lobechat/types';
2
+ import { memo } from 'react';
3
+
4
+ import { getBuiltinRender } from '@/tools/renders';
5
+
6
+ import CustomRender from './CustomRender';
7
+ import { FallbackArgumentRender } from './FallbacktArgumentRender';
8
+
9
+ interface ToolRenderProps {
10
+ content: string;
11
+ messageId?: string;
12
+ plugin?: ChatPluginPayload;
13
+ pluginState?: any;
14
+ showCustomToolRender?: boolean;
15
+ toolCallId: string;
16
+ }
17
+
18
+ const ToolRender = memo<ToolRenderProps>(
19
+ ({ showCustomToolRender, content, messageId, plugin, pluginState, toolCallId }) => {
20
+ const hasCustomRender = !!getBuiltinRender(plugin?.identifier, plugin?.apiName);
21
+
22
+ if (hasCustomRender && showCustomToolRender) {
23
+ return (
24
+ <CustomRender
25
+ content={content}
26
+ messageId={messageId}
27
+ plugin={plugin}
28
+ pluginState={pluginState}
29
+ toolCallId={toolCallId}
30
+ />
31
+ );
32
+ }
33
+
34
+ return (
35
+ <FallbackArgumentRender
36
+ content={content}
37
+ requestArgs={plugin?.arguments}
38
+ toolCallId={toolCallId}
39
+ />
40
+ );
41
+ },
42
+ );
43
+
44
+ ToolRender.displayName = 'ToolResultRender';
45
+
46
+ export default ToolRender;
@@ -6,12 +6,12 @@ import { Suspense, memo } from 'react';
6
6
  import { getBuiltinStreaming } from '@/tools/streamings';
7
7
 
8
8
  import AbortResponse from './AbortResponse';
9
- import CustomRender from './CustomRender';
10
9
  import ErrorResponse from './ErrorResponse';
11
10
  import Intervention from './Intervention';
12
11
  import ModeSelector from './Intervention/ModeSelector';
13
12
  import LoadingPlaceholder from './LoadingPlaceholder';
14
13
  import RejectedResponse from './RejectedResponse';
14
+ import ToolRender from './Render';
15
15
 
16
16
  interface RenderProps {
17
17
  apiName: string;
@@ -26,8 +26,7 @@ interface RenderProps {
26
26
  */
27
27
  messageId: string;
28
28
  result?: ChatToolResult;
29
- setShowPluginRender: (show: boolean) => void;
30
- showPluginRender: boolean;
29
+ showCustomToolRender?: boolean;
31
30
  toolCallId: string;
32
31
  toolMessageId?: string;
33
32
  type?: string;
@@ -45,8 +44,6 @@ const Render = memo<RenderProps>(
45
44
  messageId,
46
45
  arguments: requestArgs,
47
46
  disableEditing,
48
- showPluginRender,
49
- setShowPluginRender,
50
47
  identifier,
51
48
  apiName,
52
49
  result,
@@ -55,6 +52,7 @@ const Render = memo<RenderProps>(
55
52
  toolMessageId,
56
53
  isArgumentsStreaming,
57
54
  isToolCalling,
55
+ showCustomToolRender,
58
56
  }) => {
59
57
  if (toolMessageId && intervention?.status === 'pending' && !disableEditing) {
60
58
  return (
@@ -124,7 +122,9 @@ const Render = memo<RenderProps>(
124
122
  apiName={apiName}
125
123
  identifier={identifier}
126
124
  loading
125
+ messageId={messageId}
127
126
  requestArgs={requestArgs}
127
+ toolCallId={toolCallId}
128
128
  />
129
129
  );
130
130
 
@@ -133,23 +133,17 @@ const Render = memo<RenderProps>(
133
133
  return (
134
134
  <Suspense fallback={placeholder}>
135
135
  <Flexbox gap={8}>
136
- <CustomRender
136
+ <ToolRender
137
137
  content={result.content || ''}
138
138
  messageId={toolMessageId}
139
- plugin={
140
- type
141
- ? ({
142
- apiName,
143
- arguments: requestArgs || '',
144
- identifier,
145
- type,
146
- } as any)
147
- : undefined
148
- }
139
+ plugin={{
140
+ apiName,
141
+ arguments: requestArgs || '',
142
+ identifier,
143
+ type: type as any,
144
+ }}
149
145
  pluginState={result.state}
150
- requestArgs={requestArgs}
151
- setShowPluginRender={setShowPluginRender}
152
- showPluginRender={showPluginRender}
146
+ showCustomToolRender={showCustomToolRender}
153
147
  toolCallId={toolCallId}
154
148
  />
155
149
  {!disableEditing && (
@@ -21,7 +21,7 @@ const Debug = dynamic(() => import('./Debug'), {
21
21
  ssr: false,
22
22
  });
23
23
 
24
- const Render = dynamic(() => import('./Render'), {
24
+ const Detail = dynamic(() => import('./Detail'), {
25
25
  loading: () => <Skeleton.Block active height={120} width={'100%'} />,
26
26
  ssr: false,
27
27
  });
@@ -57,7 +57,9 @@ const Tool = memo<GroupToolProps>(
57
57
  toolSelectors.getRenderDisplayControl(identifier, apiName),
58
58
  );
59
59
  const [showDebug, setShowDebug] = useState(false);
60
- const [showPluginRender, setShowPluginRender] = useState(false);
60
+ const [showToolRender, setShowToolRender] = useState(false);
61
+ // Controls switching between custom render and fallback ArgumentRender
62
+ const [showCustomToolRender, setShowCustomToolRender] = useState(true);
61
63
 
62
64
  const isPending = intervention?.status === 'pending';
63
65
  const isReject = intervention?.status === 'rejected';
@@ -65,8 +67,6 @@ const Tool = memo<GroupToolProps>(
65
67
  const needExpand = renderDisplayControl !== 'collapsed' || isPending;
66
68
  const isAlwaysExpand = renderDisplayControl === 'alwaysExpand';
67
69
 
68
- const showCustomPluginRender = !isPending && !isReject && !isAbort;
69
-
70
70
  let isArgumentsStreaming = false;
71
71
  try {
72
72
  JSON.parse(requestArgs || '{}');
@@ -88,14 +88,16 @@ const Tool = memo<GroupToolProps>(
88
88
  const isToolCalling = isToolCallingFromOperation || isToolCallingFallback;
89
89
 
90
90
  const hasCustomRender = !!getBuiltinRender(identifier, apiName);
91
+ // Only allow toggle when has custom render and not in pending/reject/abort state
92
+ const canToggleCustomToolRender = hasCustomRender && !isPending && !isReject && !isAbort;
91
93
 
92
- // Handle expand state changes with showPluginRender
94
+ // Handle expand state changes
93
95
  const handleExpand = (expand?: boolean) => {
94
96
  // Block collapse action when alwaysExpand is set
95
97
  if (isAlwaysExpand && expand === false) {
96
98
  return;
97
99
  }
98
- setShowPluginRender(!!expand);
100
+ setShowToolRender(!!expand);
99
101
  };
100
102
 
101
103
  useEffect(() => {
@@ -104,27 +106,26 @@ const Tool = memo<GroupToolProps>(
104
106
  }
105
107
  }, [needExpand]);
106
108
 
107
- const isToolRenderExpand = forceShowStreamingRender || showPluginRender;
109
+ const isToolDetailExpand = forceShowStreamingRender || showToolRender || showDebug;
110
+
108
111
  return (
109
112
  <AccordionItem
110
113
  action={
111
114
  !disableEditing && (
112
115
  <Actions
113
116
  assistantMessageId={assistantMessageId}
114
- handleExpand={handleExpand}
117
+ canToggleCustomToolRender={canToggleCustomToolRender}
115
118
  identifier={identifier}
119
+ setShowCustomToolRender={setShowCustomToolRender}
116
120
  setShowDebug={setShowDebug}
117
- setShowPluginRender={setShowPluginRender}
118
- showCustomPluginRender={showCustomPluginRender}
121
+ showCustomToolRender={showCustomToolRender}
119
122
  showDebug={showDebug}
120
- showPluginRender={showPluginRender}
121
123
  />
122
124
  )
123
125
  }
124
- allowExpand={hasCustomRender}
125
- expand={isToolRenderExpand}
126
+ expand={isToolDetailExpand}
126
127
  itemKey={id}
127
- onExpandChange={setShowPluginRender}
128
+ onExpandChange={handleExpand}
128
129
  paddingBlock={4}
129
130
  paddingInline={4}
130
131
  title={
@@ -151,7 +152,7 @@ const Tool = memo<GroupToolProps>(
151
152
  />
152
153
  )}
153
154
  <ToolErrorBoundary apiName={apiName} identifier={identifier}>
154
- <Render
155
+ <Detail
155
156
  apiName={apiName}
156
157
  arguments={requestArgs}
157
158
  disableEditing={disableEditing}
@@ -161,8 +162,7 @@ const Tool = memo<GroupToolProps>(
161
162
  isToolCalling={isToolCalling}
162
163
  messageId={assistantMessageId}
163
164
  result={result}
164
- setShowPluginRender={setShowPluginRender}
165
- showPluginRender={showPluginRender}
165
+ showCustomToolRender={showCustomToolRender}
166
166
  toolCallId={id}
167
167
  toolMessageId={toolMessageId}
168
168
  type={type}
@@ -3,6 +3,7 @@ import { type CSSProperties, memo, useState } from 'react';
3
3
 
4
4
  import Actions from '@/features/Conversation/Messages/AssistantGroup/Tool/Actions';
5
5
  import dynamic from '@/libs/next/dynamic';
6
+ import { getBuiltinRender } from '@/tools/renders';
6
7
 
7
8
  import { dataSelectors, messageStateSelectors, useConversationStore } from '../../../store';
8
9
  import Inspectors from '../../AssistantGroup/Tool/Inspector';
@@ -12,7 +13,7 @@ const Debug = dynamic(() => import('../../AssistantGroup/Tool/Debug'), {
12
13
  ssr: false,
13
14
  });
14
15
 
15
- const Render = dynamic(() => import('../../AssistantGroup/Tool/Render'), {
16
+ const Detail = dynamic(() => import('../../AssistantGroup/Tool/Detail'), {
16
17
  loading: () => <Skeleton.Block active height={120} width={'100%'} />,
17
18
  ssr: false,
18
19
  });
@@ -44,7 +45,7 @@ const Tool = memo<InspectorProps>(
44
45
  type,
45
46
  }) => {
46
47
  const [showDebug, setShowDebug] = useState(false);
47
- const [showPluginRender, setShowPluginRender] = useState(false);
48
+ const [showCustomToolRender, setShowCustomToolRender] = useState(true);
48
49
  const [expand, setExpand] = useState(true);
49
50
 
50
51
  // Fetch tool message from store
@@ -68,6 +69,8 @@ const Tool = memo<InspectorProps>(
68
69
  // Don't render if still loading and no message yet
69
70
  if (loading && !toolMessage) return null;
70
71
 
72
+ const hasCustomRender = !!getBuiltinRender(identifier, apiName);
73
+
71
74
  return (
72
75
  <Accordion
73
76
  expandedKeys={expand ? ['tool'] : []}
@@ -79,13 +82,12 @@ const Tool = memo<InspectorProps>(
79
82
  !disableEditing && (
80
83
  <Actions
81
84
  assistantMessageId={messageId}
82
- handleExpand={(expand) => setExpand(!!expand)}
85
+ canToggleCustomToolRender={hasCustomRender}
83
86
  identifier={identifier}
87
+ setShowCustomToolRender={setShowCustomToolRender}
84
88
  setShowDebug={setShowDebug}
85
- setShowPluginRender={setShowPluginRender}
86
- showCustomPluginRender={false}
89
+ showCustomToolRender={showCustomToolRender}
87
90
  showDebug={showDebug}
88
- showPluginRender={showPluginRender}
89
91
  />
90
92
  )
91
93
  }
@@ -105,15 +107,14 @@ const Tool = memo<InspectorProps>(
105
107
  type={type}
106
108
  />
107
109
  )}
108
- <Render
110
+ <Detail
109
111
  apiName={apiName}
110
112
  arguments={requestArgs}
111
113
  disableEditing={disableEditing}
112
114
  identifier={identifier}
113
115
  messageId={messageId}
114
116
  result={result}
115
- setShowPluginRender={setShowPluginRender}
116
- showPluginRender={showPluginRender}
117
+ showCustomToolRender={showCustomToolRender}
117
118
  toolCallId={toolCallId}
118
119
  type={type}
119
120
  />