@stack-spot/ai-chat-widget 1.0.0-dev.1769003016623 → 1.0.0-dev.1769120820021
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/app-metadata.json +3 -3
- package/dist/chat-interceptors/send-message.d.ts.map +1 -1
- package/dist/chat-interceptors/send-message.js +5 -1
- package/dist/chat-interceptors/send-message.js.map +1 -1
- package/dist/components/Selector/SelectVersion.d.ts +12 -0
- package/dist/components/Selector/SelectVersion.d.ts.map +1 -0
- package/dist/components/Selector/SelectVersion.js +33 -0
- package/dist/components/Selector/SelectVersion.js.map +1 -0
- package/dist/components/Selector/index.d.ts +2 -0
- package/dist/components/Selector/index.d.ts.map +1 -1
- package/dist/components/Selector/index.js +5 -2
- package/dist/components/Selector/index.js.map +1 -1
- package/dist/components/Selector/styled.d.ts +2 -0
- package/dist/components/Selector/styled.d.ts.map +1 -1
- package/dist/components/Selector/styled.js +45 -0
- package/dist/components/Selector/styled.js.map +1 -1
- package/dist/hooks/enabled-feature-flags.d.ts +5 -0
- package/dist/hooks/enabled-feature-flags.d.ts.map +1 -0
- package/dist/hooks/enabled-feature-flags.js +28 -0
- package/dist/hooks/enabled-feature-flags.js.map +1 -0
- package/dist/state/types.d.ts +1 -0
- package/dist/state/types.d.ts.map +1 -1
- package/dist/utils/tools.d.ts +5 -5
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +2 -2
- package/dist/utils/tools.js.map +1 -1
- package/dist/views/Agents/AgentDescription.d.ts +6 -2
- package/dist/views/Agents/AgentDescription.d.ts.map +1 -1
- package/dist/views/Agents/AgentDescription.js +25 -10
- 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 +21 -4
- 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/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessage.js +6 -5
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/ChatHistory/utils.d.ts.map +1 -1
- package/dist/views/ChatHistory/utils.js +14 -7
- 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.d.ts.map +1 -1
- package/dist/views/MessageInput/AgentSelector.js +11 -1
- package/dist/views/MessageInput/AgentSelector.js.map +1 -1
- package/dist/views/MessageInput/ModelSwitcher/index.d.ts.map +1 -1
- package/dist/views/MessageInput/ModelSwitcher/index.js +3 -1
- package/dist/views/MessageInput/ModelSwitcher/index.js.map +1 -1
- package/dist/views/MessageInput/ModelSwitcher/utils.d.ts +2 -2
- package/dist/views/MessageInput/ModelSwitcher/utils.d.ts.map +1 -1
- package/dist/views/MessageInput/ModelSwitcher/utils.js +6 -6
- package/dist/views/MessageInput/ModelSwitcher/utils.js.map +1 -1
- package/dist/views/Resources.js +8 -5
- package/dist/views/Resources.js.map +1 -1
- package/dist/views/Tools.js +3 -2
- package/dist/views/Tools.js.map +1 -1
- package/package.json +2 -2
- package/src/app-metadata.json +3 -3
- package/src/chat-interceptors/send-message.ts +6 -2
- package/src/components/Selector/SelectVersion.tsx +55 -0
- package/src/components/Selector/index.tsx +11 -2
- package/src/components/Selector/styled.ts +47 -0
- package/src/hooks/enabled-feature-flags.ts +31 -0
- package/src/state/types.ts +1 -0
- package/src/utils/tools.ts +4 -4
- package/src/views/Agents/AgentDescription.tsx +48 -14
- package/src/views/Agents/AgentsTab.tsx +31 -13
- package/src/views/Agents/dictionary.ts +2 -1
- package/src/views/Chat/ChatMessage.tsx +8 -6
- package/src/views/ChatHistory/utils.ts +18 -10
- package/src/views/Home/CustomAgent.tsx +4 -4
- package/src/views/MessageInput/AgentSelector.tsx +15 -5
- package/src/views/MessageInput/ModelSwitcher/index.tsx +3 -2
- package/src/views/MessageInput/ModelSwitcher/utils.tsx +9 -8
- package/src/views/Resources.tsx +10 -6
- package/src/views/Tools.tsx +5 -4
package/src/app-metadata.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stack-spot/ai-chat-widget",
|
|
3
|
-
"version": "1.0.0-dev.
|
|
4
|
-
"date": "
|
|
3
|
+
"version": "1.0.0-dev.1769120820021",
|
|
4
|
+
"date": "Thu Jan 22 2026 22:27:05 GMT+0000 (Coordinated Universal Time)",
|
|
5
5
|
"dependencies": [
|
|
6
6
|
{
|
|
7
7
|
"name": "@stack-spot/app-metadata",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
"name": "@stack-spot/portal-network",
|
|
128
|
-
"version": "1.0.0-dev.
|
|
128
|
+
"version": "1.0.0-dev.1769117840606(@stack-spot/auth@6.1.0)(@stack-spot/opa@2.5.0(@stack-spot/auth@6.1.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(@stack-spot/portal-translate@2.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)"
|
|
129
129
|
},
|
|
130
130
|
{
|
|
131
131
|
"name": "@stack-spot/portal-theme",
|
|
@@ -202,8 +202,12 @@ export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState,
|
|
|
202
202
|
chat.set('label', content || entry.getValue().upload?.[0]?.name || 'Chat')
|
|
203
203
|
chat.untitled = false
|
|
204
204
|
}
|
|
205
|
-
|
|
206
|
-
const stream = aiClient.sendChatMessage({
|
|
205
|
+
|
|
206
|
+
const stream = aiClient.sendChatMessage({
|
|
207
|
+
context,
|
|
208
|
+
user_prompt: buildPrompt(content, data),
|
|
209
|
+
agent_version_number: chat.get('agent')?.agent_version_number,
|
|
210
|
+
})
|
|
207
211
|
signal.addEventListener('abort', () => stream.cancel())
|
|
208
212
|
const botEntry = ChatEntry.createStreamedBotEntry()
|
|
209
213
|
// we add the chat entry and show the streaming if the streaming feature is enabled
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
import { Select } from '@stack-spot/citric-react'
|
|
3
|
+
import { useTranslate } from '@stack-spot/portal-translate'
|
|
4
|
+
import { Dispatch, MouseEvent, SetStateAction, useEffect, useState } from 'react'
|
|
5
|
+
import { isEqual } from 'lodash'
|
|
6
|
+
import { VersionSelector } from './styled'
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
value?: number,
|
|
10
|
+
onChange: Dispatch<SetStateAction<number | undefined>>,
|
|
11
|
+
options?: number[],
|
|
12
|
+
lazyLoadOptions?: boolean,
|
|
13
|
+
useVersions?: (id: string, enabled: boolean) => number[] | undefined,
|
|
14
|
+
id: string,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const SelectVersion = ({ useVersions, value, onChange, options: initialOptions, id, lazyLoadOptions=false }: Props) => {
|
|
18
|
+
const t = useTranslate(dictionary)
|
|
19
|
+
const [options, setOptions] = useState(initialOptions)
|
|
20
|
+
const [enabled, setEnabled] = useState(!lazyLoadOptions)
|
|
21
|
+
const versions = useVersions?.(id, enabled)
|
|
22
|
+
|
|
23
|
+
const onClick = (e?: MouseEvent<HTMLDivElement>) => {
|
|
24
|
+
e?.stopPropagation()
|
|
25
|
+
if (lazyLoadOptions) {
|
|
26
|
+
setEnabled(true)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (lazyLoadOptions && !isEqual(versions, options)){
|
|
32
|
+
setOptions(versions)
|
|
33
|
+
}
|
|
34
|
+
}, [versions])
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<VersionSelector>
|
|
38
|
+
<Select className="version-selector"
|
|
39
|
+
options={options || []}
|
|
40
|
+
value={value}
|
|
41
|
+
onChange={onChange}
|
|
42
|
+
onClick={onClick}
|
|
43
|
+
renderLabel={(item) =>`${t.version} ${item}`} />
|
|
44
|
+
</VersionSelector>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const dictionary = {
|
|
49
|
+
en: {
|
|
50
|
+
version: 'Version',
|
|
51
|
+
},
|
|
52
|
+
pt: {
|
|
53
|
+
version: 'Versão',
|
|
54
|
+
},
|
|
55
|
+
}
|
|
@@ -10,6 +10,7 @@ import { useCurrentChatState, useWidgetState } from '../../context/hooks'
|
|
|
10
10
|
import { getUrlToStackSpotAI } from '../../utils/url'
|
|
11
11
|
import { ButtonFavorite } from '../ButtonFavorite'
|
|
12
12
|
import { Fading } from '../Fading'
|
|
13
|
+
import { SelectVersion } from './SelectVersion'
|
|
13
14
|
import { SelectorBox } from './styled'
|
|
14
15
|
|
|
15
16
|
type SectionVisibility = AgentVisibilityLevel | VisibilityLevelEnum
|
|
@@ -20,6 +21,7 @@ interface Item {
|
|
|
20
21
|
slug: string,
|
|
21
22
|
description: string,
|
|
22
23
|
visibility_level: SectionVisibility,
|
|
24
|
+
version_number?: number,
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
interface Favorite<T> {
|
|
@@ -69,6 +71,8 @@ interface SelectorConfig<T> {
|
|
|
69
71
|
regex: RegExp,
|
|
70
72
|
urlBuilder: (item: T) => string,
|
|
71
73
|
searchProp: keyof T,
|
|
74
|
+
isEnabledVersionContent?: boolean,
|
|
75
|
+
useVersions?: (id: string, enabled: boolean) => number[] | undefined,
|
|
72
76
|
isEnabled: boolean,
|
|
73
77
|
sections: SectionVisibility[],
|
|
74
78
|
renderComponentItem: FC<T>,
|
|
@@ -91,10 +95,11 @@ interface SelectorProps<T> {
|
|
|
91
95
|
|
|
92
96
|
const ListItem = <T extends Item>({ item, selectorConfig, onSelect, favorite }: ListItemProps<T>) => {
|
|
93
97
|
const t = useTranslate(dictionary)
|
|
94
|
-
const { urlBuilder, renderComponentItem } = selectorConfig
|
|
98
|
+
const { urlBuilder, renderComponentItem, useVersions, isEnabledVersionContent } = selectorConfig
|
|
95
99
|
const linkTitle = interpolate(t.open, item.slug)
|
|
96
100
|
const listFavorites = favorite?.useFavorites?.()
|
|
97
|
-
|
|
101
|
+
const [selectedVersion, setSelectedVersion] = useState(item.version_number)
|
|
102
|
+
|
|
98
103
|
return (
|
|
99
104
|
<li>
|
|
100
105
|
<button
|
|
@@ -106,6 +111,10 @@ const ListItem = <T extends Item>({ item, selectorConfig, onSelect, favorite }:
|
|
|
106
111
|
>
|
|
107
112
|
{renderComponentItem(item)}
|
|
108
113
|
</button>
|
|
114
|
+
{isEnabledVersionContent &&
|
|
115
|
+
<SelectVersion options={item.version_number ? [item.version_number] : []} id={item.id}
|
|
116
|
+
value={selectedVersion} onChange={setSelectedVersion} lazyLoadOptions={true} useVersions={useVersions}
|
|
117
|
+
/> }
|
|
109
118
|
<IconLink
|
|
110
119
|
icon="ExternalLink"
|
|
111
120
|
title={linkTitle}
|
|
@@ -156,3 +156,50 @@ export const SelectorBox = styled.div<{ $tabsCount: number }>`
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
`
|
|
159
|
+
|
|
160
|
+
export const VersionSelector = styled.div`
|
|
161
|
+
position: relative;
|
|
162
|
+
min-width: 100px;
|
|
163
|
+
|
|
164
|
+
.version-selector {
|
|
165
|
+
height: 28px;
|
|
166
|
+
position: absolute;
|
|
167
|
+
top: -18px;
|
|
168
|
+
left: -12px;
|
|
169
|
+
|
|
170
|
+
header {
|
|
171
|
+
height: 20px;
|
|
172
|
+
background-color: ${theme.color.light[300]};
|
|
173
|
+
border: none;
|
|
174
|
+
margin-bottom: 0;
|
|
175
|
+
gap: 0;
|
|
176
|
+
padding: 0;
|
|
177
|
+
|
|
178
|
+
}
|
|
179
|
+
.selection-panel .options{
|
|
180
|
+
overflow: hidden;
|
|
181
|
+
}
|
|
182
|
+
li {
|
|
183
|
+
gap: 5px;
|
|
184
|
+
padding: 0 8px 0 !important;
|
|
185
|
+
padding-left: 5px;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
`
|
|
190
|
+
|
|
191
|
+
export const VersionSelectorBox = styled.div`
|
|
192
|
+
border: 1px solid ${theme.color.light[500]};
|
|
193
|
+
border-radius: 4px;
|
|
194
|
+
.version-selector {
|
|
195
|
+
position: relative;
|
|
196
|
+
top: 0;
|
|
197
|
+
left: 0;
|
|
198
|
+
}
|
|
199
|
+
> div {
|
|
200
|
+
position: relative;
|
|
201
|
+
.options {
|
|
202
|
+
overflow: hidden;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
`
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { accountClient } from '@stack-spot/portal-network'
|
|
2
|
+
|
|
3
|
+
const useEnabledFeatureFlags = (resourceType?: string, resourceSlug?: string) => {
|
|
4
|
+
const queryParams = resourceType && resourceSlug ? { [resourceType]: resourceSlug } : {}
|
|
5
|
+
const [featureFlags, , error, { isLoading }] = accountClient.getEnabledFeatureFlagsForAccount.useStatefulQuery({
|
|
6
|
+
queryParams,
|
|
7
|
+
})
|
|
8
|
+
return { featureFlags, isLoading, error }
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const useIsFeatureFlagEnabled = (
|
|
12
|
+
flagSlug: string,
|
|
13
|
+
resourceType?: string,
|
|
14
|
+
resourceSlug?: string,
|
|
15
|
+
) => {
|
|
16
|
+
const { featureFlags, isLoading } = useEnabledFeatureFlags(resourceType, resourceSlug)
|
|
17
|
+
if (resourceType && resourceSlug) {
|
|
18
|
+
const featureFlag = featureFlags?.find((flag) => flag.slug === flagSlug)
|
|
19
|
+
const resourcesByType = featureFlag?.resources?.[resourceType]
|
|
20
|
+
if (!!featureFlag && !!resourcesByType) {
|
|
21
|
+
if (resourcesByType.mode === 'ALL') {
|
|
22
|
+
return { flagEnabled: true, isLoading }
|
|
23
|
+
} else {
|
|
24
|
+
return { flagEnabled: !!featureFlag.resources?.[resourceType].slugs.some((slug) => slug === resourceSlug), isLoading }
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return { flagEnabled: false, isLoading }
|
|
28
|
+
} else {
|
|
29
|
+
return { flagEnabled: !!featureFlags?.some((flag) => flag.slug === flagSlug), isLoading }
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/state/types.ts
CHANGED
package/src/utils/tools.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
export type ToolWithImage = { id?: string, image?: string, name
|
|
2
|
+
export type ToolWithImage = { id?: string | null, image?: string, name?: string, description?: string }
|
|
3
3
|
|
|
4
4
|
interface Toolkit {
|
|
5
5
|
id?: string | null,
|
|
6
|
-
tools?: { id?: string, name?: string, description?: string, function?: { name: string, description
|
|
6
|
+
tools?: { id?: string | null, name?: string, description?: string, function?: { name: string, description: string } | null }[] | null,
|
|
7
7
|
image_url?: string | null,
|
|
8
8
|
avatar?: string | null,
|
|
9
9
|
}
|
|
@@ -22,8 +22,8 @@ export function toolById(id: string, toolkits: Toolkit[] | undefined): ToolWithI
|
|
|
22
22
|
if (mcp) {
|
|
23
23
|
const [, toolkitId, toolName] = mcp
|
|
24
24
|
const toolkit = toolkits?.find(tk => tk.id === toolkitId)
|
|
25
|
-
const tool = toolkit?.tools?.find(t => t.name === toolName)
|
|
26
|
-
return { id, image: toolkit?.avatar ?? undefined, name:
|
|
25
|
+
const tool = toolkit?.tools?.find(t => t.name === toolName || t.function?.name === toolName)
|
|
26
|
+
return { id, image: toolkit?.avatar ?? undefined, name: tool?.function?.name, description: tool?.function?.description }
|
|
27
27
|
}
|
|
28
28
|
const { tool, toolkit } = findToolById(id, toolkits ?? []) ?? {}
|
|
29
29
|
return (tool && toolkit)
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import { Icon } from '@stack-spot/citric-icons'
|
|
2
|
-
import { AsyncContent, Badge, Card, IconBox, ImageBox, ImageWithFallback, Text } from '@stack-spot/citric-react'
|
|
2
|
+
import { AsyncContent, Badge, Card, IconBox, ImageBox, ImageWithFallback, Row, Text } from '@stack-spot/citric-react'
|
|
3
3
|
import { agentToolsClient } from '@stack-spot/portal-network'
|
|
4
|
-
import { useMemo } from 'react'
|
|
4
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
5
|
+
import { SelectVersion } from '../../components/Selector/SelectVersion'
|
|
6
|
+
import { VersionSelectorBox } from '../../components/Selector/styled'
|
|
5
7
|
import { useAgentsDictionary } from './dictionary'
|
|
6
8
|
import { AgentDescriptionBox } from './styled'
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
interface Props {
|
|
11
|
+
agentId?: string,
|
|
12
|
+
enableVersionSelect?: boolean,
|
|
13
|
+
onVersionChange?: (version?: number) => void,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const AgentDescription = ({ agentId, enableVersionSelect, onVersionChange }:Props) => {
|
|
9
17
|
const t = useAgentsDictionary()
|
|
10
|
-
const [
|
|
11
|
-
const
|
|
18
|
+
const [selectedVersion, setSelectedVersion] = useState<number | undefined>(undefined)
|
|
19
|
+
const [agent,, error, { isLoading }] = agentToolsClient.agentV2.useStatefulQuery({ agentCoreId: agentId!,
|
|
20
|
+
versionNumber: selectedVersion }, { enabled: !!agentId })
|
|
21
|
+
const [listVersions, , errorAgentWithVersion, { isLoading: isLoadingAgentWithVersions }] =
|
|
22
|
+
agentToolsClient.listAgentVersions.useStatefulQuery({ agentCoreId: agentId! },
|
|
23
|
+
{ enabled: enableVersionSelect && !!agentId })
|
|
24
|
+
const optionsVersions = listVersions?.map((version) => version.version_number)
|
|
25
|
+
const numberOfKnowledgeSources = agent?.version.knowledge_sources_config?.knowledge_sources.length ?? 0
|
|
12
26
|
|
|
13
27
|
const knowledgeSources = useMemo(
|
|
14
|
-
() => agent?.knowledge_sources_config?.knowledge_sources_details?.map((ks, index) => (
|
|
28
|
+
() => agent?.version.knowledge_sources_config?.knowledge_sources_details?.map((ks, index) => (
|
|
15
29
|
<li key={index}>
|
|
16
30
|
<Card gap="10px" direction="row" flex={1} size="xxs" bgLevel={500} justifyContent="space-between">
|
|
17
31
|
<Text color="light.contrastText">{ks.name}</Text>
|
|
@@ -21,12 +35,12 @@ export const AgentDescription = ({ agentId }: { agentId?: string }) => {
|
|
|
21
35
|
)),
|
|
22
36
|
[agent],
|
|
23
37
|
)
|
|
24
|
-
|
|
38
|
+
|
|
25
39
|
const { tools, multiAgents } = useMemo(() => {
|
|
26
40
|
const tools: React.ReactElement[] = []
|
|
27
41
|
const multiAgents: React.ReactElement[] = []
|
|
28
|
-
const builtInTools = agent?.toolkits?.builtin_toolkits ?? []
|
|
29
|
-
const customToolkits = agent?.toolkits?.custom_toolkits ?? []
|
|
42
|
+
const builtInTools = agent?.version.toolkits?.builtin_toolkits ?? []
|
|
43
|
+
const customToolkits = agent?.version.toolkits?.custom_toolkits ?? []
|
|
30
44
|
for (const toolkit of builtInTools) {
|
|
31
45
|
for (const tool of toolkit.tools ?? []) {
|
|
32
46
|
if (toolkit.id == 'UTILITIES'){
|
|
@@ -66,22 +80,42 @@ export const AgentDescription = ({ agentId }: { agentId?: string }) => {
|
|
|
66
80
|
return { tools, multiAgents }
|
|
67
81
|
}, [agent])
|
|
68
82
|
|
|
69
|
-
const mcpToolkits = useMemo(() => agent?.toolkits?.mcp_toolkits?.map(t => (
|
|
83
|
+
const mcpToolkits = useMemo(() => agent?.version.toolkits?.mcp_toolkits?.map(t => (
|
|
70
84
|
<li key={`mcp-${t.id}`}>
|
|
71
85
|
<Card gap="10px" direction="row" flex={1} size="xxs" bgLevel={500}>
|
|
72
86
|
<ImageBox><ImageWithFallback src={t.avatar ?? undefined} fallback={<Icon icon="Cog" />} /></ImageBox>
|
|
73
87
|
<Text color="light.contrastText">{t.name}</Text>
|
|
74
88
|
</Card>
|
|
75
89
|
</li>
|
|
76
|
-
)), [agent?.toolkits?.mcp_toolkits])
|
|
90
|
+
)), [agent?.version.toolkits?.mcp_toolkits])
|
|
91
|
+
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (!selectedVersion && agent?.version.version_number !== selectedVersion){
|
|
94
|
+
setSelectedVersion(agent?.version.version_number)
|
|
95
|
+
}
|
|
96
|
+
}, [agent?.version.version_number])
|
|
97
|
+
|
|
98
|
+
const onChangeVersion = (version?: number) => {
|
|
99
|
+
setSelectedVersion(version)
|
|
100
|
+
onVersionChange?.(version)
|
|
101
|
+
}
|
|
77
102
|
|
|
78
103
|
return (
|
|
79
|
-
<AsyncContent loading={isLoading} error={error}>
|
|
104
|
+
<AsyncContent loading={isLoading || isLoadingAgentWithVersions} error={error || errorAgentWithVersion}>
|
|
80
105
|
<AgentDescriptionBox>
|
|
81
106
|
{agent?.description && <section>
|
|
82
107
|
<Text appearance="microtext1" className="title">{t.description}</Text>
|
|
83
108
|
<Text>{agent?.description}</Text>
|
|
84
109
|
</section>}
|
|
110
|
+
{enableVersionSelect && optionsVersions && optionsVersions?.length > 0 && <section>
|
|
111
|
+
<VersionSelectorBox>
|
|
112
|
+
<Row justifyContent="space-between" p={4}>
|
|
113
|
+
<Text>{t.version}</Text>
|
|
114
|
+
<SelectVersion options={optionsVersions} value={selectedVersion}
|
|
115
|
+
onChange={(value?: any) => onChangeVersion(value)} id={agent?.id ?? ''} />
|
|
116
|
+
</Row>
|
|
117
|
+
</VersionSelectorBox>
|
|
118
|
+
</section>}
|
|
85
119
|
{(!!numberOfKnowledgeSources || !!knowledgeSources?.length) && <section>
|
|
86
120
|
<Text appearance="microtext1" className="title">Knowledge sources</Text>
|
|
87
121
|
<ul>{knowledgeSources}</ul>
|
|
@@ -97,9 +131,9 @@ export const AgentDescription = ({ agentId }: { agentId?: string }) => {
|
|
|
97
131
|
<Text appearance="microtext1" className="title">{t.multiAgent}</Text>
|
|
98
132
|
<ul>{multiAgents}</ul>
|
|
99
133
|
</section>}
|
|
100
|
-
{agent?.model_name && <section>
|
|
134
|
+
{agent?.version.model_name && <section>
|
|
101
135
|
<Text appearance="microtext1" className="title">LLM</Text>
|
|
102
|
-
<Badge colorPalette="orange" appearance="square">{agent?.model_name}</Badge>
|
|
136
|
+
<Badge colorPalette="orange" appearance="square">{agent?.version.model_name}</Badge>
|
|
103
137
|
</section>}
|
|
104
138
|
</AgentDescriptionBox>
|
|
105
139
|
</AsyncContent>
|
|
@@ -9,6 +9,7 @@ import { NavigationComponent } from '../../components/ComponentNavigator'
|
|
|
9
9
|
import { DescribedRadioGroup } from '../../components/form/DescribedRadioGroup'
|
|
10
10
|
import { WorkspaceTabNavigator } from '../../components/WorkspaceTabNavigator'
|
|
11
11
|
import { useCurrentChat } from '../../context/hooks'
|
|
12
|
+
import { useIsFeatureFlagEnabled } from '../../hooks/enabled-feature-flags'
|
|
12
13
|
import { useRightPanel } from '../../right-panel/hooks'
|
|
13
14
|
import { ChatProperties } from '../../state/ChatState'
|
|
14
15
|
import { AgentDescription } from './AgentDescription'
|
|
@@ -28,9 +29,10 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
28
29
|
const chat = useCurrentChat()
|
|
29
30
|
const { useFavorites, onAddFavorite, onRemoveFavorite } = useAgentFavorites()
|
|
30
31
|
const [submitEnabled, setSubmitEnabled] = useState(false)
|
|
32
|
+
const featureFlag = useIsFeatureFlagEnabled('ENABLE_VERSION_CONTENT_AI')
|
|
31
33
|
const listFavorites = useFavorites()
|
|
32
34
|
const agentDefault = agentToolsClient.agentDefault.useQuery()
|
|
33
|
-
|
|
35
|
+
const [agentVersions, setAgentVersions] = useState<Record<string, number | undefined>>({})
|
|
34
36
|
const [filter, setFilter] = useState<string | undefined>()
|
|
35
37
|
const [apiFilter, setApiFilter] = useState<string | undefined>()
|
|
36
38
|
const [isPending, startTransition] = useTransition()
|
|
@@ -59,15 +61,15 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
59
61
|
|
|
60
62
|
const agents = workspaceId ? workspaceAgents : agentsData
|
|
61
63
|
|
|
62
|
-
const initialValue = useMemo<AgentResponseWithBuiltIn | undefined>(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
const initialValue = useMemo<AgentResponseWithBuiltIn | undefined>(() => {
|
|
65
|
+
const initial = agent.current
|
|
66
|
+
? agents?.find(a => a.id === agent.current?.id)
|
|
67
|
+
: chat.get('agent') ?
|
|
68
|
+
agents?.find(a => a.id === chat.get('agent')?.id) : { ...agentDefault, suggested_prompts: null } as AgentResponseWithBuiltIn
|
|
69
|
+
if (initial && !submitEnabled) setSubmitEnabled(true)
|
|
70
|
+
return initial
|
|
71
|
+
},
|
|
72
|
+
[agents],
|
|
71
73
|
)
|
|
72
74
|
|
|
73
75
|
function submit() {
|
|
@@ -75,12 +77,26 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
75
77
|
close()
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
const onVersionChange = (ag: AgentResponseWithBuiltIn, version?: number) => {
|
|
81
|
+
setAgentVersions(prev => ({
|
|
82
|
+
...prev,
|
|
83
|
+
[ag.id]: version,
|
|
84
|
+
}))
|
|
85
|
+
|
|
86
|
+
if (agent.current?.id === ag.id) {
|
|
87
|
+
agent.current = {
|
|
88
|
+
...agent.current,
|
|
89
|
+
agent_version_number: version,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
78
94
|
return <>
|
|
79
95
|
<div className="content">
|
|
80
96
|
<DescribedRadioGroup
|
|
81
97
|
fetchNextPage={fetchNextPage}
|
|
82
98
|
hasNextPage={hasNextPage && !workspaceId}
|
|
83
|
-
options={agents}
|
|
99
|
+
options={agents || []}
|
|
84
100
|
initialValue={initialValue}
|
|
85
101
|
filter={workspaceId ? undefined : filter}
|
|
86
102
|
setFilter={workspaceId ? undefined : (value?: string) => {
|
|
@@ -89,7 +105,8 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
89
105
|
}}
|
|
90
106
|
onChange={(ag) => {
|
|
91
107
|
agent.current = ag
|
|
92
|
-
? { ...ag, label: ag.name, image: ag.avatar!, slug: ag.slug, builtIn: ag.visibility_level === 'built_in'
|
|
108
|
+
? { ...ag, label: ag.name, image: ag.avatar!, slug: ag.slug, builtIn: ag.visibility_level === 'built_in',
|
|
109
|
+
agent_version_number: agentVersions[ag.id] ?? ag.version_number }
|
|
93
110
|
: undefined
|
|
94
111
|
setSubmitEnabled(true)
|
|
95
112
|
}}
|
|
@@ -98,7 +115,8 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
98
115
|
idOrSlug: ag.id,
|
|
99
116
|
// below, "key" is important. I don't know why exactly, but sometimes the avatar doesn't update if we don't do this.
|
|
100
117
|
image: <ImageWithFallback key={ag.id} src={ag.avatar ?? undefined} fallback={<Icon icon="Agent" />} />,
|
|
101
|
-
description: <AgentDescription agentId={ag.id}
|
|
118
|
+
description: <AgentDescription agentId={ag.id} enableVersionSelect={featureFlag.flagEnabled}
|
|
119
|
+
onVersionChange={(version?: number) => onVersionChange(ag, version)} />,
|
|
102
120
|
name: ag.name,
|
|
103
121
|
listFavorites,
|
|
104
122
|
onAddFavorite,
|
|
@@ -19,6 +19,7 @@ const dictionary = {
|
|
|
19
19
|
tools: 'Tools',
|
|
20
20
|
spots: 'Spots',
|
|
21
21
|
multiAgent: 'Multi-agents',
|
|
22
|
+
version: 'Version',
|
|
22
23
|
},
|
|
23
24
|
pt: {
|
|
24
25
|
title: 'Agentes',
|
|
@@ -38,7 +39,7 @@ const dictionary = {
|
|
|
38
39
|
tools: 'Ferramentas',
|
|
39
40
|
spots: 'Spots',
|
|
40
41
|
multiAgent: 'Multi-agents',
|
|
41
|
-
|
|
42
|
+
version: 'Versão',
|
|
42
43
|
},
|
|
43
44
|
} satisfies Dictionary
|
|
44
45
|
|
|
@@ -215,14 +215,16 @@ export const ChatMessage = ({ message, isLast, beforeMessage, afterMessage, cust
|
|
|
215
215
|
const chat = useCurrentChat()
|
|
216
216
|
const agentId = entry.agent?.id ?? ''
|
|
217
217
|
// enabled: we don't want to make any request if there is no agent
|
|
218
|
-
const [agent] = agentToolsClient.
|
|
218
|
+
const [agent] = agentToolsClient.agentV2.useStatefulQuery({ agentCoreId: agentId, versionNumber: entry.agent?.agent_version_number },
|
|
219
|
+
{ enabled: !!agentId })
|
|
219
220
|
const toolkits = useMemo(() => [
|
|
220
|
-
...agent?.toolkits?.builtin_toolkits ?? [],
|
|
221
|
-
...agent?.toolkits?.custom_toolkits ?? [],
|
|
222
|
-
...agent?.toolkits?.mcp_toolkits ?? [],
|
|
221
|
+
...agent?.version?.toolkits?.builtin_toolkits ?? [],
|
|
222
|
+
...agent?.version?.toolkits?.custom_toolkits ?? [],
|
|
223
|
+
...agent?.version?.toolkits?.mcp_toolkits ?? [],
|
|
223
224
|
], [agent])
|
|
224
|
-
const
|
|
225
|
-
|
|
225
|
+
const agentsSearch = entry.tools?.map((id) => ({ agent_core_id: id })) ?? []
|
|
226
|
+
const [agentsTools] = agentToolsClient.agentsByIdsV2.useStatefulQuery(
|
|
227
|
+
{ searchAgentsRequestV2: { agents: agentsSearch } }, { enabled: !!entry.tools?.length })
|
|
226
228
|
const [copied, setCopied] = useState(false)
|
|
227
229
|
const [showUserButtonCopy, setShowUserButtonCopy] = useState(false)
|
|
228
230
|
const isPlanning = useCurrentChatState('isPlaning') ?? false
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { agentToolsClient, aiClient, AnswerChatStep, ChatAgentTool, ChatStep, PlanningChatStep, workspaceClient } from '@stack-spot/portal-network'
|
|
2
|
-
import {
|
|
2
|
+
import { AgentCoreWithSingleVersionResponse2 } from '@stack-spot/portal-network/api/agent-tools'
|
|
3
3
|
import { last } from 'lodash'
|
|
4
4
|
import { ChatEntry } from '../../state/ChatEntry'
|
|
5
5
|
import { ChatProperties, ChatState } from '../../state/ChatState'
|
|
@@ -56,11 +56,11 @@ function toJSONString(data: any) {
|
|
|
56
56
|
return `${data}`
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function findTool(agent:
|
|
59
|
+
function findTool(agent: AgentCoreWithSingleVersionResponse2 | undefined, id: string) {
|
|
60
60
|
const allToolkits = [
|
|
61
|
-
...agent?.toolkits?.builtin_toolkits ?? [],
|
|
62
|
-
...agent?.toolkits?.custom_toolkits ?? [],
|
|
63
|
-
...agent?.toolkits?.mcp_toolkits ?? [],
|
|
61
|
+
...agent?.version?.toolkits?.builtin_toolkits ?? [],
|
|
62
|
+
...agent?.version?.toolkits?.custom_toolkits ?? [],
|
|
63
|
+
...agent?.version?.toolkits?.mcp_toolkits ?? [],
|
|
64
64
|
]
|
|
65
65
|
for (const toolkit of allToolkits) {
|
|
66
66
|
for (const tool of toolkit.tools ?? []) {
|
|
@@ -75,9 +75,10 @@ async function stepsFromAgentInfo(
|
|
|
75
75
|
): Promise<ChatStep[] | undefined> {
|
|
76
76
|
const planningInfo = agentInfo?.find(i => i.type === 'planning' && !!i.data)
|
|
77
77
|
if (planningInfo) {
|
|
78
|
-
let agent:
|
|
78
|
+
let agent: AgentCoreWithSingleVersionResponse2 | undefined
|
|
79
79
|
try {
|
|
80
|
-
|
|
80
|
+
//TODO: avaliar se vamos precisar da versao aqui
|
|
81
|
+
agent = agentId ? await agentToolsClient.agentV2.query({ agentCoreId: agentId }) : undefined
|
|
81
82
|
} catch { /* empty */ }
|
|
82
83
|
const planning: PlanningChatStep = {
|
|
83
84
|
type: 'planning',
|
|
@@ -105,7 +106,7 @@ async function stepsFromAgentInfo(
|
|
|
105
106
|
return {
|
|
106
107
|
id: t.tool_id,
|
|
107
108
|
executionId: t.tool_execution_id,
|
|
108
|
-
name: tool?.name,
|
|
109
|
+
name: ('name' in tool ? tool.name : ('function' in tool ? tool?.function?.name : undefined) ?? ''),
|
|
109
110
|
description: 'description' in tool ? tool.description : undefined,
|
|
110
111
|
image: toolkit ? (('image_url' in toolkit ? toolkit?.image_url : toolkit?.avatar) ?? undefined) : undefined,
|
|
111
112
|
goal: t.goal,
|
|
@@ -139,11 +140,18 @@ function toolsFromAgentInfo(agentInfo: any[] | null | undefined): string[] {
|
|
|
139
140
|
*/
|
|
140
141
|
export async function loadChat(widget: WidgetState, conversationId: string) {
|
|
141
142
|
const chat = await aiClient.chat.query({ conversationId })
|
|
142
|
-
const
|
|
143
|
+
const historyAgents = chat.history?.reduce<{ agent_core_id: string }[]>((accumulator, item) => {
|
|
144
|
+
const agentId = item.custom_agent?.id
|
|
145
|
+
if (agentId !== undefined) {
|
|
146
|
+
accumulator.push({ agent_core_id: agentId })
|
|
147
|
+
}
|
|
148
|
+
return accumulator
|
|
149
|
+
}, []) ?? []
|
|
150
|
+
|
|
143
151
|
const [stack, workspace, agents] = await Promise.all([
|
|
144
152
|
findStack(chat.ai_stack_id),
|
|
145
153
|
findWorkspace(chat.workspace_id),
|
|
146
|
-
agentToolsClient.
|
|
154
|
+
agentToolsClient.agentsByIdsV2.query({ searchAgentsRequestV2: { agents: historyAgents } }),
|
|
147
155
|
])
|
|
148
156
|
const agentsAsLabeledAgents: LabeledAgent[] = agents
|
|
149
157
|
.map((a) => ({ ...a, label: a.name, image: a.avatar ?? '', builtIn: a.visibility_level === 'built_in' }))
|
|
@@ -11,16 +11,16 @@ import { HomeBox } from './styled'
|
|
|
11
11
|
* This is the home rendered when the agent is custom.
|
|
12
12
|
*/
|
|
13
13
|
export const CustomAgent = () => {
|
|
14
|
-
const { id, label, image } = useCurrentChatState('agent') ?? {}
|
|
15
|
-
const [agent] = agentToolsClient.
|
|
14
|
+
const { id, label, image, agent_version_number } = useCurrentChatState('agent') ?? {}
|
|
15
|
+
const [agent] = agentToolsClient.agentV2.useStatefulQuery({ agentCoreId: id!, versionNumber: agent_version_number })
|
|
16
16
|
const chat = useCurrentChat()
|
|
17
|
-
const suggestions = useMemo(() => agent?.conversation_starter?.map((prompt, index) => (
|
|
17
|
+
const suggestions = useMemo(() => agent?.version?.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?.conversation_starter])
|
|
23
|
+
)), [agent?.version?.conversation_starter])
|
|
24
24
|
|
|
25
25
|
function send(message: string) {
|
|
26
26
|
chat.pushMessage(ChatEntry.createUserEntry(message))
|
|
@@ -5,16 +5,16 @@ import { VisibilityLevelEnum } from '@stack-spot/portal-network/api/agent-tools'
|
|
|
5
5
|
import { useCallback } from 'react'
|
|
6
6
|
import { Selector } from '../../components/Selector'
|
|
7
7
|
import { useCurrentChat, useCurrentChatState, useWidgetState } from '../../context/hooks'
|
|
8
|
+
import { useIsFeatureFlagEnabled } from '../../hooks/enabled-feature-flags'
|
|
8
9
|
import { agentRegex } from '../../regex'
|
|
9
10
|
import { useAgentFavorites } from '../Agents/useAgentFavorites'
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const AgentItem = ({ avatar, name, spaceName }: AgentWithSpaceName) => {
|
|
12
|
+
const AgentItem = ({ avatar, name, spaceName }: AgentResponseWithBuiltIn) => {
|
|
14
13
|
const avatarComponent = avatar
|
|
15
14
|
? <img style={{ width: '32px', height: '32px', borderRadius: '50%' }} src={avatar} />
|
|
16
15
|
: <IconBox size="md" icon="Agent" style={{ backgroundColor: 'transparent' }} />
|
|
17
16
|
|
|
17
|
+
|
|
18
18
|
return <Row gap="8px" style={{ flexWrap: 'nowrap' }}>
|
|
19
19
|
{avatarComponent}
|
|
20
20
|
<div>
|
|
@@ -31,10 +31,11 @@ export const AgentSelector = ({ inputRef, isTrial }: {
|
|
|
31
31
|
const chat = useCurrentChat()
|
|
32
32
|
const isAgentEnabled = useCurrentChatState('features').agent
|
|
33
33
|
const spotId = useWidgetState('features')?.workspaceId
|
|
34
|
+
const featureFlag = useIsFeatureFlagEnabled('ENABLE_VERSION_CONTENT_AI')
|
|
34
35
|
|
|
35
36
|
const { useFavorites, onAddFavorite, onRemoveFavorite } = useAgentFavorites()
|
|
36
37
|
|
|
37
|
-
const onSelectItem = useCallback(async (agent: AgentResponseWithBuiltIn) => {
|
|
38
|
+
const onSelectItem = useCallback(async (agent: AgentResponseWithBuiltIn, selectedVersion?: number) => {
|
|
38
39
|
const newValue = `@${agent.slug}`
|
|
39
40
|
chat.set('nextMessage', undefined)
|
|
40
41
|
chat.set(
|
|
@@ -42,10 +43,11 @@ export const AgentSelector = ({ inputRef, isTrial }: {
|
|
|
42
43
|
{
|
|
43
44
|
id: agent.id,
|
|
44
45
|
label: agent.name,
|
|
45
|
-
image: agent.avatar,
|
|
46
|
+
image: agent.avatar,
|
|
46
47
|
slug: agent.slug,
|
|
47
48
|
builtIn: agent.builtIn,
|
|
48
49
|
visibility_level: agent.visibility_level,
|
|
50
|
+
agent_version_number: selectedVersion || agent.version_number,
|
|
49
51
|
},
|
|
50
52
|
)
|
|
51
53
|
|
|
@@ -70,6 +72,12 @@ export const AgentSelector = ({ inputRef, isTrial }: {
|
|
|
70
72
|
}) }
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
const getAgentVersions = (id: string, enabled: boolean) => {
|
|
76
|
+
const [listVersions] = agentToolsClient.listAgentVersions.useStatefulQuery({ agentCoreId: id }, { enabled })
|
|
77
|
+
const optionsVersions = listVersions?.map((version) => version.version_number)
|
|
78
|
+
return optionsVersions
|
|
79
|
+
}
|
|
80
|
+
|
|
73
81
|
return <Selector
|
|
74
82
|
inputRef={inputRef}
|
|
75
83
|
favorite={{ useFavorites, onAddFavorite, onRemoveFavorite }}
|
|
@@ -85,8 +93,10 @@ export const AgentSelector = ({ inputRef, isTrial }: {
|
|
|
85
93
|
['favorite', 'personal', 'workspace', 'account', 'shared', 'built_in', 'recently_used'],
|
|
86
94
|
renderComponentItem: AgentItem,
|
|
87
95
|
isEnabled: isAgentEnabled,
|
|
96
|
+
isEnabledVersionContent: featureFlag.flagEnabled,
|
|
88
97
|
onSelect: onSelectItem,
|
|
89
98
|
useData: getAgents,
|
|
99
|
+
useVersions: getAgentVersions,
|
|
90
100
|
}}
|
|
91
101
|
/>
|
|
92
102
|
}
|