@stack-spot/ai-chat-widget 2.1.1 → 2.2.0-beta.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 +30 -2
- package/dist/app-metadata.json +5 -5
- package/dist/chat-interceptors/send-message.d.ts.map +1 -1
- package/dist/chat-interceptors/send-message.js +125 -1
- package/dist/chat-interceptors/send-message.js.map +1 -1
- package/dist/layout.css +6 -0
- package/dist/state/ChatEntry.d.ts +1 -1
- package/dist/state/ChatEntry.d.ts.map +1 -1
- package/dist/state/ChatEntry.js +2 -1
- package/dist/state/ChatEntry.js.map +1 -1
- package/dist/state/ChatState.d.ts +8 -0
- package/dist/state/ChatState.d.ts.map +1 -1
- package/dist/state/ChatState.js.map +1 -1
- package/dist/utils/chat.d.ts.map +1 -1
- package/dist/utils/chat.js +1 -0
- package/dist/utils/chat.js.map +1 -1
- package/dist/utils/planning-tool.d.ts +17 -0
- package/dist/utils/planning-tool.d.ts.map +1 -0
- package/dist/utils/planning-tool.js +32 -0
- package/dist/utils/planning-tool.js.map +1 -0
- package/dist/utils/update-tool-step.d.ts +3 -0
- package/dist/utils/update-tool-step.d.ts.map +1 -0
- package/dist/utils/update-tool-step.js +23 -0
- package/dist/utils/update-tool-step.js.map +1 -0
- 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 +21 -6
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/Chat/StepsList.d.ts +12 -2
- package/dist/views/Chat/StepsList.d.ts.map +1 -1
- package/dist/views/Chat/StepsList.js +155 -18
- package/dist/views/Chat/StepsList.js.map +1 -1
- package/dist/views/Chat/styled.d.ts.map +1 -1
- package/dist/views/Chat/styled.js +17 -10
- package/dist/views/Chat/styled.js.map +1 -1
- package/dist/views/MessageInput/ButtonBar.d.ts.map +1 -1
- package/dist/views/MessageInput/ButtonBar.js +2 -1
- package/dist/views/MessageInput/ButtonBar.js.map +1 -1
- package/dist/views/MessageInput/ModelSwitcher.d.ts +2 -0
- package/dist/views/MessageInput/ModelSwitcher.d.ts.map +1 -0
- package/dist/views/MessageInput/ModelSwitcher.js +77 -0
- package/dist/views/MessageInput/ModelSwitcher.js.map +1 -0
- package/dist/views/MessageInput/SelectContent.js +1 -1
- package/dist/views/MessageInput/SelectContent.js.map +1 -1
- package/dist/views/MessageInput/dictionary.d.ts +1 -1
- package/dist/views/MessageInput/styled.d.ts +3 -0
- package/dist/views/MessageInput/styled.d.ts.map +1 -1
- package/dist/views/MessageInput/styled.js +12 -0
- package/dist/views/MessageInput/styled.js.map +1 -1
- package/dist/views/Steps/FlowChart/NodeStep.js +1 -1
- package/dist/views/Steps/FlowChart/NodeStep.js.map +1 -1
- package/dist/views/Steps/FlowChart/layout.d.ts +1 -1
- package/dist/views/Steps/FlowChart/layout.d.ts.map +1 -1
- package/dist/views/Steps/FlowChart/layout.js +1 -0
- package/dist/views/Steps/FlowChart/layout.js.map +1 -1
- package/dist/views/Steps/FlowChart/types.d.ts +1 -1
- package/dist/views/Steps/FlowChart/types.d.ts.map +1 -1
- package/dist/views/Steps/StepModal.js +2 -2
- package/dist/views/Steps/StepModal.js.map +1 -1
- package/dist/views/Steps/dictionary.d.ts +1 -1
- package/dist/views/Steps/utils.d.ts +1 -1
- package/dist/views/Steps/utils.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/app-metadata.json +5 -5
- package/src/chat-interceptors/send-message.ts +137 -2
- package/src/layout.css +6 -0
- package/src/state/ChatEntry.ts +2 -1
- package/src/state/ChatState.ts +8 -0
- package/src/utils/chat.ts +1 -0
- package/src/utils/planning-tool.ts +41 -0
- package/src/utils/update-tool-step.tsx +27 -0
- package/src/views/Chat/ChatMessage.tsx +25 -5
- package/src/views/Chat/StepsList.tsx +337 -44
- package/src/views/Chat/styled.ts +17 -10
- package/src/views/MessageInput/ButtonBar.tsx +2 -0
- package/src/views/MessageInput/ModelSwitcher.tsx +127 -0
- package/src/views/MessageInput/SelectContent.tsx +1 -1
- package/src/views/MessageInput/styled.ts +12 -0
- package/src/views/Steps/FlowChart/NodeStep.tsx +1 -1
- package/src/views/Steps/FlowChart/layout.ts +1 -0
- package/src/views/Steps/FlowChart/types.ts +1 -1
- package/src/views/Steps/StepModal.tsx +2 -2
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { Button, Icon } from '@stack-spot/citric-react'
|
|
2
|
+
import { SelectionList } from '@stack-spot/portal-components/SelectionList'
|
|
3
|
+
import { agentToolsClient, genAiInferenceClient } from '@stack-spot/portal-network'
|
|
4
|
+
import { AgentLlmModelDto, AgentModel } from '@stack-spot/portal-network/api/agent-tools'
|
|
5
|
+
import { LlmModelsResponse, PaginatedResponseLlmModelsResponse } from '@stack-spot/portal-network/api/genAiInference'
|
|
6
|
+
import { Dispatch, ReactElement, useState } from 'react'
|
|
7
|
+
import { CSSProperties } from 'styled-components'
|
|
8
|
+
import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
9
|
+
import { useMessageInputDictionary } from './dictionary'
|
|
10
|
+
import { RowWrapperStyled } from './styled'
|
|
11
|
+
|
|
12
|
+
const styles = {
|
|
13
|
+
selection: {
|
|
14
|
+
position: 'absolute',
|
|
15
|
+
bottom: 'calc(100% + 10px)',
|
|
16
|
+
right: '0',
|
|
17
|
+
margin: '0',
|
|
18
|
+
'ul': {
|
|
19
|
+
margin: '0px',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const ModelSwitcher = () => {
|
|
25
|
+
const t = useMessageInputDictionary()
|
|
26
|
+
const agent = useCurrentChatState('agent')
|
|
27
|
+
const chat = useCurrentChat()
|
|
28
|
+
const [visibleMenu, setVisibleMenu] = useState(false)
|
|
29
|
+
const [agentData] = agentToolsClient.agent.useStatefulQuery({ agentId: agent?.id || '' })
|
|
30
|
+
const [selectedLLMName, setSelectedLLMName] = useState<string | undefined>()
|
|
31
|
+
const [models] = genAiInferenceClient.listModels.useStatefulQuery({ pageSize: 999 })
|
|
32
|
+
|
|
33
|
+
const { modelName, listItems } = getModelData(chat, setSelectedLLMName, setVisibleMenu, selectedLLMName, agentData, models)
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<RowWrapperStyled>
|
|
37
|
+
<Button
|
|
38
|
+
className="button-select-model"
|
|
39
|
+
colorScheme="light"
|
|
40
|
+
size="sm"
|
|
41
|
+
aria-label={t.agent}
|
|
42
|
+
title={t.agent}
|
|
43
|
+
onClick={() => setVisibleMenu(state => !state)}
|
|
44
|
+
>
|
|
45
|
+
{modelName}
|
|
46
|
+
<Icon icon="ChevronDown" group="fill" size="sm" />
|
|
47
|
+
</Button>
|
|
48
|
+
<SelectionList
|
|
49
|
+
id="menuModelSwitcher"
|
|
50
|
+
visible={visibleMenu}
|
|
51
|
+
onHide={() => setVisibleMenu(false)}
|
|
52
|
+
items={listItems || []}
|
|
53
|
+
style={styles.selection as CSSProperties}
|
|
54
|
+
/>
|
|
55
|
+
</RowWrapperStyled>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
function getModelData(
|
|
61
|
+
chat: any,
|
|
62
|
+
setSelectedModelName: Dispatch<React.SetStateAction<string | undefined>>,
|
|
63
|
+
setVisibleMenu: Dispatch<React.SetStateAction<boolean>>,
|
|
64
|
+
selectedModelName?: string,
|
|
65
|
+
agent?: AgentModel,
|
|
66
|
+
models?: PaginatedResponseLlmModelsResponse) {
|
|
67
|
+
|
|
68
|
+
const modelListData = parseModelList(
|
|
69
|
+
setSelectedModelName, setVisibleMenu, chat,
|
|
70
|
+
agent?.visibility_level !== 'built_in' && !!agent?.model_id ? agent?.available_llm_models : models?.items,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if (agent?.visibility_level === 'built_in' || !!agent?.model_id) {
|
|
74
|
+
const modelDefaultFromList = modelListData.find((model) => model.active)
|
|
75
|
+
return { modelName: modelDefaultFromList?.label, listItems: modelListData }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const listItems =
|
|
79
|
+
modelListData && modelListData?.length > 0 ? modelListData :
|
|
80
|
+
[{
|
|
81
|
+
active: true,
|
|
82
|
+
label: agent?.model_name || agent?.available_llm_models?.find((model) => model.is_default)?.model_name || '',
|
|
83
|
+
icon: <Icon icon="StackSpot" />,
|
|
84
|
+
}]
|
|
85
|
+
|
|
86
|
+
const modelSelectedName = selectedModelName || agent?.model_name ||
|
|
87
|
+
agent?.available_llm_models?.find((model) => model.is_default)?.model_name
|
|
88
|
+
|
|
89
|
+
return { modelName: modelSelectedName, listItems }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function parseModelList(
|
|
93
|
+
setSelectedModelName: Dispatch<React.SetStateAction<string | undefined>>,
|
|
94
|
+
setVisibleMenu: Dispatch<React.SetStateAction<boolean>>,
|
|
95
|
+
chat: any,
|
|
96
|
+
listModel?: Array<AgentLlmModelDto | LlmModelsResponse>,
|
|
97
|
+
) {
|
|
98
|
+
const data = Array<{active?: boolean, label: string, icon: ReactElement, onClick: VoidFunction }>()
|
|
99
|
+
|
|
100
|
+
listModel?.forEach((model) => {
|
|
101
|
+
if ('model_id' in model) {
|
|
102
|
+
data.push({
|
|
103
|
+
active: chat.get('selected_model_id') ? chat.get('selected_model_id') === model.model_id : model.is_default,
|
|
104
|
+
label: model?.model_name || 'LLM',
|
|
105
|
+
icon: <Icon icon="Bookmark"/>,
|
|
106
|
+
onClick: () => {
|
|
107
|
+
setSelectedModelName(model.model_name)
|
|
108
|
+
chat.set('selected_model_id', model.model_id)
|
|
109
|
+
setVisibleMenu(false)
|
|
110
|
+
},
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
data.push({
|
|
115
|
+
active: chat.get('selected_model_id') ? chat.get('selected_model_id') === model.id : model.resources[0]?.is_default,
|
|
116
|
+
label: model?.display_name || 'LLM',
|
|
117
|
+
icon: <Icon icon="Bookmark"/>,
|
|
118
|
+
onClick: () => {
|
|
119
|
+
setSelectedModelName(model.display_name)
|
|
120
|
+
chat.set('selected_model_id', model.id)
|
|
121
|
+
setVisibleMenu(false)
|
|
122
|
+
},
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
return data
|
|
127
|
+
}
|
|
@@ -83,7 +83,7 @@ export const SelectContent = () => {
|
|
|
83
83
|
if (!hasFeatureButtons) return null
|
|
84
84
|
|
|
85
85
|
return itemConfigs.length > 1 ? (
|
|
86
|
-
<MenuOverlay items={listItems} position="
|
|
86
|
+
<MenuOverlay items={listItems} position="right" bgLevel={500} roundedItems menuClass="menu-citric-hr" alignment="end">
|
|
87
87
|
<IconButton icon="Plus" />
|
|
88
88
|
</MenuOverlay>
|
|
89
89
|
) : (
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Flex } from '@citric/core'
|
|
1
2
|
import { theme } from '@stack-spot/portal-theme'
|
|
2
3
|
import { styled } from 'styled-components'
|
|
3
4
|
|
|
@@ -302,3 +303,14 @@ export const MessageInputBox = styled.div`
|
|
|
302
303
|
}
|
|
303
304
|
}
|
|
304
305
|
`
|
|
306
|
+
export const RowWrapperStyled = styled(Flex)`
|
|
307
|
+
width: 100%;
|
|
308
|
+
justify-content: end;
|
|
309
|
+
margin-right: 4px;
|
|
310
|
+
ul {
|
|
311
|
+
margin: 0;
|
|
312
|
+
}
|
|
313
|
+
.button-select-model {
|
|
314
|
+
border-radius: 15px !important;
|
|
315
|
+
}
|
|
316
|
+
`
|
|
@@ -37,7 +37,7 @@ export const NodeStep = ({ data: { step, index, nextStatus, onClick } }: Props)
|
|
|
37
37
|
{!!step.attempts[0].tools?.length && <StackedBadge
|
|
38
38
|
label={t.tools}
|
|
39
39
|
images={step.attempts[0].tools?.slice(0, 3).map(
|
|
40
|
-
tool => ({ key: tool.id, name: tool.name, url: tool.image, icon: <Icon icon="Cog" /> }),
|
|
40
|
+
tool => ({ key: tool.id, name: tool.name ?? '', url: tool.image, icon: <Icon icon="Cog" /> }),
|
|
41
41
|
)}
|
|
42
42
|
/>}
|
|
43
43
|
</div>}
|
|
@@ -127,7 +127,7 @@ export const StepModal = ({ message, stepId, onClose }: Props) => {
|
|
|
127
127
|
|
|
128
128
|
const tools = step?.type === 'step' ? step.attempts[attempt]?.tools?.map(tool => (
|
|
129
129
|
<div className="tool" key={tool.id}>
|
|
130
|
-
<ToolBadge name={tool.name} duration={tool.duration} image={tool.image} description={tool.description} />
|
|
130
|
+
<ToolBadge name={tool.name ?? ''} duration={tool.duration} image={tool.image} description={tool.description} />
|
|
131
131
|
{tool.input && <>
|
|
132
132
|
<Text appearance="microtext1" color="light.700">{t.input}:</Text>
|
|
133
133
|
<Code language="json" className="tool-input" showLineNumbers={false} showActionBar>{tool.input}</Code>
|
|
@@ -191,7 +191,7 @@ export const StepModal = ({ message, stepId, onClose }: Props) => {
|
|
|
191
191
|
{!!s.attempts[0].tools?.length && <ul className="side-by-side-tools">
|
|
192
192
|
{s.attempts[0].tools.map((tool) => (
|
|
193
193
|
<li key={tool.id}>
|
|
194
|
-
<ToolBadge name={tool.name} image={tool.image} />
|
|
194
|
+
<ToolBadge name={tool.name ?? ''} image={tool.image} />
|
|
195
195
|
</li>
|
|
196
196
|
))}
|
|
197
197
|
</ul>}
|