@stack-spot/ai-chat-widget 1.13.2-beta.0 → 1.13.2
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 +35 -0
- package/dist/StackspotAIWidget.d.ts.map +1 -1
- package/dist/StackspotAIWidget.js +5 -2
- package/dist/StackspotAIWidget.js.map +1 -1
- package/dist/app-metadata.json +3 -3
- package/dist/chat-interceptors/send-message.d.ts.map +1 -1
- package/dist/chat-interceptors/send-message.js +2 -0
- package/dist/chat-interceptors/send-message.js.map +1 -1
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown.js +1 -1
- package/dist/components/Markdown.js.map +1 -1
- package/dist/components/StackedBadge.d.ts +14 -0
- package/dist/components/StackedBadge.d.ts.map +1 -0
- package/dist/components/StackedBadge.js +56 -0
- package/dist/components/StackedBadge.js.map +1 -0
- package/dist/components/ToolBadge.d.ts +14 -0
- package/dist/components/ToolBadge.d.ts.map +1 -0
- package/dist/components/ToolBadge.js +108 -0
- package/dist/components/ToolBadge.js.map +1 -0
- package/dist/state/ChatEntry.d.ts +9 -16
- package/dist/state/ChatEntry.d.ts.map +1 -1
- package/dist/state/ChatEntry.js.map +1 -1
- package/dist/state/ChatState.d.ts +0 -1
- package/dist/state/ChatState.d.ts.map +1 -1
- package/dist/state/WidgetState.d.ts +3 -4
- package/dist/state/WidgetState.d.ts.map +1 -1
- package/dist/state/WidgetState.js +1 -12
- package/dist/state/WidgetState.js.map +1 -1
- package/dist/utils/check-is-trial.d.ts +2 -0
- package/dist/utils/check-is-trial.d.ts.map +1 -0
- package/dist/utils/check-is-trial.js +6 -0
- package/dist/utils/check-is-trial.js.map +1 -0
- package/dist/utils/tools.d.ts +7 -0
- package/dist/utils/tools.d.ts.map +1 -0
- package/dist/utils/tools.js +9 -0
- package/dist/utils/tools.js.map +1 -0
- package/dist/views/Agents/AgentDescription.d.ts.map +1 -1
- package/dist/views/Agents/AgentDescription.js +11 -1
- package/dist/views/Agents/AgentDescription.js.map +1 -1
- package/dist/views/Agents/AgentsPanel.d.ts.map +1 -1
- package/dist/views/Agents/AgentsPanel.js +13 -6
- package/dist/views/Agents/AgentsPanel.js.map +1 -1
- package/dist/views/Agents/AgentsTab.d.ts.map +1 -1
- package/dist/views/Agents/AgentsTab.js +10 -8
- package/dist/views/Agents/AgentsTab.js.map +1 -1
- package/dist/views/Agents/dictionary.d.ts +1 -1
- package/dist/views/Agents/dictionary.d.ts.map +1 -1
- package/dist/views/Agents/dictionary.js +2 -0
- package/dist/views/Agents/dictionary.js.map +1 -1
- package/dist/views/Agents/styled.js +1 -1
- package/dist/views/Chat/AgentInfo.js +3 -3
- package/dist/views/Chat/AgentInfo.js.map +1 -1
- package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessage.js +19 -4
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/Chat/StepsList.d.ts +2 -2
- package/dist/views/Chat/StepsList.d.ts.map +1 -1
- package/dist/views/Chat/StepsList.js +2 -2
- package/dist/views/Chat/StepsList.js.map +1 -1
- package/dist/views/Chat/styled.d.ts.map +1 -1
- package/dist/views/Chat/styled.js +21 -12
- package/dist/views/Chat/styled.js.map +1 -1
- package/dist/views/ChatTabSelection.d.ts.map +1 -1
- package/dist/views/ChatTabSelection.js +16 -2
- package/dist/views/ChatTabSelection.js.map +1 -1
- package/dist/views/KnowledgeSources.d.ts.map +1 -1
- package/dist/views/KnowledgeSources.js +10 -5
- package/dist/views/KnowledgeSources.js.map +1 -1
- package/dist/views/MessageInput/AgentSelector.d.ts +2 -1
- package/dist/views/MessageInput/AgentSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/AgentSelector.js +15 -8
- package/dist/views/MessageInput/AgentSelector.js.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.d.ts +2 -1
- package/dist/views/MessageInput/QuickCommandSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.js +2 -2
- package/dist/views/MessageInput/QuickCommandSelector.js.map +1 -1
- package/dist/views/MessageInput/index.d.ts.map +1 -1
- package/dist/views/MessageInput/index.js +4 -2
- package/dist/views/MessageInput/index.js.map +1 -1
- package/dist/views/Stacks.d.ts.map +1 -1
- package/dist/views/Stacks.js +10 -5
- package/dist/views/Stacks.js.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/HandleGroup.d.ts.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/HandleGroup.js.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/NodeStep.d.ts.map +1 -1
- package/dist/views/Steps/FlowChart/NodeStep.js +13 -0
- package/dist/views/Steps/FlowChart/NodeStep.js.map +1 -0
- package/dist/views/Steps/FlowChart/index.d.ts +10 -0
- package/dist/views/Steps/FlowChart/index.d.ts.map +1 -0
- package/dist/views/{Tools → Steps}/FlowChart/index.js +1 -5
- package/dist/views/{Tools → Steps}/FlowChart/index.js.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/layout.d.ts.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/layout.js.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/styled.d.ts.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/styled.js +0 -49
- package/dist/views/{Tools → Steps}/FlowChart/styled.js.map +1 -1
- package/dist/views/{Tools → Steps}/FlowChart/types.d.ts +3 -3
- package/dist/views/Steps/FlowChart/types.d.ts.map +1 -0
- package/dist/views/Steps/FlowChart/types.js.map +1 -0
- package/dist/views/Steps/StepModal.d.ts +9 -0
- package/dist/views/Steps/StepModal.d.ts.map +1 -0
- package/dist/views/Steps/StepModal.js +124 -0
- package/dist/views/Steps/StepModal.js.map +1 -0
- package/dist/views/Steps/StepsPanel.d.ts +6 -0
- package/dist/views/Steps/StepsPanel.d.ts.map +1 -0
- package/dist/views/{Tools/ToolsPanel.js → Steps/StepsPanel.js} +3 -3
- package/dist/views/{Tools/ToolsPanel.js.map → Steps/StepsPanel.js.map} +1 -1
- package/dist/views/{Tools → Steps}/dictionary.d.ts +9 -11
- package/dist/views/Steps/dictionary.d.ts.map +1 -0
- package/dist/views/{Tools → Steps}/dictionary.js +9 -11
- package/dist/views/Steps/dictionary.js.map +1 -0
- package/dist/views/{Tools → Steps}/index.d.ts +1 -1
- package/dist/views/Steps/index.d.ts.map +1 -0
- package/dist/views/{Tools → Steps}/index.js +10 -10
- package/dist/views/{Tools → Steps}/index.js.map +1 -1
- package/dist/views/Steps/utils.d.ts +6 -0
- package/dist/views/Steps/utils.d.ts.map +1 -0
- package/dist/views/{Tools → Steps}/utils.js.map +1 -1
- package/dist/views/Tools.d.ts +2 -0
- package/dist/views/Tools.d.ts.map +1 -0
- package/dist/views/Tools.js +51 -0
- package/dist/views/Tools.js.map +1 -0
- package/package.json +2 -2
- package/src/StackspotAIWidget.tsx +8 -3
- package/src/app-metadata.json +3 -3
- package/src/chat-interceptors/send-message.ts +2 -0
- package/src/components/Markdown.tsx +1 -0
- package/src/components/StackedBadge.tsx +77 -0
- package/src/components/ToolBadge.tsx +146 -0
- package/src/state/ChatEntry.ts +9 -17
- package/src/state/ChatState.ts +1 -1
- package/src/state/WidgetState.ts +4 -16
- package/src/utils/check-is-trial.ts +6 -0
- package/src/utils/tools.ts +11 -0
- package/src/views/Agents/AgentDescription.tsx +14 -0
- package/src/views/Agents/AgentsPanel.tsx +11 -3
- package/src/views/Agents/AgentsTab.tsx +11 -10
- package/src/views/Agents/dictionary.ts +2 -0
- package/src/views/Agents/styled.ts +1 -1
- package/src/views/Chat/AgentInfo.tsx +4 -4
- package/src/views/Chat/ChatMessage.tsx +30 -4
- package/src/views/Chat/StepsList.tsx +6 -6
- package/src/views/Chat/styled.ts +21 -12
- package/src/views/ChatTabSelection.tsx +22 -4
- package/src/views/KnowledgeSources.tsx +9 -3
- package/src/views/MessageInput/AgentSelector.tsx +19 -8
- package/src/views/MessageInput/QuickCommandSelector.tsx +3 -2
- package/src/views/MessageInput/index.tsx +5 -4
- package/src/views/Stacks.tsx +10 -4
- package/src/views/{Tools → Steps}/FlowChart/NodeStep.tsx +11 -23
- package/src/views/{Tools → Steps}/FlowChart/index.tsx +3 -7
- package/src/views/{Tools → Steps}/FlowChart/styled.ts +0 -49
- package/src/views/{Tools → Steps}/FlowChart/types.ts +3 -3
- package/src/views/Steps/StepModal.tsx +216 -0
- package/src/views/{Tools/ToolsPanel.tsx → Steps/StepsPanel.tsx} +2 -2
- package/src/views/{Tools → Steps}/dictionary.ts +9 -11
- package/src/views/{Tools → Steps}/index.tsx +10 -10
- package/src/views/{Tools → Steps}/utils.tsx +4 -4
- package/src/views/Tools.tsx +71 -0
- package/dist/utils/agent.d.ts +0 -2
- package/dist/utils/agent.d.ts.map +0 -1
- package/dist/utils/agent.js +0 -2
- package/dist/utils/agent.js.map +0 -1
- package/dist/views/Tools/FlowChart/NodeStep.js +0 -15
- package/dist/views/Tools/FlowChart/NodeStep.js.map +0 -1
- package/dist/views/Tools/FlowChart/index.d.ts +0 -9
- package/dist/views/Tools/FlowChart/index.d.ts.map +0 -1
- package/dist/views/Tools/FlowChart/types.d.ts.map +0 -1
- package/dist/views/Tools/FlowChart/types.js.map +0 -1
- package/dist/views/Tools/StepModal.d.ts +0 -9
- package/dist/views/Tools/StepModal.d.ts.map +0 -1
- package/dist/views/Tools/StepModal.js +0 -156
- package/dist/views/Tools/StepModal.js.map +0 -1
- package/dist/views/Tools/ToolsPanel.d.ts +0 -6
- package/dist/views/Tools/ToolsPanel.d.ts.map +0 -1
- package/dist/views/Tools/dictionary.d.ts.map +0 -1
- package/dist/views/Tools/dictionary.js.map +0 -1
- package/dist/views/Tools/index.d.ts.map +0 -1
- package/dist/views/Tools/utils.d.ts +0 -6
- package/dist/views/Tools/utils.d.ts.map +0 -1
- package/src/utils/agent.ts +0 -1
- package/src/views/Tools/StepModal.tsx +0 -247
- /package/dist/views/{Tools → Steps}/FlowChart/HandleGroup.d.ts +0 -0
- /package/dist/views/{Tools → Steps}/FlowChart/HandleGroup.js +0 -0
- /package/dist/views/{Tools → Steps}/FlowChart/NodeStep.d.ts +0 -0
- /package/dist/views/{Tools → Steps}/FlowChart/layout.d.ts +0 -0
- /package/dist/views/{Tools → Steps}/FlowChart/layout.js +0 -0
- /package/dist/views/{Tools → Steps}/FlowChart/styled.d.ts +0 -0
- /package/dist/views/{Tools → Steps}/FlowChart/types.js +0 -0
- /package/dist/views/{Tools → Steps}/utils.js +0 -0
- /package/src/views/{Tools → Steps}/FlowChart/HandleGroup.tsx +0 -0
- /package/src/views/{Tools → Steps}/FlowChart/layout.ts +0 -0
|
@@ -3,6 +3,8 @@ import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
|
3
3
|
import { useMemo } from 'react'
|
|
4
4
|
import { TabManager } from '../components/TabManager'
|
|
5
5
|
import { useChatState, useChatTabs, useWidget, useWidgetState } from '../context/hooks'
|
|
6
|
+
import { useRightPanel } from '../right-panel/hooks'
|
|
7
|
+
import { ChatState } from '../state/ChatState'
|
|
6
8
|
import { ButtonAction } from '../types'
|
|
7
9
|
|
|
8
10
|
const TabLabel = ({ id }: { id: string }) => {
|
|
@@ -18,13 +20,29 @@ export const ChatTabSelection = () => {
|
|
|
18
20
|
const widget = useWidget()
|
|
19
21
|
const { chatHistory } = useWidgetState('features') ?? {}
|
|
20
22
|
const { active, chats } = useChatTabs()
|
|
23
|
+
const { close: closeRightPanel } = useRightPanel()
|
|
24
|
+
|
|
25
|
+
function create() {
|
|
26
|
+
widget.createChat()
|
|
27
|
+
closeRightPanel()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function select({ id }: ChatState) {
|
|
31
|
+
widget.chatTabs.select(id)
|
|
32
|
+
closeRightPanel()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function remove({ id }: ChatState) {
|
|
36
|
+
widget.chatTabs.remove(id)
|
|
37
|
+
closeRightPanel()
|
|
38
|
+
}
|
|
21
39
|
|
|
22
40
|
const buttons = useMemo<ButtonAction[]>(
|
|
23
41
|
() => {
|
|
24
42
|
const actions: ButtonAction[] = [{
|
|
25
43
|
icon: <Plus />,
|
|
26
44
|
label: t.newChat,
|
|
27
|
-
onClick:
|
|
45
|
+
onClick: create,
|
|
28
46
|
}]
|
|
29
47
|
if (chatHistory) {
|
|
30
48
|
actions.push({
|
|
@@ -39,14 +57,14 @@ export const ChatTabSelection = () => {
|
|
|
39
57
|
},
|
|
40
58
|
[chatHistory],
|
|
41
59
|
)
|
|
42
|
-
|
|
60
|
+
|
|
43
61
|
return <TabManager
|
|
44
62
|
tabs={chats}
|
|
45
63
|
active={active.id}
|
|
46
64
|
renderLabel={({ id }) => <TabLabel id={id} />}
|
|
47
65
|
keygen={({ id }) => id}
|
|
48
|
-
onRemove={
|
|
49
|
-
onSelect={
|
|
66
|
+
onRemove={remove}
|
|
67
|
+
onSelect={select}
|
|
50
68
|
buttons={buttons}
|
|
51
69
|
/>
|
|
52
70
|
}
|
|
@@ -12,6 +12,7 @@ import { RightPanelTabs } from '../components/RightPanelTabs'
|
|
|
12
12
|
import { useCurrentChat, useWidget, useWidgetState } from '../context/hooks'
|
|
13
13
|
import { useRightPanel } from '../right-panel/hooks'
|
|
14
14
|
import { ChatProperties } from '../state/ChatState'
|
|
15
|
+
import { checkIsTrial } from '../utils/check-is-trial'
|
|
15
16
|
|
|
16
17
|
interface TabProps {
|
|
17
18
|
visibility: VisibilityLevelEnum,
|
|
@@ -43,6 +44,7 @@ const KnowledgeSourcesPanel = () => {
|
|
|
43
44
|
const chat = useCurrentChat()
|
|
44
45
|
const allKS = useRef(chat.get('knowledgeSources') ?? [])
|
|
45
46
|
const { close } = useRightPanel()
|
|
47
|
+
const isTrial = checkIsTrial()
|
|
46
48
|
|
|
47
49
|
const onSubmit = useCallback(() => {
|
|
48
50
|
chat.set('knowledgeSources', allKS.current)
|
|
@@ -52,12 +54,16 @@ const KnowledgeSourcesPanel = () => {
|
|
|
52
54
|
useEffect(() => {
|
|
53
55
|
allKS.current = chat.get('knowledgeSources') ?? []
|
|
54
56
|
}, [chat])
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
|
|
58
|
+
const tabs = isTrial ? [
|
|
59
|
+
{ title: t.personal, content: <KnowledgeSourcesTab key="personal" visibility="personal" allKS={allKS} onSubmit={onSubmit} /> },
|
|
60
|
+
]: [
|
|
57
61
|
{ title: t.personal, content: <KnowledgeSourcesTab key="personal" visibility="personal" allKS={allKS} onSubmit={onSubmit} /> },
|
|
58
62
|
{ title: t.shared, content: <KnowledgeSourcesTab key="shared" visibility="shared" allKS={allKS} onSubmit={onSubmit} /> },
|
|
59
63
|
{ title: t.account, content: <KnowledgeSourcesTab key="account" visibility="account" allKS={allKS} onSubmit={onSubmit} /> },
|
|
60
|
-
]
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
return <RightPanelTabs key={chat.id} tabs={tabs} />
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit }: TabProps) => {
|
|
@@ -8,15 +8,26 @@ import { useCallback } from 'react'
|
|
|
8
8
|
import { Selector } from '../../components/Selector'
|
|
9
9
|
import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
10
10
|
import { agentRegex } from '../../regex'
|
|
11
|
-
import { isAgentDefault } from '../../utils/agent'
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
const AGENT_DEFAULT_SLUG = 'stackspot_ai'
|
|
13
|
+
|
|
14
|
+
const isAgentStackspotAI = (slug: string) => slug === AGENT_DEFAULT_SLUG
|
|
15
|
+
|
|
16
|
+
const defaultAgent = {
|
|
17
|
+
id: '',
|
|
18
|
+
name: 'StackSpot AI',
|
|
19
|
+
slug: AGENT_DEFAULT_SLUG,
|
|
20
|
+
visibility_level: 'builtIn',
|
|
21
|
+
} as AgentResponse
|
|
22
|
+
|
|
23
|
+
export const AgentSelector = ({ inputRef, isTrial }: { isTrial: boolean,
|
|
24
|
+
inputRef: React.RefObject<HTMLTextAreaElement | HTMLInputElement>, }) => {
|
|
14
25
|
const chat = useCurrentChat()
|
|
15
26
|
const isAgentEnabled = useCurrentChatState('features').agent
|
|
16
27
|
const onSelectItem = useCallback((agent: AgentResponse) => {
|
|
17
28
|
const newValue = `@${agent.slug}`
|
|
18
29
|
chat.set('nextMessage', undefined)
|
|
19
|
-
chat.set('agent',
|
|
30
|
+
chat.set('agent', isAgentStackspotAI(agent.slug)
|
|
20
31
|
? undefined
|
|
21
32
|
: { id: agent.id, label: agent.name, image: agent.avatar, builtIn: agent.visibility_level === 'builtIn' },
|
|
22
33
|
)
|
|
@@ -28,10 +39,10 @@ export const AgentSelector = ({ inputRef }: { inputRef: React.RefObject<HTMLText
|
|
|
28
39
|
|
|
29
40
|
const getAgents = () => {
|
|
30
41
|
const personalAgents = agentClient.agents.useQuery({ visibility: 'PERSONAL' })
|
|
31
|
-
const accountAgents = agentClient.agents.useQuery({ visibility: 'ACCOUNT' })
|
|
32
|
-
const sharedAgents = agentClient.agents.useQuery({ visibility: 'SHARED' })
|
|
42
|
+
const accountAgents = agentClient.agents.useQuery({ visibility: 'ACCOUNT' }, { enabled: !isTrial })
|
|
43
|
+
const sharedAgents = agentClient.agents.useQuery({ visibility: 'SHARED' }, { enabled: !isTrial })
|
|
33
44
|
const publicAgents = agentClient.publicAgents.useQuery({})
|
|
34
|
-
const buildIns = [...publicAgents.map((agent) => ({ ...agent, visibility_level: 'builtIn' }))]
|
|
45
|
+
const buildIns = [...[defaultAgent], ...publicAgents.map((agent) => ({ ...agent, visibility_level: 'builtIn' }))]
|
|
35
46
|
|
|
36
47
|
return uniqBy([...personalAgents, ...accountAgents, ...sharedAgents, ...buildIns], 'id')
|
|
37
48
|
}
|
|
@@ -40,7 +51,7 @@ export const AgentSelector = ({ inputRef }: { inputRef: React.RefObject<HTMLText
|
|
|
40
51
|
const AvatarComponent = avatar ? <Image width="32" height="32" radius="full" src={avatar} /> : <IconBox size="md"><Agent /></IconBox>
|
|
41
52
|
|
|
42
53
|
return <Flex flexWrap="nowrap" alignItems="center" sx={{ gap: '8px' }}>
|
|
43
|
-
{
|
|
54
|
+
{isAgentStackspotAI(slug) ? <MiniLogo style={{ width: '32px', height: '32px' }} /> : AvatarComponent}
|
|
44
55
|
<p className="selector-title">{name}</p>
|
|
45
56
|
</Flex>
|
|
46
57
|
}
|
|
@@ -54,7 +65,7 @@ export const AgentSelector = ({ inputRef }: { inputRef: React.RefObject<HTMLText
|
|
|
54
65
|
regex: agentRegex,
|
|
55
66
|
urlBuilder: (agent) => `/agents/${agent?.id}`,
|
|
56
67
|
searchProp: 'name',
|
|
57
|
-
sections: ['personal', 'account', 'shared', 'builtIn'],
|
|
68
|
+
sections: isTrial ? ['personal', 'builtIn'] : ['personal', 'account', 'shared', 'builtIn'],
|
|
58
69
|
renderComponentItem: AgentItem,
|
|
59
70
|
isEnabled: isAgentEnabled,
|
|
60
71
|
onSelect: onSelectItem,
|
|
@@ -6,7 +6,8 @@ import { Selector } from '../../components/Selector'
|
|
|
6
6
|
import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
7
7
|
import { quickCommandRegex } from '../../regex'
|
|
8
8
|
|
|
9
|
-
export const QuickCommandSelector = ({ inputRef }:
|
|
9
|
+
export const QuickCommandSelector = ({ inputRef, isTrial }:
|
|
10
|
+
{ isTrial: boolean, inputRef: React.RefObject<HTMLTextAreaElement | HTMLInputElement> }) => {
|
|
10
11
|
const chat = useCurrentChat()
|
|
11
12
|
const isQuickCommandEnabled = useCurrentChatState('features').quickCommands
|
|
12
13
|
|
|
@@ -33,7 +34,7 @@ export const QuickCommandSelector = ({ inputRef }: { inputRef: React.RefObject<H
|
|
|
33
34
|
searchProp: 'slug',
|
|
34
35
|
urlBuilder: (qc) => `/quick-command/${qc?.slug}`,
|
|
35
36
|
regex: quickCommandRegex,
|
|
36
|
-
sections: ['personal', 'workspace', 'account', 'shared'],
|
|
37
|
+
sections: isTrial ? ['personal'] : ['personal', 'workspace', 'account', 'shared'],
|
|
37
38
|
isEnabled: isQuickCommandEnabled,
|
|
38
39
|
onSelect: onSelectItem,
|
|
39
40
|
renderComponentItem: QuickCommandItem,
|
|
@@ -6,13 +6,13 @@ import { ProgressBar } from '../../components/ProgressBar'
|
|
|
6
6
|
import { useCurrentChat, useCurrentChatState, useWidgetState } from '../../context/hooks'
|
|
7
7
|
import { quickCommandRegex } from '../../regex'
|
|
8
8
|
import { ChatEntry } from '../../state/ChatEntry'
|
|
9
|
+
import { checkIsTrial } from '../../utils/check-is-trial'
|
|
9
10
|
import { AgentSelector } from './AgentSelector'
|
|
10
11
|
import { ButtonAgent } from './ButtonAgent'
|
|
11
12
|
import { ButtonGroup } from './ButtonGroup'
|
|
13
|
+
import { useUserEntryHistoryShortcut } from './chat-entry-history'
|
|
12
14
|
import { useMessageInputDictionary } from './dictionary'
|
|
13
15
|
import { InfoBar } from './InfoBar'
|
|
14
|
-
|
|
15
|
-
import { useUserEntryHistoryShortcut } from './chat-entry-history'
|
|
16
16
|
import { QuickCommandSelector } from './QuickCommandSelector'
|
|
17
17
|
import { MAX_INPUT_HEIGHT, MessageInputBox, MIN_INPUT_HEIGHT } from './styled'
|
|
18
18
|
|
|
@@ -33,6 +33,7 @@ export const MessageInput = () => {
|
|
|
33
33
|
const textAreaRef = useRef<HTMLTextAreaElement>(null)
|
|
34
34
|
const agentLabel = useCurrentChatState('agent')?.label ?? 'Stackspot AI'
|
|
35
35
|
const { handleKeyDown, handleKeyUp } = useUserEntryHistoryShortcut()
|
|
36
|
+
const isTrial = checkIsTrial()
|
|
36
37
|
|
|
37
38
|
const onSend = useCallback(async () => {
|
|
38
39
|
const message = chat.get('nextMessage')
|
|
@@ -63,8 +64,8 @@ export const MessageInput = () => {
|
|
|
63
64
|
<ProgressBar visible={isLoading} shimmer />
|
|
64
65
|
<InfoBar />
|
|
65
66
|
<div className="wrapper-action">
|
|
66
|
-
<QuickCommandSelector inputRef={textAreaRef} />
|
|
67
|
-
<AgentSelector inputRef={textAreaRef} />
|
|
67
|
+
<QuickCommandSelector inputRef={textAreaRef} isTrial={isTrial} />
|
|
68
|
+
<AgentSelector inputRef={textAreaRef} isTrial={isTrial} />
|
|
68
69
|
<div className={listToClass(['action-box', focused && 'focused', isLoading && 'disabled'])}>
|
|
69
70
|
<ButtonAgent />
|
|
70
71
|
<AdaptiveTextArea
|
package/src/views/Stacks.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import { IconInput } from '../components/IconInput'
|
|
|
10
10
|
import { RightPanelTabs } from '../components/RightPanelTabs'
|
|
11
11
|
import { useCurrentChat, useWidget, useWidgetState } from '../context/hooks'
|
|
12
12
|
import { useRightPanel } from '../right-panel/hooks'
|
|
13
|
+
import { checkIsTrial } from '../utils/check-is-trial'
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Renders the Stack selection form in the Right Panel if this is the panel that is currently opened.
|
|
@@ -30,15 +31,20 @@ export const Stacks = () => {
|
|
|
30
31
|
return null
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
const StacksPanel =
|
|
34
|
+
const StacksPanel = () => {
|
|
34
35
|
const t = useTranslate(dictionary)
|
|
35
36
|
const chat = useCurrentChat()
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const isTrial = checkIsTrial()
|
|
38
|
+
|
|
39
|
+
const tabs = useMemo(() => isTrial ? [
|
|
40
|
+
{ title: t.personal, content: <StacksTab key="personal" visibility="personal" /> },
|
|
41
|
+
]: [
|
|
38
42
|
{ title: t.personal, content: <StacksTab key="personal" visibility="personal" /> },
|
|
39
43
|
{ title: t.shared, content: <StacksTab key="shared" visibility="shared" /> },
|
|
40
44
|
{ title: t.account, content: <StacksTab key="account" visibility="account" /> },
|
|
41
|
-
]
|
|
45
|
+
], [t, isTrial])
|
|
46
|
+
|
|
47
|
+
return <RightPanelTabs key={chat.id} tabs={tabs} />
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
const StacksTab = ({ visibility }: { visibility: VisibilityLevelEnum }) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { IconBox, Text } from '@citric/core'
|
|
2
2
|
import { Cog } from '@citric/icons'
|
|
3
3
|
import { listToClass } from '@stack-spot/portal-theme'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { StackedBadge } from '../../../components/StackedBadge'
|
|
5
|
+
import { useStepsDictionary } from '../dictionary'
|
|
6
6
|
import { getStatusIcon, getTitle, getTypeIcon } from '../utils'
|
|
7
7
|
import { HandleGroup } from './HandleGroup'
|
|
8
8
|
import { NodeData } from './types'
|
|
@@ -12,7 +12,7 @@ interface Props {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const NodeStep = ({ data: { step, index, nextStatus, onClick } }: Props) => {
|
|
15
|
-
const t =
|
|
15
|
+
const t = useStepsDictionary()
|
|
16
16
|
|
|
17
17
|
return (
|
|
18
18
|
<div
|
|
@@ -28,28 +28,16 @@ export const NodeStep = ({ data: { step, index, nextStatus, onClick } }: Props)
|
|
|
28
28
|
<Text className="step-index">{getTitle(t, step, index)}</Text>
|
|
29
29
|
{getStatusIcon(step.status)}
|
|
30
30
|
</header>
|
|
31
|
-
{step.
|
|
31
|
+
{step.type === 'planning' && <Text className="step-title">{step.goal}</Text>}
|
|
32
|
+
{step.type === 'step' && step.input && <Text className="step-title">{step.input}</Text>}
|
|
32
33
|
{step.type === 'step' && <div className="step-details">
|
|
33
|
-
<Text className={listToClass(['step-description', !!step.tools?.length && 'with-tools'])}>
|
|
34
|
-
{step.output
|
|
34
|
+
<Text className={listToClass(['step-description', !!step.attempts[0].tools?.length && 'with-tools'])}>
|
|
35
|
+
{step.output}
|
|
35
36
|
</Text>
|
|
36
|
-
{!!step.tools?.length &&
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{step.tools.slice(0, 3).map(
|
|
41
|
-
({ id, name, image }) => (
|
|
42
|
-
<li key={id}>
|
|
43
|
-
{image
|
|
44
|
-
? <img alt={name} aria-label={name} title={name} src={image} />
|
|
45
|
-
: <IconBox size="xs" aria-label={name} title={name}><Cog /></IconBox>
|
|
46
|
-
}
|
|
47
|
-
</li>
|
|
48
|
-
),
|
|
49
|
-
)}
|
|
50
|
-
</ul>
|
|
51
|
-
</div>
|
|
52
|
-
)}
|
|
37
|
+
{!!step.attempts[0].tools?.length && <StackedBadge
|
|
38
|
+
label={t.tools}
|
|
39
|
+
images={step.attempts[0].tools?.slice(0, 3).map(tool => ({ key: tool.id, name: tool.name, url: tool.image, icon: <Cog /> }))}
|
|
40
|
+
/>}
|
|
53
41
|
</div>}
|
|
54
42
|
<HandleGroup renderSource={step.type !== 'answer'} renderTarget={step.type !== 'planning'} />
|
|
55
43
|
</div>
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import { ChatStep } from '@stack-spot/portal-network'
|
|
1
2
|
import { listToClass, theme } from '@stack-spot/portal-theme'
|
|
2
3
|
import { Background, Controls, Edge, MarkerType, ReactFlow } from '@xyflow/react'
|
|
3
4
|
import '@xyflow/react/dist/style.css'
|
|
4
5
|
import { useMemo } from 'react'
|
|
5
6
|
import { useChatEntry } from '../../../context/hooks'
|
|
6
|
-
import { ChatEntry
|
|
7
|
+
import { ChatEntry } from '../../../state/ChatEntry'
|
|
7
8
|
import { useLayoutedElements } from './layout'
|
|
8
9
|
import { NodeStep } from './NodeStep'
|
|
9
10
|
import { FlowChartBox, runningColor } from './styled'
|
|
10
11
|
|
|
11
12
|
interface Props {
|
|
12
13
|
message: ChatEntry,
|
|
13
|
-
onClick: (step:
|
|
14
|
+
onClick: (step: ChatStep, index: number) => void,
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
const nodeTypes = {
|
|
@@ -56,11 +57,6 @@ export const FlowChart = ({ message, onClick }: Props) => {
|
|
|
56
57
|
edges={layouted.edges}
|
|
57
58
|
nodeTypes={nodeTypes}
|
|
58
59
|
snapToGrid={true}
|
|
59
|
-
fitViewOptions={{
|
|
60
|
-
minZoom: 1,
|
|
61
|
-
maxZoom: 1,
|
|
62
|
-
nodes: [layouted.nodes.find(n => n.data?.nextStatus === 'pending') ?? layouted.nodes[0]],
|
|
63
|
-
}}
|
|
64
60
|
fitView
|
|
65
61
|
>
|
|
66
62
|
<Controls orientation="horizontal" className="controls" showInteractive={false} />
|
|
@@ -88,55 +88,6 @@ export const FlowChartBox = styled.div`
|
|
|
88
88
|
-webkit-line-clamp: 2;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
|
|
92
|
-
.step-tools {
|
|
93
|
-
border-radius: 25px;
|
|
94
|
-
background-color: ${theme.color.light[600]};
|
|
95
|
-
border: 1px solid ${theme.color.light[500]};
|
|
96
|
-
color: ${theme.color.light[700]};
|
|
97
|
-
padding: 2px 7px;
|
|
98
|
-
display: flex;
|
|
99
|
-
gap: 5px;
|
|
100
|
-
align-items: center;
|
|
101
|
-
|
|
102
|
-
small {
|
|
103
|
-
line-height: 0.75rem;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
ul {
|
|
107
|
-
list-style: none;
|
|
108
|
-
margin: 0;
|
|
109
|
-
padding: 0;
|
|
110
|
-
display: flex;
|
|
111
|
-
flex-direction: row;
|
|
112
|
-
|
|
113
|
-
li {
|
|
114
|
-
border: 1px solid ${theme.color.light[600]};
|
|
115
|
-
background-color: ${theme.color.light[400]};
|
|
116
|
-
border-radius: 50%;
|
|
117
|
-
width: 16px;
|
|
118
|
-
height: 16px;
|
|
119
|
-
overflow: hidden;
|
|
120
|
-
display: flex;
|
|
121
|
-
align-items: center;
|
|
122
|
-
justify-content: center;
|
|
123
|
-
|
|
124
|
-
&:not(:first-child) {
|
|
125
|
-
margin-left: -12px;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
i {
|
|
130
|
-
width: 12px;
|
|
131
|
-
height: 12px;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
img, svg {
|
|
135
|
-
width: 100%;
|
|
136
|
-
height: 100%;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
91
|
}
|
|
141
92
|
}
|
|
142
93
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChatStep } from '@stack-spot/portal-network'
|
|
2
2
|
|
|
3
3
|
export interface NodeData {
|
|
4
|
-
nextStatus:
|
|
4
|
+
nextStatus: ChatStep['status'] | undefined,
|
|
5
5
|
onClick?: () => void,
|
|
6
|
-
step:
|
|
6
|
+
step: ChatStep,
|
|
7
7
|
index: number,
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { Flex, Text } from '@citric/core'
|
|
2
|
+
import { ChevronLeft, ChevronRight } from '@citric/icons'
|
|
3
|
+
import { Badge, IconButton } from '@citric/ui'
|
|
4
|
+
import { theme } from '@stack-spot/portal-theme'
|
|
5
|
+
import { useMemo, useState } from 'react'
|
|
6
|
+
import { styled } from 'styled-components'
|
|
7
|
+
import { Code } from '../../components/Code'
|
|
8
|
+
import { Markdown } from '../../components/Markdown'
|
|
9
|
+
import { Modal } from '../../components/Modal'
|
|
10
|
+
import { ToolBadge } from '../../components/ToolBadge'
|
|
11
|
+
import { useChatEntry } from '../../context/hooks'
|
|
12
|
+
import { ChatEntry } from '../../state/ChatEntry'
|
|
13
|
+
import { useStepsDictionary } from './dictionary'
|
|
14
|
+
import { getTitle, toPrecision } from './utils'
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
message: ChatEntry,
|
|
18
|
+
stepId: string | undefined,
|
|
19
|
+
onClose: () => void,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const StyledSection = styled.section`
|
|
23
|
+
padding: 18px 14px;
|
|
24
|
+
border-bottom: 1px solid var(--light-600);
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
gap: 12px;
|
|
28
|
+
align-items: start;
|
|
29
|
+
|
|
30
|
+
&:last-child {
|
|
31
|
+
border-bottom: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&.restrict-image-size img {
|
|
35
|
+
max-width: 100%;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.markdown p {
|
|
39
|
+
margin-top: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.tool {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
align-items: start;
|
|
46
|
+
align-self: stretch;
|
|
47
|
+
gap: 6px;
|
|
48
|
+
background-color: ${theme.color.light[500]};
|
|
49
|
+
border-radius: 5px;
|
|
50
|
+
padding: 6px;
|
|
51
|
+
|
|
52
|
+
&:not(:last-child) {
|
|
53
|
+
border-bottom: 1px solid ${theme.color.light[500]};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.tool-input {
|
|
57
|
+
align-self: stretch;
|
|
58
|
+
&, .highlighter {
|
|
59
|
+
background: ${theme.color.light[300]} !important;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
p {
|
|
65
|
+
line-height: 20px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
ul.steps {
|
|
69
|
+
margin: 0;
|
|
70
|
+
padding: 0;
|
|
71
|
+
list-style: none;
|
|
72
|
+
display: flex;
|
|
73
|
+
flex-direction: column;
|
|
74
|
+
gap: 8px;
|
|
75
|
+
|
|
76
|
+
> li {
|
|
77
|
+
padding: 8px 12px;
|
|
78
|
+
background-color: ${theme.color.light[500]};
|
|
79
|
+
border-radius: 6px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.step-description {
|
|
83
|
+
color: ${theme.color.light[700]};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
ul.side-by-side-tools {
|
|
88
|
+
margin: 14px 0 0 0;
|
|
89
|
+
padding: 0;
|
|
90
|
+
list-style: none;
|
|
91
|
+
display: flex;
|
|
92
|
+
gap: 10px;
|
|
93
|
+
flex-wrap: wrap;
|
|
94
|
+
}
|
|
95
|
+
`
|
|
96
|
+
|
|
97
|
+
const ExecutionBox = styled.div`
|
|
98
|
+
border-radius: 4px;
|
|
99
|
+
background-color: ${theme.color.light[500]};
|
|
100
|
+
color: ${theme.color.light[700]};
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
.time {
|
|
104
|
+
padding: 6px 8px;
|
|
105
|
+
border-right: 1px solid ${theme.color.light[600]};
|
|
106
|
+
}
|
|
107
|
+
.navigator {
|
|
108
|
+
display: flex;
|
|
109
|
+
gap: 4px;
|
|
110
|
+
align-items: center;
|
|
111
|
+
padding: 2px 8px;
|
|
112
|
+
button {
|
|
113
|
+
width: 12px;
|
|
114
|
+
height: 12px;
|
|
115
|
+
padding: 0;
|
|
116
|
+
}
|
|
117
|
+
small {
|
|
118
|
+
line-height: 0.75rem;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
`
|
|
122
|
+
|
|
123
|
+
export const StepModal = ({ message, stepId, onClose }: Props) => {
|
|
124
|
+
const t = useStepsDictionary()
|
|
125
|
+
const entry = useChatEntry(message)
|
|
126
|
+
const [attempt, setAttempt] = useState(0)
|
|
127
|
+
const stepIndex = useMemo(() => entry.steps?.findIndex(s => s.id === stepId) ?? -1, [entry, stepId])
|
|
128
|
+
const step = entry.steps?.[stepIndex]
|
|
129
|
+
|
|
130
|
+
const tools = step?.type === 'step' ? step.attempts[attempt]?.tools?.map(tool => (
|
|
131
|
+
<div className="tool" key={tool.id}>
|
|
132
|
+
<ToolBadge name={tool.name} duration={tool.duration} image={tool.image} description={tool.description} />
|
|
133
|
+
{tool.input && <>
|
|
134
|
+
<Text appearance="microtext1" colorScheme="light.700">{t.input}:</Text>
|
|
135
|
+
<Code language="json" className="tool-input" showLineNumbers={false} showActionBar>{tool.input}</Code>
|
|
136
|
+
</>}
|
|
137
|
+
{tool.output && <>
|
|
138
|
+
<Text appearance="microtext1" colorScheme="light.700">{t.response}:</Text>
|
|
139
|
+
<Code language="json" className="tool-input" showLineNumbers={false} showActionBar>{tool.output}</Code>
|
|
140
|
+
</>}
|
|
141
|
+
</div>
|
|
142
|
+
)) : undefined
|
|
143
|
+
|
|
144
|
+
const title = (
|
|
145
|
+
<Flex flex={1} justifyContent="space-between" alignItems="center">
|
|
146
|
+
<Text appearance="h6">{getTitle(t, step, stepIndex)}</Text>
|
|
147
|
+
<ExecutionBox>
|
|
148
|
+
<Text className="time" appearance="microtext1">
|
|
149
|
+
{step?.status === 'running' && t.running}
|
|
150
|
+
{step?.status === 'pending' && t.pending}
|
|
151
|
+
{step?.status === 'success' && `${t.executionTime}: ${step?.duration ? `${toPrecision(step?.duration)}s` : t.unknown}`}
|
|
152
|
+
</Text>
|
|
153
|
+
{step?.type === 'step' && step.attempts.length > 1 && <div className="navigator">
|
|
154
|
+
{attempt > 0 && (
|
|
155
|
+
<IconButton
|
|
156
|
+
size="xs"
|
|
157
|
+
appearance="text"
|
|
158
|
+
title={t.previousAttempt}
|
|
159
|
+
aria-label={t.previousAttempt}
|
|
160
|
+
onClick={() => setAttempt(attempt - 1)}
|
|
161
|
+
>
|
|
162
|
+
<ChevronLeft />
|
|
163
|
+
</IconButton>
|
|
164
|
+
)}
|
|
165
|
+
<Text appearance="microtext1">{attempt + 1}/{step.attempts.length}</Text>
|
|
166
|
+
{attempt < step.attempts.length - 1 && (
|
|
167
|
+
<IconButton
|
|
168
|
+
size="xs"
|
|
169
|
+
appearance="text"
|
|
170
|
+
title={t.nextAttempt}
|
|
171
|
+
aria-label={t.nextAttempt}
|
|
172
|
+
onClick={() => setAttempt(attempt + 1)}
|
|
173
|
+
>
|
|
174
|
+
<ChevronRight />
|
|
175
|
+
</IconButton>
|
|
176
|
+
)}
|
|
177
|
+
</div>}
|
|
178
|
+
</ExecutionBox>
|
|
179
|
+
</Flex>
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<Modal open={!!step} onClose={onClose} title={title}>
|
|
184
|
+
{step?.type === 'answer' && <StyledSection className="restrict-image-size">
|
|
185
|
+
{entry.type === 'md' ? <Markdown>{entry.content}</Markdown> : <Text>{entry.content}</Text>}
|
|
186
|
+
</StyledSection>}
|
|
187
|
+
|
|
188
|
+
{step?.type === 'planning' && <StyledSection style={{ alignItems: 'stretch' }}>
|
|
189
|
+
<Badge appearance="square" palette="blue" style={{ alignSelf: 'start' }}>Prompt</Badge>
|
|
190
|
+
<Text>{step.goal}</Text>
|
|
191
|
+
<ul className="steps">
|
|
192
|
+
{entry.steps?.filter(s => s.type === 'step').map((s, index) => (
|
|
193
|
+
<li key={index}>
|
|
194
|
+
<Flex mb={2}>
|
|
195
|
+
<Text>{t.step} {index + 1}: <span className="step-description">{s.input}</span></Text>
|
|
196
|
+
</Flex>
|
|
197
|
+
{!!s.attempts[0].tools?.length && <ul className="side-by-side-tools">
|
|
198
|
+
{s.attempts[0].tools.map((tool) => (
|
|
199
|
+
<li key={tool.id}>
|
|
200
|
+
<ToolBadge name={tool.name} image={tool.image} appearance="round" />
|
|
201
|
+
</li>
|
|
202
|
+
))}
|
|
203
|
+
</ul>}
|
|
204
|
+
</li>
|
|
205
|
+
))}
|
|
206
|
+
</ul>
|
|
207
|
+
</StyledSection>}
|
|
208
|
+
|
|
209
|
+
{step?.type === 'step' && step?.input && <StyledSection>
|
|
210
|
+
<Badge appearance="square" palette="blue">Prompt</Badge>
|
|
211
|
+
<Text>{step.input}</Text>
|
|
212
|
+
</StyledSection>}
|
|
213
|
+
{!!tools?.length && <StyledSection>{tools}</StyledSection>}
|
|
214
|
+
</Modal>
|
|
215
|
+
)
|
|
216
|
+
}
|
|
@@ -5,7 +5,7 @@ import { useWidget } from '../../context/hooks'
|
|
|
5
5
|
import { FlowChart } from './FlowChart'
|
|
6
6
|
import { StepModal } from './StepModal'
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const StepsPanel = ({ chatId, messageId }: { chatId: string, messageId: number }) => {
|
|
9
9
|
const [currentStepId, setCurrentStepId] = useState<string | undefined>()
|
|
10
10
|
const widget = useWidget()
|
|
11
11
|
const message = useMemo(
|
|
@@ -21,4 +21,4 @@ const ToolsPanel = ({ chatId, messageId }: { chatId: string, messageId: number }
|
|
|
21
21
|
) : null
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export default
|
|
24
|
+
export default StepsPanel
|