@stack-spot/ai-chat-widget 1.29.0-beta.0 → 1.29.1-beta.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.
- 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/components/AdaptiveTextArea.d.ts +2 -2
- package/dist/components/AdaptiveTextArea.d.ts.map +1 -1
- package/dist/components/AdaptiveTextArea.js +8 -2
- package/dist/components/AdaptiveTextArea.js.map +1 -1
- package/dist/components/AgentCard/dictionary.d.ts +4 -2
- package/dist/components/AgentCard/dictionary.d.ts.map +1 -1
- package/dist/components/AgentCard/dictionary.js +4 -2
- package/dist/components/AgentCard/dictionary.js.map +1 -1
- package/dist/components/Selector/index.d.ts +2 -2
- package/dist/components/Selector/index.d.ts.map +1 -1
- package/dist/components/Selector/index.js +2 -2
- package/dist/components/Selector/index.js.map +1 -1
- package/dist/state/types.d.ts +1 -1
- package/dist/state/types.d.ts.map +1 -1
- package/dist/utils/tools.d.ts +2 -2
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +3 -6
- package/dist/utils/tools.js.map +1 -1
- package/dist/views/Agents/AgentDescription.d.ts +2 -9
- package/dist/views/Agents/AgentDescription.d.ts.map +1 -1
- package/dist/views/Agents/AgentDescription.js +12 -9
- 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 +11 -11
- package/dist/views/Agents/AgentsPanel.js.map +1 -1
- package/dist/views/Agents/AgentsTab.d.ts +2 -2
- package/dist/views/Agents/AgentsTab.d.ts.map +1 -1
- package/dist/views/Agents/AgentsTab.js +6 -6
- package/dist/views/Agents/AgentsTab.js.map +1 -1
- package/dist/views/Agents/useAgentFavorites.d.ts +1 -1
- package/dist/views/Agents/useAgentFavorites.js +4 -4
- package/dist/views/Agents/useAgentFavorites.js.map +1 -1
- package/dist/views/Chat/ChatMessage.js +3 -3
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/ChatHistory/HistoryItem.d.ts.map +1 -1
- package/dist/views/ChatHistory/HistoryItem.js +8 -5
- package/dist/views/ChatHistory/HistoryItem.js.map +1 -1
- package/dist/views/ChatHistory/utils.d.ts +0 -6
- package/dist/views/ChatHistory/utils.d.ts.map +1 -1
- package/dist/views/ChatHistory/utils.js +1 -16
- package/dist/views/ChatHistory/utils.js.map +1 -1
- package/dist/views/Home/CustomAgent.js +3 -3
- package/dist/views/Home/CustomAgent.js.map +1 -1
- package/dist/views/MessageInput/AgentSelector.js +4 -4
- package/dist/views/MessageInput/AgentSelector.js.map +1 -1
- package/dist/views/MessageInput/ButtonAgent.js +2 -2
- package/dist/views/MessageInput/ButtonAgent.js.map +1 -1
- package/dist/views/MessageInput/index.d.ts +3 -1
- package/dist/views/MessageInput/index.d.ts.map +1 -1
- package/dist/views/MessageInput/index.js +5 -6
- package/dist/views/MessageInput/index.js.map +1 -1
- package/dist/views/MessageInput/styled.d.ts +0 -1
- package/dist/views/MessageInput/styled.d.ts.map +1 -1
- package/dist/views/MessageInput/styled.js +0 -1
- package/dist/views/MessageInput/styled.js.map +1 -1
- package/dist/views/Tools.js +3 -3
- package/dist/views/Tools.js.map +1 -1
- package/dist/views/Workspaces/WorkspacesTab.js +1 -1
- package/package.json +2 -2
- package/src/StackspotAIWidget.tsx +4 -3
- package/src/app-metadata.json +3 -3
- package/src/components/AdaptiveTextArea.tsx +13 -4
- package/src/components/AgentCard/dictionary.ts +4 -2
- package/src/components/Selector/index.tsx +4 -5
- package/src/state/types.ts +1 -1
- package/src/utils/tools.ts +5 -7
- package/src/views/Agents/AgentDescription.tsx +19 -25
- package/src/views/Agents/AgentsPanel.tsx +11 -12
- package/src/views/Agents/AgentsTab.tsx +12 -17
- package/src/views/Agents/useAgentFavorites.ts +4 -4
- package/src/views/Chat/ChatMessage.tsx +3 -3
- package/src/views/ChatHistory/HistoryItem.tsx +10 -5
- package/src/views/ChatHistory/utils.ts +1 -18
- package/src/views/Home/CustomAgent.tsx +4 -4
- package/src/views/MessageInput/AgentSelector.tsx +4 -4
- package/src/views/MessageInput/ButtonAgent.tsx +2 -2
- package/src/views/MessageInput/index.tsx +4 -5
- package/src/views/MessageInput/styled.ts +0 -1
- package/src/views/Tools.tsx +4 -3
- package/src/views/Workspaces/WorkspacesTab.tsx +1 -1
|
@@ -83,7 +83,8 @@ export const StackspotAIWidget = (
|
|
|
83
83
|
const isCurrentChatEmpty = currentChat.length === 0
|
|
84
84
|
const isTrial = checkIsTrial()
|
|
85
85
|
const features = useCurrentChatState('features')
|
|
86
|
-
|
|
86
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
87
|
+
|
|
87
88
|
return useMemo(() => (
|
|
88
89
|
<FallbackBoundary>
|
|
89
90
|
<TooltipProvider>
|
|
@@ -97,7 +98,7 @@ export const StackspotAIWidget = (
|
|
|
97
98
|
}
|
|
98
99
|
</>
|
|
99
100
|
}
|
|
100
|
-
<div className="chat-container">
|
|
101
|
+
<div ref={containerRef} className="chat-container">
|
|
101
102
|
<div className="chat-content">
|
|
102
103
|
{prefix}
|
|
103
104
|
{isCurrentChatEmpty
|
|
@@ -105,7 +106,7 @@ export const StackspotAIWidget = (
|
|
|
105
106
|
: <Chat username={username} beforeMessage={beforeMessage} afterMessage={afterMessage} />
|
|
106
107
|
}
|
|
107
108
|
</div>
|
|
108
|
-
{features.messageInput && <MessageInput />}
|
|
109
|
+
{features.messageInput && <MessageInput containerRef={containerRef} />}
|
|
109
110
|
</div>
|
|
110
111
|
</div>
|
|
111
112
|
<Stacks />
|
package/src/app-metadata.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stack-spot/ai-chat-widget",
|
|
3
|
-
"version": "1.29.
|
|
4
|
-
"date": "Thu Jul 03 2025
|
|
3
|
+
"version": "1.29.1-beta.0",
|
|
4
|
+
"date": "Thu Jul 03 2025 20:43:41 GMT-0300 (Brasilia Standard Time)",
|
|
5
5
|
"dependencies": [
|
|
6
6
|
{
|
|
7
7
|
"name": "@stack-spot/app-metadata",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"name": "@stack-spot/portal-network",
|
|
116
|
-
"version": "0.
|
|
116
|
+
"version": "0.149.0-beta.2(@stack-spot/auth@5.3.2)(@stack-spot/opa@2.5.0(@stack-spot/auth@5.3.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@stack-spot/portal-translate@1.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@tanstack/react-query@5.59.16(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"name": "@stack-spot/portal-theme",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* eslint-disable react/display-name */
|
|
2
2
|
import { Textarea } from '@citric/core'
|
|
3
|
-
import { forwardRef, useEffect, useRef } from 'react'
|
|
3
|
+
import { forwardRef, useEffect, useMemo, useRef } from 'react'
|
|
4
4
|
import { PropsOf } from '../types'
|
|
5
|
+
import { MIN_INPUT_HEIGHT } from '../views/MessageInput/styled'
|
|
5
6
|
|
|
6
7
|
interface Props extends PropsOf<typeof Textarea> {
|
|
7
8
|
/**
|
|
@@ -13,20 +14,28 @@ interface Props extends PropsOf<typeof Textarea> {
|
|
|
13
14
|
*/
|
|
14
15
|
onResetSize?: () => void,
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
+
* Reference to parent container to calculate dynamic max height
|
|
17
18
|
*/
|
|
18
|
-
|
|
19
|
+
containerRef?: React.RefObject<HTMLElement>,
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* The adaptive textarea grows in height whenever needed until the maximum height is reached.
|
|
23
24
|
*/
|
|
24
25
|
export const AdaptiveTextArea = forwardRef<HTMLTextAreaElement, Props>((
|
|
25
|
-
{ value, onIncreaseSize, onResetSize,
|
|
26
|
+
{ value, onIncreaseSize, onResetSize, style, containerRef, ...props },
|
|
26
27
|
externalRef,
|
|
27
28
|
) => {
|
|
28
29
|
const localRef = useRef<HTMLTextAreaElement>(null)
|
|
29
30
|
const ref = externalRef as React.RefObject<HTMLTextAreaElement> ?? localRef
|
|
31
|
+
/**
|
|
32
|
+
* Calculates the maximum height for the textarea.
|
|
33
|
+
* Uses 40% of container height if available, otherwise falls back to MIN_INPUT_HEIGHT.
|
|
34
|
+
*/
|
|
35
|
+
const maxHeight = useMemo(
|
|
36
|
+
() => containerRef?.current?.offsetHeight ? containerRef?.current?.offsetHeight * 0.4 : MIN_INPUT_HEIGHT,
|
|
37
|
+
[containerRef?.current?.offsetHeight],
|
|
38
|
+
)
|
|
30
39
|
|
|
31
40
|
const handleIncreaseSize = (newHeight: number) => {
|
|
32
41
|
onIncreaseSize?.()
|
|
@@ -2,7 +2,8 @@ import { Dictionary } from '@stack-spot/portal-translate'
|
|
|
2
2
|
|
|
3
3
|
export const dictionary = {
|
|
4
4
|
en: {
|
|
5
|
-
|
|
5
|
+
'built_in': 'Built-in',
|
|
6
|
+
workspace: 'Spot',
|
|
6
7
|
personal: 'Personal',
|
|
7
8
|
account: 'Account',
|
|
8
9
|
shared: 'Shared',
|
|
@@ -10,7 +11,8 @@ export const dictionary = {
|
|
|
10
11
|
create: 'Create',
|
|
11
12
|
},
|
|
12
13
|
pt: {
|
|
13
|
-
|
|
14
|
+
'built_in': 'Embutido',
|
|
15
|
+
workspace: 'Spot',
|
|
14
16
|
personal: 'Personal',
|
|
15
17
|
account: 'Conta',
|
|
16
18
|
shared: 'Compartilhado',
|
|
@@ -2,7 +2,7 @@ import { IconBox, Text } from '@citric/core'
|
|
|
2
2
|
import { ExternalLink } from '@citric/icons'
|
|
3
3
|
import { IconButton } from '@citric/ui'
|
|
4
4
|
import { useKeyboardControls } from '@stack-spot/portal-components'
|
|
5
|
-
import {
|
|
5
|
+
import { AgentVisibilityLevel } from '@stack-spot/portal-network'
|
|
6
6
|
import { Dictionary, interpolate, useTranslate } from '@stack-spot/portal-translate'
|
|
7
7
|
import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
8
8
|
import { useCurrentChatState } from '../../context/hooks'
|
|
@@ -12,8 +12,7 @@ import { Fading } from '../Fading'
|
|
|
12
12
|
import { FallbackBoundary } from '../FallbackBoundary'
|
|
13
13
|
import { SelectorBox } from './styled'
|
|
14
14
|
|
|
15
|
-
type SectionVisibility =
|
|
16
|
-
|
|
15
|
+
type SectionVisibility = AgentVisibilityLevel
|
|
17
16
|
type SelectorShortcut = '/' | '@'
|
|
18
17
|
|
|
19
18
|
interface Item {
|
|
@@ -268,7 +267,7 @@ const dictionary = {
|
|
|
268
267
|
personal: 'Personal',
|
|
269
268
|
account: 'Account',
|
|
270
269
|
shared: 'Shared',
|
|
271
|
-
'
|
|
270
|
+
'built_in': 'Built-in',
|
|
272
271
|
workspace: 'Spot',
|
|
273
272
|
error: 'Could not load the $0s.',
|
|
274
273
|
noData: 'You don\'t have any $0 yet.',
|
|
@@ -282,7 +281,7 @@ const dictionary = {
|
|
|
282
281
|
account: 'Conta',
|
|
283
282
|
shared: 'Compartilhado',
|
|
284
283
|
workspace: 'Spot',
|
|
285
|
-
'
|
|
284
|
+
'built_in': 'Embutido',
|
|
286
285
|
error: 'Não foi possível carregar os $0s.',
|
|
287
286
|
noData: 'Você ainda não possui $0s.',
|
|
288
287
|
noResults: 'Não $0s para mostrar aqui.',
|
package/src/state/types.ts
CHANGED
package/src/utils/tools.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BuiltinToolkitResponse, BuiltinToolResponse } from '@stack-spot/portal-network/api/agent'
|
|
2
|
+
import { keyBy } from 'lodash'
|
|
2
3
|
|
|
3
4
|
export type ToolWithImage = BuiltinToolResponse & { id: string, image?: string }
|
|
4
5
|
|
|
5
|
-
export function toolById(id: string, toolkits:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (tool.id === id) return { ...tool, id, image: toolkit.image_url }
|
|
9
|
-
}
|
|
10
|
-
}
|
|
6
|
+
export function toolById(id: string, toolkits: BuiltinToolkitResponse[] | undefined): ToolWithImage | undefined {
|
|
7
|
+
const tools = toolkits?.map(({ image_url, tools }) => tools?.map((tool) => ({ ...tool, id: tool.id!, image: image_url! }))).flat()
|
|
8
|
+
return keyBy(tools, 'id')[id]
|
|
11
9
|
}
|
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
import { Text } from '@citric/core'
|
|
2
2
|
import { Badge, Skeleton } from '@citric/ui'
|
|
3
|
-
import {
|
|
3
|
+
import { agentToolsClient } from '@stack-spot/portal-network'
|
|
4
4
|
import { useMemo } from 'react'
|
|
5
5
|
import { ToolBadge } from '../../components/ToolBadge'
|
|
6
|
+
import { toolById } from '../../utils/tools'
|
|
6
7
|
import { useAgentsDictionary } from './dictionary'
|
|
7
8
|
import { AgentDescriptionBox } from './styled'
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
agentId?: string,
|
|
11
|
-
llm?: string,
|
|
12
|
-
description?: string,
|
|
13
|
-
numberOfKnowledgeSources: number,
|
|
14
|
-
visibility: AgentVisibilityLevel,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export const AgentDescription = ({ agentId, llm, description, numberOfKnowledgeSources, visibility }: Props) => {
|
|
10
|
+
export const AgentDescription = ({ agentId }: { agentId?: string }) => {
|
|
18
11
|
const t = useAgentsDictionary()
|
|
19
|
-
const [agent, , , { isLoading }] =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)
|
|
12
|
+
const [agent, , , { isLoading }] = agentToolsClient.agent.useStatefulQuery({ agentId: agentId! }, { enabled: !!agentId })
|
|
13
|
+
const [toolKits, , , { isLoading: isLoadingToolKit }] = agentToolsClient.tools.useStatefulQuery({})
|
|
14
|
+
const numberOfKnowledgeSources = agent?.knowledge_source_config?.knowledge_sources.length ?? 0
|
|
23
15
|
|
|
24
16
|
const knowledgeSources = useMemo(
|
|
25
|
-
() => agent?.
|
|
26
|
-
<li key={index}><Badge palette="teal" appearance="square">{ks
|
|
17
|
+
() => agent?.knowledge_source_config?.knowledge_sources?.map((ks, index) => (
|
|
18
|
+
<li key={index}><Badge palette="teal" appearance="square">{ks}</Badge></li>
|
|
27
19
|
)),
|
|
28
20
|
[agent],
|
|
29
21
|
)
|
|
@@ -36,31 +28,33 @@ export const AgentDescription = ({ agentId, llm, description, numberOfKnowledgeS
|
|
|
36
28
|
}, [numberOfKnowledgeSources])
|
|
37
29
|
const tools = useMemo(() => {
|
|
38
30
|
const result: React.ReactElement[] = []
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
31
|
+
const builtInTools = agent?.toolkits?.builtin_toolkits?.[0].tools
|
|
32
|
+
for (const tool of builtInTools ?? []) {
|
|
33
|
+
const toolWithImage = toolById(tool.id, toolKits)
|
|
34
|
+
result.push(<li key={tool.id}>
|
|
35
|
+
<ToolBadge name={toolWithImage?.name || toolWithImage?.id || 'unknown'} image={toolWithImage?.image} />
|
|
36
|
+
</li>)
|
|
43
37
|
}
|
|
44
38
|
return result
|
|
45
39
|
}, [agent])
|
|
46
40
|
|
|
47
41
|
return (
|
|
48
42
|
<AgentDescriptionBox>
|
|
49
|
-
{description && <section>
|
|
43
|
+
{agent?.description && <section>
|
|
50
44
|
<Text appearance="microtext1" className="title">{t.description}</Text>
|
|
51
|
-
<Text>{description}</Text>
|
|
45
|
+
<Text>{agent?.description}</Text>
|
|
52
46
|
</section>}
|
|
53
47
|
{(!!numberOfKnowledgeSources || !!knowledgeSources?.length) && <section>
|
|
54
48
|
<Text appearance="microtext1" className="title">Knowledge sources</Text>
|
|
55
|
-
<ul>{isLoading ? skeleton : knowledgeSources}</ul>
|
|
49
|
+
<ul>{isLoading || isLoadingToolKit ? skeleton : knowledgeSources}</ul>
|
|
56
50
|
</section>}
|
|
57
51
|
{!!tools.length && <section>
|
|
58
52
|
<Text appearance="microtext1" className="title">{t.tools}</Text>
|
|
59
53
|
<ul>{tools}</ul>
|
|
60
54
|
</section>}
|
|
61
|
-
{
|
|
55
|
+
{agent?.model_name && <section>
|
|
62
56
|
<Text appearance="microtext1" className="title">LLM</Text>
|
|
63
|
-
<Badge palette="orange" appearance="square">{
|
|
57
|
+
<Badge palette="orange" appearance="square">{agent?.model_name}</Badge>
|
|
64
58
|
</section>}
|
|
65
59
|
</AgentDescriptionBox>
|
|
66
60
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { agentToolsClient } from '@stack-spot/portal-network'
|
|
1
2
|
import { useEffect, useMemo, useRef } from 'react'
|
|
2
3
|
import { RightPanelTabs } from '../../components/RightPanelTabs'
|
|
3
4
|
import { useCurrentChat } from '../../context/hooks'
|
|
@@ -5,8 +6,6 @@ import { checkIsTrial } from '../../utils/check-is-trial'
|
|
|
5
6
|
import { AgentsTab, AgentsTabWorkspace } from './AgentsTab'
|
|
6
7
|
import { useAgentsDictionary } from './dictionary'
|
|
7
8
|
|
|
8
|
-
const agentDefaultSlug = 'stk_code_buddy'
|
|
9
|
-
|
|
10
9
|
/**
|
|
11
10
|
* Renders the Agent selection form in the Right Panel if this is the panel that is currently opened.
|
|
12
11
|
*/
|
|
@@ -17,22 +16,22 @@ export const AgentsPanel = () => {
|
|
|
17
16
|
const agent = useRef(chat.get('agent'))
|
|
18
17
|
|
|
19
18
|
useEffect(() => {
|
|
20
|
-
if (agentDefaultSlug !== chat.get('agent')?.slug) {
|
|
19
|
+
if (agentToolsClient.agentDefaultSlug !== chat.get('agent')?.slug) {
|
|
21
20
|
agent.current = chat.get('agent')
|
|
22
21
|
}
|
|
23
22
|
}, [chat])
|
|
24
23
|
|
|
25
24
|
const tabs= useMemo(() => isTrial ? [
|
|
26
|
-
{ title: t.favorites, content: <AgentsTab key="favorite" visibility="
|
|
27
|
-
{ title: t.builtin, content: <AgentsTab key="builtin" visibility="
|
|
28
|
-
{ title: t.personal, content: <AgentsTab key="personal" visibility="
|
|
25
|
+
{ title: t.favorites, content: <AgentsTab key="favorite" visibility="favorite" agent={agent} /> },
|
|
26
|
+
{ title: t.builtin, content: <AgentsTab key="builtin" visibility="built_in" agent={agent} /> },
|
|
27
|
+
{ title: t.personal, content: <AgentsTab key="personal" visibility="personal" agent={agent} /> },
|
|
29
28
|
]: [
|
|
30
|
-
{ title: t.favorites, content: <AgentsTab key="favorite" visibility="
|
|
31
|
-
{ title: t.builtin, content: <AgentsTab key="builtin" visibility="
|
|
32
|
-
{ title: t.personal, content: <AgentsTab key="personal" visibility="
|
|
33
|
-
{ title: t.shared, content: <AgentsTab key="shared" visibility="
|
|
34
|
-
{ title: t.spots, content: <AgentsTabWorkspace key="workspace" visibility="
|
|
35
|
-
{ title: t.account, content: <AgentsTab key="account" visibility="
|
|
29
|
+
{ title: t.favorites, content: <AgentsTab key="favorite" visibility="favorite" agent={agent} /> },
|
|
30
|
+
{ title: t.builtin, content: <AgentsTab key="builtin" visibility="built_in" agent={agent} /> },
|
|
31
|
+
{ title: t.personal, content: <AgentsTab key="personal" visibility="personal" agent={agent} /> },
|
|
32
|
+
{ title: t.shared, content: <AgentsTab key="shared" visibility="shared" agent={agent} /> },
|
|
33
|
+
{ title: t.spots, content: <AgentsTabWorkspace key="workspace" visibility="workspace" agent={agent} /> },
|
|
34
|
+
{ title: t.account, content: <AgentsTab key="account" visibility="account" agent={agent} /> },
|
|
36
35
|
|
|
37
36
|
], [t, isTrial, agent])
|
|
38
37
|
|
|
@@ -2,8 +2,7 @@ import { Button, IconBox, Text } from '@citric/core'
|
|
|
2
2
|
import { Agent, Search } from '@citric/icons'
|
|
3
3
|
import { Placeholder } from '@stack-spot/portal-components/Placeholder'
|
|
4
4
|
import { MiniLogo } from '@stack-spot/portal-components/svg'
|
|
5
|
-
import {
|
|
6
|
-
import { VisibilityLevel } from '@stack-spot/portal-network/api/agent'
|
|
5
|
+
import { AgentResponseWithBuiltIn, agentToolsClient, AgentVisibilityLevel, workspaceAiClient } from '@stack-spot/portal-network'
|
|
7
6
|
import { WorkspaceResponse } from '@stack-spot/portal-network/api/workspace-ai'
|
|
8
7
|
import { useCallback, useMemo, useState } from 'react'
|
|
9
8
|
import { ButtonFavorite } from '../../components/ButtonFavorite'
|
|
@@ -20,7 +19,7 @@ import { AgentLabel } from './styled'
|
|
|
20
19
|
import { useAgentFavorites } from './useAgentFavorites'
|
|
21
20
|
|
|
22
21
|
export interface AgentTabProps {
|
|
23
|
-
visibility:
|
|
22
|
+
visibility: AgentVisibilityLevel,
|
|
24
23
|
workspaceId?: string,
|
|
25
24
|
agent: React.MutableRefObject<ChatProperties['agent']>,
|
|
26
25
|
showSubmitButton?: boolean,
|
|
@@ -33,16 +32,15 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
33
32
|
const [filter, setFilter] = useState('')
|
|
34
33
|
const { useFavorites, onAddFavorite, onRemoveFavorite } = useAgentFavorites()
|
|
35
34
|
const listFavorites = useFavorites()
|
|
36
|
-
const agentDefault =
|
|
35
|
+
const agentDefault = agentToolsClient.agentDefault.useQuery()
|
|
37
36
|
const agents = workspaceId
|
|
38
|
-
? workspaceAiClient.getAgentFromWorkspaceAi.useQuery({ workspaceId })
|
|
39
|
-
:
|
|
40
|
-
|
|
37
|
+
? workspaceAiClient.getAgentFromWorkspaceAi.useQuery({ workspaceId }) as AgentResponseWithBuiltIn[]
|
|
38
|
+
: agentToolsClient.agents.useQuery({ visibility })
|
|
41
39
|
|
|
42
40
|
const [value, setValue] = useState<AgentResponseWithBuiltIn | undefined>(
|
|
43
41
|
agent.current
|
|
44
42
|
? agents.find(a => a.id === agent.current?.id)
|
|
45
|
-
: chat.get('agent') ? agents.find(a => a.id === chat.get('agent')?.id) : agentDefault,
|
|
43
|
+
: chat.get('agent') ? agents.find(a => a.id === chat.get('agent')?.id) : agentDefault as unknown as AgentResponseWithBuiltIn,
|
|
46
44
|
)
|
|
47
45
|
|
|
48
46
|
const filtered = useMemo(
|
|
@@ -53,14 +51,17 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
53
51
|
|
|
54
52
|
function submit() {
|
|
55
53
|
if (value) {
|
|
56
|
-
chat.set(
|
|
54
|
+
chat.set(
|
|
55
|
+
'agent',
|
|
56
|
+
{ id: value.id, label: value.name, image: value.avatar!, builtIn: value.visibility_level === 'built_in', slug: value.slug },
|
|
57
|
+
)
|
|
57
58
|
}
|
|
58
59
|
close()
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
const onChange = useCallback((newValue: AgentResponseWithBuiltIn) => {
|
|
62
63
|
setValue(newValue)
|
|
63
|
-
agent.current = { ...newValue, label: newValue.name, builtIn:
|
|
64
|
+
agent.current = { ...newValue, label: newValue.name, builtIn: newValue.visibility_level === 'built_in' }
|
|
64
65
|
}, [])
|
|
65
66
|
|
|
66
67
|
return (
|
|
@@ -83,13 +84,7 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
83
84
|
<Text>{name}</Text>
|
|
84
85
|
</AgentLabel>
|
|
85
86
|
)}
|
|
86
|
-
renderDescription={a => <AgentDescription
|
|
87
|
-
agentId={a.id}
|
|
88
|
-
visibility={visibility}
|
|
89
|
-
description={a.description}
|
|
90
|
-
llm={a.llm_config?.model_slug}
|
|
91
|
-
numberOfKnowledgeSources={a.knowledge_sources_config?.knowledge_sources?.length ?? 0}
|
|
92
|
-
/>}
|
|
87
|
+
renderDescription={a => <AgentDescription agentId={a.id} />}
|
|
93
88
|
optionClassName={a => (a === value && filter && !a.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase()))
|
|
94
89
|
? 'filtered-out'
|
|
95
90
|
: ''
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/* eslint-disable filenames/match-regex */
|
|
2
|
-
import { agentClient } from '@stack-spot/portal-network'
|
|
2
|
+
import { agentClient, agentToolsClient } from '@stack-spot/portal-network'
|
|
3
3
|
|
|
4
4
|
export function useAgentFavorites() {
|
|
5
|
-
const useFavorites = () =>
|
|
5
|
+
const useFavorites = () => agentToolsClient.agents.useQuery({ visibility: 'favorite' })
|
|
6
6
|
const [addFavorite, pendingAddFav] = agentClient.addFavoriteAgent.useMutation()
|
|
7
7
|
const [removeFavorite, pendingRemoveFav] = agentClient.removeFavoriteAgent.useMutation()
|
|
8
8
|
|
|
9
9
|
const removeFavoriteAgent = async (idOrSlug?: string) => {
|
|
10
10
|
try {
|
|
11
11
|
await removeFavorite({ agentId: idOrSlug || '' })
|
|
12
|
-
await
|
|
12
|
+
await agentToolsClient.agents.invalidate({ visibility: 'favorite' })
|
|
13
13
|
} catch (error) {
|
|
14
14
|
// eslint-disable-next-line no-console
|
|
15
15
|
console.error(error)
|
|
@@ -19,7 +19,7 @@ export function useAgentFavorites() {
|
|
|
19
19
|
const addFavoriteAgent = async (idOrSlug?: string) => {
|
|
20
20
|
try {
|
|
21
21
|
await addFavorite({ agentId: idOrSlug || '' })
|
|
22
|
-
await
|
|
22
|
+
await agentToolsClient.agents.invalidate({ visibility: 'favorite' })
|
|
23
23
|
} catch (error) {
|
|
24
24
|
// eslint-disable-next-line no-console
|
|
25
25
|
console.error(error)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, Button, Checkbox, Flex, IconBox, Input, Label, Radio, Text } from '@citric/core'
|
|
2
2
|
import { Check, Cog, Copy, Dislike, DislikeFill, Like, LikeFill, TimesCircle } from '@citric/icons'
|
|
3
3
|
import { Badge, IconButton, Tooltip } from '@citric/ui'
|
|
4
|
-
import {
|
|
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'
|
|
7
7
|
import { groupBy } from 'lodash'
|
|
@@ -193,7 +193,7 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage }: Pr
|
|
|
193
193
|
const widget = useWidget()
|
|
194
194
|
const chat = useCurrentChat()
|
|
195
195
|
const agentId = entry.agent?.id ?? ''
|
|
196
|
-
const [
|
|
196
|
+
const [toolKits] = agentToolsClient.tools.useStatefulQuery({}, { enabled: !!agentId })
|
|
197
197
|
const [copied, setCopied] = useState(false)
|
|
198
198
|
const [showUserButtonCopy, setShowUserButtonCopy] = useState(false)
|
|
199
199
|
|
|
@@ -348,7 +348,7 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage }: Pr
|
|
|
348
348
|
className="tools-badge"
|
|
349
349
|
label={t.tools}
|
|
350
350
|
images={entry.tools.slice(0, 3).map((id) => {
|
|
351
|
-
const tool = toolById(id,
|
|
351
|
+
const tool = toolById(id, toolKits)
|
|
352
352
|
return { key: id, name: tool?.name || id, icon: <Cog />, url: tool?.image }
|
|
353
353
|
})}
|
|
354
354
|
onClick={openToolsPanel}
|
|
@@ -2,7 +2,7 @@ import { IconBox, Input } from '@citric/core'
|
|
|
2
2
|
import { Check, Download, EllipsisHorizontal, Pencil, Trash } from '@citric/icons'
|
|
3
3
|
import { IconButton, LoadingCircular } from '@citric/ui'
|
|
4
4
|
import { focusNextIgnoringChildren } from '@stack-spot/portal-components'
|
|
5
|
-
import { aiClient } from '@stack-spot/portal-network'
|
|
5
|
+
import { agentToolsClient, aiClient } from '@stack-spot/portal-network'
|
|
6
6
|
import { ConversationResponse } from '@stack-spot/portal-network/api/ai'
|
|
7
7
|
import { theme } from '@stack-spot/portal-theme'
|
|
8
8
|
import { last } from 'lodash'
|
|
@@ -11,12 +11,13 @@ import { OverlayMenu } from '../../components/OverlayMenu'
|
|
|
11
11
|
import { useWidget } from '../../context/hooks'
|
|
12
12
|
import { ChatEntry } from '../../state/ChatEntry'
|
|
13
13
|
import { ChatState } from '../../state/ChatState'
|
|
14
|
+
import { LabeledAgent } from '../../state/types'
|
|
14
15
|
import { ButtonAction } from '../../types'
|
|
15
16
|
import { download } from '../../utils/download'
|
|
16
17
|
import { genericSourcesToKnowledgeSources } from '../../utils/knowledge-source'
|
|
17
18
|
import { useHistoryDictionary } from './dictionary'
|
|
18
19
|
import { HistoryItemBox } from './styled'
|
|
19
|
-
import { findStack, findWorkspace
|
|
20
|
+
import { findStack, findWorkspace } from './utils'
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Renders an item of the list of conversations (history).
|
|
@@ -88,12 +89,16 @@ export const HistoryItem = ({ item }: { item: ConversationResponse }) => {
|
|
|
88
89
|
setLoading(true)
|
|
89
90
|
try {
|
|
90
91
|
const chat = await aiClient.chat.query({ conversationId: item.id })
|
|
92
|
+
const historyAgentIds = chat.history?.map(item => item.custom_agent?.id).filter(Boolean) as string[] ?? []
|
|
91
93
|
const [stack, workspace, agents] = await Promise.all([
|
|
92
94
|
findStack(chat.ai_stack_id),
|
|
93
95
|
findWorkspace(chat.workspace_id),
|
|
94
|
-
|
|
96
|
+
agentToolsClient.agentsByIds.query({ searchAgentsRequest: { ids: historyAgentIds } }),
|
|
95
97
|
])
|
|
96
|
-
const
|
|
98
|
+
const agentsAsLabeledAgents: LabeledAgent[] = agents
|
|
99
|
+
.map((a) => ({ ...a, label: a.name, image: a.avatar ?? '', builtIn: a.visibility_level === 'built_in' }))
|
|
100
|
+
|
|
101
|
+
const agent = agentsAsLabeledAgents.find(a => a.id === last(chat.history)?.custom_agent?.id)
|
|
97
102
|
const builtIn = !!last(chat.history ?? [])?.custom_agent?.built_in
|
|
98
103
|
widget.chatTabs.add(new ChatState({
|
|
99
104
|
id: chat.id,
|
|
@@ -103,7 +108,7 @@ export const HistoryItem = ({ item }: { item: ConversationResponse }) => {
|
|
|
103
108
|
agentType: item.agent === 'USER' ? 'user' : 'bot',
|
|
104
109
|
content: item.content,
|
|
105
110
|
type: 'md',
|
|
106
|
-
agent:
|
|
111
|
+
agent: agentsAsLabeledAgents.find(a => a.id === item.custom_agent?.id),
|
|
107
112
|
messageId: item.message_id,
|
|
108
113
|
knowledgeSources: item.agent === 'USER' ? undefined : genericSourcesToKnowledgeSources(item.sources),
|
|
109
114
|
updated: item.updated,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { aiClient, workspaceClient } from '@stack-spot/portal-network'
|
|
2
2
|
import { ChatProperties } from '../../state/ChatState'
|
|
3
|
-
import { LabeledWithImage } from '../../state/types'
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Finds a stack by its id.
|
|
@@ -36,19 +35,3 @@ export async function findWorkspace(id: string | null): Promise<ChatProperties['
|
|
|
36
35
|
return { id, label: id }
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Finds all the agents, including common agents and public agents.
|
|
43
|
-
* @returns an array with every agent.
|
|
44
|
-
*/
|
|
45
|
-
export async function getAllAgents(): Promise<LabeledWithImage[]> {
|
|
46
|
-
try {
|
|
47
|
-
const agents = await agentClient.allAgents.query({ visibilities: ['ALL'] })
|
|
48
|
-
return agents.map(a => ({ id: a.id, label: a.name, image: a.avatar, slug: a.slug, builtIn: a.builtIn }))
|
|
49
|
-
} catch (error) {
|
|
50
|
-
// eslint-disable-next-line no-console
|
|
51
|
-
console.error(error)
|
|
52
|
-
return []
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IconBox, Text } from '@citric/core'
|
|
2
2
|
import { Agent } from '@citric/icons'
|
|
3
|
-
import {
|
|
3
|
+
import { agentToolsClient } from '@stack-spot/portal-network'
|
|
4
4
|
import { useMemo } from 'react'
|
|
5
5
|
import { QuickStartButton } from '../../components/QuickStartButton'
|
|
6
6
|
import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
@@ -12,15 +12,15 @@ import { HomeBox } from './styled'
|
|
|
12
12
|
*/
|
|
13
13
|
export const CustomAgent = () => {
|
|
14
14
|
const { id, label, image } = useCurrentChatState('agent') ?? {}
|
|
15
|
-
const [agent] =
|
|
15
|
+
const [agent] = agentToolsClient.agent.useStatefulQuery({ agentId: id! })
|
|
16
16
|
const chat = useCurrentChat()
|
|
17
|
-
const suggestions = useMemo(() => agent?.
|
|
17
|
+
const suggestions = useMemo(() => agent?.conversation_starter?.map((prompt, index) => (
|
|
18
18
|
<QuickStartButton
|
|
19
19
|
key={index}
|
|
20
20
|
label={prompt}
|
|
21
21
|
onClick={() => send(prompt)}
|
|
22
22
|
/>
|
|
23
|
-
)), [agent?.
|
|
23
|
+
)), [agent?.conversation_starter])
|
|
24
24
|
|
|
25
25
|
function send(message: string) {
|
|
26
26
|
chat.pushMessage(ChatEntry.createUserEntry(message))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Flex, IconBox, Image } from '@citric/core'
|
|
2
2
|
import { Agent } from '@citric/icons'
|
|
3
|
-
import {
|
|
3
|
+
import { AgentResponseWithBuiltIn, agentToolsClient } from '@stack-spot/portal-network'
|
|
4
4
|
import { useCallback } from 'react'
|
|
5
5
|
import { Selector } from '../../components/Selector'
|
|
6
6
|
import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
@@ -53,9 +53,9 @@ export const AgentSelector = ({ inputRef, isTrial }: {
|
|
|
53
53
|
|
|
54
54
|
const getAgents = () => {
|
|
55
55
|
if (isTrial) {
|
|
56
|
-
return
|
|
56
|
+
return agentToolsClient.allAgents.useQuery({ visibilities: ['personal', 'built_in'] })
|
|
57
57
|
}
|
|
58
|
-
return
|
|
58
|
+
return agentToolsClient.allAgents.useQuery({ visibilities: ['account', 'shared', 'personal', 'built_in', 'workspace'] })
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
return <Selector
|
|
@@ -68,7 +68,7 @@ export const AgentSelector = ({ inputRef, isTrial }: {
|
|
|
68
68
|
regex: agentRegex,
|
|
69
69
|
urlBuilder: (agent) => `/agents/${agent?.id}`,
|
|
70
70
|
searchProp: 'name',
|
|
71
|
-
sections: isTrial ? ['favorite', 'personal', '
|
|
71
|
+
sections: isTrial ? ['favorite', 'personal', 'built_in'] : ['favorite', 'personal', 'workspace', 'account', 'shared', 'built_in'],
|
|
72
72
|
renderComponentItem: AgentItem,
|
|
73
73
|
isEnabled: isAgentEnabled,
|
|
74
74
|
onSelect: onSelectItem,
|
|
@@ -2,14 +2,14 @@ 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 {
|
|
5
|
+
import { agentToolsClient } from '@stack-spot/portal-network'
|
|
6
6
|
import { useEffect } from 'react'
|
|
7
7
|
import { useCurrentChat, useCurrentChatState, useWidget } from '../../context/hooks'
|
|
8
8
|
import { useMessageInputDictionary } from './dictionary'
|
|
9
9
|
|
|
10
10
|
export const ButtonAgent = () => {
|
|
11
11
|
const t = useMessageInputDictionary()
|
|
12
|
-
const agentDefault =
|
|
12
|
+
const agentDefault = agentToolsClient.agentDefault.useQuery()
|
|
13
13
|
const widget = useWidget()
|
|
14
14
|
const chat = useCurrentChat()
|
|
15
15
|
const agent = useCurrentChatState('agent')
|
|
@@ -3,7 +3,7 @@ import { interpolate } from '@stack-spot/portal-translate'
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
4
4
|
import { AdaptiveTextArea } from '../../components/AdaptiveTextArea'
|
|
5
5
|
import { ProgressBar } from '../../components/ProgressBar'
|
|
6
|
-
import { useCurrentChat, useCurrentChatState
|
|
6
|
+
import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
7
7
|
import { quickCommandRegex } from '../../regex'
|
|
8
8
|
import { ChatEntry } from '../../state/ChatEntry'
|
|
9
9
|
import { checkIsTrial } from '../../utils/check-is-trial'
|
|
@@ -16,7 +16,7 @@ import { useUserEntryHistoryShortcut } from './chat-entry-history'
|
|
|
16
16
|
import { ContextBar } from './ContextBar'
|
|
17
17
|
import { useMessageInputDictionary } from './dictionary'
|
|
18
18
|
import { QuickCommandSelector } from './QuickCommandSelector'
|
|
19
|
-
import {
|
|
19
|
+
import { MessageInputBox } from './styled'
|
|
20
20
|
import { UploadBar } from './UploadBar'
|
|
21
21
|
import { UploadDragNDrop, useUploadDragDrop } from './UploadDragNDrop'
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ import { UploadDragNDrop, useUploadDragDrop } from './UploadDragNDrop'
|
|
|
25
25
|
* going to be used for the question and the buttons to send, cancel, set the workspace, among others. This also includes the Quick
|
|
26
26
|
* Commands panel for auto completing.
|
|
27
27
|
*/
|
|
28
|
-
export const MessageInput = () => {
|
|
28
|
+
export const MessageInput = ({ containerRef }: { containerRef?: React.RefObject<HTMLElement> }) => {
|
|
29
29
|
const t = useMessageInputDictionary()
|
|
30
30
|
const [focused, setFocused] = useState(false)
|
|
31
31
|
const [, setExpanded] = useState(true)
|
|
@@ -33,7 +33,6 @@ export const MessageInput = () => {
|
|
|
33
33
|
const chat = useCurrentChat()
|
|
34
34
|
const isLoading = useCurrentChatState('isLoading') ?? false
|
|
35
35
|
const value = useCurrentChatState('nextMessage') ?? ''
|
|
36
|
-
const isMinimized = useWidgetState('isMinimized')
|
|
37
36
|
const textAreaRef = useRef<HTMLTextAreaElement>(null)
|
|
38
37
|
const agentLabel = useCurrentChatState('agent')?.label
|
|
39
38
|
const { handleKeyDown, handleKeyUp } = useUserEntryHistoryShortcut()
|
|
@@ -120,6 +119,7 @@ export const MessageInput = () => {
|
|
|
120
119
|
<div className={listToClass(['action-box', focused && 'focused', isLoading && 'disabled'])}>
|
|
121
120
|
<ButtonAgent />
|
|
122
121
|
<AdaptiveTextArea
|
|
122
|
+
containerRef={containerRef}
|
|
123
123
|
ref={textAreaRef}
|
|
124
124
|
placeholder={
|
|
125
125
|
agentLabel
|
|
@@ -134,7 +134,6 @@ export const MessageInput = () => {
|
|
|
134
134
|
onKeyUp={handleKeyUp}
|
|
135
135
|
onIncreaseSize={() => setExpanded(false)}
|
|
136
136
|
onResetSize={() => !expansionLocked.current && setExpanded(true)}
|
|
137
|
-
maxHeight={isMinimized ? MIN_INPUT_HEIGHT : MAX_INPUT_HEIGHT}
|
|
138
137
|
/>
|
|
139
138
|
</div>
|
|
140
139
|
</div>
|