@stack-spot/ai-chat-widget 3.4.0-beta.5 → 3.5.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/app-metadata.json +4 -4
- package/dist/chat-interceptors/send-message.d.ts.map +1 -1
- package/dist/chat-interceptors/send-message.js +1 -0
- package/dist/chat-interceptors/send-message.js.map +1 -1
- package/dist/state/ChatEntry.d.ts +10 -1
- package/dist/state/ChatEntry.d.ts.map +1 -1
- package/dist/state/ChatEntry.js +16 -2
- package/dist/state/ChatEntry.js.map +1 -1
- package/dist/views/Chat/ChatMessage.d.ts +1 -1
- package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessage.js +3 -2
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/Chat/StepsList.js +1 -1
- package/dist/views/Chat/StepsList.js.map +1 -1
- package/dist/views/ChatHistory/utils.d.ts.map +1 -1
- package/dist/views/ChatHistory/utils.js +94 -2
- package/dist/views/ChatHistory/utils.js.map +1 -1
- package/dist/views/KnowledgeSources.d.ts +1 -1
- package/dist/views/KnowledgeSources.d.ts.map +1 -1
- package/dist/views/KnowledgeSources.js +35 -7
- package/dist/views/KnowledgeSources.js.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.js +52 -29
- package/dist/views/MessageInput/QuickCommandSelector.js.map +1 -1
- package/dist/views/MessageInput/UploadBar.d.ts.map +1 -1
- package/dist/views/MessageInput/UploadBar.js +0 -5
- package/dist/views/MessageInput/UploadBar.js.map +1 -1
- package/package.json +3 -3
- package/src/app-metadata.json +4 -4
- package/src/chat-interceptors/send-message.ts +1 -0
- package/src/state/ChatEntry.ts +18 -2
- package/src/views/Chat/ChatMessage.tsx +4 -2
- package/src/views/Chat/StepsList.tsx +1 -1
- package/src/views/ChatHistory/utils.ts +96 -3
- package/src/views/KnowledgeSources.tsx +60 -17
- package/src/views/MessageInput/QuickCommandSelector.tsx +93 -39
- package/src/views/MessageInput/UploadBar.tsx +0 -6
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Box } from '@citric/core'
|
|
1
2
|
import { Button, Tab } from '@stack-spot/citric-react'
|
|
2
3
|
import { Placeholder } from '@stack-spot/portal-components/Placeholder'
|
|
3
4
|
import { aiClient, dataIntegrationClient, workspaceAiClient } from '@stack-spot/portal-network'
|
|
@@ -5,6 +6,7 @@ import { VisibilityLevelEnum } from '@stack-spot/portal-network/api/ai'
|
|
|
5
6
|
import { WorkspaceResponse } from '@stack-spot/portal-network/api/workspace-ai'
|
|
6
7
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
7
8
|
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
|
|
9
|
+
import InfiniteScroll from 'react-infinite-scroll-component'
|
|
8
10
|
import { NavigationComponent } from '../components/ComponentNavigator'
|
|
9
11
|
import { DescribedCheckboxGroup } from '../components/form/DescribedCheckboxGroup'
|
|
10
12
|
import { RightPanelContentList } from '../components/RightPanelContentList'
|
|
@@ -95,15 +97,46 @@ const KnowledgeSourcesPanel = () => {
|
|
|
95
97
|
|
|
96
98
|
export const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit, workspaceId, showSubmitButton = true }: TabProps) => {
|
|
97
99
|
const t = useTranslate(dictionary)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
|
|
101
|
+
let knowledgeSources: any[] = []
|
|
102
|
+
let fetchNextPage: (() => void) | undefined
|
|
103
|
+
let hasNextPage: boolean | undefined
|
|
104
|
+
let isLoadingKnowledgeSources: boolean | undefined
|
|
105
|
+
let ksListError: any
|
|
106
|
+
|
|
107
|
+
if (workspaceId) {
|
|
108
|
+
knowledgeSources = workspaceAiClient.getKSFromWorkspaceAi.useQuery({ workspaceId })
|
|
109
|
+
fetchNextPage = undefined
|
|
110
|
+
hasNextPage = false
|
|
111
|
+
isLoadingKnowledgeSources = false
|
|
112
|
+
ksListError = undefined
|
|
113
|
+
} else {
|
|
114
|
+
const [
|
|
115
|
+
ksListPages,
|
|
116
|
+
_isLoadingKnowledgeSources,
|
|
117
|
+
_ksListError,
|
|
118
|
+
{ fetchNextPage: _fetchNextPage, hasNextPage: _hasNextPage },
|
|
119
|
+
] = dataIntegrationClient.knowledgeSourcesV2.useStatefulInfiniteQuery(
|
|
120
|
+
{
|
|
121
|
+
order: 'a-to-z',
|
|
122
|
+
visibilityList: visibility ? [visibility] : [],
|
|
123
|
+
types: ['snippet', 'api', 'event', 'custom'],
|
|
124
|
+
size: 20,
|
|
125
|
+
},
|
|
126
|
+
{ enabled: true },
|
|
127
|
+
)
|
|
128
|
+
knowledgeSources = ksListPages?.flat() ?? []
|
|
129
|
+
fetchNextPage = _fetchNextPage
|
|
130
|
+
hasNextPage = _hasNextPage
|
|
131
|
+
isLoadingKnowledgeSources = _isLoadingKnowledgeSources
|
|
132
|
+
ksListError = _ksListError
|
|
133
|
+
}
|
|
134
|
+
|
|
103
135
|
const initialValue = useMemo(() => {
|
|
104
136
|
const currentlySelected = allKS.current?.map(ks => ks.id)
|
|
105
137
|
return knowledgeSources.filter(ks => currentlySelected?.includes(ks.slug))
|
|
106
|
-
}, [])
|
|
138
|
+
}, [knowledgeSources, allKS])
|
|
139
|
+
|
|
107
140
|
const listFavorites = dataIntegrationClient.knowledgeSources.useQuery({ visibility: 'favorite' })
|
|
108
141
|
const [addFavorite, pendingAddFav] = dataIntegrationClient.addFavoriteKnowledgeSource.useMutation()
|
|
109
142
|
const [removeFavorite, pendingRemoveFav] = dataIntegrationClient.removeFavoriteKnowledgeSource.useMutation()
|
|
@@ -134,6 +167,9 @@ export const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit, workspaceId,
|
|
|
134
167
|
}
|
|
135
168
|
})
|
|
136
169
|
|
|
170
|
+
if (isLoadingKnowledgeSources && knowledgeSources.length === 0) {return null}
|
|
171
|
+
if (ksListError) {return null}
|
|
172
|
+
|
|
137
173
|
const addFavoriteKs = async (idOrSlug: string) => {
|
|
138
174
|
try {
|
|
139
175
|
await addFavorite({ slug: idOrSlug })
|
|
@@ -162,16 +198,24 @@ export const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit, workspaceId,
|
|
|
162
198
|
|
|
163
199
|
return (
|
|
164
200
|
<>
|
|
165
|
-
<
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
201
|
+
<Box className="content" id="ks-scrollable" style={{ overflow: 'auto', height: '100%' }}>
|
|
202
|
+
<InfiniteScroll
|
|
203
|
+
scrollableTarget="ks-scrollable"
|
|
204
|
+
dataLength={knowledgeSources.length}
|
|
205
|
+
next={fetchNextPage ?? (() => {})}
|
|
206
|
+
hasMore={hasNextPage}
|
|
207
|
+
loader={isLoadingKnowledgeSources}
|
|
208
|
+
>
|
|
209
|
+
<DescribedCheckboxGroup
|
|
210
|
+
options={knowledgeSources}
|
|
211
|
+
initialValue={initialValue}
|
|
212
|
+
globalSelection={allKS}
|
|
213
|
+
data={ks => ({ idOrSlug: ks.slug, description: ks.description, name: ks.name, listFavorites, onAddFavorite, onRemoveFavorite })}
|
|
214
|
+
emptyResults={<Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} />}
|
|
215
|
+
emptyDataset={<Placeholder title={t.noData} description={t.noDataDescription} className="no-data-placeholder" />}
|
|
216
|
+
/>
|
|
217
|
+
</InfiniteScroll>
|
|
218
|
+
</Box>
|
|
175
219
|
{!!knowledgeSources.length && showSubmitButton && <Button onClick={onSubmit}>{t.apply}</Button>}
|
|
176
220
|
</>
|
|
177
221
|
)
|
|
@@ -188,7 +232,6 @@ export function KnowledgeSourcesTabWorkspace({ allKS, onSubmit }: TabProps) {
|
|
|
188
232
|
return <WorkspaceTabNavigator components={workspaceTabComponents} getNavigateParam={buildNavigateParams} />
|
|
189
233
|
}
|
|
190
234
|
|
|
191
|
-
|
|
192
235
|
const dictionary = {
|
|
193
236
|
en: {
|
|
194
237
|
title: 'Knowledge Sources',
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { Box } from '@citric/core'
|
|
1
2
|
import { Icon } from '@stack-spot/citric-icons'
|
|
2
3
|
import { aiClient, workspaceAiClient } from '@stack-spot/portal-network'
|
|
3
4
|
import { QuickCommandResponse } from '@stack-spot/portal-network/api/ai'
|
|
4
|
-
import { useCallback } from 'react'
|
|
5
|
+
import { useCallback, useMemo } from 'react'
|
|
6
|
+
import InfiniteScroll from 'react-infinite-scroll-component'
|
|
5
7
|
import { Selector } from '../../components/Selector'
|
|
6
8
|
import { useCurrentChat, useCurrentChatState, useWidgetState } from '../../context/hooks'
|
|
7
9
|
import { quickCommandRegex } from '../../regex'
|
|
@@ -77,51 +79,103 @@ export const QuickCommandSelector = ({ inputRef, isTrial }:
|
|
|
77
79
|
inputRef.current.focus()
|
|
78
80
|
}, [chat, inputRef])
|
|
79
81
|
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
const [quickCommandsPages = [], isLoadingQuickCommands, _qcListError, infiniteQueryResult,
|
|
83
|
+
] = aiClient.allQuickCommandsV3.useStatefulInfiniteQuery(
|
|
84
|
+
{
|
|
85
|
+
size: 20,
|
|
86
|
+
page: 1,
|
|
87
|
+
order: 'a-to-z',
|
|
88
|
+
},
|
|
89
|
+
{ enabled: !spotId },
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
const quickCommands = useMemo(() => quickCommandsPages, [quickCommandsPages])
|
|
93
|
+
|
|
94
|
+
const quickCommandsFiltered = useMemo(() => quickCommands.filter(
|
|
95
|
+
(qc) => qc.visibility_level.toLowerCase() !== 'workspace'), [quickCommands],
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
const workspaceQuickCommands = workspaceAiClient.workspacesContentsByType.useQuery({
|
|
99
|
+
contentType: 'quick_command',
|
|
100
|
+
}) || []
|
|
101
|
+
|
|
102
|
+
const workspaceQuickCommandsWithWorkspaceName: QuickCommandResponseWithSpaceName[] =
|
|
103
|
+
useMemo(
|
|
104
|
+
() =>
|
|
105
|
+
workspaceQuickCommands.flatMap(({ qcs, space_name }) =>
|
|
106
|
+
qcs?.map((qc) => ({ ...qc, spaceName: space_name })),
|
|
107
|
+
) as QuickCommandResponseWithSpaceName[],
|
|
108
|
+
[workspaceQuickCommands],
|
|
88
109
|
)
|
|
89
110
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
111
|
+
const allQuickCommands =
|
|
112
|
+
spotId
|
|
113
|
+
? workspaceAiClient.getQCFromWorkspaceAi.useQuery({ workspaceId: spotId }) || []
|
|
114
|
+
: [...quickCommandsFiltered, ...workspaceQuickCommandsWithWorkspaceName]
|
|
93
115
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
qcs?.map((qc) => ({ ...qc, spaceName: space_name })),
|
|
97
|
-
) as QuickCommandResponseWithSpaceName[]
|
|
116
|
+
const fetchNextPage = !spotId ? infiniteQueryResult?.fetchNextPage : undefined
|
|
117
|
+
const hasNextPage = !spotId ? infiniteQueryResult?.hasNextPage : false
|
|
98
118
|
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const QuickCommandItem = ({ slug, description, spaceName }: QuickCommandResponseWithSpaceName) => <>
|
|
119
|
+
const QuickCommandItem = ({ slug, description, spaceName }: QuickCommandResponseWithSpaceName) => (<>
|
|
103
120
|
<p className="selector-description">{spaceName}</p>
|
|
104
121
|
<p className="selector-title">/{slug?.toUpperCase()}</p>
|
|
105
122
|
<p className="selector-description">{description}</p>
|
|
106
123
|
</>
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
if (spotId) {
|
|
127
|
+
return (
|
|
128
|
+
<Selector
|
|
129
|
+
inputRef={inputRef}
|
|
130
|
+
favorite={{
|
|
131
|
+
useFavorites, onAddFavorite, onRemoveFavorite, favoriteIsSlug: true,
|
|
132
|
+
}}
|
|
133
|
+
selectorConfig={{
|
|
134
|
+
resourceName: 'Quick Command',
|
|
135
|
+
shortcut: '/',
|
|
136
|
+
icon: <Icon icon="QuickCommand" />,
|
|
137
|
+
searchProp: 'slug',
|
|
138
|
+
urlBuilder: (qc) => `/quick-command/${qc?.slug}`,
|
|
139
|
+
regex: quickCommandRegex,
|
|
140
|
+
sections: isTrial ? ['favorite', 'personal'] : ['favorite', 'personal', 'workspace', 'account', 'shared'],
|
|
141
|
+
isEnabled: isQuickCommandEnabled,
|
|
142
|
+
onSelect: onSelectItem,
|
|
143
|
+
renderComponentItem: QuickCommandItem,
|
|
144
|
+
useData: () => allQuickCommands,
|
|
145
|
+
}}
|
|
146
|
+
/>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
107
149
|
|
|
108
|
-
return
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
150
|
+
return (
|
|
151
|
+
<Box className="content" id="qc-scrollable" style={{ overflow: 'auto', height: '100%' }}>
|
|
152
|
+
<InfiniteScroll
|
|
153
|
+
scrollableTarget="qc-scrollable"
|
|
154
|
+
dataLength={allQuickCommands.length}
|
|
155
|
+
next={fetchNextPage as any}
|
|
156
|
+
hasMore={!!hasNextPage}
|
|
157
|
+
loader={isLoadingQuickCommands}
|
|
158
|
+
>
|
|
159
|
+
<Selector
|
|
160
|
+
inputRef={inputRef}
|
|
161
|
+
favorite={{
|
|
162
|
+
useFavorites, onAddFavorite, onRemoveFavorite, favoriteIsSlug: true,
|
|
163
|
+
}}
|
|
164
|
+
selectorConfig={{
|
|
165
|
+
resourceName: 'Quick Command',
|
|
166
|
+
shortcut: '/',
|
|
167
|
+
icon: <Icon icon="QuickCommand" />,
|
|
168
|
+
searchProp: 'slug',
|
|
169
|
+
urlBuilder: (qc) => `/quick-command/${qc?.slug}`,
|
|
170
|
+
regex: quickCommandRegex,
|
|
171
|
+
sections: isTrial ? ['favorite', 'personal'] : ['favorite', 'personal', 'workspace', 'account', 'shared'],
|
|
172
|
+
isEnabled: isQuickCommandEnabled,
|
|
173
|
+
onSelect: onSelectItem,
|
|
174
|
+
renderComponentItem: QuickCommandItem,
|
|
175
|
+
useData: () => allQuickCommands,
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
</InfiniteScroll>
|
|
179
|
+
</Box>
|
|
180
|
+
)
|
|
127
181
|
}
|
|
@@ -80,12 +80,6 @@ export const UploadBar = () => {
|
|
|
80
80
|
setAriaMessage(lines.join(' '))
|
|
81
81
|
setTimeout(() => setAriaMessage(''), 2000)
|
|
82
82
|
chat.pushMessage(new ChatEntry({ agentType: 'system', type: 'md', content: lines.join('\n\n') }))
|
|
83
|
-
|
|
84
|
-
if (lines.length) {
|
|
85
|
-
setAriaMessage(lines.join(' '))
|
|
86
|
-
setTimeout(() => setAriaMessage(''), 2000)
|
|
87
|
-
chat.pushMessage(new ChatEntry({ agentType: 'system', type: 'md', content: lines.join('\n\n') }))
|
|
88
|
-
}
|
|
89
83
|
})
|
|
90
84
|
|
|
91
85
|
return (
|