@stack-spot/ai-chat-widget 1.13.2-beta.0 → 1.14.0-beta.1
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 +21 -0
- package/dist/StackspotAIWidget.d.ts.map +1 -1
- package/dist/StackspotAIWidget.js +3 -2
- package/dist/StackspotAIWidget.js.map +1 -1
- package/dist/app-metadata.json +3 -3
- package/dist/chat-interceptors/CustomInputs.d.ts +2 -2
- package/dist/chat-interceptors/CustomInputs.d.ts.map +1 -1
- package/dist/chat-interceptors/CustomInputs.js.map +1 -1
- package/dist/chat-interceptors/quick-commands.js.map +1 -1
- 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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/state/ChatEntry.d.ts +12 -19
- package/dist/state/ChatEntry.d.ts.map +1 -1
- package/dist/state/ChatEntry.js.map +1 -1
- package/dist/state/ChatState.d.ts +2 -5
- 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/state/types.d.ts +3 -1
- package/dist/state/types.d.ts.map +1 -1
- 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/AgentsTab.d.ts.map +1 -1
- package/dist/views/Agents/AgentsTab.js +4 -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.d.ts +2 -2
- package/dist/views/Chat/AgentInfo.d.ts.map +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 +22 -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/ChatHistory/utils.d.ts +2 -2
- package/dist/views/ChatHistory/utils.d.ts.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/MessageInput/AgentSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/AgentSelector.js +5 -9
- package/dist/views/MessageInput/AgentSelector.js.map +1 -1
- package/dist/views/MessageInput/ButtonAgent.d.ts.map +1 -1
- package/dist/views/MessageInput/ButtonAgent.js +21 -2
- package/dist/views/MessageInput/ButtonAgent.js.map +1 -1
- package/dist/views/MessageInput/index.js +2 -2
- package/dist/views/MessageInput/index.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 +2 -0
- package/src/app-metadata.json +3 -3
- package/src/chat-interceptors/CustomInputs.ts +3 -3
- package/src/chat-interceptors/quick-commands.ts +2 -2
- package/src/chat-interceptors/send-message.ts +4 -2
- package/src/components/Markdown.tsx +1 -0
- package/src/components/StackedBadge.tsx +77 -0
- package/src/components/ToolBadge.tsx +146 -0
- package/src/index.ts +1 -1
- package/src/state/ChatEntry.ts +12 -20
- package/src/state/ChatState.ts +2 -2
- package/src/state/WidgetState.ts +4 -16
- package/src/state/types.ts +4 -1
- package/src/utils/agent.ts +1 -1
- package/src/utils/tools.ts +11 -0
- package/src/views/Agents/AgentDescription.tsx +14 -0
- package/src/views/Agents/AgentsTab.tsx +5 -10
- package/src/views/Agents/dictionary.ts +2 -0
- package/src/views/Agents/styled.ts +1 -1
- package/src/views/Chat/AgentInfo.tsx +6 -6
- package/src/views/Chat/ChatMessage.tsx +34 -4
- package/src/views/Chat/StepsList.tsx +6 -6
- package/src/views/Chat/styled.ts +21 -12
- package/src/views/ChatHistory/utils.ts +2 -2
- package/src/views/ChatTabSelection.tsx +22 -4
- package/src/views/MessageInput/AgentSelector.tsx +7 -9
- package/src/views/MessageInput/ButtonAgent.tsx +26 -2
- package/src/views/MessageInput/index.tsx +2 -2
- 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/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/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
|
@@ -2,16 +2,40 @@ import { Flex, IconBox } from '@citric/core'
|
|
|
2
2
|
import { Agent, TimesMini } from '@citric/icons'
|
|
3
3
|
import { IconButton, Tooltip } from '@citric/ui'
|
|
4
4
|
import { MiniLogo } from '@stack-spot/portal-components/svg'
|
|
5
|
+
import { agentClient } from '@stack-spot/portal-network'
|
|
6
|
+
import { useEffect } from 'react'
|
|
5
7
|
import { useCurrentChat, useCurrentChatState, useWidget } from '../../context/hooks'
|
|
8
|
+
import { isAgentDefault } from '../../utils/agent'
|
|
6
9
|
import { useMessageInputDictionary } from './dictionary'
|
|
7
10
|
|
|
8
11
|
export const ButtonAgent = () => {
|
|
9
12
|
const t = useMessageInputDictionary()
|
|
13
|
+
const [agentsBuiltIn] = agentClient.publicAgents.useStatefulQuery({})
|
|
14
|
+
const agentDefault = agentsBuiltIn?.find((agent) => isAgentDefault(agent.slug))
|
|
10
15
|
const widget = useWidget()
|
|
11
16
|
const chat = useCurrentChat()
|
|
12
17
|
const agent = useCurrentChatState('agent')
|
|
13
18
|
const features = useCurrentChatState('features')
|
|
14
19
|
|
|
20
|
+
const setAgentDefault = () => {
|
|
21
|
+
agentDefault && chat.set(
|
|
22
|
+
'agent',
|
|
23
|
+
{
|
|
24
|
+
id: agentDefault.id,
|
|
25
|
+
slug: agentDefault.slug,
|
|
26
|
+
label: agentDefault.name,
|
|
27
|
+
image: agentDefault.avatar,
|
|
28
|
+
builtIn: true,
|
|
29
|
+
},
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!agent && !!agentDefault) {
|
|
35
|
+
setAgentDefault()
|
|
36
|
+
}
|
|
37
|
+
}, [agentDefault, agent])
|
|
38
|
+
|
|
15
39
|
return (
|
|
16
40
|
<div className="button-group">
|
|
17
41
|
{features.agent && (
|
|
@@ -19,9 +43,9 @@ export const ButtonAgent = () => {
|
|
|
19
43
|
<IconButton aria-label={t.agent} title={t.agent} className="agent" onClick={() => widget.set('panel', 'agent')}>
|
|
20
44
|
<MiniLogo />
|
|
21
45
|
</IconButton>
|
|
22
|
-
{agent?.id &&
|
|
46
|
+
{agent?.id && !isAgentDefault(agent?.slug) &&
|
|
23
47
|
<Tooltip text={t.remove} >
|
|
24
|
-
<IconButton aria-label={t.remove} className="agent agent-selected" onClick={
|
|
48
|
+
<IconButton aria-label={t.remove} className="agent agent-selected" onClick={setAgentDefault}>
|
|
25
49
|
{agent?.image ? <img src={agent.image} className="image" /> : <IconBox className="image" size="xs"><Agent /></IconBox>}
|
|
26
50
|
<Flex className="icon-remove" alignContent="center" justifyContent="center">
|
|
27
51
|
<TimesMini />
|
|
@@ -31,7 +31,7 @@ export const MessageInput = () => {
|
|
|
31
31
|
const value = useCurrentChatState('nextMessage') ?? ''
|
|
32
32
|
const isMinimized = useWidgetState('isMinimized')
|
|
33
33
|
const textAreaRef = useRef<HTMLTextAreaElement>(null)
|
|
34
|
-
const agentLabel = useCurrentChatState('agent')?.label
|
|
34
|
+
const agentLabel = useCurrentChatState('agent')?.label
|
|
35
35
|
const { handleKeyDown, handleKeyUp } = useUserEntryHistoryShortcut()
|
|
36
36
|
|
|
37
37
|
const onSend = useCallback(async () => {
|
|
@@ -70,7 +70,7 @@ export const MessageInput = () => {
|
|
|
70
70
|
<AdaptiveTextArea
|
|
71
71
|
ref={textAreaRef}
|
|
72
72
|
disabled={isLoading}
|
|
73
|
-
placeholder={interpolate(t.placeholder, agentLabel)}
|
|
73
|
+
placeholder={agentLabel && interpolate(t.placeholder, agentLabel)}
|
|
74
74
|
onChange={e => chat.set('nextMessage', e.target.value)}
|
|
75
75
|
value={value}
|
|
76
76
|
onFocus={() => setFocused(true)}
|
|
@@ -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
|
|
@@ -2,7 +2,8 @@ import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
|
2
2
|
|
|
3
3
|
export const dictionary = {
|
|
4
4
|
en: {
|
|
5
|
-
|
|
5
|
+
stepsPanelDescription: 'The steps and tools used to reach the answer',
|
|
6
|
+
steps: 'Steps',
|
|
6
7
|
step: 'Step',
|
|
7
8
|
response: 'Response',
|
|
8
9
|
tools: 'Tools',
|
|
@@ -12,15 +13,15 @@ export const dictionary = {
|
|
|
12
13
|
unknown: 'unknown',
|
|
13
14
|
running: 'Running',
|
|
14
15
|
pending: 'Pending',
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
thoughtFor: 'Thought for $0 seconds',
|
|
16
|
+
nextAttempt: 'Next execution',
|
|
17
|
+
previousAttempt: 'Previous execution',
|
|
18
18
|
open: 'Open',
|
|
19
19
|
close: 'Close',
|
|
20
20
|
input: 'Input',
|
|
21
21
|
},
|
|
22
22
|
pt: {
|
|
23
|
-
|
|
23
|
+
stepsPanelDescription: 'Os passos e ferramentas usados para chegar na resposta',
|
|
24
|
+
steps: 'Passos',
|
|
24
25
|
step: 'Passo',
|
|
25
26
|
response: 'Resposta',
|
|
26
27
|
tools: 'Ferramentas',
|
|
@@ -30,16 +31,13 @@ export const dictionary = {
|
|
|
30
31
|
unknown: 'desconhecido',
|
|
31
32
|
running: 'Executando',
|
|
32
33
|
pending: 'Aguardando',
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
thoughtFor: 'Pensado por $0 segundos',
|
|
36
|
-
open: 'Open',
|
|
37
|
-
close: 'Close',
|
|
34
|
+
nextAttempt: 'Próxima execução',
|
|
35
|
+
previousAttempt: 'Execução anterior',
|
|
38
36
|
input: 'Entrada',
|
|
39
37
|
},
|
|
40
38
|
} satisfies Dictionary
|
|
41
39
|
|
|
42
|
-
export function
|
|
40
|
+
export function useStepsDictionary() {
|
|
43
41
|
return useTranslate(dictionary)
|
|
44
42
|
}
|
|
45
43
|
|
|
@@ -3,31 +3,31 @@ import { LoadingCircular } from '@citric/ui'
|
|
|
3
3
|
import { lazy, Suspense, useEffect } from 'react'
|
|
4
4
|
import { useWidget, useWidgetState } from '../../context/hooks'
|
|
5
5
|
import { useRightPanel } from '../../right-panel/hooks'
|
|
6
|
-
import {
|
|
6
|
+
import { useStepsDictionary } from './dictionary'
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const LazyStepsPanel = lazy(() => import('./StepsPanel'))
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Renders the Stack selection form in the Right Panel if this is the panel that is currently opened.
|
|
12
12
|
*/
|
|
13
|
-
export const
|
|
14
|
-
const t =
|
|
13
|
+
export const Steps = () => {
|
|
14
|
+
const t = useStepsDictionary()
|
|
15
15
|
const panel = useWidgetState('panel')
|
|
16
|
-
const message = useWidgetState('
|
|
16
|
+
const message = useWidgetState('currentMessageInPanel')
|
|
17
17
|
const { open } = useRightPanel()
|
|
18
18
|
const widget = useWidget()
|
|
19
19
|
|
|
20
20
|
useEffect(() => {
|
|
21
|
-
if (panel === '
|
|
21
|
+
if (panel === 'steps' && message) open(
|
|
22
22
|
<Suspense fallback={<Flex alignItems="center" justifyContent="center" flex={1}><LoadingCircular /></Flex>}>
|
|
23
|
-
<
|
|
23
|
+
<LazyStepsPanel key={message.messageId} chatId={message.chatId} messageId={message.messageId} />
|
|
24
24
|
</Suspense>,
|
|
25
25
|
{
|
|
26
|
-
title: t.
|
|
27
|
-
description: t.
|
|
26
|
+
title: t.steps,
|
|
27
|
+
description: t.stepsPanelDescription,
|
|
28
28
|
onClose: () => {
|
|
29
29
|
widget.set('panel', undefined)
|
|
30
|
-
widget.set('
|
|
30
|
+
widget.set('currentMessageInPanel', undefined)
|
|
31
31
|
},
|
|
32
32
|
},
|
|
33
33
|
)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { IconBox } from '@citric/core'
|
|
2
2
|
import { CheckCircleFill, ListUnordered, PlayFill, TimesCircleFill } from '@citric/icons'
|
|
3
3
|
import { LoadingCircular } from '@citric/ui'
|
|
4
|
-
import {
|
|
4
|
+
import { ChatStep } from '@stack-spot/portal-network'
|
|
5
5
|
|
|
6
|
-
export function getStatusIcon(status:
|
|
6
|
+
export function getStatusIcon(status: ChatStep['status']) {
|
|
7
7
|
switch (status) {
|
|
8
8
|
case 'success': return <IconBox colorIcon="success.500"><CheckCircleFill /></IconBox>
|
|
9
9
|
case 'error': return <IconBox colorIcon="danger.500"><TimesCircleFill /></IconBox>
|
|
@@ -12,14 +12,14 @@ export function getStatusIcon(status: ChatEntryStep['status']) {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export function getTypeIcon(type:
|
|
15
|
+
export function getTypeIcon(type: ChatStep['type']) {
|
|
16
16
|
switch (type) {
|
|
17
17
|
case 'planning': return <ListUnordered />
|
|
18
18
|
default: return <PlayFill />
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export function getTitle(translation: Record<'planning' | 'step' | 'answer', string>, step:
|
|
22
|
+
export function getTitle(translation: Record<'planning' | 'step' | 'answer', string>, step: ChatStep | undefined, index: number) {
|
|
23
23
|
if (!step) return ''
|
|
24
24
|
switch (step.type) {
|
|
25
25
|
case 'planning': return translation.planning
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { agentClient } from '@stack-spot/portal-network'
|
|
2
|
+
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
3
|
+
import { useEffect, useMemo } from 'react'
|
|
4
|
+
import styled from 'styled-components'
|
|
5
|
+
import { ToolBadge } from '../components/ToolBadge'
|
|
6
|
+
import { useWidget, useWidgetState } from '../context/hooks'
|
|
7
|
+
import { useRightPanel } from '../right-panel/hooks'
|
|
8
|
+
import { toolById } from '../utils/tools'
|
|
9
|
+
|
|
10
|
+
const ToolList = styled.ul`
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
list-style: none;
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: 8px;
|
|
17
|
+
`
|
|
18
|
+
|
|
19
|
+
export const Tools = () => {
|
|
20
|
+
const t = useTranslate(dictionary)
|
|
21
|
+
const panel = useWidgetState('panel')
|
|
22
|
+
const message = useWidgetState('currentMessageInPanel')
|
|
23
|
+
const { open } = useRightPanel()
|
|
24
|
+
const widget = useWidget()
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (panel === 'tools' && message) open(
|
|
28
|
+
<ToolsPanel key={message.messageId} />,
|
|
29
|
+
{ title: t.title, description: t.description, onClose: () => widget.set('panel', undefined) },
|
|
30
|
+
)
|
|
31
|
+
}, [panel, t])
|
|
32
|
+
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const ToolsPanel = () => {
|
|
37
|
+
const { chatId, messageId } = useWidgetState('currentMessageInPanel') ?? {}
|
|
38
|
+
const widget = useWidget()
|
|
39
|
+
const message = useMemo(() => {
|
|
40
|
+
const chat = widget.chatTabs.getAll().find(c => c.id === chatId)
|
|
41
|
+
return chat?.getMessages().find(m => m.id === messageId)?.getValue()
|
|
42
|
+
}, [messageId])
|
|
43
|
+
const [agent] = agentClient.agent.useStatefulQuery({ agentId: message?.agent?.id ?? '' }, { enabled: !!message?.agent?.id })
|
|
44
|
+
const tools = useMemo(() => message?.tools?.map(id => toolById(id, agent?.toolkits) ?? { id }), [messageId, agent])
|
|
45
|
+
|
|
46
|
+
return !!tools?.length && (
|
|
47
|
+
<ToolList>
|
|
48
|
+
{tools.map((tool) => (
|
|
49
|
+
<li key={tool.id}>
|
|
50
|
+
<ToolBadge
|
|
51
|
+
name={tool.name || tool.id}
|
|
52
|
+
image={tool.image}
|
|
53
|
+
description={tool.description}
|
|
54
|
+
backgroundColor="light.500"
|
|
55
|
+
/>
|
|
56
|
+
</li>
|
|
57
|
+
))}
|
|
58
|
+
</ToolList>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const dictionary = {
|
|
63
|
+
en: {
|
|
64
|
+
title: 'Tools',
|
|
65
|
+
description: 'The tools used to generate the answer.',
|
|
66
|
+
},
|
|
67
|
+
pt: {
|
|
68
|
+
title: 'Ferramentas',
|
|
69
|
+
description: 'As ferramentas usadas para gerar a resposta.',
|
|
70
|
+
},
|
|
71
|
+
} satisfies Dictionary
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { IconBox, Text } from '@citric/core';
|
|
3
|
-
import { Cog } from '@citric/icons';
|
|
4
|
-
import { listToClass } from '@stack-spot/portal-theme';
|
|
5
|
-
import { last } from 'lodash';
|
|
6
|
-
import { useToolsDictionary } from '../dictionary.js';
|
|
7
|
-
import { getStatusIcon, getTitle, getTypeIcon } from '../utils.js';
|
|
8
|
-
import { HandleGroup } from './HandleGroup.js';
|
|
9
|
-
export const NodeStep = ({ data: { step, index, nextStatus, onClick } }) => {
|
|
10
|
-
const t = useToolsDictionary();
|
|
11
|
-
return (_jsxs("div", { className: listToClass(['chart-node', step.type, nextStatus]), onClick: onClick, onKeyDown: e => e.key === 'Enter' && onClick?.(), tabIndex: 0, role: "button", "aria-label": getTitle(t, step, index), children: [_jsxs("header", { children: [_jsx(IconBox, { children: getTypeIcon(step.type) }), _jsx(Text, { className: "step-index", children: getTitle(t, step, index) }), getStatusIcon(step.status)] }), step.input && _jsx(Text, { className: "step-title", children: step.input }), step.type === 'step' && _jsxs("div", { className: "step-details", children: [_jsx(Text, { className: listToClass(['step-description', !!step.tools?.length && 'with-tools']), children: step.output || last(step.tools)?.output }), !!step.tools?.length && (_jsxs("div", { className: "step-tools", children: [_jsx(Text, { appearance: "microtext1", children: t.tools }), _jsx("ul", { children: step.tools.slice(0, 3).map(({ id, name, image }) => (_jsx("li", { children: image
|
|
12
|
-
? _jsx("img", { alt: name, "aria-label": name, title: name, src: image })
|
|
13
|
-
: _jsx(IconBox, { size: "xs", "aria-label": name, title: name, children: _jsx(Cog, {}) }) }, id))) })] }))] }), _jsx(HandleGroup, { renderSource: step.type !== 'answer', renderTarget: step.type !== 'planning' })] }));
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=NodeStep.js.map
|