@stack-spot/ai-chat-widget 2.12.2 → 2.13.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 (80) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/app-metadata.json +3 -3
  3. package/dist/components/Selector/SelectVersion.d.ts +12 -0
  4. package/dist/components/Selector/SelectVersion.d.ts.map +1 -0
  5. package/dist/components/Selector/SelectVersion.js +33 -0
  6. package/dist/components/Selector/SelectVersion.js.map +1 -0
  7. package/dist/components/Selector/index.d.ts +3 -1
  8. package/dist/components/Selector/index.d.ts.map +1 -1
  9. package/dist/components/Selector/index.js +10 -7
  10. package/dist/components/Selector/index.js.map +1 -1
  11. package/dist/components/Selector/styled.d.ts +2 -0
  12. package/dist/components/Selector/styled.d.ts.map +1 -1
  13. package/dist/components/Selector/styled.js +45 -0
  14. package/dist/components/Selector/styled.js.map +1 -1
  15. package/dist/hooks/enabled-feature-flags.d.ts +5 -0
  16. package/dist/hooks/enabled-feature-flags.d.ts.map +1 -0
  17. package/dist/hooks/enabled-feature-flags.js +28 -0
  18. package/dist/hooks/enabled-feature-flags.js.map +1 -0
  19. package/dist/state/types.d.ts +1 -0
  20. package/dist/state/types.d.ts.map +1 -1
  21. package/dist/utils/chat.d.ts.map +1 -1
  22. package/dist/utils/chat.js +1 -0
  23. package/dist/utils/chat.js.map +1 -1
  24. package/dist/utils/tools.d.ts +5 -5
  25. package/dist/utils/tools.d.ts.map +1 -1
  26. package/dist/utils/tools.js +2 -2
  27. package/dist/utils/tools.js.map +1 -1
  28. package/dist/views/Agents/AgentDescription.d.ts +6 -2
  29. package/dist/views/Agents/AgentDescription.d.ts.map +1 -1
  30. package/dist/views/Agents/AgentDescription.js +25 -10
  31. package/dist/views/Agents/AgentDescription.js.map +1 -1
  32. package/dist/views/Agents/AgentsTab.d.ts.map +1 -1
  33. package/dist/views/Agents/AgentsTab.js +21 -4
  34. package/dist/views/Agents/AgentsTab.js.map +1 -1
  35. package/dist/views/Agents/dictionary.d.ts +1 -1
  36. package/dist/views/Agents/dictionary.d.ts.map +1 -1
  37. package/dist/views/Agents/dictionary.js +2 -0
  38. package/dist/views/Agents/dictionary.js.map +1 -1
  39. package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
  40. package/dist/views/Chat/ChatMessage.js +6 -5
  41. package/dist/views/Chat/ChatMessage.js.map +1 -1
  42. package/dist/views/ChatHistory/utils.d.ts.map +1 -1
  43. package/dist/views/ChatHistory/utils.js +20 -10
  44. package/dist/views/ChatHistory/utils.js.map +1 -1
  45. package/dist/views/Home/CustomAgent.js +3 -3
  46. package/dist/views/Home/CustomAgent.js.map +1 -1
  47. package/dist/views/MessageInput/AgentSelector.d.ts.map +1 -1
  48. package/dist/views/MessageInput/AgentSelector.js +13 -3
  49. package/dist/views/MessageInput/AgentSelector.js.map +1 -1
  50. package/dist/views/MessageInput/ModelSwitcher/index.d.ts.map +1 -1
  51. package/dist/views/MessageInput/ModelSwitcher/index.js +3 -1
  52. package/dist/views/MessageInput/ModelSwitcher/index.js.map +1 -1
  53. package/dist/views/MessageInput/ModelSwitcher/utils.d.ts +2 -2
  54. package/dist/views/MessageInput/ModelSwitcher/utils.d.ts.map +1 -1
  55. package/dist/views/MessageInput/ModelSwitcher/utils.js +6 -6
  56. package/dist/views/MessageInput/ModelSwitcher/utils.js.map +1 -1
  57. package/dist/views/Resources.js +8 -5
  58. package/dist/views/Resources.js.map +1 -1
  59. package/dist/views/Tools.js +3 -2
  60. package/dist/views/Tools.js.map +1 -1
  61. package/package.json +2 -2
  62. package/src/app-metadata.json +3 -3
  63. package/src/components/Selector/SelectVersion.tsx +55 -0
  64. package/src/components/Selector/index.tsx +20 -11
  65. package/src/components/Selector/styled.ts +47 -0
  66. package/src/hooks/enabled-feature-flags.ts +31 -0
  67. package/src/state/types.ts +1 -0
  68. package/src/utils/chat.ts +1 -0
  69. package/src/utils/tools.ts +4 -4
  70. package/src/views/Agents/AgentDescription.tsx +48 -14
  71. package/src/views/Agents/AgentsTab.tsx +31 -13
  72. package/src/views/Agents/dictionary.ts +2 -1
  73. package/src/views/Chat/ChatMessage.tsx +8 -6
  74. package/src/views/ChatHistory/utils.ts +25 -13
  75. package/src/views/Home/CustomAgent.tsx +4 -4
  76. package/src/views/MessageInput/AgentSelector.tsx +17 -7
  77. package/src/views/MessageInput/ModelSwitcher/index.tsx +3 -2
  78. package/src/views/MessageInput/ModelSwitcher/utils.tsx +9 -8
  79. package/src/views/Resources.tsx +10 -6
  80. package/src/views/Tools.tsx +5 -4
@@ -1 +1 @@
1
- {"version":3,"file":"Tools.js","sourceRoot":"","sources":["../../src/views/Tools.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Tools.js","sourceRoot":"","sources":["../../src/views/Tools.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stack-spot/ai-chat-widget",
3
- "version": "2.12.2",
3
+ "version": "2.13.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -16,7 +16,7 @@
16
16
  "@citric/core": "^6.4.0",
17
17
  "@stack-spot/portal-components": "^2.27.3",
18
18
  "@citric/icons": "^5.13.0",
19
- "@stack-spot/portal-network": "0.218.1",
19
+ "@stack-spot/portal-network": "0.219.0",
20
20
  "@citric/ui": "^6.10.2",
21
21
  "@stack-spot/portal-translate": "^2.1.0",
22
22
  "lodash": "^4.17.0",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stack-spot/ai-chat-widget",
3
- "version": "2.12.2",
4
- "date": "Wed Feb 04 2026 13:13:16 GMT+0000 (Coordinated Universal Time)",
3
+ "version": "2.13.0",
4
+ "date": "Mon Feb 09 2026 20:24:04 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": "0.218.1(@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)"
128
+ "version": "0.219.0(@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",
@@ -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> {
@@ -40,7 +42,7 @@ interface ListProps<T> {
40
42
  filter?: string,
41
43
  visibility?: SectionVisibility,
42
44
  selectorConfig: SelectorConfig<T>,
43
- onSelect: (item: T) => void,
45
+ onSelect: (item: T, selectedVersion?: number) => void,
44
46
  favorite?: Favorite<T>,
45
47
  }
46
48
 
@@ -69,10 +71,12 @@ 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>,
75
- onSelect: (item: T) => void,
79
+ onSelect: (item: T, selectedVersion?: number) => void,
76
80
  /**
77
81
  * A react hook or a simple function that returns the selectable items.
78
82
  *
@@ -91,21 +95,26 @@ 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
101
106
  className="selector"
102
- onClick={() => onSelect(item)}
107
+ onClick={() => onSelect(item, selectedVersion)}
103
108
  onKeyDown={(e) => e.key === 'Enter' && e.preventDefault()}
104
109
  onFocus={(e) => e.target.closest('li')?.classList.add('focus')}
105
110
  onBlur={(e) => e.target.closest('li')?.classList.remove('focus')}
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}
@@ -148,14 +157,14 @@ const List = <T extends Item>({ selectorConfig, filter, visibility, onSelect, fa
148
157
  )
149
158
  }
150
159
 
151
- const SelectorContent = ({ filter, onClose, selectorConfig, favorite }: ContentProps<any>) => {
160
+ const SelectorContent = <T, > ({ filter, onClose, selectorConfig, favorite }: ContentProps<T>) => {
152
161
  const t = useTranslate(dictionary)
153
162
  const ref = useRef<HTMLDivElement>(null)
154
- const [visibility, setVisibility] = useState<SectionVisibility | undefined>()
155
- const isGroupResourcesByScope = useWidgetState('features')?.groupResourcesByScope
156
163
  const { resourceName, icon, onSelect, sections } = selectorConfig
157
- const onSelectItem = useCallback((slug: string) => {
158
- onSelect(slug)
164
+ const [visibility, setVisibility] = useState<SectionVisibility | undefined>(sections[0])
165
+ const isGroupResourcesByScope = useWidgetState('features')?.groupResourcesByScope
166
+ const onSelectItem = useCallback((item: any, selectedVersion?: number) => {
167
+ onSelect(item, selectedVersion)
159
168
  onClose()
160
169
  }, [])
161
170
 
@@ -187,8 +196,8 @@ const SelectorContent = ({ filter, onClose, selectorConfig, favorite }: ContentP
187
196
  <div className="body">
188
197
  {isGroupResourcesByScope && (
189
198
  <ul className="tabs">
190
- {createSectionItem()}
191
199
  {sections.map(createSectionItem)}
200
+ {createSectionItem()}
192
201
  </ul>
193
202
  )}
194
203
  <FallbackBoundary message={interpolate(t.error, selectorConfig.resourceName)}>
@@ -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
+ }
@@ -11,6 +11,7 @@ export interface LabeledAgent extends LabeledWithImage {
11
11
  builtIn?: boolean,
12
12
  slug?: string,
13
13
  visibility_level?: string,
14
+ agent_version_number?: number,
14
15
  }
15
16
 
16
17
  export interface FileSize {
package/src/utils/chat.ts CHANGED
@@ -19,6 +19,7 @@ export function buildConversationContext(state: ChatState, message?: ChatEntry |
19
19
  knowledge_sources: state.get('knowledgeSources')?.map(ks => ks.id),
20
20
  upload_ids: message?.getValue().upload?.map(f => f.id),
21
21
  selected_model: state.get('selected_model_id') ?? null,
22
+ agent_version_number: state.get('agent')?.agent_version_number,
22
23
  context: {
23
24
  os: navigator.userAgent,
24
25
  platform: 'web-widget',
@@ -1,9 +1,9 @@
1
1
 
2
- export type ToolWithImage = { id?: string, image?: string, name: string, description?: string }
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?: string } }[] | null,
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: toolName, description: tool?.function?.description }
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
- export const AgentDescription = ({ agentId }: { agentId?: string }) => {
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 [agent,, error, { isLoading }] = agentToolsClient.agent.useStatefulQuery({ agentId: agentId! }, { enabled: !!agentId })
11
- const numberOfKnowledgeSources = agent?.knowledge_sources_config?.knowledge_sources.length ?? 0
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
- const initial = agent.current
65
- ? agents?.find(a => a.id === agent.current?.id)
66
- : chat.get('agent') ? agents?.find(a => a.id === chat.get('agent')?.id) : agentDefault as unknown as AgentResponseWithBuiltIn
67
- if (initial && !submitEnabled) setSubmitEnabled(true)
68
- return initial
69
- },
70
- [agents],
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.agent.useStatefulQuery({ agentId }, { enabled: !!agentId })
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 [agentsTools] = agentToolsClient.agentsByIds.useStatefulQuery(
225
- { searchAgentsRequest: { ids: entry.tools || [''] } }, { enabled: !!entry.tools?.length })
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