@stack-spot/ai-chat-widget 2.8.5 → 2.10.0

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 (72) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/app-metadata.json +3 -3
  3. package/dist/chat-interceptors/quick-commands.d.ts.map +1 -1
  4. package/dist/chat-interceptors/quick-commands.js +14 -5
  5. package/dist/chat-interceptors/quick-commands.js.map +1 -1
  6. package/dist/views/Chat/ButtonExecutionDetail.d.ts +5 -0
  7. package/dist/views/Chat/ButtonExecutionDetail.d.ts.map +1 -0
  8. package/dist/views/Chat/ButtonExecutionDetail.js +34 -0
  9. package/dist/views/Chat/ButtonExecutionDetail.js.map +1 -0
  10. package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
  11. package/dist/views/Chat/ChatMessage.js +9 -7
  12. package/dist/views/Chat/ChatMessage.js.map +1 -1
  13. package/dist/views/Steps/FlowChart/HandleGroup.d.ts +4 -1
  14. package/dist/views/Steps/FlowChart/HandleGroup.d.ts.map +1 -1
  15. package/dist/views/Steps/FlowChart/HandleGroup.js +1 -1
  16. package/dist/views/Steps/FlowChart/HandleGroup.js.map +1 -1
  17. package/dist/views/Steps/FlowChart/NodeDynamic.d.ts +15 -0
  18. package/dist/views/Steps/FlowChart/NodeDynamic.d.ts.map +1 -0
  19. package/dist/views/Steps/FlowChart/NodeDynamic.js +41 -0
  20. package/dist/views/Steps/FlowChart/NodeDynamic.js.map +1 -0
  21. package/dist/views/Steps/FlowChart/NodeStep.d.ts +4 -1
  22. package/dist/views/Steps/FlowChart/NodeStep.d.ts.map +1 -1
  23. package/dist/views/Steps/FlowChart/NodeStep.js +2 -2
  24. package/dist/views/Steps/FlowChart/NodeStep.js.map +1 -1
  25. package/dist/views/Steps/FlowChart/hooks.d.ts +7 -0
  26. package/dist/views/Steps/FlowChart/hooks.d.ts.map +1 -0
  27. package/dist/views/Steps/FlowChart/hooks.js +31 -0
  28. package/dist/views/Steps/FlowChart/hooks.js.map +1 -0
  29. package/dist/views/Steps/FlowChart/index.d.ts +4 -2
  30. package/dist/views/Steps/FlowChart/index.d.ts.map +1 -1
  31. package/dist/views/Steps/FlowChart/index.js +53 -23
  32. package/dist/views/Steps/FlowChart/index.js.map +1 -1
  33. package/dist/views/Steps/FlowChart/layout.d.ts +4 -13
  34. package/dist/views/Steps/FlowChart/layout.d.ts.map +1 -1
  35. package/dist/views/Steps/FlowChart/layout.js +25 -7
  36. package/dist/views/Steps/FlowChart/layout.js.map +1 -1
  37. package/dist/views/Steps/FlowChart/styled.d.ts +0 -1
  38. package/dist/views/Steps/FlowChart/styled.d.ts.map +1 -1
  39. package/dist/views/Steps/FlowChart/styled.js +39 -15
  40. package/dist/views/Steps/FlowChart/styled.js.map +1 -1
  41. package/dist/views/Steps/FlowChart/types.d.ts +14 -2
  42. package/dist/views/Steps/FlowChart/types.d.ts.map +1 -1
  43. package/dist/views/Steps/StepModal.d.ts +2 -1
  44. package/dist/views/Steps/StepModal.d.ts.map +1 -1
  45. package/dist/views/Steps/StepModal.js +24 -7
  46. package/dist/views/Steps/StepModal.js.map +1 -1
  47. package/dist/views/Steps/StepsPanel.d.ts.map +1 -1
  48. package/dist/views/Steps/StepsPanel.js +6 -2
  49. package/dist/views/Steps/StepsPanel.js.map +1 -1
  50. package/dist/views/Steps/dictionary.d.ts +5 -1
  51. package/dist/views/Steps/dictionary.d.ts.map +1 -1
  52. package/dist/views/Steps/dictionary.js +4 -0
  53. package/dist/views/Steps/dictionary.js.map +1 -1
  54. package/dist/views/Steps/utils.js +2 -2
  55. package/dist/views/Steps/utils.js.map +1 -1
  56. package/package.json +2 -2
  57. package/src/app-metadata.json +3 -3
  58. package/src/chat-interceptors/quick-commands.ts +14 -5
  59. package/src/views/Chat/ButtonExecutionDetail.tsx +46 -0
  60. package/src/views/Chat/ChatMessage.tsx +10 -6
  61. package/src/views/Steps/FlowChart/HandleGroup.tsx +5 -3
  62. package/src/views/Steps/FlowChart/NodeDynamic.tsx +97 -0
  63. package/src/views/Steps/FlowChart/NodeStep.tsx +6 -4
  64. package/src/views/Steps/FlowChart/hooks.ts +41 -0
  65. package/src/views/Steps/FlowChart/index.tsx +67 -23
  66. package/src/views/Steps/FlowChart/layout.ts +39 -16
  67. package/src/views/Steps/FlowChart/styled.ts +39 -15
  68. package/src/views/Steps/FlowChart/types.ts +16 -2
  69. package/src/views/Steps/StepModal.tsx +36 -13
  70. package/src/views/Steps/StepsPanel.tsx +9 -2
  71. package/src/views/Steps/dictionary.ts +4 -0
  72. package/src/views/Steps/utils.tsx +2 -2
@@ -1,10 +1,9 @@
1
1
  import { theme } from '@stack-spot/portal-theme'
2
2
  import { styled } from 'styled-components'
3
3
 
4
- export const stepNodeSize = { width: 160, height: 167 }
5
- export const planningNodeSize = { width: 160, height: 61 }
6
- export const answerNodeSize = { width: 160, height: 40 }
7
- export const runningColor = '#0097FA'
4
+ export const stepNodeSize = { width: 400, height: 167 }
5
+ export const planningNodeSize = { width: 400, height: 61 }
6
+ export const answerNodeSize = { width: 400, height: 40 }
8
7
 
9
8
  export const FlowChartBox = styled.div`
10
9
  width: 100%;
@@ -19,31 +18,35 @@ export const FlowChartBox = styled.div`
19
18
  border: 1px solid ${theme.color.light[600]};
20
19
  background-color: ${theme.color.light[500]};
21
20
  box-sizing: border-box;
22
- justify-content: center;
23
-
24
- &.running .source-handle {
25
- background-color: ${runningColor};
26
- }
21
+ justify-content: center;
22
+ width: 400px;
27
23
 
28
24
  &.pending .source-handle {
29
25
  opacity: 0.3;
30
26
  }
31
27
 
28
+ .source-handle {
29
+ transition: opacity 1s ease; opacity: 1;
30
+ }
31
+
32
+ &.running .source-handle {
33
+ opacity: 0;
34
+ }
35
+
32
36
  &.step {
33
37
  width: ${stepNodeSize.width}px;
34
- height: ${stepNodeSize.height}px;
38
+ min-height: ${stepNodeSize.height}px;
35
39
  }
36
40
 
37
41
  &.planning {
38
42
  width: ${planningNodeSize.width}px;
39
- height: ${planningNodeSize.height}px;
43
+ min-height: ${planningNodeSize.height}px;
40
44
  }
41
45
 
42
46
  &.answer {
43
47
  width: ${answerNodeSize.width}px;
44
- height: ${answerNodeSize.height}px;
48
+ min-height: ${answerNodeSize.height}px;
45
49
  }
46
-
47
50
  header {
48
51
  display: flex;
49
52
  gap: 4px;
@@ -71,7 +74,7 @@ export const FlowChartBox = styled.div`
71
74
  flex-direction: column;
72
75
  align-items: start;
73
76
  justify-content: space-between;
74
- gap: 10px;
77
+ gap: 8px;
75
78
  overflow: hidden;
76
79
 
77
80
  .step-description {
@@ -89,6 +92,28 @@ export const FlowChartBox = styled.div`
89
92
  }
90
93
  }
91
94
  }
95
+
96
+ .wrapper-tool {
97
+ &:not(:last-child) {
98
+ border-bottom: 1px solid ${theme.color.light[600]};
99
+ padding-bottom: 8px;
100
+ }
101
+
102
+ .tool {
103
+ padding: 8px;
104
+ border-radius: 4px;
105
+ min-height: 48px;
106
+ border: 1px solid ${theme.color.light[500]};
107
+ background-color: ${theme.color.light[400]};
108
+ border-bottom: 1px solid ${theme.color.light[300]};
109
+ cursor: pointer;
110
+
111
+ &:hover .title {
112
+ text-decoration: underline;
113
+ }
114
+ }
115
+ }
116
+
92
117
  }
93
118
 
94
119
  .source-handle {
@@ -121,7 +146,6 @@ export const FlowChartBox = styled.div`
121
146
  opacity: 0.3;
122
147
  }
123
148
  &.running path {
124
- stroke: ${runningColor};
125
149
  stroke-dasharray: 5, 5;
126
150
  }
127
151
  }
@@ -1,14 +1,28 @@
1
1
  import { ChatStep } from '@stack-spot/portal-network'
2
+ import { Node } from '@xyflow/react'
3
+ import { ChatEntry } from '../../../state/ChatEntry'
4
+
5
+ export type NodeType = 'step' | 'planning' | 'answer' | 'tool'
2
6
 
3
7
  export interface NodeData {
4
8
  nextStatus: ChatStep['status'] | undefined,
5
- onClick?: () => void,
9
+ onClick?: (toolIndex?: number) => void,
6
10
  step: ChatStep,
7
11
  index: number,
12
+ message: ChatEntry,
13
+ onResize?: (size: { width: number, height: number }) => void,
8
14
  }
9
15
 
10
16
  export interface NodeWithoutLayout {
11
17
  id: string,
12
- type: 'step' | 'planning' | 'answer' | 'tool',
18
+ type: NodeType,
13
19
  data?: NodeData,
14
20
  }
21
+
22
+ export type NodeDataFullProps = NodeData & Record<string, unknown>
23
+
24
+ export interface NodeFullProps extends Node<NodeDataFullProps> {
25
+ type: NodeType,
26
+ }
27
+
28
+
@@ -1,5 +1,7 @@
1
- import { Badge, IconButton, Row, Text } from '@stack-spot/citric-react'
1
+ import { Avatar, Badge, Divider, IconButton, Row, Text } from '@stack-spot/citric-react'
2
+ import { ChatAgentTool } from '@stack-spot/portal-network'
2
3
  import { theme } from '@stack-spot/portal-theme'
4
+ import { isNil } from 'lodash'
3
5
  import { useMemo, useState } from 'react'
4
6
  import { styled } from 'styled-components'
5
7
  import { Code } from '../../components/Code'
@@ -14,6 +16,7 @@ import { getTitle, toPrecision } from './utils'
14
16
  interface Props {
15
17
  message: ChatEntry,
16
18
  stepId: string | undefined,
19
+ toolIndex?: number,
17
20
  onClose: () => void,
18
21
  }
19
22
 
@@ -43,16 +46,26 @@ const StyledSection = styled.section`
43
46
  align-items: start;
44
47
  align-self: stretch;
45
48
  gap: 6px;
46
- background-color: ${theme.color.light[500]};
49
+ background-color: ${theme.color.light[400]};
47
50
  border-radius: 5px;
48
- padding: 6px;
51
+ padding: 0 6px;
49
52
 
50
53
  &:not(:last-child) {
51
54
  border-bottom: 1px solid ${theme.color.light[500]};
52
55
  }
53
56
 
57
+ hr {
58
+ margin: 16px 0;
59
+ }
60
+
61
+ .header-code {
62
+ background-color: ${theme.color.light[300]};
63
+ }
64
+
54
65
  .tool-input {
55
66
  align-self: stretch;
67
+ border: 1px solid ${theme.color.light[600]};
68
+ margin-top: 8px;
56
69
  &, .highlighter {
57
70
  background: ${theme.color.light[300]} !important;
58
71
  }
@@ -118,29 +131,39 @@ const ExecutionBox = styled.div`
118
131
  }
119
132
  `
120
133
 
121
- export const StepModal = ({ message, stepId, onClose }: Props) => {
134
+ export const StepModal = ({ message, stepId, toolIndex, onClose }: Props) => {
122
135
  const t = useStepsDictionary()
123
136
  const entry = useChatEntry(message)
124
137
  const [attempt, setAttempt] = useState(0)
125
138
  const stepIndex = useMemo(() => entry.steps?.findIndex(s => s.id === stepId) ?? -1, [entry, stepId])
126
139
  const step = entry.steps?.[stepIndex]
140
+ const showSingleTool = !isNil(toolIndex)
141
+ const attemptTools: ChatAgentTool[] | undefined = step?.type === 'step' ? step.attempts[attempt]?.tools : undefined
142
+ const toolsToRender = showSingleTool && attemptTools ? [attemptTools[toolIndex]].filter(Boolean) : attemptTools
127
143
 
128
- const tools = step?.type === 'step' ? step.attempts[attempt]?.tools?.map(tool => (
144
+ const tools = toolsToRender?.map(tool => (
129
145
  <div className="tool" key={tool.id}>
130
- <ToolBadge name={tool.name ?? ''} duration={tool.duration} image={tool.image} description={tool.description} />
146
+ {!showSingleTool && <ToolBadge name={tool.name ?? ''} duration={tool.duration} image={tool.image} description={tool.description} />}
131
147
  {tool.input && <>
132
- <Text appearance="microtext1" color="light.700">{t.input}:</Text>
148
+ <Badge appearance="square" colorPalette="cyan">{t.input}</Badge>
133
149
  <Code language="json" className="tool-input" showLineNumbers={false} showActionBar>{tool.input}</Code>
134
150
  </>}
135
151
  {tool.output && <>
136
- <Text appearance="microtext1" color="light.700">{t.response}:</Text>
152
+ <Divider />
153
+ <Badge appearance="square" colorPalette="cyan">{t.response}</Badge>
137
154
  <Code language="json" className="tool-input" showLineNumbers={false} showActionBar>{tool.output}</Code>
138
155
  </>}
139
156
  </div>
140
- )) : undefined
157
+ ))
141
158
 
142
- const title = (
143
- <Row flex={1} justifyContent="space-between">
159
+ const singleTool = showSingleTool ? toolsToRender?.[0] : undefined
160
+
161
+ const title = (showSingleTool
162
+ ? <Row flex={1} gap="8px">
163
+ {!!singleTool?.name && <Avatar size="xxs" image={singleTool?.image} name={singleTool?.name} />}
164
+ <Text appearance="h6">{singleTool?.name ?? t.finalAnswer}</Text>
165
+ </Row>
166
+ : <Row flex={1} justifyContent="space-between">
144
167
  <Text appearance="h6">{getTitle(t, step, stepIndex)}</Text>
145
168
  <ExecutionBox>
146
169
  <Text className="time" appearance="microtext1">
@@ -176,7 +199,7 @@ export const StepModal = ({ message, stepId, onClose }: Props) => {
176
199
  return (
177
200
  <Modal open={!!step} onClose={onClose} title={title}>
178
201
  {step?.type === 'answer' && <StyledSection className="restrict-image-size">
179
- {entry.type === 'md' ? <Markdown>{entry.content}</Markdown> : <Text>{entry.content}</Text>}
202
+ {entry.type === 'md' ? <Markdown>{entry.content}</Markdown> : <Text>{entry.content}</Text>}
180
203
  </StyledSection>}
181
204
 
182
205
  {step?.type === 'planning' && <StyledSection style={{ alignItems: 'stretch' }}>
@@ -199,7 +222,7 @@ export const StepModal = ({ message, stepId, onClose }: Props) => {
199
222
  ))}
200
223
  </ul>
201
224
  </StyledSection>}
202
-
225
+
203
226
  {step?.type === 'step' && step?.input && <StyledSection>
204
227
  <Badge appearance="square" colorPalette="blue">Prompt</Badge>
205
228
  <Text>{step.input}</Text>
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable import/no-default-export */
2
2
 
3
+ import { ChatStep } from '@stack-spot/portal-network'
3
4
  import { useMemo, useState } from 'react'
4
5
  import { useWidget } from '../../context/hooks'
5
6
  import { FlowChart } from './FlowChart'
@@ -7,16 +8,22 @@ import { StepModal } from './StepModal'
7
8
 
8
9
  const StepsPanel = ({ chatId, messageId }: { chatId: string, messageId: number }) => {
9
10
  const [currentStepId, setCurrentStepId] = useState<string | undefined>()
11
+ const [toolIndex, setToolIndex] = useState<number | undefined>()
10
12
  const widget = useWidget()
11
13
  const message = useMemo(
12
14
  () => widget.chatTabs.getAll().find(c => c.id === chatId)?.getMessages().find(m => m.id === messageId),
13
15
  [chatId, messageId],
14
16
  )
15
17
 
18
+ const handleClick = (step: ChatStep, tooIndex?: number) => {
19
+ setCurrentStepId(step.id)
20
+ setToolIndex(tooIndex)
21
+ }
22
+
16
23
  return message ? (
17
24
  <>
18
- <FlowChart message={message} onClick={(step) => setCurrentStepId(step.id)} />
19
- <StepModal message={message} stepId={currentStepId} onClose={() => setCurrentStepId(undefined)} />
25
+ <FlowChart message={message} onClick={handleClick} direction="TB" />
26
+ <StepModal message={message} stepId={currentStepId} toolIndex={toolIndex} onClose={() => setCurrentStepId(undefined)} />
20
27
  </>
21
28
  ) : null
22
29
  }
@@ -18,6 +18,8 @@ export const dictionary = {
18
18
  open: 'Open',
19
19
  close: 'Close',
20
20
  input: 'Input',
21
+ finalAnswer: 'Final answer',
22
+ userPrompt: 'User prompt',
21
23
  },
22
24
  pt: {
23
25
  stepsPanelDescription: 'Os passos e ferramentas usados para chegar na resposta',
@@ -34,6 +36,8 @@ export const dictionary = {
34
36
  nextAttempt: 'Próxima execução',
35
37
  previousAttempt: 'Execução anterior',
36
38
  input: 'Entrada',
39
+ finalAnswer: 'Resposta final',
40
+ userPrompt: 'Prompt do usuário',
37
41
  },
38
42
  } satisfies Dictionary
39
43
 
@@ -14,8 +14,8 @@ export function getStatusIcon(status: ChatStep['status']) {
14
14
 
15
15
  export function getTypeIcon(type: ChatStep['type']): WithIcon {
16
16
  switch (type) {
17
- case 'planning': return { group: 'outline', icon: 'ListUnordered' }
18
- default: return { group: 'fill', icon: 'Play' }
17
+ case 'planning': return { group: 'fill', icon: 'ChevronRight' }
18
+ default: return { group: 'outline', icon: 'StackSpot' }
19
19
  }
20
20
  }
21
21