@stack-spot/ai-chat-widget 2.11.1 → 2.12.1
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/StackspotAIWidget.d.ts +1 -0
- package/dist/StackspotAIWidget.d.ts.map +1 -1
- package/dist/StackspotAIWidget.js +1 -0
- package/dist/StackspotAIWidget.js.map +1 -1
- package/dist/app-metadata.json +15 -3
- package/dist/chat-interceptors/quick-commands.d.ts +15 -0
- package/dist/chat-interceptors/quick-commands.d.ts.map +1 -1
- package/dist/chat-interceptors/quick-commands.js +20 -2
- package/dist/chat-interceptors/quick-commands.js.map +1 -1
- package/dist/chat-interceptors/send-message.d.ts.map +1 -1
- package/dist/chat-interceptors/send-message.js +39 -34
- package/dist/chat-interceptors/send-message.js.map +1 -1
- package/dist/components/Code.d.ts.map +1 -1
- package/dist/components/Code.js +19 -4
- package/dist/components/Code.js.map +1 -1
- package/dist/components/FileDescription.js +1 -1
- package/dist/components/FileDescription.js.map +1 -1
- package/dist/components/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown.js +22 -6
- package/dist/components/Markdown.js.map +1 -1
- package/dist/components/TabManager.d.ts.map +1 -1
- package/dist/components/TabManager.js +20 -4
- package/dist/components/TabManager.js.map +1 -1
- package/dist/state/ChatState.d.ts +5 -0
- package/dist/state/ChatState.d.ts.map +1 -1
- package/dist/state/ChatState.js.map +1 -1
- package/dist/utils/chat.d.ts +4 -12
- package/dist/utils/chat.d.ts.map +1 -1
- package/dist/utils/chat.js +19 -19
- package/dist/utils/chat.js.map +1 -1
- package/dist/utils/knowledge-source.js +1 -1
- package/dist/utils/knowledge-source.js.map +1 -1
- package/dist/views/KnowledgeSources.js +1 -1
- package/dist/views/KnowledgeSources.js.map +1 -1
- package/dist/views/MessageInput/ContextBar.js +1 -1
- package/dist/views/MessageInput/ContextBar.js.map +1 -1
- package/package.json +6 -3
- package/src/StackspotAIWidget.tsx +1 -0
- package/src/app-metadata.json +15 -3
- package/src/chat-interceptors/quick-commands.ts +28 -7
- package/src/chat-interceptors/send-message.ts +39 -35
- package/src/components/Code.tsx +19 -4
- package/src/components/FileDescription.tsx +1 -1
- package/src/components/Markdown.tsx +42 -23
- package/src/components/TabManager.tsx +31 -8
- package/src/state/ChatState.ts +6 -0
- package/src/utils/chat.ts +22 -22
- package/src/utils/knowledge-source.ts +1 -1
- package/src/views/KnowledgeSources.tsx +1 -1
- package/src/views/MessageInput/ContextBar.tsx +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AgentInfo, aiClient, ChatResponseWithPMResources, ChatResponseWithSteps, ChatStep, StackspotAPIError, StreamCanceledError } from '@stack-spot/portal-network'
|
|
2
|
-
import { ChatResponse3 } from '@stack-spot/portal-network/api/ai'
|
|
1
|
+
import { AgentInfo, aiClient, ChatResponse, ChatResponseWithPMResources, ChatResponseWithSteps, ChatStep, genAiInferenceClient, StackspotAPIError, StreamCanceledError } from '@stack-spot/portal-network'
|
|
3
2
|
import { findLast } from 'lodash'
|
|
4
3
|
import { ChatEntry, KnowledgeSource, TextChatEntry } from '../state/ChatEntry'
|
|
5
4
|
import { ChatState } from '../state/ChatState'
|
|
@@ -27,13 +26,13 @@ export function createEntryValueFromChatResponse(
|
|
|
27
26
|
const entry = {
|
|
28
27
|
agentType: 'bot',
|
|
29
28
|
type: 'md',
|
|
30
|
-
content: response.
|
|
29
|
+
content: response.message ?? '',
|
|
31
30
|
messageId: response.message_id ?? undefined,
|
|
32
31
|
knowledgeSources,
|
|
33
32
|
agent: agent,
|
|
34
33
|
updated: includeDate ? new Date().toISOString() : undefined,
|
|
35
34
|
steps: response.steps,
|
|
36
|
-
tools: response.
|
|
35
|
+
tools: response.tools_id,
|
|
37
36
|
opportunities: response.opportunities,
|
|
38
37
|
hypothesis: response.hypothesis,
|
|
39
38
|
prfaq: response.prfaq,
|
|
@@ -112,39 +111,44 @@ const updatePlanningMessage = (messages: ChatEntry[]) => {
|
|
|
112
111
|
|
|
113
112
|
export function helperSendMessage(messages: ChatEntry[], value: Partial<ChatResponseWithSteps> & { opportunities?: any },
|
|
114
113
|
chat: ChatState, botEntry: ChatEntry, knowledgeSources: KnowledgeSource[] | undefined) {
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
for (const agent_info of value.agent_info ?? []) {
|
|
115
|
+
if (agent_info?.type === 'planning') {
|
|
116
|
+
if (agent_info.action === 'start') {
|
|
117
|
+
chat.set('isPlaning', true)
|
|
118
|
+
} else {
|
|
119
|
+
chat.set('isPlaning', false)
|
|
120
|
+
}
|
|
120
121
|
}
|
|
121
|
-
}
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
if (agent_info?.type === 'chat' && agent_info?.action === 'end') {
|
|
124
|
+
//When an error happens, the step can still be running, so we enforce the error
|
|
125
|
+
const stepRunning = findLast(value.steps, (item) => item.status === 'running')
|
|
126
|
+
if (stepRunning?.status) {
|
|
127
|
+
stepRunning.status = 'error'
|
|
128
|
+
}
|
|
128
129
|
}
|
|
129
|
-
}
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
const lastPlanningAwaiting = getLastPlanningAwaiting(messages)
|
|
132
|
+
if (lastPlanningAwaiting && value.steps) {
|
|
133
|
+
value.steps?.map(step => {
|
|
134
|
+
if (step.type === 'planning') {
|
|
135
|
+
updatePlanningMessage(messages)
|
|
136
|
+
} else if (step.type === 'step') {
|
|
137
|
+
updateStepMessage(step, messages)
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
}
|
|
134
141
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (step.type === 'planning') {
|
|
139
|
-
updatePlanningMessage(messages)
|
|
140
|
-
} else if (step.type === 'step') {
|
|
141
|
-
updateStepMessage(step, messages)
|
|
142
|
-
}
|
|
143
|
-
})
|
|
142
|
+
if (agent_info?.type === 'tool' && agent_info?.action !== 'awaiting_approval') {
|
|
143
|
+
updateToolStatus(agent_info, messages)
|
|
144
|
+
}
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
if (
|
|
147
|
-
|
|
147
|
+
if (chat.get('features').showSourcesInResponse) {
|
|
148
|
+
const mergedSources = [...(value.source ?? []), ...(value.cross_account_source ?? [])]
|
|
149
|
+
if (mergedSources.length !== (knowledgeSources?.length ?? 0)) {
|
|
150
|
+
knowledgeSources = genericSourcesToKnowledgeSources(mergedSources)
|
|
151
|
+
}
|
|
148
152
|
}
|
|
149
153
|
|
|
150
154
|
if (value.steps) {
|
|
@@ -193,7 +197,7 @@ export function helperSendMessage(messages: ChatEntry[], value: Partial<ChatResp
|
|
|
193
197
|
export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState, signal: AbortSignal) {
|
|
194
198
|
const { agentType, content, data } = entry.getValue()
|
|
195
199
|
if (agentType !== 'user') return
|
|
196
|
-
const context = buildConversationContext(chat, entry)
|
|
200
|
+
const context = buildConversationContext(chat, entry, buildPrompt(content, data))
|
|
197
201
|
chat.set('isLoading', true)
|
|
198
202
|
const untitled = chat.untitled
|
|
199
203
|
const messages = chat.getMessages()
|
|
@@ -203,7 +207,7 @@ export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState,
|
|
|
203
207
|
chat.untitled = false
|
|
204
208
|
}
|
|
205
209
|
|
|
206
|
-
const stream =
|
|
210
|
+
const stream = genAiInferenceClient.sendChatMessage(context)
|
|
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
|
|
@@ -216,14 +220,14 @@ export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState,
|
|
|
216
220
|
helperSendMessage(messages, value, chat, botEntry, knowledgeSources)
|
|
217
221
|
})
|
|
218
222
|
|
|
219
|
-
let finalValue: Partial<
|
|
223
|
+
let finalValue: Partial<ChatResponse> | undefined
|
|
220
224
|
try {
|
|
221
225
|
finalValue = await stream.getValue()
|
|
222
226
|
|
|
223
227
|
const lastPlanningAwaiting = getLastPlanningAwaiting(messages)
|
|
224
228
|
if (lastPlanningAwaiting) {
|
|
225
229
|
const value = lastPlanningAwaiting.getValue()
|
|
226
|
-
value.content = finalValue.
|
|
230
|
+
value.content = finalValue.message || value.content
|
|
227
231
|
lastPlanningAwaiting.setValue(value)
|
|
228
232
|
}
|
|
229
233
|
// if the streaming feature is not enabled, we only add the chat entry once the streaming has finished
|
|
@@ -243,7 +247,7 @@ export async function sendMessageInterceptor(entry: ChatEntry, chat: ChatState,
|
|
|
243
247
|
})
|
|
244
248
|
}
|
|
245
249
|
}
|
|
246
|
-
if (finalValue?.
|
|
250
|
+
if (finalValue?.message) {
|
|
247
251
|
botEntry.setValue({
|
|
248
252
|
...createEntryValueFromChatResponse(finalValue, botEntry.getValue().knowledgeSources, chat.get('agent'), true),
|
|
249
253
|
hasPlanning: botEntry.getValue().hasPlanning,
|
package/src/components/Code.tsx
CHANGED
|
@@ -36,7 +36,9 @@ export interface Props extends WithChildren {
|
|
|
36
36
|
const CodeBox = styled.code`
|
|
37
37
|
background: ${theme.color.light[500]};
|
|
38
38
|
border-radius: 6px;
|
|
39
|
-
overflow:
|
|
39
|
+
overflow: visible;
|
|
40
|
+
display: block;
|
|
41
|
+
position: relative;
|
|
40
42
|
|
|
41
43
|
.highlighter {
|
|
42
44
|
margin: 0 !important;
|
|
@@ -55,13 +57,26 @@ const CodeBox = styled.code`
|
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
.header-code {
|
|
60
|
+
position: sticky;
|
|
61
|
+
top: 0;
|
|
62
|
+
z-index: 10;
|
|
58
63
|
display: flex;
|
|
59
64
|
flex-direction: row;
|
|
60
65
|
justify-content: space-between;
|
|
61
|
-
background: ${theme.color.light[
|
|
66
|
+
background: ${theme.color.light[400]};
|
|
62
67
|
padding: 4px 6px;
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
&:after {
|
|
69
|
+
content: '';
|
|
70
|
+
position: absolute;
|
|
71
|
+
top: 0;
|
|
72
|
+
left: 0;
|
|
73
|
+
right: 0;
|
|
74
|
+
bottom: 0;
|
|
75
|
+
border-top-left-radius: 6px;
|
|
76
|
+
border-top-right-radius: 6px;
|
|
77
|
+
background: ${theme.color.light[600]};
|
|
78
|
+
z-index: -1;
|
|
79
|
+
}
|
|
65
80
|
|
|
66
81
|
.action-bar {
|
|
67
82
|
display: flex;
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import { Children, Fragment } from 'react'
|
|
6
6
|
import ReactMarkdown from 'react-markdown'
|
|
7
|
+
import rehypeKatex from 'rehype-katex'
|
|
7
8
|
import remarkGfm from 'remark-gfm'
|
|
9
|
+
import remarkMath from 'remark-math'
|
|
8
10
|
import { WithChildren } from '../types'
|
|
9
11
|
import { Code, Props as CodeProps } from './Code'
|
|
10
12
|
|
|
@@ -29,26 +31,43 @@ export const Markdown = (
|
|
|
29
31
|
onCopyCode,
|
|
30
32
|
children,
|
|
31
33
|
}: Props,
|
|
32
|
-
) =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
) => {
|
|
35
|
+
|
|
36
|
+
// fix parsing LaTex: https://github.com/remarkjs/react-markdown/issues/785
|
|
37
|
+
const content = typeof children === 'string'
|
|
38
|
+
? children
|
|
39
|
+
.replace(/\\\\\[/g, '$$$$') // Replace '\\[' with '$$'
|
|
40
|
+
.replace(/\\\\\]/g, '$$$$') // Replace '\\]' with '$$'
|
|
41
|
+
.replace(/\\\\\(/g, '$$$$') // Replace '\\(' with '$$'
|
|
42
|
+
.replace(/\\\\\)/g, '$$$$') // Replace '\\)' with '$$'
|
|
43
|
+
.replace(/\\\[/g, '$$$$') // Replace '\[' with '$$'
|
|
44
|
+
.replace(/\\\]/g, '$$$$') // Replace '\]' with '$$'
|
|
45
|
+
.replace(/\\\(/g, '$$$$') // Replace '\(' with '$$'
|
|
46
|
+
.replace(/\\\)/g, '$$$$') // Replace '\)' with '$$';
|
|
47
|
+
: children
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<>
|
|
51
|
+
<ReactMarkdown
|
|
52
|
+
className="markdown apply-citric"
|
|
53
|
+
remarkPlugins={[[remarkMath, { singleDollarTextMath: true }], remarkGfm]}
|
|
54
|
+
rehypePlugins={[rehypeKatex]}
|
|
55
|
+
components={{
|
|
56
|
+
a: props => <a target="_blank" rel="noopener noreferrer" style={{ textDecoration: 'underline' }} {...props} />,
|
|
57
|
+
code: props =>
|
|
58
|
+
<Code
|
|
59
|
+
{...props}
|
|
60
|
+
onInsertCode={onInsertCode}
|
|
61
|
+
onNewFile={onNewFile}
|
|
62
|
+
onCopyCode={onCopyCode}
|
|
63
|
+
showActionBar
|
|
64
|
+
/>,
|
|
65
|
+
pre: ({ children }) => <>{children}</>,
|
|
66
|
+
p: ({ children }) => <p>{Children.map(children, renderP)}</p>,
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
{content}
|
|
70
|
+
</ReactMarkdown>
|
|
71
|
+
</>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
@@ -5,7 +5,7 @@ import { Button, IconButton } from '@stack-spot/citric-react'
|
|
|
5
5
|
import { listToClass, theme } from '@stack-spot/portal-theme'
|
|
6
6
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
7
7
|
import { last } from 'lodash'
|
|
8
|
-
import { useCallback, useEffect, useMemo, useRef } from 'react'
|
|
8
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
9
9
|
import { styled } from 'styled-components'
|
|
10
10
|
import { ButtonAction } from '../types'
|
|
11
11
|
import { FadingOverflow } from './FadingOverflow'
|
|
@@ -152,19 +152,31 @@ export function TabManager<T, Key extends React.Key>(
|
|
|
152
152
|
const t = useTranslate(dictionary)
|
|
153
153
|
const tabList = useRef<HTMLUListElement>(null)
|
|
154
154
|
const lastNumberOfTabs = useRef(tabs.length)
|
|
155
|
+
const [ariaMessage, setAriaMessage] = useState('')
|
|
155
156
|
|
|
156
157
|
const onClickTab = useCallback((event: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
|
157
158
|
const target = event.target as HTMLElement
|
|
158
159
|
if (target.tagName === 'LI') target.querySelector('button')?.click()
|
|
159
160
|
}, [])
|
|
160
161
|
|
|
161
|
-
const tabItems = useMemo(() => tabs.map((tab) =>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
const tabItems = useMemo(() => tabs.map((tab, idx) => {
|
|
163
|
+
const tabLabel = typeof renderLabel(tab) === 'string'
|
|
164
|
+
? renderLabel(tab)
|
|
165
|
+
: `${t.tab} ${idx + 1}`
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<li key={keygen(tab)} className={keygen(tab) === active ? 'active' : undefined} onClick={onClickTab}>
|
|
169
|
+
<button className="label" aria-label={`${t.chat} ${tabLabel}`} onClick={() => onSelect(tab)}>
|
|
170
|
+
<FadingOverflow>{renderLabel(tab)}</FadingOverflow>
|
|
171
|
+
</button>
|
|
172
|
+
{tabs.length > 1 &&
|
|
173
|
+
<IconButton appearance="text" icon="TimesMini" aria-label={`${tabLabel}`}
|
|
174
|
+
title={t.close} onClick={() => { onRemove(tab), setAriaMessage(`${t.chat} ${tabLabel} ${t.closed}`)
|
|
175
|
+
|
|
176
|
+
// Clears the message after a short time to prevent it from repeating
|
|
177
|
+
setTimeout(() => setAriaMessage(''), 1000)}} />}
|
|
178
|
+
</li>
|
|
179
|
+
)}), [tabs, active])
|
|
168
180
|
|
|
169
181
|
const extras = useMemo(() => buttons.map(({
|
|
170
182
|
ariaLabel, title, label, onClick, group, icon, appearance, size, className, style, disabled }) => label
|
|
@@ -204,6 +216,11 @@ export function TabManager<T, Key extends React.Key>(
|
|
|
204
216
|
|
|
205
217
|
return (
|
|
206
218
|
<Tabs $numberOfExtraButtons={buttons.length} className="tabs">
|
|
219
|
+
<div
|
|
220
|
+
aria-live="polite" aria-atomic="true"
|
|
221
|
+
style={{ position: 'absolute', left: '-9999px', width: '1px', height: '1px', overflow: 'hidden' }}>
|
|
222
|
+
{ariaMessage}
|
|
223
|
+
</div>
|
|
207
224
|
<FadingOverflow className="list-overflow" scroll="arrows" enableHorizontalScrollWithVerticalWheel>
|
|
208
225
|
<ul ref={tabList}>{tabItems}</ul>
|
|
209
226
|
</FadingOverflow>
|
|
@@ -215,9 +232,15 @@ export function TabManager<T, Key extends React.Key>(
|
|
|
215
232
|
const dictionary = {
|
|
216
233
|
en: {
|
|
217
234
|
close: 'Close',
|
|
235
|
+
tab: 'Tab',
|
|
236
|
+
chat: 'Chat',
|
|
237
|
+
closed: 'Closed',
|
|
218
238
|
},
|
|
219
239
|
pt: {
|
|
220
240
|
close: 'Fechar',
|
|
241
|
+
tab: 'Aba',
|
|
242
|
+
chat: 'Chat',
|
|
243
|
+
closed: 'Fechado',
|
|
221
244
|
},
|
|
222
245
|
} satisfies Dictionary
|
|
223
246
|
|
package/src/state/ChatState.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ChatRequest } from '@stack-spot/portal-network/api/genAiInference'
|
|
1
2
|
import { dropRight, last, pull } from 'lodash'
|
|
2
3
|
import { ulid } from 'ulid'
|
|
3
4
|
import { AbortedError } from '../AbortedError'
|
|
@@ -63,6 +64,11 @@ export interface ChatPropertiesWithOptionalFeatures {
|
|
|
63
64
|
* The current LLM (Large Language Model) being used for this chat.
|
|
64
65
|
*/
|
|
65
66
|
selected_model_id?: string,
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Extra options to be merged into the chat request payload sent to the backend.
|
|
70
|
+
*/
|
|
71
|
+
requestOptions?: Pick<ChatRequest, 'deep_search_ks' | 'return_ks_in_response' | 'use_conversation'>,
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
export interface ChatProperties extends ChatPropertiesWithOptionalFeatures {
|
package/src/utils/chat.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { FixedChatRequest } from '@stack-spot/portal-network'
|
|
1
|
+
import type { FixedChatRequest } from '@stack-spot/portal-network'
|
|
2
2
|
import appData from '../app-metadata.json'
|
|
3
|
-
import { ChatEntry } from '../state/ChatEntry'
|
|
4
|
-
import { ChatState } from '../state/ChatState'
|
|
5
|
-
import { defaultLanguage } from './programming-languages'
|
|
3
|
+
import type { ChatEntry } from '../state/ChatEntry'
|
|
4
|
+
import type { ChatState } from '../state/ChatState'
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
* The conversation context is needed by most backend services.
|
|
11
|
-
*
|
|
12
|
-
* @param state the ChatState to build the context from.
|
|
13
|
-
* @returns the conversation context ready to be sent to the backend.
|
|
14
|
-
*/
|
|
15
|
-
export function buildConversationContext(state: ChatState, message?: ChatEntry): FixedChatRequest['context'] {
|
|
6
|
+
export function buildConversationContext(state: ChatState, message?: ChatEntry | undefined, userPrompt?: string): FixedChatRequest {
|
|
7
|
+
const requestOptions = state.get('requestOptions')
|
|
16
8
|
return {
|
|
17
|
-
|
|
9
|
+
streaming: true,
|
|
10
|
+
show_chat_processing_state: true,
|
|
11
|
+
return_ks_in_response: state.get('features')?.showSourcesInResponse,
|
|
12
|
+
deep_search_ks: false,
|
|
13
|
+
stackspot_knowledge: false,
|
|
14
|
+
user_prompt: userPrompt ?? '',
|
|
15
|
+
use_conversation: true,
|
|
18
16
|
conversation_id: state.id,
|
|
17
|
+
workspace_id: state.get('workspace')?.id,
|
|
19
18
|
stack_id: state.get('stack')?.id,
|
|
20
|
-
language: state.get('codeLanguage') || (state.get('codeSelection') ? defaultLanguage : undefined),
|
|
21
19
|
knowledge_sources: state.get('knowledgeSources')?.map(ks => ks.id),
|
|
22
20
|
upload_ids: message?.getValue().upload?.map(f => f.id),
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
selected_model: state.get('selected_model_id') ?? null,
|
|
22
|
+
context: {
|
|
23
|
+
os: navigator.userAgent,
|
|
24
|
+
platform: 'web-widget',
|
|
25
|
+
platform_version: navigator.userAgent,
|
|
26
|
+
stackspot_ai_version: appData.version,
|
|
27
|
+
agent_id: state.get('agent')?.id,
|
|
28
|
+
},
|
|
29
|
+
...requestOptions,
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -62,7 +62,7 @@ export function extractCodeFromKSDocument(document: DocumentResponse): { languag
|
|
|
62
62
|
export function genericSourcesToKnowledgeSources(
|
|
63
63
|
sources: (SourceStackAi | SourceKnowledgeSource | SourceProjectFile3)[] | undefined,
|
|
64
64
|
): KnowledgeSource[] | undefined {
|
|
65
|
-
return sources?.filter(s => s.type === 'knowledge_source').map(ks => {
|
|
65
|
+
return sources?.filter(s => s.type === 'knowledge_source' || s.type === 'cross_account').map(ks => {
|
|
66
66
|
const { document_id: documentId, document_score: documentScore, name, slug } = ks as SourceKnowledgeSource
|
|
67
67
|
return { documentId, documentScore, name, slug }
|
|
68
68
|
})
|
|
@@ -189,7 +189,7 @@ export const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit, workspaceId,
|
|
|
189
189
|
hasNextPage={hasNextPage && !workspaceId}
|
|
190
190
|
fetchNextPage={fetchNextPage}
|
|
191
191
|
data={(ks: KnowledgeSourceItemResponse) => ({
|
|
192
|
-
idOrSlug: ks.
|
|
192
|
+
idOrSlug: ks.id, description: ks.description, name: ks.name, listFavorites,
|
|
193
193
|
onAddFavorite, onRemoveFavorite,
|
|
194
194
|
})}
|
|
195
195
|
emptyResults={<Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} />}
|
|
@@ -21,7 +21,7 @@ const ContextBadge = ({ label, color, dismiss, onDismiss }: ContextBadgeProps) =
|
|
|
21
21
|
appearance="none"
|
|
22
22
|
onClick={onDismiss}
|
|
23
23
|
title={dismiss}
|
|
24
|
-
|
|
24
|
+
aria-label={dismiss}
|
|
25
25
|
style={{ padding: '2px 0 2px 2px', color: 'inherit' }}
|
|
26
26
|
/>}
|
|
27
27
|
</Badge>
|