@stack-spot/ai-chat-widget 1.37.0-beta.1 → 1.38.1-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 +20 -11
- package/dist/StackspotAIWidget.d.ts.map +1 -1
- package/dist/StackspotAIWidget.js +2 -1
- package/dist/StackspotAIWidget.js.map +1 -1
- package/dist/app-metadata.json +4 -4
- package/dist/chat-interceptors/quick-commands.js +2 -2
- package/dist/chat-interceptors/quick-commands.js.map +1 -1
- package/dist/components/FileDescription.d.ts +0 -1
- package/dist/components/FileDescription.d.ts.map +1 -1
- package/dist/components/FileDescription.js.map +1 -1
- package/dist/state/WidgetState.d.ts +1 -1
- package/dist/state/WidgetState.d.ts.map +1 -1
- package/dist/views/Agents/AgentDescription.d.ts.map +1 -1
- package/dist/views/Agents/AgentDescription.js +26 -14
- package/dist/views/Agents/AgentDescription.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.d.ts.map +1 -1
- package/dist/views/Agents/styled.js +14 -3
- package/dist/views/Agents/styled.js.map +1 -1
- package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessage.js +19 -9
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/Chat/styled.d.ts.map +1 -1
- package/dist/views/Chat/styled.js +28 -0
- package/dist/views/Chat/styled.js.map +1 -1
- package/dist/views/MessageInput/styled.js +8 -8
- package/dist/views/Resources.d.ts +2 -0
- package/dist/views/Resources.d.ts.map +1 -0
- package/dist/views/Resources.js +56 -0
- package/dist/views/Resources.js.map +1 -0
- package/dist/views/Steps/dictionary.d.ts +1 -1
- package/package.json +3 -3
- package/src/StackspotAIWidget.tsx +2 -0
- package/src/app-metadata.json +4 -4
- package/src/chat-interceptors/quick-commands.ts +2 -2
- package/src/components/FileDescription.tsx +0 -1
- package/src/state/WidgetState.ts +1 -1
- package/src/views/Agents/AgentDescription.tsx +65 -23
- package/src/views/Agents/dictionary.ts +2 -0
- package/src/views/Agents/styled.ts +14 -3
- package/src/views/Chat/ChatMessage.tsx +40 -7
- package/src/views/Chat/styled.ts +28 -0
- package/src/views/MessageInput/styled.ts +8 -8
- package/src/views/Resources.tsx +98 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, Button, Checkbox, Flex, IconBox, Input, Label, Radio, Text } from '@citric/core'
|
|
2
|
-
import { Check, Cog, Copy, Dislike, DislikeFill, Like, LikeFill, TimesCircle } from '@citric/icons'
|
|
3
|
-
import { Badge, IconButton, Tooltip } from '@citric/ui'
|
|
2
|
+
import { Agent, Check, Cog, Copy, Dislike, DislikeFill, Like, LikeFill, TimesCircle } from '@citric/icons'
|
|
3
|
+
import { Avatar, AvatarGroup, Badge, IconButton, Tooltip } from '@citric/ui'
|
|
4
4
|
import { agentToolsClient } from '@stack-spot/portal-network'
|
|
5
5
|
import { listToClass } from '@stack-spot/portal-theme'
|
|
6
6
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
@@ -10,7 +10,6 @@ import { PhoneInput } from 'react-international-phone'
|
|
|
10
10
|
import 'react-international-phone/style.css'
|
|
11
11
|
import { FileDescription } from '../../components/FileDescription'
|
|
12
12
|
import { Markdown } from '../../components/Markdown'
|
|
13
|
-
import { StackedBadge } from '../../components/StackedBadge'
|
|
14
13
|
import { useChatEntry, useCurrentChat, useWidget } from '../../context/hooks'
|
|
15
14
|
import { ChatEntry, SerializableAction, TextChatEntry } from '../../state/ChatEntry'
|
|
16
15
|
import { useDateFormatter } from '../../utils/date'
|
|
@@ -194,6 +193,8 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage }: Pr
|
|
|
194
193
|
const chat = useCurrentChat()
|
|
195
194
|
const agentId = entry.agent?.id ?? ''
|
|
196
195
|
const [toolKits] = agentToolsClient.tools.useStatefulQuery({}, { enabled: !!agentId })
|
|
196
|
+
const [agentsTools] = agentToolsClient.agentsByIds.useStatefulQuery(
|
|
197
|
+
{ searchAgentsRequest: { ids: entry.tools || [''] } }, { enabled: !!entry.tools })
|
|
197
198
|
const [copied, setCopied] = useState(false)
|
|
198
199
|
const [showUserButtonCopy, setShowUserButtonCopy] = useState(false)
|
|
199
200
|
|
|
@@ -307,12 +308,18 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage }: Pr
|
|
|
307
308
|
</form>
|
|
308
309
|
}
|
|
309
310
|
|
|
310
|
-
function openToolsPanel() {
|
|
311
|
+
// function openToolsPanel() {
|
|
312
|
+
// widget.set('currentMessageInPanel', { chatId: chat.id, messageId: message.id })
|
|
313
|
+
// widget.set('panel', 'tools')
|
|
314
|
+
// }
|
|
315
|
+
|
|
316
|
+
function openResourcesPanel() {
|
|
311
317
|
widget.set('currentMessageInPanel', { chatId: chat.id, messageId: message.id })
|
|
312
|
-
widget.set('panel', '
|
|
318
|
+
widget.set('panel', 'resources')
|
|
313
319
|
}
|
|
314
320
|
|
|
315
321
|
|
|
322
|
+
|
|
316
323
|
return (entry.content || entry.error || !!entry.steps?.length || entry.upload?.length) && (
|
|
317
324
|
<li key={entry.messageId} className={entry.agentType} ref={ref}>
|
|
318
325
|
<div className="chat-message-container"
|
|
@@ -340,7 +347,7 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage }: Pr
|
|
|
340
347
|
)}
|
|
341
348
|
</div>
|
|
342
349
|
{afterMessage && createElement(afterMessage, { message })}
|
|
343
|
-
{!!entry.tools?.length && <StackedBadge
|
|
350
|
+
{/* {!!entry.tools?.length && <StackedBadge
|
|
344
351
|
aria-label={t.openToolsPanel}
|
|
345
352
|
title={t.openToolsPanel}
|
|
346
353
|
tabIndex={0}
|
|
@@ -352,7 +359,8 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage }: Pr
|
|
|
352
359
|
return { key: id, name: tool?.name || id, icon: <Cog />, url: tool?.image }
|
|
353
360
|
})}
|
|
354
361
|
onClick={openToolsPanel}
|
|
355
|
-
/>}
|
|
362
|
+
/>} */}
|
|
363
|
+
|
|
356
364
|
{!!entry.knowledgeSources?.length && <div className="ks-box">
|
|
357
365
|
<Text appearance="microtext1" colorScheme="light.700">Knowledge Sources:</Text>
|
|
358
366
|
<ul>{entry.knowledgeSources.map((ks, index) => (
|
|
@@ -361,6 +369,28 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage }: Pr
|
|
|
361
369
|
</li>
|
|
362
370
|
))}</ul>
|
|
363
371
|
</div>}
|
|
372
|
+
|
|
373
|
+
{(!!agentsTools?.length || !!entry.tools?.length) && <div className="tools-box">
|
|
374
|
+
<AvatarGroup onClick={openResourcesPanel} aria-label={t.openResourcesPanel} role="button">
|
|
375
|
+
{agentsTools?.map((agent) => (
|
|
376
|
+
<Avatar size="xxs" key={agent.id} className="agent-info-avatar-resource">
|
|
377
|
+
{agent.avatar ?
|
|
378
|
+
<img alt={agent.name} aria-label={agent.name} title={agent.name} src={agent.avatar} /> :
|
|
379
|
+
<IconBox appearance="circle" aria-label={agent.name} title={agent.name} color="gray"><Agent /></IconBox>}
|
|
380
|
+
</Avatar>
|
|
381
|
+
))}
|
|
382
|
+
{entry.tools?.map((id) => {
|
|
383
|
+
const tool = toolById(id, toolKits)
|
|
384
|
+
return (
|
|
385
|
+
<Avatar size="xxs" key={id} className="agent-info-avatar-resource">
|
|
386
|
+
{tool?.image ?
|
|
387
|
+
<img alt={tool.name} aria-label={tool.name} title={tool.name} src={tool.image} /> :
|
|
388
|
+
<IconBox appearance="circle" aria-label={tool?.name} title={tool?.name} color="gray"><Cog /></IconBox>}
|
|
389
|
+
</Avatar>
|
|
390
|
+
)})}
|
|
391
|
+
|
|
392
|
+
</AvatarGroup>
|
|
393
|
+
</div>}
|
|
364
394
|
|
|
365
395
|
{shouldShowFooter && <div className="message-footer">
|
|
366
396
|
{entry.agentType === 'bot' && !entry.error && <div className="message-actions">
|
|
@@ -450,6 +480,8 @@ const dictionary = {
|
|
|
450
480
|
dislike: 'Dislike',
|
|
451
481
|
tools: 'Tools',
|
|
452
482
|
openToolsPanel: 'Open the tools panel to see more details.',
|
|
483
|
+
openResourcesPanel: 'Open the resources panel to see more details.',
|
|
484
|
+
|
|
453
485
|
copied: 'Copied',
|
|
454
486
|
},
|
|
455
487
|
pt: {
|
|
@@ -458,6 +490,7 @@ const dictionary = {
|
|
|
458
490
|
dislike: 'Não gostei',
|
|
459
491
|
tools: 'Ferramentas',
|
|
460
492
|
openToolsPanel: 'Abrir o painel de ferramentas para ver mais detalhes.',
|
|
493
|
+
openResourcesPanel: 'Abrir o painel de recursos para ver mais detalhes.',
|
|
461
494
|
copied: 'Copiado',
|
|
462
495
|
},
|
|
463
496
|
} satisfies Dictionary
|
package/src/views/Chat/styled.ts
CHANGED
|
@@ -219,6 +219,34 @@ export const ChatList: IStyledComponentBase<
|
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
.tools-box {
|
|
223
|
+
|
|
224
|
+
> ul {
|
|
225
|
+
display: flex;
|
|
226
|
+
flex-direction: row;
|
|
227
|
+
flex-wrap: wrap;
|
|
228
|
+
white-space: nowrap;
|
|
229
|
+
margin: 0;
|
|
230
|
+
margin-top: 8px;
|
|
231
|
+
padding: 0;
|
|
232
|
+
list-style: none;
|
|
233
|
+
gap: 6px;
|
|
234
|
+
|
|
235
|
+
&:hover{
|
|
236
|
+
cursor: pointer;
|
|
237
|
+
|
|
238
|
+
.agent-info-avatar-resource {
|
|
239
|
+
transition: margin-left 0.3s ease-in;
|
|
240
|
+
margin-left: 0px;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
222
250
|
.steps {
|
|
223
251
|
ul {
|
|
224
252
|
list-style: none;
|
|
@@ -67,14 +67,14 @@ export const MessageInputBox = styled.div<{$inputFocused?: boolean}>`
|
|
|
67
67
|
|
|
68
68
|
> .aria-live {
|
|
69
69
|
position: absolute;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
width: 1px;
|
|
71
|
+
height: 1px;
|
|
72
|
+
margin: -1px;
|
|
73
|
+
padding: 0;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
clip: rect(0 0 0 0);
|
|
76
|
+
white-space: nowrap;
|
|
77
|
+
border: 0;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
> .space {
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Box, Flex, IconBox, Text } from '@citric/core'
|
|
2
|
+
import { Agent } from '@citric/icons'
|
|
3
|
+
import { Avatar } from '@citric/ui'
|
|
4
|
+
import { agentToolsClient } from '@stack-spot/portal-network'
|
|
5
|
+
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
6
|
+
import { useEffect, useMemo } from 'react'
|
|
7
|
+
import { Accordion } from '../components/Accordion'
|
|
8
|
+
import { useWidget, useWidgetState } from '../context/hooks'
|
|
9
|
+
import { useRightPanel } from '../right-panel/hooks'
|
|
10
|
+
import { toolById } from '../utils/tools'
|
|
11
|
+
import { AgentDescription } from './Agents/AgentDescription'
|
|
12
|
+
|
|
13
|
+
export const Resources = () => {
|
|
14
|
+
const t = useTranslate(dictionary)
|
|
15
|
+
const panel = useWidgetState('panel')
|
|
16
|
+
const message = useWidgetState('currentMessageInPanel')
|
|
17
|
+
const { open } = useRightPanel()
|
|
18
|
+
const widget = useWidget()
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (panel === 'resources' && message) open(
|
|
22
|
+
<ResourcesPanel key={message.messageId} />,
|
|
23
|
+
{ title: t.title, description: t.description, onClose: () => widget.set('panel', undefined) },
|
|
24
|
+
)
|
|
25
|
+
}, [panel, t])
|
|
26
|
+
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const ResourcesPanel = () => {
|
|
31
|
+
const { chatId, messageId } = useWidgetState('currentMessageInPanel') ?? {}
|
|
32
|
+
const widget = useWidget()
|
|
33
|
+
const message = useMemo(() => {
|
|
34
|
+
const chat = widget.chatTabs.getAll().find(c => c.id === chatId)
|
|
35
|
+
return chat?.getMessages().find(m => m.id === messageId)?.getValue()
|
|
36
|
+
}, [messageId])
|
|
37
|
+
|
|
38
|
+
const [toolKits] = agentToolsClient.tools.useStatefulQuery({}, { enabled: !!message?.agent?.id })
|
|
39
|
+
const [agent] = agentToolsClient.agent.useStatefulQuery({ agentId: message?.agent?.id || '' },
|
|
40
|
+
{ enabled: !!message?.agent?.id })
|
|
41
|
+
const tools = useMemo(() => message?.tools?.map(id => toolById(id, toolKits)), [messageId, toolKits])
|
|
42
|
+
const customTools = useMemo(() => message?.tools?.map(id => toolById(id, agent?.toolkits?.custom_toolkits)),
|
|
43
|
+
[messageId, agent?.toolkits?.custom_toolkits])
|
|
44
|
+
|
|
45
|
+
const [agentsTools] = agentToolsClient.agentsByIds.useStatefulQuery({ searchAgentsRequest:{ ids: message?.tools || [] } })
|
|
46
|
+
const hasAgentTool = useMemo(() => message?.tools?.some(id => agentsTools?.find((agent) => agent.id === id)), [messageId, toolKits])
|
|
47
|
+
|
|
48
|
+
const header = (image?: string, label?: string) => (
|
|
49
|
+
<Flex alignItems="center">
|
|
50
|
+
{image ? <Avatar size="xxs">
|
|
51
|
+
<img title={label} src={image} />
|
|
52
|
+
</Avatar> :
|
|
53
|
+
<IconBox appearance="circle" title={label} color="gray"><Agent /></IconBox>}
|
|
54
|
+
<Text ml={3}>{label}</Text>
|
|
55
|
+
</Flex>
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return !!(tools?.length || customTools?.length) && (
|
|
59
|
+
<>
|
|
60
|
+
<>
|
|
61
|
+
{[...(tools || []), ...(customTools || [])].map(
|
|
62
|
+
(tool) =>
|
|
63
|
+
tool && (
|
|
64
|
+
<Box key={tool.id} mt={3}>
|
|
65
|
+
<Accordion header={header(tool?.image, tool?.name)}>
|
|
66
|
+
<Box sx={{ backgroundColor: 'light.400', m: '-10px', p: '16px' }}>
|
|
67
|
+
{tool?.description}
|
|
68
|
+
</Box>
|
|
69
|
+
</Accordion>
|
|
70
|
+
</Box>))}
|
|
71
|
+
</>
|
|
72
|
+
{hasAgentTool &&
|
|
73
|
+
<>
|
|
74
|
+
{message?.tools?.map((id) => {
|
|
75
|
+
const agentTool = agentsTools?.find((agent) => agent.id === id)
|
|
76
|
+
return (
|
|
77
|
+
<Box key={id} mt={3}>
|
|
78
|
+
<Accordion header={header(agentTool?.avatar || undefined, agentTool?.name)}>
|
|
79
|
+
<AgentDescription agentId={id} />
|
|
80
|
+
</Accordion>
|
|
81
|
+
</Box>)},
|
|
82
|
+
)}
|
|
83
|
+
</>}
|
|
84
|
+
</>
|
|
85
|
+
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const dictionary = {
|
|
90
|
+
en: {
|
|
91
|
+
title: 'Resources',
|
|
92
|
+
description: 'These are the resources used to generate this answer.',
|
|
93
|
+
},
|
|
94
|
+
pt: {
|
|
95
|
+
title: 'Recursos',
|
|
96
|
+
description: 'Esses são os recursos usados pra gerar essa resposta.',
|
|
97
|
+
},
|
|
98
|
+
} satisfies Dictionary
|