@stack-spot/ai-chat-widget 1.18.0-beta.8 → 1.18.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 +7 -0
- package/dist/StackspotAIWidget.js +1 -1
- package/dist/app-metadata.json +3 -3
- package/dist/components/RightPanelForm.d.ts.map +1 -1
- package/dist/components/RightPanelForm.js +1 -29
- package/dist/components/RightPanelForm.js.map +1 -1
- package/dist/components/Selector/index.js +5 -5
- package/dist/components/Selector/index.js.map +1 -1
- package/dist/components/Selector/styled.d.ts +1 -3
- package/dist/components/Selector/styled.d.ts.map +1 -1
- package/dist/components/Selector/styled.js +1 -2
- package/dist/components/Selector/styled.js.map +1 -1
- package/dist/components/form/DescribedCheckboxGroup.d.ts.map +1 -1
- package/dist/components/form/DescribedCheckboxGroup.js +2 -23
- package/dist/components/form/DescribedCheckboxGroup.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/state/ChatEntry.d.ts +4 -0
- package/dist/state/ChatEntry.d.ts.map +1 -1
- package/dist/state/ChatEntry.js.map +1 -1
- package/dist/views/Agents/AgentsPanel.d.ts.map +1 -1
- package/dist/views/Agents/AgentsPanel.js +11 -19
- package/dist/views/Agents/AgentsPanel.js.map +1 -1
- package/dist/views/Agents/AgentsTab.d.ts +3 -9
- package/dist/views/Agents/AgentsTab.d.ts.map +1 -1
- package/dist/views/Agents/AgentsTab.js +7 -25
- package/dist/views/Agents/AgentsTab.js.map +1 -1
- package/dist/views/Agents/dictionary.d.ts +1 -1
- package/dist/views/Agents/dictionary.d.ts.map +1 -1
- package/dist/views/Agents/dictionary.js +0 -2
- package/dist/views/Agents/dictionary.js.map +1 -1
- package/dist/views/Chat/ChatMessage.d.ts.map +1 -1
- package/dist/views/Chat/ChatMessage.js +5 -5
- package/dist/views/Chat/ChatMessage.js.map +1 -1
- package/dist/views/ChatHistory/utils.d.ts.map +1 -1
- package/dist/views/ChatHistory/utils.js +3 -12
- package/dist/views/ChatHistory/utils.js.map +1 -1
- package/dist/views/KnowledgeSources.d.ts +0 -12
- package/dist/views/KnowledgeSources.d.ts.map +1 -1
- package/dist/views/KnowledgeSources.js +6 -20
- package/dist/views/KnowledgeSources.js.map +1 -1
- package/dist/views/MessageInput/AgentSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/AgentSelector.js +7 -11
- package/dist/views/MessageInput/AgentSelector.js.map +1 -1
- package/dist/views/MessageInput/ButtonGroup.js +2 -2
- package/dist/views/MessageInput/ButtonGroup.js.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.d.ts.map +1 -1
- package/dist/views/MessageInput/QuickCommandSelector.js +4 -11
- package/dist/views/MessageInput/QuickCommandSelector.js.map +1 -1
- package/dist/views/MessageInput/dictionary.d.ts +1 -1
- package/dist/views/MessageInput/dictionary.d.ts.map +1 -1
- package/dist/views/MessageInput/dictionary.js +0 -2
- package/dist/views/MessageInput/dictionary.js.map +1 -1
- package/dist/views/Stacks.d.ts +0 -9
- package/dist/views/Stacks.d.ts.map +1 -1
- package/dist/views/Stacks.js +14 -37
- package/dist/views/Stacks.js.map +1 -1
- package/dist/views/{Workspaces/index.d.ts → Workspaces.d.ts} +1 -1
- package/dist/views/Workspaces.d.ts.map +1 -0
- package/dist/views/Workspaces.js +103 -0
- package/dist/views/Workspaces.js.map +1 -0
- package/package.json +2 -2
- package/src/app-metadata.json +3 -3
- package/src/components/RightPanelForm.tsx +1 -29
- package/src/components/Selector/index.tsx +5 -5
- package/src/components/Selector/styled.ts +2 -3
- package/src/components/form/DescribedCheckboxGroup.tsx +14 -45
- package/src/index.ts +2 -0
- package/src/state/ChatEntry.ts +4 -0
- package/src/views/Agents/AgentsPanel.tsx +11 -21
- package/src/views/Agents/AgentsTab.tsx +9 -42
- package/src/views/Agents/dictionary.ts +0 -3
- package/src/views/Chat/ChatMessage.tsx +6 -5
- package/src/views/ChatHistory/utils.ts +3 -13
- package/src/views/KnowledgeSources.tsx +14 -37
- package/src/views/MessageInput/AgentSelector.tsx +8 -19
- package/src/views/MessageInput/ButtonGroup.tsx +3 -3
- package/src/views/MessageInput/QuickCommandSelector.tsx +4 -15
- package/src/views/MessageInput/dictionary.ts +0 -2
- package/src/views/Stacks.tsx +17 -57
- package/src/views/Workspaces.tsx +137 -0
- package/dist/components/ComponentNavigator.d.ts +0 -21
- package/dist/components/ComponentNavigator.d.ts.map +0 -1
- package/dist/components/ComponentNavigator.js +0 -33
- package/dist/components/ComponentNavigator.js.map +0 -1
- package/dist/components/ListGroup.d.ts +0 -46
- package/dist/components/ListGroup.d.ts.map +0 -1
- package/dist/components/ListGroup.js +0 -16
- package/dist/components/ListGroup.js.map +0 -1
- package/dist/components/WorkspaceTabNavigator.d.ts +0 -17
- package/dist/components/WorkspaceTabNavigator.d.ts.map +0 -1
- package/dist/components/WorkspaceTabNavigator.js +0 -95
- package/dist/components/WorkspaceTabNavigator.js.map +0 -1
- package/dist/views/Workspaces/WorkspacesTab.d.ts +0 -20
- package/dist/views/Workspaces/WorkspacesTab.d.ts.map +0 -1
- package/dist/views/Workspaces/WorkspacesTab.js +0 -64
- package/dist/views/Workspaces/WorkspacesTab.js.map +0 -1
- package/dist/views/Workspaces/index.d.ts.map +0 -1
- package/dist/views/Workspaces/index.js +0 -76
- package/dist/views/Workspaces/index.js.map +0 -1
- package/src/components/ComponentNavigator.tsx +0 -78
- package/src/components/ListGroup.tsx +0 -76
- package/src/components/WorkspaceTabNavigator.tsx +0 -177
- package/src/views/Workspaces/WorkspacesTab.tsx +0 -121
- package/src/views/Workspaces/index.tsx +0 -85
|
@@ -2,32 +2,21 @@ import { Button, IconBox, Text } from '@citric/core'
|
|
|
2
2
|
import { Agent, Search } from '@citric/icons'
|
|
3
3
|
import { Placeholder } from '@stack-spot/portal-components/Placeholder'
|
|
4
4
|
import { MiniLogo } from '@stack-spot/portal-components/svg'
|
|
5
|
-
import { agentClient
|
|
5
|
+
import { agentClient } from '@stack-spot/portal-network'
|
|
6
6
|
import { AgentResponse, VisibilityLevel } from '@stack-spot/portal-network/api/agent'
|
|
7
|
-
import {
|
|
8
|
-
import { useCallback, useMemo, useState } from 'react'
|
|
7
|
+
import { useMemo, useState } from 'react'
|
|
9
8
|
import { ButtonFavorite } from '../../components/ButtonFavorite'
|
|
10
|
-
import { NavigationItem } from '../../components/ComponentNavigator'
|
|
11
9
|
import { DescribedRadioGroup } from '../../components/form/DescribedRadioGroup'
|
|
12
10
|
import { IconInput } from '../../components/IconInput'
|
|
13
|
-
import { WorkspaceTabNavigator } from '../../components/WorkspaceTabNavigator'
|
|
14
11
|
import { useCurrentChat } from '../../context/hooks'
|
|
15
12
|
import { useRightPanel } from '../../right-panel/hooks'
|
|
16
|
-
import { ChatProperties } from '../../state/ChatState'
|
|
17
13
|
import { isAgentDefault } from '../../utils/agent'
|
|
18
14
|
import { AgentDescription } from './AgentDescription'
|
|
19
15
|
import { useAgentsDictionary } from './dictionary'
|
|
20
16
|
import { AgentLabel } from './styled'
|
|
21
17
|
import { useAgentFavorites } from './useAgentFavorites'
|
|
22
18
|
|
|
23
|
-
export
|
|
24
|
-
visibility: VisibilityLevel | 'BUILT-IN',
|
|
25
|
-
workspaceId?: string,
|
|
26
|
-
agent: React.MutableRefObject<ChatProperties['agent']>,
|
|
27
|
-
showSubmitButton?: boolean,
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = true }: AgentTabProps) => {
|
|
19
|
+
export const AgentsTab = ({ visibility }: { visibility: VisibilityLevel | 'BUILT-IN' }) => {
|
|
31
20
|
const t = useAgentsDictionary()
|
|
32
21
|
const { close } = useRightPanel()
|
|
33
22
|
const chat = useCurrentChat()
|
|
@@ -37,14 +26,10 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
37
26
|
|
|
38
27
|
const agentsBuiltIn = agentClient.publicAgents.useQuery({})
|
|
39
28
|
const agentDefault = agentsBuiltIn.find((agent) => isAgentDefault(agent.slug))
|
|
40
|
-
const agents =
|
|
41
|
-
|
|
42
|
-
: visibility === 'BUILT-IN' ? agentsBuiltIn : agentClient.agents.useQuery({ visibility })
|
|
43
|
-
|
|
29
|
+
const agents = visibility === 'BUILT-IN' ? agentsBuiltIn : agentClient.agents.useQuery({ visibility })
|
|
30
|
+
|
|
44
31
|
const [value, setValue] = useState<AgentResponse | undefined>(
|
|
45
|
-
agent.
|
|
46
|
-
? agents.find(a => a.id === agent.current?.id)
|
|
47
|
-
: chat.get('agent') ? agents.find(a => a.id === chat.get('agent')?.id) : agentDefault,
|
|
32
|
+
chat.get('agent') ? agents.find(a => a.id === chat.get('agent')?.id) : agentDefault,
|
|
48
33
|
)
|
|
49
34
|
|
|
50
35
|
const filtered = useMemo(
|
|
@@ -68,13 +53,6 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
68
53
|
close()
|
|
69
54
|
}
|
|
70
55
|
|
|
71
|
-
const onChange = useCallback((newValue: AgentResponse) => {
|
|
72
|
-
const isBuiltIn = visibility === 'BUILT-IN' || agentsBuiltIn.some((agent) => agent.id === newValue.id)
|
|
73
|
-
|
|
74
|
-
setValue(newValue)
|
|
75
|
-
agent.current = { ...newValue, builtIn: isBuiltIn, label: newValue.name }
|
|
76
|
-
}, [])
|
|
77
|
-
|
|
78
56
|
return (
|
|
79
57
|
<>
|
|
80
58
|
<div className="content">
|
|
@@ -87,7 +65,7 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
87
65
|
)}
|
|
88
66
|
keygen={a => a.id}
|
|
89
67
|
value={value}
|
|
90
|
-
onChange={
|
|
68
|
+
onChange={setValue}
|
|
91
69
|
renderLabel={({ name, avatar, id }) => (
|
|
92
70
|
<AgentLabel>
|
|
93
71
|
{id ? (avatar ? <img src={avatar} /> : <IconBox size="xs"><Agent /></IconBox>) : <MiniLogo />}
|
|
@@ -96,7 +74,7 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
96
74
|
)}
|
|
97
75
|
renderDescription={a => <AgentDescription
|
|
98
76
|
agentId={a.id}
|
|
99
|
-
visibility={visibility}
|
|
77
|
+
visibility={visibility}
|
|
100
78
|
description={a.description}
|
|
101
79
|
llm={a.llm_config?.model_slug}
|
|
102
80
|
numberOfKnowledgeSources={a.knowledge_sources_config?.knowledge_sources?.length ?? 0}
|
|
@@ -111,18 +89,7 @@ export const AgentsTab = ({ visibility, workspaceId, agent, showSubmitButton = t
|
|
|
111
89
|
<Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} className="no-data-placeholder" />}
|
|
112
90
|
{!agents.length && <Placeholder title={t.noData} description={t.noDataDescription} />}
|
|
113
91
|
</div>
|
|
114
|
-
{!!filtered.length &&
|
|
92
|
+
{!!filtered.length && <Button onClick={submit} disabled={!value}>{t.apply}</Button>}
|
|
115
93
|
</>
|
|
116
94
|
)
|
|
117
95
|
}
|
|
118
|
-
|
|
119
|
-
export function AgentsTabWorkspace({ agent, visibility, showSubmitButton }: AgentTabProps) {
|
|
120
|
-
const workspaceTabComponents = useMemo(() => ({ agent: AgentsTab }), [agent])
|
|
121
|
-
|
|
122
|
-
const buildNavigateParams = (workspace: WorkspaceResponse): NavigationItem<typeof workspaceTabComponents> => ({
|
|
123
|
-
component: 'agent',
|
|
124
|
-
props: { visibility, workspaceId: workspace.id, agent, showSubmitButton },
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
return <WorkspaceTabNavigator components={workspaceTabComponents} getNavigateParam={buildNavigateParams} />
|
|
128
|
-
}
|
|
@@ -17,7 +17,6 @@ const dictionary = {
|
|
|
17
17
|
description: 'Description',
|
|
18
18
|
favorites: 'Favorites',
|
|
19
19
|
tools: 'Tools',
|
|
20
|
-
spaces: 'Spaces',
|
|
21
20
|
},
|
|
22
21
|
pt: {
|
|
23
22
|
title: 'Agentes',
|
|
@@ -35,8 +34,6 @@ const dictionary = {
|
|
|
35
34
|
description: 'Descrição',
|
|
36
35
|
favorites: 'Favoritos',
|
|
37
36
|
tools: 'Ferramentas',
|
|
38
|
-
spaces: 'Spaces',
|
|
39
|
-
|
|
40
37
|
},
|
|
41
38
|
} satisfies Dictionary
|
|
42
39
|
|
|
@@ -61,7 +61,8 @@ const RenderInputsEntry = ({ isLast, entry, value, setValue, labels, setLabels }
|
|
|
61
61
|
|
|
62
62
|
const renderInputs = () => {
|
|
63
63
|
if (entry.type === 'input-text') {
|
|
64
|
-
return <Input name={entry.name}
|
|
64
|
+
return <Input name={entry.name}
|
|
65
|
+
value={value[0] ?? ''}
|
|
65
66
|
sx={{ maxWidth: '500px' }}
|
|
66
67
|
autoFocus
|
|
67
68
|
{...entry.validations} onChange={(data) => setValue([data.target.value])} required={entry.required} />
|
|
@@ -113,7 +114,7 @@ const RenderInputsEntry = ({ isLast, entry, value, setValue, labels, setLabels }
|
|
|
113
114
|
|
|
114
115
|
if (entry.type === 'input-checkbox') {
|
|
115
116
|
return <Flex className="checkbox-group">
|
|
116
|
-
{entry.options?.map((option) => (<Flex w={6} key={option.label} alignItems="center" className="checkbox-item">
|
|
117
|
+
{entry.options?.map((option) => (<Flex as="label" w={6} key={option.label} alignItems="center" className="checkbox-item">
|
|
117
118
|
<Checkbox name={entry.name} key={option.label} onChange={(data) => {
|
|
118
119
|
if (data.target.checked) {
|
|
119
120
|
setValue([...value, option.label])
|
|
@@ -159,8 +160,8 @@ const RenderInputsEntry = ({ isLast, entry, value, setValue, labels, setLabels }
|
|
|
159
160
|
export const ChatMessage = ({ message, username, isLast }: Props) => {
|
|
160
161
|
const t = useTranslate(dictionary)
|
|
161
162
|
const [liked, setLiked] = useState<boolean | undefined>()
|
|
162
|
-
const [value, setValue] = useState<string[]>([])
|
|
163
|
-
const [labels, setLabels] = useState<string[]>([])
|
|
163
|
+
const [value, setValue] = useState<string[]>(message.getValue()?.initialValue ?? [])
|
|
164
|
+
const [labels, setLabels] = useState<string[]>(message.getValue()?.initialValue ?? [])
|
|
164
165
|
const entry = useChatEntry(message)
|
|
165
166
|
const dateFormatter = useDateFormatter()
|
|
166
167
|
const userInfo = entry.agentType === 'user' ? <Avatar size="xs">{username}</Avatar> : <AgentInfo agent={entry.agent} />
|
|
@@ -267,7 +268,7 @@ export const ChatMessage = ({ message, username, isLast }: Props) => {
|
|
|
267
268
|
}
|
|
268
269
|
|
|
269
270
|
return (entry.content || entry.error || !!entry.steps?.length) && (
|
|
270
|
-
<li className={entry.agentType} ref={ref}>
|
|
271
|
+
<li key={entry.messageId} className={entry.agentType} ref={ref}>
|
|
271
272
|
<div className="chat-message" ref={chatRef} onKeyDown={handleKeyDown} tabIndex={0}>
|
|
272
273
|
<div className={`user-info ${entry.agentType}`}>{userInfo}</div>
|
|
273
274
|
{(entry.content || entry.steps) && <div className={listToClass(['message-content', entry.card && 'card', entry.type])}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { agentClient, aiClient,
|
|
1
|
+
import { agentClient, aiClient, workspaceClient } from '@stack-spot/portal-network'
|
|
2
2
|
import { ChatProperties } from '../../state/ChatState'
|
|
3
3
|
import { LabeledWithImage } from '../../state/types'
|
|
4
4
|
|
|
@@ -44,19 +44,9 @@ export async function findWorkspace(id: string | null): Promise<ChatProperties['
|
|
|
44
44
|
*/
|
|
45
45
|
export async function getAllAgents(): Promise<LabeledWithImage[]> {
|
|
46
46
|
try {
|
|
47
|
-
const [
|
|
48
|
-
agentClient.agents.query({ visibility: 'ACCOUNT' }),
|
|
49
|
-
agentClient.agents.query({ visibility: 'PERSONAL' }),
|
|
50
|
-
agentClient.agents.query({ visibility: 'SHARED' }),
|
|
51
|
-
agentClient.publicAgents.query({}),
|
|
52
|
-
|
|
53
|
-
workspaceAiClient.workspacesContentsByType.query({ contentType: 'agent' }),
|
|
54
|
-
])
|
|
55
|
-
const workspaceAgentsAsArray = workspaceAgents.flatMap((workspaceAgent: any) =>workspaceAgent?.agents)
|
|
47
|
+
const [agents, publicAgents] = await Promise.all([agentClient.agents.query({}), agentClient.publicAgents.query({})])
|
|
56
48
|
const builtInAgents = publicAgents.map((a) => ({ id: a.id, label: a.name, image: a.avatar, slug: a.slug, builtIn: true }))
|
|
57
|
-
return
|
|
58
|
-
.map(a => ({ id: a.id, label: a.name, image: a.avatar, slug: a.slug, builtIn: false }))
|
|
59
|
-
.concat(builtInAgents)
|
|
49
|
+
return agents.map(a => ({ id: a.id, label: a.name, image: a.avatar, slug: a.slug, builtIn: false })).concat(builtInAgents)
|
|
60
50
|
} catch (error) {
|
|
61
51
|
// eslint-disable-next-line no-console
|
|
62
52
|
console.error(error)
|
|
@@ -1,29 +1,24 @@
|
|
|
1
1
|
import { Button } from '@citric/core'
|
|
2
2
|
import { Search } from '@citric/icons'
|
|
3
3
|
import { Placeholder } from '@stack-spot/portal-components/Placeholder'
|
|
4
|
-
import { aiClient, dataIntegrationClient
|
|
4
|
+
import { aiClient, dataIntegrationClient } from '@stack-spot/portal-network'
|
|
5
5
|
import { KnowledgeSourceItemResponse, VisibilityLevelEnum } from '@stack-spot/portal-network/api/ai'
|
|
6
|
-
import { WorkspaceResponse } from '@stack-spot/portal-network/api/workspace-ai'
|
|
7
6
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
8
7
|
import { difference, uniqBy } from 'lodash'
|
|
9
8
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
10
9
|
import { ButtonFavorite } from '../components/ButtonFavorite'
|
|
11
|
-
import { NavigationItem } from '../components/ComponentNavigator'
|
|
12
10
|
import { DescribedCheckboxGroup } from '../components/form/DescribedCheckboxGroup'
|
|
13
11
|
import { IconInput } from '../components/IconInput'
|
|
14
12
|
import { RightPanelTabs } from '../components/RightPanelTabs'
|
|
15
|
-
import { WorkspaceTabNavigator } from '../components/WorkspaceTabNavigator'
|
|
16
13
|
import { useCurrentChat, useWidget, useWidgetState } from '../context/hooks'
|
|
17
14
|
import { useRightPanel } from '../right-panel/hooks'
|
|
18
15
|
import { ChatProperties } from '../state/ChatState'
|
|
19
16
|
import { checkIsTrial } from '../utils/check-is-trial'
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
interface TabProps {
|
|
22
19
|
visibility: VisibilityLevelEnum,
|
|
20
|
+
onSubmit: () => void,
|
|
23
21
|
allKS: React.MutableRefObject<ChatProperties['knowledgeSources']>,
|
|
24
|
-
workspaceId?: string,
|
|
25
|
-
showSubmitButton?: boolean,
|
|
26
|
-
onSubmit?: () => void,
|
|
27
22
|
}
|
|
28
23
|
|
|
29
24
|
export const KnowledgeSources = () => {
|
|
@@ -60,7 +55,7 @@ const KnowledgeSourcesPanel = () => {
|
|
|
60
55
|
useEffect(() => {
|
|
61
56
|
allKS.current = chat.get('knowledgeSources') ?? []
|
|
62
57
|
}, [chat])
|
|
63
|
-
|
|
58
|
+
|
|
64
59
|
const tabs = isTrial ? [
|
|
65
60
|
{ title: t.favorites, content: <KnowledgeSourcesTab key="favorite" visibility="favorite" allKS={allKS} onSubmit={onSubmit} /> },
|
|
66
61
|
{ title: t.personal, content: <KnowledgeSourcesTab key="personal" visibility="personal" allKS={allKS} onSubmit={onSubmit} /> },
|
|
@@ -68,23 +63,19 @@ const KnowledgeSourcesPanel = () => {
|
|
|
68
63
|
{ title: t.favorites, content: <KnowledgeSourcesTab key="favorite" visibility="favorite" allKS={allKS} onSubmit={onSubmit} /> },
|
|
69
64
|
{ title: t.personal, content: <KnowledgeSourcesTab key="personal" visibility="personal" allKS={allKS} onSubmit={onSubmit} /> },
|
|
70
65
|
{ title: t.shared, content: <KnowledgeSourcesTab key="shared" visibility="shared" allKS={allKS} onSubmit={onSubmit} /> },
|
|
71
|
-
{ title: t.
|
|
72
|
-
{ title: t.account, content: <KnowledgeSourcesTab key="account" visibility="account" allKS={allKS} onSubmit={onSubmit} /> },
|
|
66
|
+
{ title: t.account, content: <KnowledgeSourcesTab key="account" visibility="account" allKS={allKS} onSubmit={onSubmit} /> },
|
|
73
67
|
]
|
|
74
|
-
|
|
68
|
+
|
|
75
69
|
return <RightPanelTabs key={chat.id} tabs={tabs} />
|
|
76
70
|
}
|
|
77
71
|
|
|
78
|
-
|
|
72
|
+
const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit }: TabProps) => {
|
|
79
73
|
const t = useTranslate(dictionary)
|
|
80
74
|
const [filter, setFilter] = useState('')
|
|
81
|
-
|
|
82
|
-
const knowledgeSources =
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
visibility, order: 'a-to-z', types: ['snippet', 'api', 'event', 'custom'],
|
|
86
|
-
})
|
|
87
|
-
|
|
75
|
+
|
|
76
|
+
const knowledgeSources = aiClient.knowledgeSources.useQuery({
|
|
77
|
+
visibility, order: 'a-to-z', types: ['snippet', 'api', 'event', 'custom'],
|
|
78
|
+
})
|
|
88
79
|
const listFavorites = dataIntegrationClient.knowledgeSources.useQuery({ visibility: 'favorite' })
|
|
89
80
|
const [addFavorite, pendingAddFav] = dataIntegrationClient.addFavoriteKnowledgeSource.useMutation()
|
|
90
81
|
const [removeFavorite, pendingRemoveFav] = dataIntegrationClient.removeFavoriteKnowledgeSource.useMutation()
|
|
@@ -140,7 +131,7 @@ export const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit, workspaceId,
|
|
|
140
131
|
reject(error)
|
|
141
132
|
}
|
|
142
133
|
})
|
|
143
|
-
|
|
134
|
+
|
|
144
135
|
const [value, setValue] = useState<KnowledgeSourceItemResponse[]>((() => {
|
|
145
136
|
const currentlySelected = allKS.current?.map(ks => ks.id)
|
|
146
137
|
return knowledgeSources.filter(ks => currentlySelected?.includes(ks.slug))
|
|
@@ -148,7 +139,7 @@ export const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit, workspaceId,
|
|
|
148
139
|
const filtered = useMemo(
|
|
149
140
|
() => filter
|
|
150
141
|
// Recreate the list so that the favorites list is taken into account
|
|
151
|
-
? knowledgeSources.filter(ks => value.includes(ks) || ks.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase()))
|
|
142
|
+
? knowledgeSources.filter(ks => value.includes(ks) || ks.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase()))
|
|
152
143
|
: [...knowledgeSources]
|
|
153
144
|
, [knowledgeSources, filter, value, listFavorites],
|
|
154
145
|
)
|
|
@@ -190,23 +181,11 @@ export const KnowledgeSourcesTab = ({ visibility, allKS, onSubmit, workspaceId,
|
|
|
190
181
|
)}
|
|
191
182
|
{!filtered.length && <Placeholder title={t.noData} description={t.noDataDescription} className="no-data-placeholder" />}
|
|
192
183
|
</div>
|
|
193
|
-
{!!filtered.length &&
|
|
184
|
+
{!!filtered.length && <Button onClick={onSubmit}>{t.apply}</Button>}
|
|
194
185
|
</>
|
|
195
186
|
)
|
|
196
187
|
}
|
|
197
188
|
|
|
198
|
-
export function KnowledgeSourcesTabWorkspace({ allKS, onSubmit }: TabProps) {
|
|
199
|
-
const workspaceTabComponents = useMemo(() => ({ ks: KnowledgeSourcesTab }), [allKS, onSubmit])
|
|
200
|
-
|
|
201
|
-
const buildNavigateParams = (workspace: WorkspaceResponse): NavigationItem<typeof workspaceTabComponents> => ({
|
|
202
|
-
component: 'ks',
|
|
203
|
-
props: { visibility: 'workspace', workspaceId: workspace.id, allKS, onSubmit },
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
return <WorkspaceTabNavigator components={workspaceTabComponents} getNavigateParam={buildNavigateParams} />
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
189
|
const dictionary = {
|
|
211
190
|
en: {
|
|
212
191
|
title: 'Knowledge Sources',
|
|
@@ -220,7 +199,6 @@ const dictionary = {
|
|
|
220
199
|
noSearchResultsDescription: 'Please, try another search term.',
|
|
221
200
|
noData: 'There are no knowledge sources in this category yet.',
|
|
222
201
|
noDataDescription: 'Use the tabs above to try other categories or use the AI portal to create new knowledge sources.',
|
|
223
|
-
spaces: 'Spaces',
|
|
224
202
|
},
|
|
225
203
|
pt: {
|
|
226
204
|
title: 'Knowledge Sources',
|
|
@@ -234,6 +212,5 @@ const dictionary = {
|
|
|
234
212
|
noSearchResultsDescription: 'Por favor, tente outra busca.',
|
|
235
213
|
noData: 'Ainda não há knowledge sources nesta categoria.',
|
|
236
214
|
noDataDescription: 'Use as abas acima para tentar outras categorias ou use o Portal AI para criar novos knowledge sources.',
|
|
237
|
-
spaces: 'Spaces',
|
|
238
215
|
},
|
|
239
216
|
} satisfies Dictionary
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Flex, IconBox, Image } from '@citric/core'
|
|
2
2
|
import { Agent } from '@citric/icons'
|
|
3
|
-
import { agentClient
|
|
3
|
+
import { agentClient } from '@stack-spot/portal-network'
|
|
4
4
|
import { AgentResponse } from '@stack-spot/portal-network/api/agent'
|
|
5
5
|
import { uniqBy } from 'lodash'
|
|
6
6
|
import { useCallback } from 'react'
|
|
@@ -9,22 +9,17 @@ import { useCurrentChat, useCurrentChatState } from '../../context/hooks'
|
|
|
9
9
|
import { agentRegex } from '../../regex'
|
|
10
10
|
import { useAgentFavorites } from '../Agents/useAgentFavorites'
|
|
11
11
|
|
|
12
|
-
const AgentItem = ({ avatar, name
|
|
12
|
+
const AgentItem = ({ avatar, name }: AgentResponse) => {
|
|
13
13
|
const avatarComponent = avatar ? <Image width="32" height="32" radius="full" src={avatar} /> : <IconBox size="md"><Agent /></IconBox>
|
|
14
14
|
|
|
15
15
|
return <Flex flexWrap="nowrap" alignItems="center" sx={{ gap: '8px' }}>
|
|
16
16
|
{avatarComponent}
|
|
17
|
-
<
|
|
18
|
-
<p className="selector-description">{spaceName}</p>
|
|
19
|
-
<p className="selector-title">{name}</p>
|
|
20
|
-
</div>
|
|
21
|
-
|
|
17
|
+
<p className="selector-title">{name}</p>
|
|
22
18
|
</Flex>
|
|
23
19
|
}
|
|
24
20
|
|
|
25
21
|
export const AgentSelector = ({ inputRef, isTrial }: { isTrial: boolean,
|
|
26
|
-
inputRef: React.RefObject<HTMLTextAreaElement | HTMLInputElement>,
|
|
27
|
-
}) => {
|
|
22
|
+
inputRef: React.RefObject<HTMLTextAreaElement | HTMLInputElement>, }) => {
|
|
28
23
|
const chat = useCurrentChat()
|
|
29
24
|
const isAgentEnabled = useCurrentChatState('features').agent
|
|
30
25
|
|
|
@@ -38,10 +33,8 @@ export const AgentSelector = ({ inputRef, isTrial }: { isTrial: boolean,
|
|
|
38
33
|
const isBuiltIn = agent.visibility_level === 'builtIn' || builtInsAgents.some((builtInAgent) => builtInAgent.id === agent.id)
|
|
39
34
|
chat.set(
|
|
40
35
|
'agent',
|
|
41
|
-
{
|
|
42
|
-
|
|
43
|
-
builtIn: isBuiltIn, visibility_level: agent.visibility_level
|
|
44
|
-
},
|
|
36
|
+
{ id: agent.id, label: agent.name, image: agent.avatar, slug: agent.slug,
|
|
37
|
+
builtIn: isBuiltIn, visibility_level: agent.visibility_level },
|
|
45
38
|
)
|
|
46
39
|
|
|
47
40
|
if (!inputRef.current) return
|
|
@@ -53,10 +46,6 @@ export const AgentSelector = ({ inputRef, isTrial }: { isTrial: boolean,
|
|
|
53
46
|
const personalAgents = agentClient.agents.useQuery({ visibility: 'PERSONAL' })
|
|
54
47
|
const publicAgents = agentClient.publicAgents.useQuery({})
|
|
55
48
|
const builtInsAgents = [...publicAgents.map((agent) => ({ ...agent, visibility_level: 'builtIn' }))]
|
|
56
|
-
const workspaceAgents = workspaceAiClient.workspacesContentsByType.useQuery({ contentType: 'agent' })
|
|
57
|
-
|
|
58
|
-
const workspaceAgentsWithWorkspaceName = workspaceAgents.flatMap(({ agents, space_name }: any) =>
|
|
59
|
-
agents.map((agent: any) => ({ ...agent, spaceName: space_name })))
|
|
60
49
|
let accountAgents: AgentResponse[] = []
|
|
61
50
|
let sharedAgents: AgentResponse[] = []
|
|
62
51
|
if (!isTrial) {
|
|
@@ -64,7 +53,7 @@ export const AgentSelector = ({ inputRef, isTrial }: { isTrial: boolean,
|
|
|
64
53
|
sharedAgents = agentClient.agents.useQuery({ visibility: 'SHARED' }) || []
|
|
65
54
|
}
|
|
66
55
|
|
|
67
|
-
return uniqBy([...personalAgents, ...
|
|
56
|
+
return uniqBy([...personalAgents, ...accountAgents, ...sharedAgents, ...builtInsAgents], 'id')
|
|
68
57
|
}
|
|
69
58
|
|
|
70
59
|
return <Selector
|
|
@@ -77,7 +66,7 @@ export const AgentSelector = ({ inputRef, isTrial }: { isTrial: boolean,
|
|
|
77
66
|
regex: agentRegex,
|
|
78
67
|
urlBuilder: (agent) => `/agents/${agent?.id}`,
|
|
79
68
|
searchProp: 'name',
|
|
80
|
-
sections: isTrial ? ['favorite', 'personal', 'builtIn'] : ['favorite', 'personal', '
|
|
69
|
+
sections: isTrial ? ['favorite', 'personal', 'builtIn'] : ['favorite', 'personal', 'account', 'shared', 'builtIn'],
|
|
81
70
|
renderComponentItem: AgentItem,
|
|
82
71
|
isEnabled: isAgentEnabled,
|
|
83
72
|
onSelect: onSelectItem,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChevronRight,
|
|
1
|
+
import { ChevronRight, Code, KnowledgeSource, Send, Stack, Times, Workspace } from '@citric/icons'
|
|
2
2
|
import { IconButton } from '@citric/ui'
|
|
3
3
|
import { listToClass } from '@stack-spot/portal-theme'
|
|
4
4
|
import { useEffect, useRef } from 'react'
|
|
@@ -62,8 +62,8 @@ export const ButtonGroup = ({ onSend, onCancel, expanded, setExpanded, isLoading
|
|
|
62
62
|
style={{ width: expanded ? featureButtonsWidth.current : 0 }}
|
|
63
63
|
>
|
|
64
64
|
{features.workspace && (
|
|
65
|
-
<IconButton aria-label={t.
|
|
66
|
-
<
|
|
65
|
+
<IconButton aria-label={t.workspace} title={t.workspace} onClick={() => widget.set('panel', 'workspace')}>
|
|
66
|
+
<Workspace />
|
|
67
67
|
</IconButton>
|
|
68
68
|
)}
|
|
69
69
|
{features.knowledgeSource && (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QuickCommand } from '@citric/icons'
|
|
2
|
-
import { aiClient
|
|
2
|
+
import { aiClient } from '@stack-spot/portal-network'
|
|
3
3
|
import { QuickCommandListResponse } from '@stack-spot/portal-network/api/ai'
|
|
4
4
|
import { useCallback } from 'react'
|
|
5
5
|
import { Selector } from '../../components/Selector'
|
|
@@ -74,19 +74,8 @@ export const QuickCommandSelector = ({ inputRef, isTrial }:
|
|
|
74
74
|
inputRef.current.focus()
|
|
75
75
|
}, [chat, inputRef])
|
|
76
76
|
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
const quickCommandsFiltered = quickCommands.filter((qc) => qc.visibility_level.toLowerCase() !== 'workspace')
|
|
80
|
-
const workspaceQuickCommands = workspaceAiClient.workspacesContentsByType.useQuery({ contentType: 'quick_command' })
|
|
81
|
-
const workspaceQuickCommandsWithWorkspaceName = workspaceQuickCommands.flatMap(({ qcs, space_name }: any) =>
|
|
82
|
-
qcs.map((qc: any) => ({ ...qc, spaceName: space_name })))
|
|
83
|
-
|
|
84
|
-
return [...quickCommandsFiltered, ...workspaceQuickCommandsWithWorkspaceName]
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const QuickCommandItem = ({ slug, description, spaceName }: QuickCommandListResponse & { spaceName?: string }) => <>
|
|
88
|
-
<p className="selector-description">{spaceName}</p>
|
|
89
|
-
<p className="selector-title">/{slug?.toUpperCase()}</p>
|
|
77
|
+
const QuickCommandItem = ({ slug, description }: QuickCommandListResponse) => <>
|
|
78
|
+
<p className="selector-title">/{slug.toUpperCase()}</p>
|
|
90
79
|
<p className="selector-description">{description}</p>
|
|
91
80
|
</>
|
|
92
81
|
|
|
@@ -106,7 +95,7 @@ export const QuickCommandSelector = ({ inputRef, isTrial }:
|
|
|
106
95
|
isEnabled: isQuickCommandEnabled,
|
|
107
96
|
onSelect: onSelectItem,
|
|
108
97
|
renderComponentItem: QuickCommandItem,
|
|
109
|
-
useData:
|
|
98
|
+
useData: () => aiClient.quickCommands.useQuery({ order: 'a-to-z' }),
|
|
110
99
|
}}
|
|
111
100
|
/>
|
|
112
101
|
}
|
|
@@ -5,7 +5,6 @@ const dictionary = {
|
|
|
5
5
|
stack: 'Select stack',
|
|
6
6
|
code: 'Open code editor',
|
|
7
7
|
workspace: 'Select workspace',
|
|
8
|
-
space: 'Select space',
|
|
9
8
|
knowledgeSource: 'Select knowledge sources',
|
|
10
9
|
agent: 'Select agent',
|
|
11
10
|
collapse: 'Hide buttons',
|
|
@@ -25,7 +24,6 @@ const dictionary = {
|
|
|
25
24
|
stack: 'Selecionar stack',
|
|
26
25
|
code: 'Abrir editor de código',
|
|
27
26
|
workspace: 'Selecionar workspace',
|
|
28
|
-
space: 'Select Space',
|
|
29
27
|
knowledgeSource: 'Selecionar knowledge sources',
|
|
30
28
|
agent: 'Selecionar agente',
|
|
31
29
|
collapse: 'Esconder botões',
|
package/src/views/Stacks.tsx
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { Button } from '@citric/core'
|
|
2
2
|
import { Search } from '@citric/icons'
|
|
3
3
|
import { Placeholder } from '@stack-spot/portal-components/Placeholder'
|
|
4
|
-
import { aiClient
|
|
4
|
+
import { aiClient } from '@stack-spot/portal-network'
|
|
5
5
|
import { GetAiStackResponse, VisibilityLevelEnum } from '@stack-spot/portal-network/api/ai'
|
|
6
|
-
import { WorkspaceResponse } from '@stack-spot/portal-network/api/workspace-ai'
|
|
7
6
|
import { Dictionary, useTranslate } from '@stack-spot/portal-translate'
|
|
8
|
-
import {
|
|
7
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
9
8
|
import { ButtonFavorite } from '../components/ButtonFavorite'
|
|
10
|
-
import { NavigationItem } from '../components/ComponentNavigator'
|
|
11
9
|
import { DescribedRadioGroup } from '../components/form/DescribedRadioGroup'
|
|
12
10
|
import { IconInput } from '../components/IconInput'
|
|
13
11
|
import { RightPanelTabs } from '../components/RightPanelTabs'
|
|
14
|
-
import { WorkspaceTabNavigator } from '../components/WorkspaceTabNavigator'
|
|
15
12
|
import { useCurrentChat, useWidget, useWidgetState } from '../context/hooks'
|
|
16
13
|
import { useRightPanel } from '../right-panel/hooks'
|
|
17
|
-
import { ChatProperties } from '../state/ChatState'
|
|
18
14
|
import { checkIsTrial } from '../utils/check-is-trial'
|
|
19
15
|
|
|
20
16
|
/**
|
|
@@ -39,35 +35,23 @@ export const Stacks = () => {
|
|
|
39
35
|
const StacksPanel = () => {
|
|
40
36
|
const t = useTranslate(dictionary)
|
|
41
37
|
const chat = useCurrentChat()
|
|
38
|
+
|
|
42
39
|
const isTrial = checkIsTrial()
|
|
43
|
-
const stack = useRef(chat.get('stack'))
|
|
44
|
-
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
stack.current = chat.get('stack')
|
|
47
|
-
}, [chat])
|
|
48
40
|
|
|
49
41
|
const tabs = useMemo(() => isTrial ? [
|
|
50
|
-
{ title: t.favorites, content: <StacksTab key="favorites" visibility="favorite"
|
|
51
|
-
{ title: t.personal, content: <StacksTab key="personal" visibility="personal"
|
|
42
|
+
{ title: t.favorites, content: <StacksTab key="favorites" visibility="favorite" /> },
|
|
43
|
+
{ title: t.personal, content: <StacksTab key="personal" visibility="personal" /> },
|
|
52
44
|
]: [
|
|
53
|
-
{ title: t.favorites, content: <StacksTab key="favorites" visibility="favorite"
|
|
54
|
-
{ title: t.personal, content: <StacksTab key="personal" visibility="personal"
|
|
55
|
-
{ title: t.shared, content: <StacksTab key="shared" visibility="shared"
|
|
56
|
-
{ title: t.
|
|
57
|
-
{ title: t.account, content: <StacksTab key="account" visibility="account" stack={stack} /> },
|
|
45
|
+
{ title: t.favorites, content: <StacksTab key="favorites" visibility="favorite" /> },
|
|
46
|
+
{ title: t.personal, content: <StacksTab key="personal" visibility="personal" /> },
|
|
47
|
+
{ title: t.shared, content: <StacksTab key="shared" visibility="shared" /> },
|
|
48
|
+
{ title: t.account, content: <StacksTab key="account" visibility="account" /> },
|
|
58
49
|
], [t, isTrial])
|
|
59
50
|
|
|
60
51
|
return <RightPanelTabs key={chat.id} tabs={tabs} />
|
|
61
52
|
}
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
visibility: VisibilityLevelEnum,
|
|
65
|
-
workspaceId?: string,
|
|
66
|
-
stack: React.MutableRefObject<ChatProperties['stack']>,
|
|
67
|
-
showSubmitButton?: boolean,
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export const StacksTab = ({ visibility, workspaceId, stack, showSubmitButton = true }: StacksTabProps) => {
|
|
54
|
+
const StacksTab = ({ visibility }: { visibility: VisibilityLevelEnum }) => {
|
|
71
55
|
const t = useTranslate(dictionary)
|
|
72
56
|
const { close } = useRightPanel()
|
|
73
57
|
const chat = useCurrentChat()
|
|
@@ -127,19 +111,13 @@ export const StacksTab = ({ visibility, workspaceId, stack, showSubmitButton = t
|
|
|
127
111
|
}
|
|
128
112
|
})
|
|
129
113
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
? workspaceAiClient.getStackFromWorkspaceAi.useQuery({ workspaceId })
|
|
134
|
-
//@ts-ignore
|
|
135
|
-
: aiClient.aiStacks.useQuery({ visibility, order: 'a-to-z' })
|
|
136
|
-
|
|
137
|
-
const currentStackId = stack.current ? stack.current.id : chat.get('stack')?.id
|
|
138
|
-
const [value, setValue] = useState<GetAiStackResponse | undefined>(stacks.find(s => s.id === currentStackId))
|
|
114
|
+
//@ts-ignore
|
|
115
|
+
const stacks = aiClient.aiStacks.useQuery({ visibility, order: 'a-to-z' })
|
|
116
|
+
const [value, setValue] = useState<GetAiStackResponse | undefined>(stacks.find(s => s.id === chat.get('stack')?.id))
|
|
139
117
|
const filtered = useMemo(() => filter ?
|
|
140
118
|
// Recreate the list so that the favorites list is taken into account
|
|
141
|
-
stacks.filter(s => s === value || s.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase())) : [...stacks],
|
|
142
|
-
[stacks, listFavorites, filter, value],
|
|
119
|
+
stacks.filter(s => s === value || s.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase())) : [...stacks],
|
|
120
|
+
[stacks, listFavorites, filter, value],
|
|
143
121
|
)
|
|
144
122
|
|
|
145
123
|
function submit() {
|
|
@@ -147,11 +125,6 @@ export const StacksTab = ({ visibility, workspaceId, stack, showSubmitButton = t
|
|
|
147
125
|
close()
|
|
148
126
|
}
|
|
149
127
|
|
|
150
|
-
const onChange = useCallback((newValue: GetAiStackResponse) => {
|
|
151
|
-
setValue(newValue)
|
|
152
|
-
stack.current = { ...newValue, label: newValue.name }
|
|
153
|
-
}, [])
|
|
154
|
-
|
|
155
128
|
return (
|
|
156
129
|
<>
|
|
157
130
|
<div className="content">
|
|
@@ -163,7 +136,7 @@ export const StacksTab = ({ visibility, workspaceId, stack, showSubmitButton = t
|
|
|
163
136
|
}
|
|
164
137
|
keygen={s => s.id}
|
|
165
138
|
value={value}
|
|
166
|
-
onChange={
|
|
139
|
+
onChange={setValue}
|
|
167
140
|
renderLabel={s => s.name}
|
|
168
141
|
renderDescription={s => s.use_case}
|
|
169
142
|
optionClassName={s => (s === value && filter && !s.name.toLocaleLowerCase().includes(filter.toLocaleLowerCase()))
|
|
@@ -176,22 +149,11 @@ export const StacksTab = ({ visibility, workspaceId, stack, showSubmitButton = t
|
|
|
176
149
|
<Placeholder title={t.noSearchResults} description={t.noSearchResultsDescription} className="no-data-placeholder"/>}
|
|
177
150
|
{!stacks.length && <Placeholder title={t.noData} description={t.noDataDescription} />}
|
|
178
151
|
</div>
|
|
179
|
-
{!!filtered.length &&
|
|
152
|
+
{!!filtered.length && <Button onClick={submit} disabled={!value}>{t.apply}</Button>}
|
|
180
153
|
</>
|
|
181
154
|
)
|
|
182
155
|
}
|
|
183
156
|
|
|
184
|
-
function StacksTabWorkspace({ stack, visibility, showSubmitButton }: StacksTabProps) {
|
|
185
|
-
const workspaceTabComponents = useMemo(() => ({ stack: StacksTab }), [stack])
|
|
186
|
-
|
|
187
|
-
const buildNavigateParams = (workspace: WorkspaceResponse): NavigationItem<typeof workspaceTabComponents> => ({
|
|
188
|
-
component: 'stack',
|
|
189
|
-
props: { visibility, workspaceId: workspace.id, stack, showSubmitButton },
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
return <WorkspaceTabNavigator components={workspaceTabComponents} getNavigateParam={buildNavigateParams} />
|
|
193
|
-
}
|
|
194
|
-
|
|
195
157
|
const dictionary = {
|
|
196
158
|
en: {
|
|
197
159
|
title: 'Stacks AI',
|
|
@@ -205,7 +167,6 @@ const dictionary = {
|
|
|
205
167
|
noData: 'There are no stacks in this category yet.',
|
|
206
168
|
noDataDescription: 'Use the tabs above to try other categories or use the AI portal to create new stacks.',
|
|
207
169
|
favorites: 'Favorites',
|
|
208
|
-
spaces: 'Spaces',
|
|
209
170
|
},
|
|
210
171
|
pt: {
|
|
211
172
|
title: 'Stacks AI',
|
|
@@ -219,6 +180,5 @@ const dictionary = {
|
|
|
219
180
|
noData: 'Ainda não há stacks nesta categoria.',
|
|
220
181
|
noDataDescription: 'Use as abas acima para tentar outras categorias ou use o Portal AI para criar novas stacks.',
|
|
221
182
|
favorites: 'Favoritos',
|
|
222
|
-
spaces: 'Spaces',
|
|
223
183
|
},
|
|
224
184
|
} satisfies Dictionary
|