@stack-spot/ai-chat-widget 2.4.1 → 2.5.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 (47) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/app-metadata.json +5 -5
  3. package/dist/chat-interceptors/send-message.d.ts +16 -1
  4. package/dist/chat-interceptors/send-message.d.ts.map +1 -1
  5. package/dist/chat-interceptors/send-message.js +143 -137
  6. package/dist/chat-interceptors/send-message.js.map +1 -1
  7. package/dist/components/form/DescribedRadioGroup.d.ts +3 -1
  8. package/dist/components/form/DescribedRadioGroup.d.ts.map +1 -1
  9. package/dist/components/form/DescribedRadioGroup.js +33 -18
  10. package/dist/components/form/DescribedRadioGroup.js.map +1 -1
  11. package/dist/features.d.ts +4 -0
  12. package/dist/features.d.ts.map +1 -1
  13. package/dist/features.js +1 -0
  14. package/dist/features.js.map +1 -1
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/state/ChatEntry.d.ts +13 -1
  20. package/dist/state/ChatEntry.d.ts.map +1 -1
  21. package/dist/state/ChatEntry.js.map +1 -1
  22. package/dist/views/Agents/AgentsTab.d.ts.map +1 -1
  23. package/dist/views/Agents/AgentsTab.js +8 -5
  24. package/dist/views/Agents/AgentsTab.js.map +1 -1
  25. package/dist/views/Agents/useAgentFavorites.d.ts +1 -1
  26. package/dist/views/Agents/useAgentFavorites.js +3 -3
  27. package/dist/views/Agents/useAgentFavorites.js.map +1 -1
  28. package/dist/views/Chat/StepsList.js +3 -3
  29. package/dist/views/Chat/StepsList.js.map +1 -1
  30. package/dist/views/MessageInput/ButtonBar.js +1 -1
  31. package/dist/views/MessageInput/ButtonBar.js.map +1 -1
  32. package/dist/views/MessageInput/ModelSwitcher/index.d.ts.map +1 -1
  33. package/dist/views/MessageInput/ModelSwitcher/index.js +1 -1
  34. package/dist/views/MessageInput/ModelSwitcher/index.js.map +1 -1
  35. package/package.json +4 -4
  36. package/src/app-metadata.json +5 -5
  37. package/src/chat-interceptors/send-message.ts +159 -150
  38. package/src/components/form/DescribedRadioGroup.tsx +66 -39
  39. package/src/features.ts +8 -3
  40. package/src/index.ts +2 -0
  41. package/src/state/ChatEntry.ts +19 -7
  42. package/src/views/Agents/AgentsTab.tsx +40 -33
  43. package/src/views/Agents/useAgentFavorites.ts +3 -3
  44. package/src/views/Chat/StepsList.tsx +3 -3
  45. package/src/views/MessageInput/ButtonBar.tsx +1 -1
  46. package/src/views/MessageInput/ModelSwitcher/index.tsx +2 -1
  47. package/src/views/MessageInput/index.tsx +2 -2
@@ -29,16 +29,22 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
29
29
  const [submitEnabled, setSubmitEnabled] = useState(false)
30
30
  const listFavorites = useFavorites()
31
31
  const agentDefault = agentToolsClient.agentDefault.useQuery()
32
- const agents = workspaceId
33
- ? workspaceAiClient.getAgentFromWorkspaceAi.useQuery({ workspaceId }) as AgentResponseWithBuiltIn[]
34
- : agentToolsClient.agents.useQuery({ visibility })
32
+ const data = workspaceAiClient.getAgentFromWorkspaceAi.useStatefulQuery({ workspaceId: workspaceId! },
33
+ { enabled: !!workspaceId })
34
+ const workspaceAgents = data?.[0] as AgentResponseWithBuiltIn[]
35
+ const [agentsData=[], { hasNextPage, fetchNextPage }] =
36
+ agentToolsClient.agentsMultipleFilters.useInfiniteQuery({
37
+ filters: { visibility_list: [visibility!], page: 1, size: 20 },
38
+ }, { enabled: !workspaceId && !!visibility })
39
+
40
+ const agents = workspaceId ? workspaceAgents : agentsData
35
41
 
36
42
  const initialValue = useMemo<AgentResponseWithBuiltIn | undefined>(
37
43
  () => {
38
44
  const initial = agent.current
39
45
  ? agents.find(a => a.id === agent.current?.id)
40
46
  : chat.get('agent') ? agents.find(a => a.id === chat.get('agent')?.id) : agentDefault as unknown as AgentResponseWithBuiltIn
41
- if (initial) setSubmitEnabled(true)
47
+ if (initial && !submitEnabled) setSubmitEnabled(true)
42
48
  return initial
43
49
  },
44
50
  [agents],
@@ -49,35 +55,36 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
49
55
  close()
50
56
  }
51
57
 
52
- return (
53
- <>
54
- <div className="content">
55
- <DescribedRadioGroup
56
- options={agents}
57
- initialValue={initialValue}
58
- onChange={(ag) => {
59
- agent.current = ag
60
- ? { ...ag, label: ag.name, image: ag.avatar!, slug: ag.slug, builtIn: ag.visibility_level === 'built_in' }
61
- : undefined
62
- setSubmitEnabled(true)
63
- }}
64
- data={ag => ({
65
- idOrSlug: ag.id,
66
- image: ag.avatar ? <img src={ag.avatar} /> : <Icon icon="Agent" />,
67
- description: <AgentDescription agentId={ag.id} />,
68
- name: ag.name,
69
- listFavorites,
70
- onAddFavorite,
71
- onRemoveFavorite,
72
- })}
73
- emptyResults={
74
- <Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} className="no-data-placeholder" />
75
- }
76
- emptyDataset={<Placeholder title={t.noData} description={t.noDataDescription} />}
77
- />
78
- </div>
79
- {!!agents.length && showSubmitButton && <Button onClick={submit} disabled={!submitEnabled}>{t.apply}</Button>}
80
- </>
58
+ return (<>
59
+ <div className="content">
60
+ <DescribedRadioGroup
61
+ fetchNextPage={fetchNextPage}
62
+ hasNextPage={hasNextPage}
63
+ options={agents}
64
+ initialValue={initialValue}
65
+ onChange={(ag) => {
66
+ agent.current = ag
67
+ ? { ...ag, label: ag.name, image: ag.avatar!, slug: ag.slug, builtIn: ag.visibility_level === 'built_in' }
68
+ : undefined
69
+ setSubmitEnabled(true)
70
+ }}
71
+ data={ag => ({
72
+ idOrSlug: ag.id,
73
+ image: ag.avatar ? <img src={ag.avatar} /> : <Icon icon="Agent" />,
74
+ description: <AgentDescription agentId={ag.id} />,
75
+ name: ag.name,
76
+ listFavorites,
77
+ onAddFavorite,
78
+ onRemoveFavorite,
79
+ })}
80
+ emptyResults={
81
+ <Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} className="no-data-placeholder" />
82
+ }
83
+ emptyDataset={<Placeholder title={t.noData} description={t.noDataDescription} />}
84
+ />
85
+ </div>
86
+ {!!agents.length && showSubmitButton && <Button onClick={submit} disabled={!submitEnabled}>{t.apply}</Button>}
87
+ </>
81
88
  )
82
89
  }
83
90
 
@@ -2,14 +2,14 @@
2
2
  import { agentToolsClient } from '@stack-spot/portal-network'
3
3
 
4
4
  export function useAgentFavorites() {
5
- const useFavorites = () => agentToolsClient.agents.useQuery({ visibility: 'favorite' })
5
+ const useFavorites = () => agentToolsClient.agentsMultipleFilters.useQuery({ filters: { visibility_list: ['favorite'] } })?.items
6
6
  const [addFavorite, pendingAddFav] = agentToolsClient.addFavorite.useMutation()
7
7
  const [removeFavorite, pendingRemoveFav] = agentToolsClient.removeFavorite.useMutation()
8
8
 
9
9
  const removeFavoriteAgent = async (idOrSlug?: string) => {
10
10
  try {
11
11
  await removeFavorite({ agentId: idOrSlug || '' })
12
- await agentToolsClient.agents.invalidate({ visibility: 'favorite' })
12
+ await agentToolsClient.agentsMultipleFilters.invalidate({ filters: { visibility_list: ['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 agentToolsClient.agents.invalidate({ visibility: 'favorite' })
22
+ await agentToolsClient.agentsMultipleFilters.invalidate({ filters: { visibility_list: ['favorite'] } })
23
23
  } catch (error) {
24
24
  // eslint-disable-next-line no-console
25
25
  console.error(error)
@@ -50,14 +50,14 @@ const StepAccordionHeader = ({ step, index, expand }: Pick<StepProps, 'step' | '
50
50
  return <Row gap="8px">
51
51
  {expand}
52
52
  {step.status === 'target' ? <Text className="step-title" appearance="body2" color="light.700">{t.planGoal}:</Text> :
53
- <Badge colorScheme="inverse" appearance="square">
53
+ <Badge colorScheme="inverse" appearance="square" style={{ whiteSpace: 'nowrap' }}>
54
54
  {t.step} {index}
55
55
  </Badge>}
56
56
  <Text className="step-title" appearance="body2">
57
57
  {step.input}
58
58
  </Text>
59
59
  {step.status === 'awaiting_approval' &&
60
- <Badge appearance="square" style={{ backgroundColor: theme.color.gray[800], color: theme.color.gray[50] }}>
60
+ <Badge appearance="square" style={{ backgroundColor: theme.color.gray[800], color: theme.color.gray[50], whiteSpace: 'nowrap' }}>
61
61
  <Icon icon="Security" />
62
62
  {t.pendingReview}
63
63
  </Badge>}
@@ -199,7 +199,7 @@ export const ToolStepsList = ({ toolStep, messageId, chatId }: { toolStep: ToolC
199
199
  return <>
200
200
  {toolStep && tool ? <AnimatedHeight>
201
201
  <div className="steps">
202
- <Badge colorPalette="yellow" appearance="square">
202
+ <Badge colorPalette="yellow" appearance="square" style={{ whiteSpace: 'nowrap' }}>
203
203
  <Icon icon="StopWatch" />
204
204
  <Text>{tool.name} {t.keepWorking}</Text>
205
205
  </Badge>
@@ -30,7 +30,7 @@ export const ButtonBar = ({ onSend, isLoading }: SelectionBarProps) => {
30
30
  <IconButton icon="Code" appearance="square" aria-label={t.code} title={t.code} onClick={() => widget.set('panel', 'editor')} />
31
31
  )}
32
32
  </Row>
33
- <ModelSwitcher />
33
+ {features.showLLMSelect && <ModelSwitcher />}
34
34
  {isLoading ? (
35
35
  <IconButton
36
36
  icon="Stop"
@@ -15,7 +15,8 @@ export const ModelSwitcher = () => {
15
15
  const chat = useCurrentChat()
16
16
  const [filter, setFilter] = useState('')
17
17
  const [visibleMenu, setVisibleMenu] = useState(false)
18
- const [agentData, isLoadingAgentData] = agentToolsClient.agent.useStatefulQuery({ agentId: agentCurrentChat?.id || '' })
18
+ const [agentData, isLoadingAgentData] = agentToolsClient.agent.useStatefulQuery({ agentId: agentCurrentChat?.id || '' },
19
+ { enabled: !!agentCurrentChat?.id })
19
20
  const [models, isLoadingModels] =
20
21
  genAiInferenceClient.listModels.useStatefulQuery({ pageSize: 999, active: true })
21
22
 
@@ -24,7 +24,7 @@ import { UploadDragNDrop, useUploadDragDrop } from './UploadDragNDrop'
24
24
  * going to be used for the question and the buttons to send, cancel, set the workspace, among others. This also includes the Quick
25
25
  * Commands panel for auto completing.
26
26
  */
27
- export const MessageInput = ({ chatWindowRef, customInputMessage }:
27
+ export const MessageInput = ({ chatWindowRef, customInputMessage }:
28
28
  { chatWindowRef?: React.RefObject<HTMLElement>, customInputMessage?: string }) => {
29
29
  const t = useMessageInputDictionary()
30
30
  const [focused, setFocused] = useState(false)
@@ -96,7 +96,7 @@ export const MessageInput = ({ chatWindowRef, customInputMessage }:
96
96
  if (!checkSendRequirements()) return
97
97
 
98
98
  // Compose prompt with code block if needed
99
- const prompt = code && !quickCommandRegex.test(message ?? '') ? `${message}\n\`\`\`${language}\n${code}\n\`\`\`` : message
99
+ const prompt = code && !quickCommandRegex.test(message ?? '') ? `${message}\n\`\`\`${language}\n${code}\n\`\`\`` : message
100
100
 
101
101
  // Validate prompt length
102
102
  if (!checkPromptMaxLength(prompt || '')) return