@sweetoburrito/backstage-plugin-ai-assistant 0.7.0 → 0.7.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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs,
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { Conversation } from '../Conversation/Conversation.esm.js';
|
|
4
4
|
import '@mui/material/Dialog';
|
|
@@ -36,11 +36,32 @@ import ListItem from '@mui/material/ListItem';
|
|
|
36
36
|
import MenuIcon from '@mui/icons-material/Menu';
|
|
37
37
|
import { signalApiRef } from '@backstage/plugin-signals-react';
|
|
38
38
|
import { useChatSettings } from '../../hooks/use-chat-settings.esm.js';
|
|
39
|
+
import { Page, Header, Content } from '@backstage/core-components';
|
|
40
|
+
import { makeStyles } from 'tss-react/mui';
|
|
39
41
|
|
|
40
|
-
const
|
|
42
|
+
const useStyles = makeStyles()(() => ({
|
|
43
|
+
page: {
|
|
44
|
+
height: "100vh",
|
|
45
|
+
maxHeight: "100vh",
|
|
46
|
+
overflow: "hidden",
|
|
47
|
+
display: "flex",
|
|
48
|
+
flexDirection: "column"
|
|
49
|
+
},
|
|
50
|
+
content: {
|
|
51
|
+
flex: 1,
|
|
52
|
+
minHeight: 0,
|
|
53
|
+
display: "flex",
|
|
54
|
+
flexDirection: "column"
|
|
55
|
+
}
|
|
56
|
+
}));
|
|
57
|
+
const AiAssistantPage = ({
|
|
58
|
+
title = "AI Assistant",
|
|
59
|
+
subtitle
|
|
60
|
+
}) => {
|
|
41
61
|
const chatApi = useApi(chatApiRef);
|
|
42
62
|
const signalApi = useApi(signalApiRef);
|
|
43
63
|
const theme = useTheme();
|
|
64
|
+
const { classes } = useStyles();
|
|
44
65
|
const chatSettings = useChatSettings();
|
|
45
66
|
useEffect(() => {
|
|
46
67
|
chatSettings.setModalVisible(false);
|
|
@@ -80,73 +101,65 @@ const AiAssistantPage = () => {
|
|
|
80
101
|
const openNewChat = () => {
|
|
81
102
|
setConversationId(void 0);
|
|
82
103
|
};
|
|
83
|
-
return /* @__PURE__ */ jsxs(
|
|
84
|
-
/* @__PURE__ */
|
|
85
|
-
|
|
86
|
-
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
children: [
|
|
94
|
-
/* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, justifyContent: "flex-end", children: [
|
|
95
|
-
/* @__PURE__ */ jsx(Tooltip, { title: "New Chat", children: /* @__PURE__ */ jsx(IconButton, { onClick: openNewChat, children: /* @__PURE__ */ jsx(AddIcon, {}) }) }),
|
|
96
|
-
conversations.length > 0 && /* @__PURE__ */ jsx(Tooltip, { title: "Chat History", children: /* @__PURE__ */ jsx(IconButton, { onClick: toggleDrawer(true), children: /* @__PURE__ */ jsx(MenuIcon, {}) }) })
|
|
97
|
-
] }),
|
|
98
|
-
/* @__PURE__ */ jsx(
|
|
99
|
-
Conversation,
|
|
100
|
-
{
|
|
101
|
-
conversationId,
|
|
102
|
-
setConversationId
|
|
103
|
-
}
|
|
104
|
-
)
|
|
105
|
-
]
|
|
106
|
-
}
|
|
107
|
-
),
|
|
108
|
-
/* @__PURE__ */ jsx(Drawer, { anchor: "right", open, onClose: toggleDrawer(false), children: /* @__PURE__ */ jsx(
|
|
109
|
-
Box,
|
|
110
|
-
{
|
|
111
|
-
sx: { width: 300 },
|
|
112
|
-
role: "presentation",
|
|
113
|
-
onClick: toggleDrawer(false),
|
|
114
|
-
children: /* @__PURE__ */ jsx(List, { children: conversations.map((conversation) => /* @__PURE__ */ jsx(
|
|
115
|
-
ListItem,
|
|
104
|
+
return /* @__PURE__ */ jsxs(Page, { themeId: "tool", className: classes.page, children: [
|
|
105
|
+
/* @__PURE__ */ jsx(Header, { title, subtitle }),
|
|
106
|
+
/* @__PURE__ */ jsxs(Content, { className: classes.content, children: [
|
|
107
|
+
/* @__PURE__ */ jsxs(Stack, { spacing: 2, flex: 1, boxSizing: "border-box", height: "100%", children: [
|
|
108
|
+
/* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, justifyContent: "flex-end", children: [
|
|
109
|
+
/* @__PURE__ */ jsx(Tooltip, { title: "New Chat", children: /* @__PURE__ */ jsx(IconButton, { onClick: openNewChat, children: /* @__PURE__ */ jsx(AddIcon, {}) }) }),
|
|
110
|
+
conversations.length > 0 && /* @__PURE__ */ jsx(Tooltip, { title: "Chat History", children: /* @__PURE__ */ jsx(IconButton, { onClick: toggleDrawer(true), children: /* @__PURE__ */ jsx(MenuIcon, {}) }) })
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsx(
|
|
113
|
+
Conversation,
|
|
116
114
|
{
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
conversationId,
|
|
116
|
+
setConversationId
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
] }),
|
|
120
|
+
/* @__PURE__ */ jsx(Drawer, { anchor: "right", open, onClose: toggleDrawer(false), children: /* @__PURE__ */ jsx(
|
|
121
|
+
Box,
|
|
122
|
+
{
|
|
123
|
+
sx: { width: 300 },
|
|
124
|
+
role: "presentation",
|
|
125
|
+
onClick: toggleDrawer(false),
|
|
126
|
+
children: /* @__PURE__ */ jsx(List, { children: conversations.map((conversation) => /* @__PURE__ */ jsx(
|
|
127
|
+
ListItem,
|
|
128
|
+
{
|
|
129
|
+
sx: {
|
|
130
|
+
fontSize: theme.typography.body1.fontSize
|
|
131
|
+
},
|
|
132
|
+
children: /* @__PURE__ */ jsx(
|
|
133
|
+
ListItemButton,
|
|
134
|
+
{
|
|
135
|
+
sx: {
|
|
136
|
+
justifyContent: "flex-start !important",
|
|
137
|
+
padding: `${theme.spacing(1)} !important`,
|
|
138
|
+
borderRadius: `${theme.spacing(1)} !important`,
|
|
139
|
+
backgroundColor: conversationId === conversation.id ? `${theme.palette.action.selected} !important` : "transparent !important"
|
|
140
|
+
},
|
|
141
|
+
onClick: () => setConversationId(conversation.id),
|
|
142
|
+
children: /* @__PURE__ */ jsx(
|
|
143
|
+
Typography,
|
|
144
|
+
{
|
|
145
|
+
variant: "body1",
|
|
146
|
+
sx: {
|
|
147
|
+
overflow: "hidden",
|
|
148
|
+
textOverflow: "ellipsis",
|
|
149
|
+
whiteSpace: "nowrap",
|
|
150
|
+
width: "100%"
|
|
151
|
+
},
|
|
152
|
+
children: conversation.title
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
)
|
|
119
157
|
},
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
padding: `${theme.spacing(1)} !important`,
|
|
126
|
-
borderRadius: `${theme.spacing(1)} !important`,
|
|
127
|
-
backgroundColor: conversationId === conversation.id ? `${theme.palette.action.selected} !important` : "transparent !important"
|
|
128
|
-
},
|
|
129
|
-
onClick: () => setConversationId(conversation.id),
|
|
130
|
-
children: /* @__PURE__ */ jsx(
|
|
131
|
-
Typography,
|
|
132
|
-
{
|
|
133
|
-
variant: "body1",
|
|
134
|
-
sx: {
|
|
135
|
-
overflow: "hidden",
|
|
136
|
-
textOverflow: "ellipsis",
|
|
137
|
-
whiteSpace: "nowrap",
|
|
138
|
-
width: "100%"
|
|
139
|
-
},
|
|
140
|
-
children: conversation.title
|
|
141
|
-
}
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
)
|
|
145
|
-
},
|
|
146
|
-
conversation.id
|
|
147
|
-
)) })
|
|
148
|
-
}
|
|
149
|
-
) })
|
|
158
|
+
conversation.id
|
|
159
|
+
)) })
|
|
160
|
+
}
|
|
161
|
+
) })
|
|
162
|
+
] })
|
|
150
163
|
] });
|
|
151
164
|
};
|
|
152
165
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiAssistantPage.esm.js","sources":["../../../src/components/AiAssistantPage/AiAssistantPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Conversation } from '../Conversation';\nimport type { Conversation as ConversationType } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { useAsync, useList } from 'react-use';\nimport { chatApiRef } from '../../api/chat';\nimport { useTheme } from '@mui/material/styles';\n\nimport Stack from '@mui/material/Stack';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport Drawer from '@mui/material/Drawer';\nimport List from '@mui/material/List';\nimport ListItemButton from '@mui/material/ListItemButton';\nimport ListItem from '@mui/material/ListItem';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\n\nimport MenuIcon from '@mui/icons-material/Menu';\nimport AddIcon from '@mui/icons-material/Add';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { signalApiRef } from '@backstage/plugin-signals-react';\nimport { useChatSettings } from '../../hooks/use-chat-settings';\n\nexport const AiAssistantPage = () => {\n const chatApi = useApi(chatApiRef);\n const signalApi = useApi(signalApiRef);\n\n const theme = useTheme();\n\n const chatSettings = useChatSettings();\n\n useEffect(() => {\n chatSettings.setModalVisible(false);\n }, [chatSettings]);\n\n const [conversationId, setConversationId] = useState<string>();\n\n const { value: conversationHistory } = useAsync(\n () => chatApi.getConversations(),\n [chatApi],\n );\n\n const [conversations, { set, updateAt }] = useList<ConversationType>([]);\n\n useEffect(() => {\n if (!conversationHistory) {\n return;\n }\n\n set(conversationHistory);\n }, [conversationHistory, set]);\n\n useEffect(() => {\n const subscription = signalApi.subscribe<{\n conversation: ConversationType;\n }>(`ai-assistant.chat.conversation-details-update`, ({ conversation }) => {\n set(currentConversations => {\n const index = currentConversations.findIndex(\n c => c.id === conversation.id,\n );\n\n if (index !== -1) {\n const newConversations = [...currentConversations];\n newConversations[index] = conversation;\n return newConversations;\n }\n return [conversation, ...currentConversations];\n });\n });\n\n return () => subscription.unsubscribe();\n }, [signalApi, set, updateAt]);\n\n const [open, setOpen] = useState(false);\n\n const toggleDrawer = (drawerOpen: boolean) => () => {\n setOpen(drawerOpen);\n };\n\n const openNewChat = () => {\n setConversationId(undefined);\n };\n\n return (\n <>\n <Stack\n padding={2}\n spacing={2}\n flex={1}\n height=\"100vh\"\n maxHeight=\"100vh\"\n boxSizing=\"border-box\"\n >\n <Stack direction=\"row\" spacing={2} justifyContent=\"flex-end\">\n <Tooltip title=\"New Chat\">\n <IconButton onClick={openNewChat}>\n <AddIcon />\n </IconButton>\n </Tooltip>\n\n {conversations.length > 0 && (\n <Tooltip title=\"Chat History\">\n <IconButton onClick={toggleDrawer(true)}>\n <MenuIcon />\n </IconButton>\n </Tooltip>\n )}\n </Stack>\n <Conversation\n conversationId={conversationId}\n setConversationId={setConversationId}\n />\n </Stack>\n <Drawer anchor=\"right\" open={open} onClose={toggleDrawer(false)}>\n <Box\n sx={{ width: 300 }}\n role=\"presentation\"\n onClick={toggleDrawer(false)}\n >\n <List>\n {conversations.map(conversation => (\n <ListItem\n key={conversation.id}\n sx={{\n fontSize: theme.typography.body1.fontSize,\n }}\n >\n <ListItemButton\n sx={{\n justifyContent: 'flex-start !important',\n padding: `${theme.spacing(1)} !important`,\n borderRadius: `${theme.spacing(1)} !important`,\n backgroundColor:\n conversationId === conversation.id\n ? `${theme.palette.action.selected} !important`\n : 'transparent !important',\n }}\n onClick={() => setConversationId(conversation.id)}\n >\n <Typography\n variant=\"body1\"\n sx={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n width: '100%',\n }}\n >\n {conversation.title}\n </Typography>\n </ListItemButton>\n </ListItem>\n ))}\n </List>\n </Box>\n </Drawer>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AiAssistantPage.esm.js","sources":["../../../src/components/AiAssistantPage/AiAssistantPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Conversation } from '../Conversation';\nimport type { Conversation as ConversationType } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { useAsync, useList } from 'react-use';\nimport { chatApiRef } from '../../api/chat';\nimport { useTheme } from '@mui/material/styles';\n\nimport Stack from '@mui/material/Stack';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport Drawer from '@mui/material/Drawer';\nimport List from '@mui/material/List';\nimport ListItemButton from '@mui/material/ListItemButton';\nimport ListItem from '@mui/material/ListItem';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\n\nimport MenuIcon from '@mui/icons-material/Menu';\nimport AddIcon from '@mui/icons-material/Add';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { signalApiRef } from '@backstage/plugin-signals-react';\nimport { useChatSettings } from '../../hooks/use-chat-settings';\nimport { Page, Content, Header } from '@backstage/core-components';\n\nimport { makeStyles } from 'tss-react/mui';\n\nexport type AiAssistantPageProps = {\n title?: string;\n subtitle?: string;\n};\n\nconst useStyles = makeStyles()(() => ({\n page: {\n height: '100vh',\n maxHeight: '100vh',\n overflow: 'hidden',\n display: 'flex',\n flexDirection: 'column',\n },\n content: {\n flex: 1,\n minHeight: 0,\n display: 'flex',\n flexDirection: 'column',\n },\n}));\n\nexport const AiAssistantPage = ({\n title = 'AI Assistant',\n subtitle,\n}: AiAssistantPageProps) => {\n const chatApi = useApi(chatApiRef);\n const signalApi = useApi(signalApiRef);\n\n const theme = useTheme();\n const { classes } = useStyles();\n\n const chatSettings = useChatSettings();\n\n useEffect(() => {\n chatSettings.setModalVisible(false);\n }, [chatSettings]);\n\n const [conversationId, setConversationId] = useState<string>();\n\n const { value: conversationHistory } = useAsync(\n () => chatApi.getConversations(),\n [chatApi],\n );\n\n const [conversations, { set, updateAt }] = useList<ConversationType>([]);\n\n useEffect(() => {\n if (!conversationHistory) {\n return;\n }\n\n set(conversationHistory);\n }, [conversationHistory, set]);\n\n useEffect(() => {\n const subscription = signalApi.subscribe<{\n conversation: ConversationType;\n }>(`ai-assistant.chat.conversation-details-update`, ({ conversation }) => {\n set(currentConversations => {\n const index = currentConversations.findIndex(\n c => c.id === conversation.id,\n );\n\n if (index !== -1) {\n const newConversations = [...currentConversations];\n newConversations[index] = conversation;\n return newConversations;\n }\n return [conversation, ...currentConversations];\n });\n });\n\n return () => subscription.unsubscribe();\n }, [signalApi, set, updateAt]);\n\n const [open, setOpen] = useState(false);\n\n const toggleDrawer = (drawerOpen: boolean) => () => {\n setOpen(drawerOpen);\n };\n\n const openNewChat = () => {\n setConversationId(undefined);\n };\n\n return (\n <Page themeId=\"tool\" className={classes.page}>\n <Header title={title} subtitle={subtitle} />\n <Content className={classes.content}>\n <Stack spacing={2} flex={1} boxSizing=\"border-box\" height=\"100%\">\n <Stack direction=\"row\" spacing={2} justifyContent=\"flex-end\">\n <Tooltip title=\"New Chat\">\n <IconButton onClick={openNewChat}>\n <AddIcon />\n </IconButton>\n </Tooltip>\n\n {conversations.length > 0 && (\n <Tooltip title=\"Chat History\">\n <IconButton onClick={toggleDrawer(true)}>\n <MenuIcon />\n </IconButton>\n </Tooltip>\n )}\n </Stack>\n <Conversation\n conversationId={conversationId}\n setConversationId={setConversationId}\n />\n </Stack>\n <Drawer anchor=\"right\" open={open} onClose={toggleDrawer(false)}>\n <Box\n sx={{ width: 300 }}\n role=\"presentation\"\n onClick={toggleDrawer(false)}\n >\n <List>\n {conversations.map(conversation => (\n <ListItem\n key={conversation.id}\n sx={{\n fontSize: theme.typography.body1.fontSize,\n }}\n >\n <ListItemButton\n sx={{\n justifyContent: 'flex-start !important',\n padding: `${theme.spacing(1)} !important`,\n borderRadius: `${theme.spacing(1)} !important`,\n backgroundColor:\n conversationId === conversation.id\n ? `${theme.palette.action.selected} !important`\n : 'transparent !important',\n }}\n onClick={() => setConversationId(conversation.id)}\n >\n <Typography\n variant=\"body1\"\n sx={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n width: '100%',\n }}\n >\n {conversation.title}\n </Typography>\n </ListItemButton>\n </ListItem>\n ))}\n </List>\n </Box>\n </Drawer>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
3
|
+
import { JSX } from 'react';
|
|
3
4
|
|
|
4
5
|
interface AiAssistantChatModalProps {
|
|
5
6
|
open?: boolean;
|
|
@@ -8,10 +9,15 @@ interface AiAssistantChatModalProps {
|
|
|
8
9
|
setConversationId?: (id: string | undefined) => void;
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
type AiAssistantPageProps = {
|
|
13
|
+
title?: string;
|
|
14
|
+
subtitle?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
11
17
|
declare const aiAssistantPlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
12
18
|
root: _backstage_core_plugin_api.RouteRef<undefined>;
|
|
13
19
|
}, {}, {}>;
|
|
14
|
-
declare const AiAssistantPage: () =>
|
|
20
|
+
declare const AiAssistantPage: (props: AiAssistantPageProps) => JSX.Element;
|
|
15
21
|
declare const AiAssistantChatModal: ({ open: controlledOpen, onClose: controlledOnClose, conversationId: controlledConversationId, setConversationId: controlledSetConversationId, }: AiAssistantChatModalProps) => react_jsx_runtime.JSX.Element;
|
|
16
22
|
|
|
17
23
|
export { AiAssistantChatModal, AiAssistantPage, aiAssistantPlugin };
|
package/dist/plugin.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n createRoutableExtension,\n createComponentExtension,\n createApiFactory,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport { chatApiRef, createChatService } from './api/chat';\nimport { mcpApiRef, createMcpService } from './api/mcp';\nimport { createSummarizerService, summarizerApiRef } from './api/summarizer';\n\nexport const aiAssistantPlugin = createPlugin({\n id: 'ai-assistant',\n routes: {\n root: rootRouteRef,\n },\n apis: [\n createApiFactory({\n api: chatApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createChatService(options),\n }),\n createApiFactory({\n api: mcpApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createMcpService(options),\n }),\n createApiFactory({\n api: summarizerApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createSummarizerService(options),\n }),\n ],\n});\n\nexport const AiAssistantPage
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n createRoutableExtension,\n createComponentExtension,\n createApiFactory,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef } from './routes';\nimport { chatApiRef, createChatService } from './api/chat';\nimport { mcpApiRef, createMcpService } from './api/mcp';\nimport { createSummarizerService, summarizerApiRef } from './api/summarizer';\nimport { AiAssistantPageProps } from './components/AiAssistantPage';\nimport { JSX } from 'react';\n\nexport const aiAssistantPlugin = createPlugin({\n id: 'ai-assistant',\n routes: {\n root: rootRouteRef,\n },\n apis: [\n createApiFactory({\n api: chatApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createChatService(options),\n }),\n createApiFactory({\n api: mcpApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createMcpService(options),\n }),\n createApiFactory({\n api: summarizerApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createSummarizerService(options),\n }),\n ],\n});\n\nexport const AiAssistantPage: (props: AiAssistantPageProps) => JSX.Element =\n aiAssistantPlugin.provide(\n createRoutableExtension({\n name: 'AiAssistantPage',\n component: () =>\n import('./components/AiAssistantPage').then(m => m.AiAssistantPage),\n mountPoint: rootRouteRef,\n }),\n );\n\nexport const AiAssistantChatModal = aiAssistantPlugin.provide(\n createComponentExtension({\n name: 'AiAssistantChatModal',\n component: {\n lazy: () =>\n import('./components/AiAssistantChatModal').then(\n m => m.AiAssistantChatModal,\n ),\n },\n }),\n);\n\nexport { useChatSettings } from './hooks';\n"],"names":[],"mappings":";;;;;;;;;AAgBO,MAAM,oBAAoB,YAAA,CAAa;AAAA,EAC5C,EAAA,EAAI,cAAA;AAAA,EACJ,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA,GACR;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,gBAAA,CAAiB;AAAA,MACf,GAAA,EAAK,UAAA;AAAA,MACL,IAAA,EAAM;AAAA,QACJ,YAAA,EAAc,eAAA;AAAA,QACd,QAAA,EAAU;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAA,OAAA,KAAW,iBAAA,CAAkB,OAAO;AAAA,KAC9C,CAAA;AAAA,IACD,gBAAA,CAAiB;AAAA,MACf,GAAA,EAAK,SAAA;AAAA,MACL,IAAA,EAAM;AAAA,QACJ,YAAA,EAAc,eAAA;AAAA,QACd,QAAA,EAAU;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAA,OAAA,KAAW,gBAAA,CAAiB,OAAO;AAAA,KAC7C,CAAA;AAAA,IACD,gBAAA,CAAiB;AAAA,MACf,GAAA,EAAK,gBAAA;AAAA,MACL,IAAA,EAAM;AAAA,QACJ,YAAA,EAAc,eAAA;AAAA,QACd,QAAA,EAAU;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAA,OAAA,KAAW,uBAAA,CAAwB,OAAO;AAAA,KACpD;AAAA;AAEL,CAAC;AAEM,MAAM,kBACX,iBAAA,CAAkB,OAAA;AAAA,EAChB,uBAAA,CAAwB;AAAA,IACtB,IAAA,EAAM,iBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,2CAA8B,EAAE,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,eAAe,CAAA;AAAA,IACpE,UAAA,EAAY;AAAA,GACb;AACH;AAEK,MAAM,uBAAuB,iBAAA,CAAkB,OAAA;AAAA,EACpD,wBAAA,CAAyB;AAAA,IACvB,IAAA,EAAM,sBAAA;AAAA,IACN,SAAA,EAAW;AAAA,MACT,IAAA,EAAM,MACJ,OAAO,gDAAmC,CAAA,CAAE,IAAA;AAAA,QAC1C,OAAK,CAAA,CAAE;AAAA;AACT;AACJ,GACD;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sweetoburrito/backstage-plugin-ai-assistant",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "dist/index.esm.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"@sweetoburrito/backstage-plugin-ai-assistant-common": "^0.6.0",
|
|
41
41
|
"react-markdown": "^10.1.0",
|
|
42
42
|
"react-use": "^17.2.4",
|
|
43
|
+
"tss-react": "^4.9.19",
|
|
43
44
|
"zustand": "^5.0.8"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|