@stack-spot/ai-chat-widget 1.1.1 → 1.3.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.
- package/CHANGELOG.md +16 -0
- package/dist/StackspotAIWidget.d.ts +1 -12
- package/dist/StackspotAIWidget.d.ts.map +1 -1
- package/dist/StackspotAIWidget.js +5 -18
- package/dist/StackspotAIWidget.js.map +1 -1
- package/dist/chat-interceptors/quick-commands.js +1 -1
- 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 +21 -2
- package/dist/chat-interceptors/send-message.js.map +1 -1
- package/dist/components/AutoFocus.d.ts.map +1 -1
- package/dist/components/AutoFocus.js +8 -1
- package/dist/components/AutoFocus.js.map +1 -1
- package/dist/components/FadingOverflow.js +2 -2
- package/dist/components/FadingOverflow.js.map +1 -1
- package/dist/components/QuickStartButton.d.ts +6 -1
- package/dist/components/QuickStartButton.d.ts.map +1 -1
- package/dist/components/QuickStartButton.js +6 -2
- package/dist/components/QuickStartButton.js.map +1 -1
- package/dist/components/RightPanelForm.d.ts.map +1 -1
- package/dist/components/RightPanelForm.js +2 -1
- package/dist/components/RightPanelForm.js.map +1 -1
- package/dist/context/hooks.d.ts +2 -7
- package/dist/context/hooks.d.ts.map +1 -1
- package/dist/context/hooks.js +4 -16
- package/dist/context/hooks.js.map +1 -1
- package/dist/features.d.ts +16 -17
- package/dist/features.d.ts.map +1 -1
- package/dist/features.js +17 -9
- package/dist/features.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/layout.css +7 -0
- package/dist/state/ChatState.d.ts +23 -3
- package/dist/state/ChatState.d.ts.map +1 -1
- package/dist/state/ChatState.js +5 -2
- package/dist/state/ChatState.js.map +1 -1
- package/dist/state/ChatTabsController.d.ts +21 -3
- package/dist/state/ChatTabsController.d.ts.map +1 -1
- package/dist/state/ChatTabsController.js +49 -11
- package/dist/state/ChatTabsController.js.map +1 -1
- package/dist/state/WidgetState.d.ts +50 -1
- package/dist/state/WidgetState.d.ts.map +1 -1
- package/dist/state/WidgetState.js +55 -2
- package/dist/state/WidgetState.js.map +1 -1
- package/dist/utils/chat.d.ts +1 -8
- package/dist/utils/chat.d.ts.map +1 -1
- package/dist/utils/chat.js +0 -15
- package/dist/utils/chat.js.map +1 -1
- package/dist/views/Agents/AgentDescription.d.ts +9 -0
- package/dist/views/Agents/AgentDescription.d.ts.map +1 -0
- package/dist/views/Agents/AgentDescription.js +21 -0
- package/dist/views/Agents/AgentDescription.js.map +1 -0
- package/dist/views/Agents/AgentsPanel.d.ts +5 -0
- package/dist/views/Agents/AgentsPanel.d.ts.map +1 -0
- package/dist/views/Agents/AgentsPanel.js +19 -0
- package/dist/views/Agents/AgentsPanel.js.map +1 -0
- package/dist/views/Agents/AgentsTab.d.ts +5 -0
- package/dist/views/Agents/AgentsTab.d.ts.map +1 -0
- package/dist/views/Agents/AgentsTab.js +43 -0
- package/dist/views/Agents/AgentsTab.js.map +1 -0
- package/dist/views/Agents/dictionary.d.ts +2 -0
- package/dist/views/Agents/dictionary.d.ts.map +1 -0
- package/dist/views/Agents/dictionary.js +35 -0
- package/dist/views/Agents/dictionary.js.map +1 -0
- package/dist/views/Agents/index.d.ts +5 -0
- package/dist/views/Agents/index.d.ts.map +1 -0
- package/dist/views/Agents/index.js +21 -0
- package/dist/views/Agents/index.js.map +1 -0
- package/dist/views/Agents/styled.d.ts +3 -0
- package/dist/views/Agents/styled.d.ts.map +1 -0
- package/dist/views/Agents/styled.js +58 -0
- package/dist/views/Agents/styled.js.map +1 -0
- package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessage.js +1 -1
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/Chat/index.js +1 -1
- package/dist/views/Chat/index.js.map +1 -1
- package/dist/views/Chat/styled.js +1 -1
- package/dist/views/ChatHistory/ChatHistoryPanel.d.ts +1 -4
- package/dist/views/ChatHistory/ChatHistoryPanel.d.ts.map +1 -1
- package/dist/views/ChatHistory/ChatHistoryPanel.js +2 -2
- package/dist/views/ChatHistory/ChatHistoryPanel.js.map +1 -1
- package/dist/views/ChatHistory/HistoryItem.d.ts +1 -3
- package/dist/views/ChatHistory/HistoryItem.d.ts.map +1 -1
- package/dist/views/ChatHistory/HistoryItem.js +2 -2
- package/dist/views/ChatHistory/HistoryItem.js.map +1 -1
- package/dist/views/ChatHistory/index.d.ts +1 -9
- package/dist/views/ChatHistory/index.d.ts.map +1 -1
- package/dist/views/ChatHistory/index.js +2 -2
- package/dist/views/ChatHistory/index.js.map +1 -1
- package/dist/views/ChatTabSelection.d.ts +1 -7
- package/dist/views/ChatTabSelection.d.ts.map +1 -1
- package/dist/views/ChatTabSelection.js +7 -7
- package/dist/views/ChatTabSelection.js.map +1 -1
- package/dist/views/Editor.d.ts.map +1 -1
- package/dist/views/Editor.js +4 -1
- package/dist/views/Editor.js.map +1 -1
- package/dist/views/Home/BuiltInAgent.d.ts +6 -0
- package/dist/views/Home/BuiltInAgent.d.ts.map +1 -0
- package/dist/views/{Home.js → Home/BuiltInAgent.js} +7 -41
- package/dist/views/Home/BuiltInAgent.js.map +1 -0
- package/dist/views/Home/CustomAgent.d.ts +5 -0
- package/dist/views/Home/CustomAgent.d.ts.map +1 -0
- package/dist/views/Home/CustomAgent.js +24 -0
- package/dist/views/Home/CustomAgent.js.map +1 -0
- package/dist/views/Home/index.d.ts +8 -0
- package/dist/views/Home/index.d.ts.map +1 -0
- package/dist/views/Home/index.js +15 -0
- package/dist/views/Home/index.js.map +1 -0
- package/dist/views/Home/styled.d.ts +2 -0
- package/dist/views/Home/styled.d.ts.map +1 -0
- package/dist/views/Home/styled.js +59 -0
- package/dist/views/Home/styled.js.map +1 -0
- package/dist/views/Home/types.d.ts +7 -0
- package/dist/views/Home/types.d.ts.map +1 -0
- package/dist/views/Home/types.js +2 -0
- package/dist/views/Home/types.js.map +1 -0
- package/dist/views/KnowledgeSources.js +1 -1
- package/dist/views/KnowledgeSources.js.map +1 -1
- package/dist/views/MessageInput/ButtonGroup.d.ts +1 -6
- package/dist/views/MessageInput/ButtonGroup.d.ts.map +1 -1
- package/dist/views/MessageInput/ButtonGroup.js +12 -4
- package/dist/views/MessageInput/ButtonGroup.js.map +1 -1
- package/dist/views/MessageInput/InfoBar.d.ts.map +1 -1
- package/dist/views/MessageInput/InfoBar.js +16 -6
- package/dist/views/MessageInput/InfoBar.js.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.js +2 -1
- package/dist/views/MessageInput/QuickCommandSelector.js.map +1 -1
- package/dist/views/MessageInput/dictionary.d.ts +1 -1
- package/dist/views/MessageInput/index.d.ts +1 -9
- package/dist/views/MessageInput/index.d.ts.map +1 -1
- package/dist/views/MessageInput/index.js +2 -2
- package/dist/views/MessageInput/index.js.map +1 -1
- package/dist/views/MessageInput/styled.d.ts.map +1 -1
- package/dist/views/MessageInput/styled.js +6 -2
- package/dist/views/MessageInput/styled.js.map +1 -1
- package/dist/views/MinimizedHeader.d.ts.map +1 -1
- package/dist/views/MinimizedHeader.js +2 -3
- package/dist/views/MinimizedHeader.js.map +1 -1
- package/dist/views/Stacks.js +2 -1
- package/dist/views/Stacks.js.map +1 -1
- package/dist/views/Workspaces.js +2 -1
- package/dist/views/Workspaces.js.map +1 -1
- package/package.json +2 -2
- package/src/StackspotAIWidget.tsx +6 -32
- package/src/chat-interceptors/quick-commands.ts +1 -1
- package/src/chat-interceptors/send-message.ts +22 -2
- package/src/components/AutoFocus.tsx +9 -1
- package/src/components/FadingOverflow.tsx +2 -2
- package/src/components/QuickStartButton.tsx +17 -5
- package/src/components/RightPanelForm.tsx +2 -1
- package/src/context/hooks.ts +8 -20
- package/src/features.ts +27 -24
- package/src/index.ts +6 -0
- package/src/layout.css +7 -0
- package/src/state/ChatState.ts +26 -4
- package/src/state/ChatTabsController.ts +50 -11
- package/src/state/WidgetState.ts +88 -2
- package/src/utils/chat.ts +1 -18
- package/src/views/Agents/AgentDescription.tsx +48 -0
- package/src/views/Agents/AgentsPanel.tsx +19 -0
- package/src/views/Agents/AgentsTab.tsx +80 -0
- package/src/views/Agents/dictionary.ts +36 -0
- package/src/views/Agents/index.tsx +26 -0
- package/src/views/Agents/styled.ts +59 -0
- package/src/views/Chat/ChatMessage.tsx +19 -17
- package/src/views/Chat/index.tsx +1 -1
- package/src/views/Chat/styled.ts +1 -1
- package/src/views/ChatHistory/ChatHistoryPanel.tsx +2 -3
- package/src/views/ChatHistory/HistoryItem.tsx +3 -3
- package/src/views/ChatHistory/index.tsx +2 -10
- package/src/views/ChatTabSelection.tsx +8 -13
- package/src/views/Editor.tsx +4 -1
- package/src/views/{Home.tsx → Home/BuiltInAgent.tsx} +7 -48
- package/src/views/Home/CustomAgent.tsx +39 -0
- package/src/views/Home/index.tsx +20 -0
- package/src/views/Home/styled.ts +59 -0
- package/src/views/Home/types.ts +6 -0
- package/src/views/KnowledgeSources.tsx +2 -2
- package/src/views/MessageInput/ButtonGroup.tsx +15 -12
- package/src/views/MessageInput/InfoBar.tsx +25 -9
- package/src/views/MessageInput/QuickCommandSelector.tsx +2 -1
- package/src/views/MessageInput/index.tsx +1 -10
- package/src/views/MessageInput/styled.ts +6 -2
- package/src/views/MinimizedHeader.tsx +2 -3
- package/src/views/Stacks.tsx +3 -2
- package/src/views/Workspaces.tsx +3 -2
- package/dist/views/Agents.d.ts +0 -2
- package/dist/views/Agents.d.ts.map +0 -1
- package/dist/views/Agents.js +0 -146
- package/dist/views/Agents.js.map +0 -1
- package/dist/views/Home.d.ts +0 -14
- package/dist/views/Home.d.ts.map +0 -1
- package/dist/views/Home.js.map +0 -1
- package/src/views/Agents.tsx +0 -203
|
@@ -2,15 +2,8 @@ import { Clock, Plus } from '@citric/icons'
|
|
|
2
2
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
3
3
|
import { useMemo } from 'react'
|
|
4
4
|
import { TabManager } from '../components/TabManager'
|
|
5
|
-
import { useChatState, useChatTabs, useWidget } from '../context/hooks'
|
|
6
|
-
import { MessageInterceptor } from '../state/ChatState'
|
|
5
|
+
import { useChatState, useChatTabs, useWidget, useWidgetState } from '../context/hooks'
|
|
7
6
|
import { ButtonAction } from '../types'
|
|
8
|
-
import { createNewChat } from '../utils/chat'
|
|
9
|
-
|
|
10
|
-
interface Props {
|
|
11
|
-
history?: boolean,
|
|
12
|
-
interceptors: MessageInterceptor[],
|
|
13
|
-
}
|
|
14
7
|
|
|
15
8
|
const TabLabel = ({ id }: { id: string }) => {
|
|
16
9
|
const label = useChatState(id, 'label')
|
|
@@ -20,9 +13,10 @@ const TabLabel = ({ id }: { id: string }) => {
|
|
|
20
13
|
/**
|
|
21
14
|
* This renders the top-most part of the layout, which includes the chat selection through tabs.
|
|
22
15
|
*/
|
|
23
|
-
export const ChatTabSelection = (
|
|
16
|
+
export const ChatTabSelection = () => {
|
|
24
17
|
const t = useTranslate(dictionary)
|
|
25
18
|
const widget = useWidget()
|
|
19
|
+
const { chatHistory } = useWidgetState('features') ?? {}
|
|
26
20
|
const { active, chats } = useChatTabs()
|
|
27
21
|
|
|
28
22
|
const buttons = useMemo<ButtonAction[]>(
|
|
@@ -30,9 +24,9 @@ export const ChatTabSelection = ({ history, interceptors }: Props) => {
|
|
|
30
24
|
const actions: ButtonAction[] = [{
|
|
31
25
|
icon: <Plus />,
|
|
32
26
|
label: t.newChat,
|
|
33
|
-
onClick: () =>
|
|
27
|
+
onClick: () => widget.createChat(),
|
|
34
28
|
}]
|
|
35
|
-
if (
|
|
29
|
+
if (chatHistory) {
|
|
36
30
|
actions.push({
|
|
37
31
|
icon: <Clock />,
|
|
38
32
|
label: t.openHistory,
|
|
@@ -43,11 +37,12 @@ export const ChatTabSelection = ({ history, interceptors }: Props) => {
|
|
|
43
37
|
}
|
|
44
38
|
return actions
|
|
45
39
|
},
|
|
46
|
-
[
|
|
40
|
+
[chatHistory],
|
|
47
41
|
)
|
|
42
|
+
|
|
48
43
|
return <TabManager
|
|
49
44
|
tabs={chats}
|
|
50
|
-
active={active}
|
|
45
|
+
active={active.id}
|
|
51
46
|
renderLabel={({ id }) => <TabLabel id={id} />}
|
|
52
47
|
keygen={({ id }) => id}
|
|
53
48
|
onRemove={({ id }) => widget.chatTabs.remove(id)}
|
package/src/views/Editor.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Text } from '@citric/core'
|
|
2
2
|
import { LoadingCircular } from '@citric/ui'
|
|
3
3
|
import MonacoEditor, { OnMount } from '@monaco-editor/react'
|
|
4
|
+
import { delay } from '@stack-spot/portal-components'
|
|
4
5
|
import { Select } from '@stack-spot/portal-components/Select'
|
|
5
6
|
import { useThemeKind } from '@stack-spot/portal-theme'
|
|
6
7
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
@@ -9,6 +10,7 @@ import { IDisposable } from 'monaco-editor'
|
|
|
9
10
|
import { useCallback, useEffect, useMemo, useRef } from 'react'
|
|
10
11
|
import { styled } from 'styled-components'
|
|
11
12
|
import { useCurrentChat, useCurrentChatState, useWidget, useWidgetState } from '../context/hooks'
|
|
13
|
+
import { panelAnimationTime } from '../right-panel/constants'
|
|
12
14
|
import { useRightPanel } from '../right-panel/hooks'
|
|
13
15
|
import { defaultLanguage, languages } from '../utils/programming-languages'
|
|
14
16
|
|
|
@@ -92,11 +94,12 @@ const EditorPanel = () => {
|
|
|
92
94
|
const chat = useCurrentChat()
|
|
93
95
|
const selectionObserver = useRef<IDisposable | undefined>()
|
|
94
96
|
|
|
95
|
-
const setup: OnMount = useCallback((editor) => {
|
|
97
|
+
const setup: OnMount = useCallback(async (editor) => {
|
|
96
98
|
selectionObserver.current = editor.onDidChangeCursorSelection(debounce((e) => {
|
|
97
99
|
const selectedText = editor.getModel()?.getValueInRange(e.selection)
|
|
98
100
|
chat.set('codeSelection', selectedText?.trim() ? selectedText : undefined)
|
|
99
101
|
}, MIN_SELECTION_UPDATE_MS))
|
|
102
|
+
await delay(panelAnimationTime)
|
|
100
103
|
editor.focus()
|
|
101
104
|
}, [])
|
|
102
105
|
|
|
@@ -2,57 +2,16 @@ import { FaceSmile, KnowledgeSource, QuickCommand } from '@citric/icons'
|
|
|
2
2
|
import { MiniLogo } from '@stack-spot/portal-components/svg'
|
|
3
3
|
import { theme } from '@stack-spot/portal-theme'
|
|
4
4
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
interface Props {
|
|
11
|
-
/**
|
|
12
|
-
* The name of the user currently logged in.
|
|
13
|
-
*/
|
|
14
|
-
username: string,
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const HomeBox = styled.div`
|
|
18
|
-
margin: auto;
|
|
19
|
-
|
|
20
|
-
.title, .subtitle {
|
|
21
|
-
font-family: 'San Francisco';
|
|
22
|
-
font-size: 26px;
|
|
23
|
-
font-weight: 600;
|
|
24
|
-
margin: 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.title {
|
|
28
|
-
display: inline-block;
|
|
29
|
-
background: linear-gradient(72.81deg, #FF9900 0.96%, #FF6633 100%);
|
|
30
|
-
background-clip: text;
|
|
31
|
-
margin-bottom: 10px;
|
|
32
|
-
color: transparent;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.subtitle {
|
|
36
|
-
color: #A0A0A0;
|
|
37
|
-
margin-bottom: 20px;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.shortcuts {
|
|
41
|
-
display: flex;
|
|
42
|
-
flex-direction: row;
|
|
43
|
-
gap: 15px;
|
|
44
|
-
li {
|
|
45
|
-
flex: 1;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
`
|
|
5
|
+
import { QuickStartButton } from '../../components/QuickStartButton'
|
|
6
|
+
import { useCurrentChat } from '../../context/hooks'
|
|
7
|
+
import { ChatEntry } from '../../state/ChatEntry'
|
|
8
|
+
import { HomeBox } from './styled'
|
|
9
|
+
import { HomeProps } from './types'
|
|
49
10
|
|
|
50
11
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* The home page can be replaced by providing children to the component `StackspotAIWidget`.
|
|
12
|
+
* This is the home rendered when the agent is built-in.
|
|
54
13
|
*/
|
|
55
|
-
export const
|
|
14
|
+
export const BuiltInAgent = ({ username }: HomeProps) => {
|
|
56
15
|
const t = useTranslate(dictionary)
|
|
57
16
|
const chat = useCurrentChat()
|
|
58
17
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Text } from '@citric/core'
|
|
2
|
+
import { MiniLogo } from '@stack-spot/portal-components/svg'
|
|
3
|
+
import { agentClient } from '@stack-spot/portal-network'
|
|
4
|
+
import { theme } from '@stack-spot/portal-theme'
|
|
5
|
+
import { useMemo } from 'react'
|
|
6
|
+
import { QuickStartButton } from '../../components/QuickStartButton'
|
|
7
|
+
import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
8
|
+
import { ChatEntry } from '../../state/ChatEntry'
|
|
9
|
+
import { HomeBox } from './styled'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This is the home rendered when the agent is custom.
|
|
13
|
+
*/
|
|
14
|
+
export const CustomAgent = () => {
|
|
15
|
+
const { id, label, image } = useCurrentChatState('agent') ?? {}
|
|
16
|
+
const [agent] = agentClient.agent.useStatefulQuery({ agentId: id! })
|
|
17
|
+
const chat = useCurrentChat()
|
|
18
|
+
const suggestions = useMemo(() => agent?.suggested_prompts?.map((prompt, index) => (
|
|
19
|
+
<QuickStartButton
|
|
20
|
+
key={index}
|
|
21
|
+
label={prompt}
|
|
22
|
+
onClick={() => send(prompt)}
|
|
23
|
+
background={theme.color.light[500]}
|
|
24
|
+
manageOverflow
|
|
25
|
+
/>
|
|
26
|
+
)), [agent?.suggested_prompts])
|
|
27
|
+
|
|
28
|
+
function send(message: string) {
|
|
29
|
+
chat.pushMessage(ChatEntry.createUserEntry(message))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<HomeBox className="home-page custom-agent">
|
|
34
|
+
{image ? <img src={image} className="avatar" /> : <MiniLogo className="avatar" />}
|
|
35
|
+
<Text appearance="h3">{label}</Text>
|
|
36
|
+
<div className="shortcuts">{suggestions?.length ? suggestions : null}</div>
|
|
37
|
+
</HomeBox>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FallbackBoundary } from '../../components/FallbackBoundary'
|
|
2
|
+
import { useCurrentChatState } from '../../context/hooks'
|
|
3
|
+
import { BuiltInAgent } from './BuiltInAgent'
|
|
4
|
+
import { CustomAgent } from './CustomAgent'
|
|
5
|
+
import { HomeProps } from './types'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Renders the default home page for the chat. This shows up when no message has been sent yet.
|
|
9
|
+
*
|
|
10
|
+
* The home page can be replaced by providing children to the component `StackspotAIWidget`.
|
|
11
|
+
*/
|
|
12
|
+
export const Home = (props: HomeProps) => {
|
|
13
|
+
const agent = useCurrentChatState('agent')
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<FallbackBoundary>
|
|
17
|
+
{agent && !agent.builtIn ? <CustomAgent /> : <BuiltInAgent {...props} />}
|
|
18
|
+
</FallbackBoundary>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { styled } from 'styled-components'
|
|
2
|
+
|
|
3
|
+
export const HomeBox = styled.div`
|
|
4
|
+
margin: auto;
|
|
5
|
+
|
|
6
|
+
.title, .subtitle {
|
|
7
|
+
font-family: 'San Francisco';
|
|
8
|
+
font-size: 26px;
|
|
9
|
+
font-weight: 600;
|
|
10
|
+
margin: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.title {
|
|
14
|
+
display: inline-block;
|
|
15
|
+
background: linear-gradient(72.81deg, #FF9900 0.96%, #FF6633 100%);
|
|
16
|
+
background-clip: text;
|
|
17
|
+
margin-bottom: 10px;
|
|
18
|
+
color: transparent;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.subtitle {
|
|
22
|
+
color: #A0A0A0;
|
|
23
|
+
margin-bottom: 20px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.shortcuts {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: row;
|
|
29
|
+
gap: 15px;
|
|
30
|
+
li {
|
|
31
|
+
flex: 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.avatar {
|
|
36
|
+
width: 74px;
|
|
37
|
+
height: 74px;
|
|
38
|
+
border-radius: 50%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&.custom-agent {
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
align-items: center;
|
|
45
|
+
gap: 20px;
|
|
46
|
+
|
|
47
|
+
.shortcuts {
|
|
48
|
+
margin-top: 10px;
|
|
49
|
+
button {
|
|
50
|
+
padding: 16px;
|
|
51
|
+
height: 100px;
|
|
52
|
+
line-height: 24px;
|
|
53
|
+
p {
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
`
|
|
@@ -105,9 +105,9 @@ const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit }: TabProps) => {
|
|
|
105
105
|
{!!knowledgeSources.length && !filtered.length && (
|
|
106
106
|
<Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} />
|
|
107
107
|
)}
|
|
108
|
-
{!knowledgeSources.length && <Placeholder title={t.noData} description={t.noDataDescription} />}
|
|
108
|
+
{!knowledgeSources.length && <Placeholder title={t.noData} description={t.noDataDescription} className="no-data-placeholder" />}
|
|
109
109
|
</div>
|
|
110
|
-
<Button onClick={onSubmit}>{t.apply}</Button>
|
|
110
|
+
{!!filtered.length && <Button onClick={onSubmit}>{t.apply}</Button>}
|
|
111
111
|
</>
|
|
112
112
|
)
|
|
113
113
|
}
|
|
@@ -4,14 +4,9 @@ import { MiniLogo } from '@stack-spot/portal-components/svg'
|
|
|
4
4
|
import { listToClass } from '@stack-spot/portal-theme'
|
|
5
5
|
import { useEffect, useRef } from 'react'
|
|
6
6
|
import { useCurrentChatState, useWidget } from '../../context/hooks'
|
|
7
|
-
import { MessageInputFeatures } from '../../features'
|
|
8
7
|
import { useMessageInputDictionary } from './dictionary'
|
|
9
8
|
|
|
10
9
|
interface ButtonGroupProps {
|
|
11
|
-
/**
|
|
12
|
-
* The features enabled and accessible through the message input.
|
|
13
|
-
*/
|
|
14
|
-
features: MessageInputFeatures,
|
|
15
10
|
/**
|
|
16
11
|
* Whether or not the button group is expanded.
|
|
17
12
|
*/
|
|
@@ -38,19 +33,27 @@ interface ButtonGroupProps {
|
|
|
38
33
|
* Renders the button group at right bottom side of the message input. This includes the send button as well as the buttons to open the
|
|
39
34
|
* editor, change the agent, the stack, etc.
|
|
40
35
|
*/
|
|
41
|
-
export const ButtonGroup = ({
|
|
36
|
+
export const ButtonGroup = ({ onSend, onCancel, expanded, setExpanded, isLoading }: ButtonGroupProps) => {
|
|
42
37
|
const t = useMessageInputDictionary()
|
|
43
38
|
const widget = useWidget()
|
|
44
39
|
const featureButtonsWidth = useRef<number | undefined>()
|
|
45
40
|
const featureButtons = useRef<HTMLDivElement>(null)
|
|
46
41
|
const agent = useCurrentChatState('agent')
|
|
47
|
-
const
|
|
42
|
+
const features = useCurrentChatState('features')
|
|
43
|
+
const hasFeatureButtons = features.agent || features.workspace || features.knowledgeSource || features.stack || features.editor
|
|
48
44
|
|
|
49
|
-
useEffect(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
useEffect(
|
|
46
|
+
() => {
|
|
47
|
+
if (!featureButtons.current) return
|
|
48
|
+
const isHidden = featureButtons.current.style.width === '0px'
|
|
49
|
+
featureButtons.current.style.width = 'auto'
|
|
50
|
+
featureButtonsWidth.current = featureButtons.current.clientWidth
|
|
51
|
+
if (isHidden) featureButtons.current.style.width = '0px'
|
|
52
|
+
else featureButtons.current.style.width = `${featureButtonsWidth.current}px`
|
|
53
|
+
},
|
|
54
|
+
// don't use the whole features object here, it would make every chat tab change rerun this effect.
|
|
55
|
+
[features.agent, features.workspace, features.knowledgeSource, features.stack, features.editor],
|
|
56
|
+
)
|
|
54
57
|
|
|
55
58
|
return (
|
|
56
59
|
<div className="button-group">
|
|
@@ -11,13 +11,13 @@ interface InfoBadgeProps {
|
|
|
11
11
|
label: string,
|
|
12
12
|
color: ColorPaletteName,
|
|
13
13
|
dismiss: string,
|
|
14
|
-
onDismiss
|
|
14
|
+
onDismiss?: () => void,
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const InfoBadge = ({ label, color, dismiss, onDismiss }: InfoBadgeProps) => (
|
|
18
18
|
<Badge appearance="square" palette={color} className="info-badge">
|
|
19
19
|
{label}
|
|
20
|
-
<IconButton onClick={onDismiss} title={dismiss} arial-label={dismiss}><TimesMini /></IconButton>
|
|
20
|
+
{onDismiss && <IconButton onClick={onDismiss} title={dismiss} arial-label={dismiss}><TimesMini /></IconButton>}
|
|
21
21
|
</Badge>
|
|
22
22
|
)
|
|
23
23
|
|
|
@@ -35,16 +35,25 @@ export const InfoBar = () => {
|
|
|
35
35
|
const currentWorkspace = useCurrentChatState('workspace')
|
|
36
36
|
const currentKnowledgeSources = useCurrentChatState('knowledgeSources')
|
|
37
37
|
const currentSelection = useCurrentChatState('codeSelection')
|
|
38
|
+
const features = useCurrentChatState('features')
|
|
38
39
|
const visible = !!(currentStack || currentWorkspace || currentKnowledgeSources?.length || currentSelection)
|
|
39
40
|
const ksToRender = useMemo(() => currentKnowledgeSources?.map(ks => {
|
|
40
|
-
const onDismiss =
|
|
41
|
+
const onDismiss = features.knowledgeSource
|
|
42
|
+
? (() => chat.set('knowledgeSources', currentKnowledgeSources.filter(({ id }) => id !== ks.id)))
|
|
43
|
+
: undefined
|
|
41
44
|
return <li key={ks.id}><InfoBadge label={ks.label} dismiss={t.removeKS} color="teal" onDismiss={onDismiss} /></li>
|
|
42
45
|
}), [currentKnowledgeSources])
|
|
46
|
+
const shouldRenderRemoveAllButton = (
|
|
47
|
+
currentSelection
|
|
48
|
+
|| (features.stack && currentStack)
|
|
49
|
+
|| (features.workspace && currentWorkspace)
|
|
50
|
+
|| (features.knowledgeSource && !!ksToRender?.length)
|
|
51
|
+
)
|
|
43
52
|
|
|
44
53
|
const removeAll = useCallback(() => {
|
|
45
|
-
chat.set('knowledgeSources', [])
|
|
46
|
-
chat.set('stack', undefined)
|
|
47
|
-
chat.set('workspace', undefined)
|
|
54
|
+
if (features.knowledgeSource) chat.set('knowledgeSources', [])
|
|
55
|
+
if (features.stack) chat.set('stack', undefined)
|
|
56
|
+
if (features.workspace) chat.set('workspace', undefined)
|
|
48
57
|
removeCodeSelection()
|
|
49
58
|
}, [])
|
|
50
59
|
|
|
@@ -57,7 +66,9 @@ export const InfoBar = () => {
|
|
|
57
66
|
<div className={listToClass(['info-bar', visible && 'visible'])}>
|
|
58
67
|
<div className="space"></div>
|
|
59
68
|
<div className="content">
|
|
60
|
-
|
|
69
|
+
{shouldRenderRemoveAllButton && (
|
|
70
|
+
<IconButton aria-label={t.removeConfig} title={t.removeConfig} onClick={removeAll}><Times /></IconButton>
|
|
71
|
+
)}
|
|
61
72
|
<FadingOverflow className="list-overflow" scroll="arrows" enableHorizontalScrollWithVerticalWheel>
|
|
62
73
|
<ul>
|
|
63
74
|
{currentSelection && (
|
|
@@ -67,7 +78,12 @@ export const InfoBar = () => {
|
|
|
67
78
|
)}
|
|
68
79
|
{currentStack && (
|
|
69
80
|
<li>
|
|
70
|
-
<InfoBadge
|
|
81
|
+
<InfoBadge
|
|
82
|
+
label={currentStack.label}
|
|
83
|
+
dismiss={t.removeStack}
|
|
84
|
+
color="cyan"
|
|
85
|
+
onDismiss={features.stack ? (() => chat.set('stack', undefined)) : undefined}
|
|
86
|
+
/>
|
|
71
87
|
</li>
|
|
72
88
|
)}
|
|
73
89
|
{currentWorkspace && (
|
|
@@ -76,7 +92,7 @@ export const InfoBar = () => {
|
|
|
76
92
|
label={currentWorkspace.label}
|
|
77
93
|
dismiss={t.removeWorkspace}
|
|
78
94
|
color="pink"
|
|
79
|
-
onDismiss={() => chat.set('workspace', undefined)}
|
|
95
|
+
onDismiss={features.workspace ? (() => chat.set('workspace', undefined)) : undefined}
|
|
80
96
|
/>
|
|
81
97
|
</li>
|
|
82
98
|
)}
|
|
@@ -139,7 +139,8 @@ export const QuickCommandSelector = ({ inputRef }: Props) => {
|
|
|
139
139
|
const filter = useMemo(() => value === '/' || quickCommandRegex.test(value) ? value.substring(1) : undefined, [value])
|
|
140
140
|
const [isClosed, setClosed] = useState(false)
|
|
141
141
|
const selectorRef = useRef<HTMLDivElement>(null)
|
|
142
|
-
const
|
|
142
|
+
const isEnabled = useCurrentChatState('features').quickCommands
|
|
143
|
+
const shouldRender = isEnabled && filter !== undefined && !isClosed
|
|
143
144
|
|
|
144
145
|
// Resets the closed state whenever the message input is cleared
|
|
145
146
|
useEffect(() => {
|
|
@@ -3,7 +3,6 @@ import { useCallback, useEffect, useRef, useState } from 'react'
|
|
|
3
3
|
import { AdaptiveTextArea } from '../../components/AdaptiveTextArea'
|
|
4
4
|
import { ProgressBar } from '../../components/ProgressBar'
|
|
5
5
|
import { useCurrentChat, useCurrentChatState, useWidgetState } from '../../context/hooks'
|
|
6
|
-
import { MessageInputFeatures } from '../../features'
|
|
7
6
|
import { quickCommandRegex } from '../../regex'
|
|
8
7
|
import { ChatEntry } from '../../state/ChatEntry'
|
|
9
8
|
import { ButtonGroup } from './ButtonGroup'
|
|
@@ -12,19 +11,12 @@ import { InfoBar } from './InfoBar'
|
|
|
12
11
|
import { QuickCommandSelector } from './QuickCommandSelector'
|
|
13
12
|
import { MAX_INPUT_HEIGHT, MessageInputBox, MIN_INPUT_HEIGHT } from './styled'
|
|
14
13
|
|
|
15
|
-
interface Props {
|
|
16
|
-
/**
|
|
17
|
-
* The features enabled and accessible through the message input.
|
|
18
|
-
*/
|
|
19
|
-
features: MessageInputFeatures,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
14
|
/**
|
|
23
15
|
* This renders the MessageInput part of the layout which includes the progress bar, the actual textarea, the badges telling what is
|
|
24
16
|
* going to be used for the question and the buttons to send, cancel, set the workspace, among others. This also includes the Quick
|
|
25
17
|
* Commands panel for auto completing.
|
|
26
18
|
*/
|
|
27
|
-
export const MessageInput = (
|
|
19
|
+
export const MessageInput = () => {
|
|
28
20
|
const t = useMessageInputDictionary()
|
|
29
21
|
const [focused, setFocused] = useState(false)
|
|
30
22
|
const [expanded, setExpanded] = useState(true)
|
|
@@ -77,7 +69,6 @@ export const MessageInput = ({ features }: Props) => {
|
|
|
77
69
|
maxHeight={isMinimized ? MIN_INPUT_HEIGHT : MAX_INPUT_HEIGHT}
|
|
78
70
|
/>
|
|
79
71
|
<ButtonGroup
|
|
80
|
-
features={features}
|
|
81
72
|
onSend={onSend}
|
|
82
73
|
onCancel={() => chat.abort()}
|
|
83
74
|
expanded={expanded}
|
|
@@ -13,6 +13,7 @@ export const MessageInputBox = styled.div`
|
|
|
13
13
|
|
|
14
14
|
> .info-bar {
|
|
15
15
|
margin-top: 8px;
|
|
16
|
+
margin-bottom: -3px;
|
|
16
17
|
position: relative;
|
|
17
18
|
overflow: hidden;
|
|
18
19
|
|
|
@@ -35,15 +36,18 @@ export const MessageInputBox = styled.div`
|
|
|
35
36
|
border-top-left-radius: 10px;
|
|
36
37
|
border-top-right-radius: 10px;
|
|
37
38
|
height: ${INFO_BAR_HEIGHT}px;
|
|
38
|
-
padding:
|
|
39
|
+
padding: 6px 4px 0;
|
|
39
40
|
background-color: ${theme.color.light[500]};
|
|
40
41
|
display: flex;
|
|
41
42
|
flex-direction: row;
|
|
42
|
-
align-items: center;
|
|
43
43
|
gap: 6px;
|
|
44
44
|
|
|
45
45
|
.list-overflow {
|
|
46
46
|
max-width: calc(100% - 30px); // close button + gap
|
|
47
|
+
height: 24px;
|
|
48
|
+
&:first-child {
|
|
49
|
+
margin-left: 0.25rem; // space added to the left when the close all button isn't rendered
|
|
50
|
+
}
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
ul {
|
|
@@ -6,7 +6,7 @@ import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
|
6
6
|
import { useCallback, useRef, useState } from 'react'
|
|
7
7
|
import { styled } from 'styled-components'
|
|
8
8
|
import { FadingOverflow } from '../components/FadingOverflow'
|
|
9
|
-
import {
|
|
9
|
+
import { useCurrentChatState } from '../context/hooks'
|
|
10
10
|
import { MinimizedActions } from '../types'
|
|
11
11
|
|
|
12
12
|
const Header = styled.header`
|
|
@@ -53,8 +53,7 @@ const Header = styled.header`
|
|
|
53
53
|
*/
|
|
54
54
|
export const MinimizedHeader = ({ onClose, onCollapse, onExpand }: MinimizedActions) => {
|
|
55
55
|
const t = useTranslate(dictionary)
|
|
56
|
-
const
|
|
57
|
-
const label = useChatState(active, 'label')
|
|
56
|
+
const label = useCurrentChatState('label')
|
|
58
57
|
const [collapsed, setCollapsed] = useState(false)
|
|
59
58
|
const ref = useRef<HTMLElement>(null)
|
|
60
59
|
const showButtons = onClose || onCollapse || onExpand
|
package/src/views/Stacks.tsx
CHANGED
|
@@ -75,10 +75,11 @@ const StacksTab = ({ visibility }: { visibility: VisibilityLevelEnum }) => {
|
|
|
75
75
|
}
|
|
76
76
|
className="option-list"
|
|
77
77
|
/>}
|
|
78
|
-
{!!stacks.length && !filtered.length &&
|
|
78
|
+
{!!stacks.length && !filtered.length &&
|
|
79
|
+
<Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} className="no-data-placeholder"/>}
|
|
79
80
|
{!stacks.length && <Placeholder title={t.noData} description={t.noDataDescription} />}
|
|
80
81
|
</div>
|
|
81
|
-
<Button onClick={submit} disabled={!value}>{t.apply}</Button>
|
|
82
|
+
{!!filtered.length && <Button onClick={submit} disabled={!value}>{t.apply}</Button>}
|
|
82
83
|
</>
|
|
83
84
|
)
|
|
84
85
|
}
|
package/src/views/Workspaces.tsx
CHANGED
|
@@ -65,10 +65,11 @@ const WorkspacesPanel = () => {
|
|
|
65
65
|
}
|
|
66
66
|
className="option-list"
|
|
67
67
|
/>}
|
|
68
|
-
{!!workspaces.length && !filtered.length &&
|
|
68
|
+
{!!workspaces.length && !filtered.length &&
|
|
69
|
+
<Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} className="no-data-placeholder" />}
|
|
69
70
|
{!workspaces.length && <Placeholder title={t.noData} description={t.noDataDescription} />}
|
|
70
71
|
</div>
|
|
71
|
-
<Button onClick={submit} disabled={!value}>{t.apply}</Button>
|
|
72
|
+
{!!filtered.length && <Button onClick={submit} disabled={!value}>{t.apply}</Button>}
|
|
72
73
|
</>
|
|
73
74
|
)
|
|
74
75
|
}
|
package/dist/views/Agents.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Agents.d.ts","sourceRoot":"","sources":["../../src/views/Agents.tsx"],"names":[],"mappings":"AAoEA,eAAO,MAAM,MAAM,YAclB,CAAA"}
|