@sweetoburrito/backstage-plugin-ai-assistant 0.12.0 → 0.12.2
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/dist/alpha.d.ts
CHANGED
|
@@ -5,9 +5,27 @@ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
|
5
5
|
declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{
|
|
6
6
|
root: _backstage_core_plugin_api.RouteRef<undefined>;
|
|
7
7
|
}, {}, {
|
|
8
|
-
"api:ai-assistant": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
8
|
+
"api:ai-assistant/chatApi": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
9
9
|
kind: "api";
|
|
10
|
-
name:
|
|
10
|
+
name: "chatApi";
|
|
11
|
+
config: {};
|
|
12
|
+
configInput: {};
|
|
13
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
14
|
+
inputs: {};
|
|
15
|
+
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
16
|
+
}>;
|
|
17
|
+
"api:ai-assistant/mcpApi": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
18
|
+
kind: "api";
|
|
19
|
+
name: "mcpApi";
|
|
20
|
+
config: {};
|
|
21
|
+
configInput: {};
|
|
22
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
23
|
+
inputs: {};
|
|
24
|
+
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
25
|
+
}>;
|
|
26
|
+
"api:ai-assistant/summarizerApi": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
|
|
27
|
+
kind: "api";
|
|
28
|
+
name: "summarizerApi";
|
|
11
29
|
config: {};
|
|
12
30
|
configInput: {};
|
|
13
31
|
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
package/dist/alpha.esm.js
CHANGED
|
@@ -14,6 +14,7 @@ const aiAssistantPage = PageBlueprint.make({
|
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
16
|
const chatApi = ApiBlueprint.make({
|
|
17
|
+
name: "chatApi",
|
|
17
18
|
params: (defineParams) => defineParams({
|
|
18
19
|
api: chatApiRef,
|
|
19
20
|
deps: {
|
|
@@ -24,6 +25,7 @@ const chatApi = ApiBlueprint.make({
|
|
|
24
25
|
})
|
|
25
26
|
});
|
|
26
27
|
const mcpApi = ApiBlueprint.make({
|
|
28
|
+
name: "mcpApi",
|
|
27
29
|
params: (defineParams) => defineParams({
|
|
28
30
|
api: mcpApiRef,
|
|
29
31
|
deps: {
|
|
@@ -34,6 +36,7 @@ const mcpApi = ApiBlueprint.make({
|
|
|
34
36
|
})
|
|
35
37
|
});
|
|
36
38
|
const summarizerApi = ApiBlueprint.make({
|
|
39
|
+
name: "summarizerApi",
|
|
37
40
|
params: (defineParams) => defineParams({
|
|
38
41
|
api: summarizerApiRef,
|
|
39
42
|
deps: {
|
package/dist/alpha.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["import {\n createFrontendPlugin,\n PageBlueprint,\n ApiBlueprint,\n AppRootElementBlueprint,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { rootRouteRef } from './routes';\n\nimport { chatApiRef, createChatService } from './api/chat';\nimport { mcpApiRef, createMcpService } from './api/mcp';\nimport { createSummarizerService, summarizerApiRef } from './api/summarizer';\n\nimport { AiAssistantChatModal } from './components/AiAssistantChatModal';\n\nconst aiAssistantPage = PageBlueprint.make({\n params: {\n path: '/ai-assistant',\n routeRef: rootRouteRef,\n loader: () =>\n import('./components/AiAssistantPage').then(m => <m.AiAssistantPage />),\n },\n});\n\nconst chatApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: chatApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createChatService(options),\n }),\n});\n\nconst mcpApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: mcpApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createMcpService(options),\n }),\n});\n\nconst summarizerApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: summarizerApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createSummarizerService(options),\n }),\n});\n\nconst aiAssistantChatModal = AppRootElementBlueprint.make({\n name: 'AiAssistantChatModal',\n params: {\n element: <AiAssistantChatModal />,\n },\n});\n\nexport default createFrontendPlugin({\n pluginId: 'ai-assistant',\n extensions: [\n aiAssistantPage,\n aiAssistantChatModal,\n chatApi,\n mcpApi,\n summarizerApi,\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n"],"names":[],"mappings":";;;;;;;;AAgBA,MAAM,eAAA,GAAkB,cAAc,IAAA,CAAK;AAAA,EACzC,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,QAAA,EAAU,YAAA;AAAA,IACV,MAAA,EAAQ,MACN,OAAO,2CAA8B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,eAAA,EAAF,EAAkB,CAAE;AAAA;AAE5E,CAAC,CAAA;AAED,MAAM,OAAA,GAAU,aAAa,IAAA,CAAK;AAAA,EAChC,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,UAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,YAAA,EAAc,eAAA;AAAA,MACd,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAA,OAAA,KAAW,iBAAA,CAAkB,OAAO;AAAA,GAC9C;AACL,CAAC,CAAA;AAED,MAAM,MAAA,GAAS,aAAa,IAAA,CAAK;AAAA,EAC/B,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,SAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,YAAA,EAAc,eAAA;AAAA,MACd,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAA,OAAA,KAAW,gBAAA,CAAiB,OAAO;AAAA,GAC7C;AACL,CAAC,CAAA;AAED,MAAM,aAAA,GAAgB,aAAa,IAAA,CAAK;AAAA,EACtC,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,gBAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,YAAA,EAAc,eAAA;AAAA,MACd,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAA,OAAA,KAAW,uBAAA,CAAwB,OAAO;AAAA,GACpD;AACL,CAAC,CAAA;AAED,MAAM,oBAAA,GAAuB,wBAAwB,IAAA,CAAK;AAAA,EACxD,IAAA,EAAM,sBAAA;AAAA,EACN,MAAA,EAAQ;AAAA,IACN,OAAA,sBAAU,oBAAA,EAAA,EAAqB;AAAA;AAEnC,CAAC,CAAA;AAED,YAAe,oBAAA,CAAqB;AAAA,EAClC,QAAA,EAAU,cAAA;AAAA,EACV,UAAA,EAAY;AAAA,IACV,eAAA;AAAA,IACA,oBAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA;AAEV,CAAC,CAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["import {\n createFrontendPlugin,\n PageBlueprint,\n ApiBlueprint,\n AppRootElementBlueprint,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { rootRouteRef } from './routes';\n\nimport { chatApiRef, createChatService } from './api/chat';\nimport { mcpApiRef, createMcpService } from './api/mcp';\nimport { createSummarizerService, summarizerApiRef } from './api/summarizer';\n\nimport { AiAssistantChatModal } from './components/AiAssistantChatModal';\n\nconst aiAssistantPage = PageBlueprint.make({\n params: {\n path: '/ai-assistant',\n routeRef: rootRouteRef,\n loader: () =>\n import('./components/AiAssistantPage').then(m => <m.AiAssistantPage />),\n },\n});\n\nconst chatApi = ApiBlueprint.make({\n name: 'chatApi',\n params: defineParams =>\n defineParams({\n api: chatApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createChatService(options),\n }),\n});\n\nconst mcpApi = ApiBlueprint.make({\n name: 'mcpApi',\n params: defineParams =>\n defineParams({\n api: mcpApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createMcpService(options),\n }),\n});\n\nconst summarizerApi = ApiBlueprint.make({\n name: 'summarizerApi',\n params: defineParams =>\n defineParams({\n api: summarizerApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: options => createSummarizerService(options),\n }),\n});\n\nconst aiAssistantChatModal = AppRootElementBlueprint.make({\n name: 'AiAssistantChatModal',\n params: {\n element: <AiAssistantChatModal />,\n },\n});\n\nexport default createFrontendPlugin({\n pluginId: 'ai-assistant',\n extensions: [\n aiAssistantPage,\n aiAssistantChatModal,\n chatApi,\n mcpApi,\n summarizerApi,\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n"],"names":[],"mappings":";;;;;;;;AAgBA,MAAM,eAAA,GAAkB,cAAc,IAAA,CAAK;AAAA,EACzC,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,QAAA,EAAU,YAAA;AAAA,IACV,MAAA,EAAQ,MACN,OAAO,2CAA8B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,eAAA,EAAF,EAAkB,CAAE;AAAA;AAE5E,CAAC,CAAA;AAED,MAAM,OAAA,GAAU,aAAa,IAAA,CAAK;AAAA,EAChC,IAAA,EAAM,SAAA;AAAA,EACN,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,UAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,YAAA,EAAc,eAAA;AAAA,MACd,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAA,OAAA,KAAW,iBAAA,CAAkB,OAAO;AAAA,GAC9C;AACL,CAAC,CAAA;AAED,MAAM,MAAA,GAAS,aAAa,IAAA,CAAK;AAAA,EAC/B,IAAA,EAAM,QAAA;AAAA,EACN,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,SAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,YAAA,EAAc,eAAA;AAAA,MACd,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAA,OAAA,KAAW,gBAAA,CAAiB,OAAO;AAAA,GAC7C;AACL,CAAC,CAAA;AAED,MAAM,aAAA,GAAgB,aAAa,IAAA,CAAK;AAAA,EACtC,IAAA,EAAM,eAAA;AAAA,EACN,MAAA,EAAQ,kBACN,YAAA,CAAa;AAAA,IACX,GAAA,EAAK,gBAAA;AAAA,IACL,IAAA,EAAM;AAAA,MACJ,YAAA,EAAc,eAAA;AAAA,MACd,QAAA,EAAU;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAA,OAAA,KAAW,uBAAA,CAAwB,OAAO;AAAA,GACpD;AACL,CAAC,CAAA;AAED,MAAM,oBAAA,GAAuB,wBAAwB,IAAA,CAAK;AAAA,EACxD,IAAA,EAAM,sBAAA;AAAA,EACN,MAAA,EAAQ;AAAA,IACN,OAAA,sBAAU,oBAAA,EAAA,EAAqB;AAAA;AAEnC,CAAC,CAAA;AAED,YAAe,oBAAA,CAAqB;AAAA,EAClC,QAAA,EAAU,cAAA;AAAA,EACV,UAAA,EAAY;AAAA,IACV,eAAA;AAAA,IACA,oBAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA;AAEV,CAAC,CAAA;;;;"}
|
|
@@ -59,38 +59,21 @@ const MessageCard = ({ message, loading }) => {
|
|
|
59
59
|
) });
|
|
60
60
|
}
|
|
61
61
|
if (message.role === "tool") {
|
|
62
|
-
return /* @__PURE__ */
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
Typography,
|
|
78
|
-
{
|
|
79
|
-
variant: "caption",
|
|
80
|
-
sx: { fontStyle: "italic", color: theme.palette.text.secondary },
|
|
81
|
-
children: [
|
|
82
|
-
"Used tool",
|
|
83
|
-
message.metadata.name ? ` ${message.metadata.name}` : "",
|
|
84
|
-
" ",
|
|
85
|
-
"to enhance response..."
|
|
86
|
-
]
|
|
87
|
-
}
|
|
88
|
-
)
|
|
89
|
-
]
|
|
90
|
-
}
|
|
91
|
-
)
|
|
92
|
-
}
|
|
93
|
-
);
|
|
62
|
+
return /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, alignItems: "end", justifyItems: "start", children: [
|
|
63
|
+
/* @__PURE__ */ jsx(ConstructionIcon, {}),
|
|
64
|
+
/* @__PURE__ */ jsxs(
|
|
65
|
+
Typography,
|
|
66
|
+
{
|
|
67
|
+
variant: "caption",
|
|
68
|
+
sx: { fontStyle: "italic", color: theme.palette.text.secondary },
|
|
69
|
+
children: [
|
|
70
|
+
"Used tool",
|
|
71
|
+
message.metadata.name ? ` ${message.metadata.name}` : "",
|
|
72
|
+
" to enhance response..."
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
] });
|
|
94
77
|
}
|
|
95
78
|
if (message.role === "system") {
|
|
96
79
|
return /* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageCard.esm.js","sources":["../../../src/components/MessageCard/MessageCard.tsx"],"sourcesContent":["import type { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport Markdown from 'react-markdown';\nimport { useTheme } from '@mui/material/styles';\nimport { useMemo, useState, type FocusEvent } from 'react';\nimport { Card } from './Card';\nimport { Actions } from './Actions';\n\nimport Skeleton from '@mui/material/Skeleton';\nimport Typography from '@mui/material/Typography';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Accordion from '@mui/material/Accordion';\nimport AccordionSummary from '@mui/material/AccordionSummary';\nimport AccordionDetails from '@mui/material/AccordionDetails';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Box from '@mui/material/Box';\n\nimport SettingsSuggestIcon from '@mui/icons-material/SettingsSuggest';\nimport ConstructionIcon from '@mui/icons-material/Construction';\n\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\n\nexport type MessageCardProps = {\n message: Message;\n loading: boolean;\n};\n\nexport const MessageCard = ({ message, loading }: MessageCardProps) => {\n const { content, role } = message;\n\n const theme = useTheme();\n const [showActions, setShowActions] = useState(false);\n\n const handleFocus = () => setShowActions(true);\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n const nextFocusTarget = event.relatedTarget as Node | null;\n if (!event.currentTarget.contains(nextFocusTarget)) {\n setShowActions(false);\n }\n };\n\n const hasThinking = useMemo(() => {\n return content.startsWith('<think>');\n }, [content]);\n\n const thinking = useMemo<boolean>(() => {\n return (\n role === 'ai' &&\n content.includes('<think>') &&\n !content.includes('</think>')\n );\n }, [content, role]);\n\n const thoughtProcess = useMemo(() => {\n // Try to match <think>...</think>\n const closedMatch = content.match(/<think>(.*?)<\\/think>/s);\n if (closedMatch) return closedMatch[1].trim();\n\n // If </think> is missing but <think> is present, get everything after <think>\n const openMatch = content.match(/<think>(.*)/s);\n if (openMatch) return openMatch[1].trim();\n\n return '';\n }, [content]);\n\n const response = useMemo<string>(() => {\n if (!hasThinking) {\n return content;\n }\n const [, contentResponse] = content.split('</think>');\n return contentResponse ?? '';\n }, [content, hasThinking]);\n\n if (loading) {\n return (\n <Card role={role}>\n <Skeleton\n variant=\"text\"\n height={theme.typography.body1.fontSize}\n width={210}\n />\n </Card>\n );\n }\n\n if (message.role === 'tool') {\n return (\n <Tooltip\n title={<Markdown>{message.content}</Markdown>}\n placement=\"bottom-start\"\n >\n <Stack\n direction=\"row\"\n spacing={1}\n alignItems=\"end\"\n justifyItems=\"start\"\n >\n <ConstructionIcon />\n <Typography\n variant=\"caption\"\n sx={{ fontStyle: 'italic', color: theme.palette.text.secondary }}\n >\n Used tool{message.metadata.name ? ` ${message.metadata.name}` : ''}{' '}\n to enhance response...\n </Typography>\n </Stack>\n </Tooltip>\n );\n }\n\n if (message.role === 'system') {\n return (\n <Tooltip\n title={<Markdown>{message.content}</Markdown>}\n placement=\"bottom-start\"\n >\n <Stack\n direction=\"row\"\n spacing={1}\n alignItems=\"end\"\n justifyItems=\"start\"\n >\n <SettingsSuggestIcon />\n <Typography\n variant=\"caption\"\n sx={{ fontStyle: 'italic', color: theme.palette.text.secondary }}\n >\n Additional Context Provided\n </Typography>\n </Stack>\n </Tooltip>\n );\n }\n\n return (\n <Box\n onMouseEnter={() => setShowActions(true)}\n onMouseLeave={() => setShowActions(false)}\n onFocusCapture={handleFocus}\n onBlurCapture={handleBlur}\n sx={{\n display: 'flex',\n justifyContent: role === 'human' ? 'flex-end' : 'flex-start',\n width: '100%',\n }}\n >\n <Card role={role}>\n {hasThinking && (\n <Accordion sx={{ paddingX: 1 }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n {thinking && !response ? (\n <Stack direction=\"row\" spacing={1} alignItems=\"center\">\n <CircularProgress size={theme.typography.caption.fontSize} />\n <Typography variant=\"caption\">Thinking</Typography>\n </Stack>\n ) : (\n <Typography variant=\"caption\">Thought Process</Typography>\n )}\n </AccordionSummary>\n <AccordionDetails>\n {thoughtProcess ? (\n <Markdown>{thoughtProcess}</Markdown>\n ) : (\n <Skeleton\n variant=\"text\"\n height={theme.typography.caption.fontSize}\n width={40}\n />\n )}\n </AccordionDetails>\n </Accordion>\n )}\n\n {message.content ? (\n <Markdown>{message.content}</Markdown>\n ) : (\n <Skeleton\n variant=\"text\"\n height={theme.typography.caption.fontSize}\n width={40}\n />\n )}\n {role === 'ai' && (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n opacity: showActions ? 1 : 0,\n visibility: showActions ? 'visible' : 'hidden',\n pointerEvents: showActions ? 'auto' : 'none',\n mt: 1,\n transition: theme.transitions.create('opacity', {\n duration: theme.transitions.duration.short,\n }),\n }}\n >\n <Actions message={message} />\n </Box>\n )}\n </Card>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MessageCard.esm.js","sources":["../../../src/components/MessageCard/MessageCard.tsx"],"sourcesContent":["import type { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport Markdown from 'react-markdown';\nimport { useTheme } from '@mui/material/styles';\nimport { useMemo, useState, type FocusEvent } from 'react';\nimport { Card } from './Card';\nimport { Actions } from './Actions';\n\nimport Skeleton from '@mui/material/Skeleton';\nimport Typography from '@mui/material/Typography';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Accordion from '@mui/material/Accordion';\nimport AccordionSummary from '@mui/material/AccordionSummary';\nimport AccordionDetails from '@mui/material/AccordionDetails';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Box from '@mui/material/Box';\n\nimport SettingsSuggestIcon from '@mui/icons-material/SettingsSuggest';\nimport ConstructionIcon from '@mui/icons-material/Construction';\n\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\n\nexport type MessageCardProps = {\n message: Message;\n loading: boolean;\n};\n\nexport const MessageCard = ({ message, loading }: MessageCardProps) => {\n const { content, role } = message;\n\n const theme = useTheme();\n const [showActions, setShowActions] = useState(false);\n\n const handleFocus = () => setShowActions(true);\n const handleBlur = (event: FocusEvent<HTMLDivElement>) => {\n const nextFocusTarget = event.relatedTarget as Node | null;\n if (!event.currentTarget.contains(nextFocusTarget)) {\n setShowActions(false);\n }\n };\n\n const hasThinking = useMemo(() => {\n return content.startsWith('<think>');\n }, [content]);\n\n const thinking = useMemo<boolean>(() => {\n return (\n role === 'ai' &&\n content.includes('<think>') &&\n !content.includes('</think>')\n );\n }, [content, role]);\n\n const thoughtProcess = useMemo(() => {\n // Try to match <think>...</think>\n const closedMatch = content.match(/<think>(.*?)<\\/think>/s);\n if (closedMatch) return closedMatch[1].trim();\n\n // If </think> is missing but <think> is present, get everything after <think>\n const openMatch = content.match(/<think>(.*)/s);\n if (openMatch) return openMatch[1].trim();\n\n return '';\n }, [content]);\n\n const response = useMemo<string>(() => {\n if (!hasThinking) {\n return content;\n }\n const [, contentResponse] = content.split('</think>');\n return contentResponse ?? '';\n }, [content, hasThinking]);\n\n if (loading) {\n return (\n <Card role={role}>\n <Skeleton\n variant=\"text\"\n height={theme.typography.body1.fontSize}\n width={210}\n />\n </Card>\n );\n }\n\n if (message.role === 'tool') {\n return (\n <Stack direction=\"row\" spacing={1} alignItems=\"end\" justifyItems=\"start\">\n <ConstructionIcon />\n <Typography\n variant=\"caption\"\n sx={{ fontStyle: 'italic', color: theme.palette.text.secondary }}\n >\n Used tool{message.metadata.name ? ` ${message.metadata.name}` : ''} to\n enhance response...\n </Typography>\n </Stack>\n );\n }\n\n if (message.role === 'system') {\n return (\n <Tooltip\n title={<Markdown>{message.content}</Markdown>}\n placement=\"bottom-start\"\n >\n <Stack\n direction=\"row\"\n spacing={1}\n alignItems=\"end\"\n justifyItems=\"start\"\n >\n <SettingsSuggestIcon />\n <Typography\n variant=\"caption\"\n sx={{ fontStyle: 'italic', color: theme.palette.text.secondary }}\n >\n Additional Context Provided\n </Typography>\n </Stack>\n </Tooltip>\n );\n }\n\n return (\n <Box\n onMouseEnter={() => setShowActions(true)}\n onMouseLeave={() => setShowActions(false)}\n onFocusCapture={handleFocus}\n onBlurCapture={handleBlur}\n sx={{\n display: 'flex',\n justifyContent: role === 'human' ? 'flex-end' : 'flex-start',\n width: '100%',\n }}\n >\n <Card role={role}>\n {hasThinking && (\n <Accordion sx={{ paddingX: 1 }}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n {thinking && !response ? (\n <Stack direction=\"row\" spacing={1} alignItems=\"center\">\n <CircularProgress size={theme.typography.caption.fontSize} />\n <Typography variant=\"caption\">Thinking</Typography>\n </Stack>\n ) : (\n <Typography variant=\"caption\">Thought Process</Typography>\n )}\n </AccordionSummary>\n <AccordionDetails>\n {thoughtProcess ? (\n <Markdown>{thoughtProcess}</Markdown>\n ) : (\n <Skeleton\n variant=\"text\"\n height={theme.typography.caption.fontSize}\n width={40}\n />\n )}\n </AccordionDetails>\n </Accordion>\n )}\n\n {message.content ? (\n <Markdown>{message.content}</Markdown>\n ) : (\n <Skeleton\n variant=\"text\"\n height={theme.typography.caption.fontSize}\n width={40}\n />\n )}\n {role === 'ai' && (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n opacity: showActions ? 1 : 0,\n visibility: showActions ? 'visible' : 'hidden',\n pointerEvents: showActions ? 'auto' : 'none',\n mt: 1,\n transition: theme.transitions.create('opacity', {\n duration: theme.transitions.duration.short,\n }),\n }}\n >\n <Actions message={message} />\n </Box>\n )}\n </Card>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AA2BO,MAAM,WAAA,GAAc,CAAC,EAAE,OAAA,EAAS,SAAQ,KAAwB;AACrE,EAAA,MAAM,EAAE,OAAA,EAAS,IAAA,EAAK,GAAI,OAAA;AAE1B,EAAA,MAAM,QAAQ,QAAA,EAAS;AACvB,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,KAAK,CAAA;AAEpD,EAAA,MAAM,WAAA,GAAc,MAAM,cAAA,CAAe,IAAI,CAAA;AAC7C,EAAA,MAAM,UAAA,GAAa,CAAC,KAAA,KAAsC;AACxD,IAAA,MAAM,kBAAkB,KAAA,CAAM,aAAA;AAC9B,IAAA,IAAI,CAAC,KAAA,CAAM,aAAA,CAAc,QAAA,CAAS,eAAe,CAAA,EAAG;AAClD,MAAA,cAAA,CAAe,KAAK,CAAA;AAAA,IACtB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,WAAA,GAAc,QAAQ,MAAM;AAChC,IAAA,OAAO,OAAA,CAAQ,WAAW,SAAS,CAAA;AAAA,EACrC,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,QAAA,GAAW,QAAiB,MAAM;AACtC,IAAA,OACE,IAAA,KAAS,QACT,OAAA,CAAQ,QAAA,CAAS,SAAS,CAAA,IAC1B,CAAC,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA;AAAA,EAEhC,CAAA,EAAG,CAAC,OAAA,EAAS,IAAI,CAAC,CAAA;AAElB,EAAA,MAAM,cAAA,GAAiB,QAAQ,MAAM;AAEnC,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,KAAA,CAAM,wBAAwB,CAAA;AAC1D,IAAA,IAAI,WAAA,EAAa,OAAO,WAAA,CAAY,CAAC,EAAE,IAAA,EAAK;AAG5C,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,CAAM,cAAc,CAAA;AAC9C,IAAA,IAAI,SAAA,EAAW,OAAO,SAAA,CAAU,CAAC,EAAE,IAAA,EAAK;AAExC,IAAA,OAAO,EAAA;AAAA,EACT,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAA,MAAM,QAAA,GAAW,QAAgB,MAAM;AACrC,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,OAAO,OAAA;AAAA,IACT;AACA,IAAA,MAAM,GAAG,eAAe,CAAA,GAAI,OAAA,CAAQ,MAAM,UAAU,CAAA;AACpD,IAAA,OAAO,eAAA,IAAmB,EAAA;AAAA,EAC5B,CAAA,EAAG,CAAC,OAAA,EAAS,WAAW,CAAC,CAAA;AAEzB,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACE,GAAA,CAAC,QAAK,IAAA,EACJ,QAAA,kBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,MAAA;AAAA,QACR,MAAA,EAAQ,KAAA,CAAM,UAAA,CAAW,KAAA,CAAM,QAAA;AAAA,QAC/B,KAAA,EAAO;AAAA;AAAA,KACT,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAQ;AAC3B,IAAA,uBACE,IAAA,CAAC,SAAM,SAAA,EAAU,KAAA,EAAM,SAAS,CAAA,EAAG,UAAA,EAAW,KAAA,EAAM,YAAA,EAAa,OAAA,EAC/D,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,gBAAA,EAAA,EAAiB,CAAA;AAAA,sBAClB,IAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAQ,SAAA;AAAA,UACR,EAAA,EAAI,EAAE,SAAA,EAAW,QAAA,EAAU,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,SAAA,EAAU;AAAA,UAChE,QAAA,EAAA;AAAA,YAAA,WAAA;AAAA,YACW,QAAQ,QAAA,CAAS,IAAA,GAAO,IAAI,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,CAAA,GAAK,EAAA;AAAA,YAAG;AAAA;AAAA;AAAA;AAErE,KAAA,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,OAAA,CAAQ,SAAS,QAAA,EAAU;AAC7B,IAAA,uBACE,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,KAAA,kBAAO,GAAA,CAAC,QAAA,EAAA,EAAU,QAAA,EAAA,OAAA,CAAQ,OAAA,EAAQ,CAAA;AAAA,QAClC,SAAA,EAAU,cAAA;AAAA,QAEV,QAAA,kBAAA,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,KAAA;AAAA,YACV,OAAA,EAAS,CAAA;AAAA,YACT,UAAA,EAAW,KAAA;AAAA,YACX,YAAA,EAAa,OAAA;AAAA,YAEb,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,mBAAA,EAAA,EAAoB,CAAA;AAAA,8BACrB,GAAA;AAAA,gBAAC,UAAA;AAAA,gBAAA;AAAA,kBACC,OAAA,EAAQ,SAAA;AAAA,kBACR,EAAA,EAAI,EAAE,SAAA,EAAW,QAAA,EAAU,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,SAAA,EAAU;AAAA,kBAChE,QAAA,EAAA;AAAA;AAAA;AAED;AAAA;AAAA;AACF;AAAA,KACF;AAAA,EAEJ;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,YAAA,EAAc,MAAM,cAAA,CAAe,IAAI,CAAA;AAAA,MACvC,YAAA,EAAc,MAAM,cAAA,CAAe,KAAK,CAAA;AAAA,MACxC,cAAA,EAAgB,WAAA;AAAA,MAChB,aAAA,EAAe,UAAA;AAAA,MACf,EAAA,EAAI;AAAA,QACF,OAAA,EAAS,MAAA;AAAA,QACT,cAAA,EAAgB,IAAA,KAAS,OAAA,GAAU,UAAA,GAAa,YAAA;AAAA,QAChD,KAAA,EAAO;AAAA,OACT;AAAA,MAEA,QAAA,kBAAA,IAAA,CAAC,QAAK,IAAA,EACH,QAAA,EAAA;AAAA,QAAA,WAAA,yBACE,SAAA,EAAA,EAAU,EAAA,EAAI,EAAE,QAAA,EAAU,GAAE,EAC3B,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,gBAAA,EAAA,EAAiB,UAAA,kBAAY,GAAA,CAAC,cAAA,EAAA,EAAe,GAC3C,QAAA,EAAA,QAAA,IAAY,CAAC,QAAA,mBACZ,IAAA,CAAC,SAAM,SAAA,EAAU,KAAA,EAAM,OAAA,EAAS,CAAA,EAAG,YAAW,QAAA,EAC5C,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,gBAAA,EAAA,EAAiB,IAAA,EAAM,KAAA,CAAM,UAAA,CAAW,QAAQ,QAAA,EAAU,CAAA;AAAA,4BAC3D,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,QAAA,EAAA,UAAA,EAAQ;AAAA,WAAA,EACxC,oBAEA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,6BAAe,CAAA,EAEjD,CAAA;AAAA,8BACC,gBAAA,EAAA,EACE,QAAA,EAAA,cAAA,mBACC,GAAA,CAAC,QAAA,EAAA,EAAU,0BAAe,CAAA,mBAE1B,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,MAAA;AAAA,cACR,MAAA,EAAQ,KAAA,CAAM,UAAA,CAAW,OAAA,CAAQ,QAAA;AAAA,cACjC,KAAA,EAAO;AAAA;AAAA,WACT,EAEJ;AAAA,SAAA,EACF,CAAA;AAAA,QAGD,QAAQ,OAAA,mBACP,GAAA,CAAC,QAAA,EAAA,EAAU,QAAA,EAAA,OAAA,CAAQ,SAAQ,CAAA,mBAE3B,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAQ,MAAA;AAAA,YACR,MAAA,EAAQ,KAAA,CAAM,UAAA,CAAW,OAAA,CAAQ,QAAA;AAAA,YACjC,KAAA,EAAO;AAAA;AAAA,SACT;AAAA,QAED,SAAS,IAAA,oBACR,GAAA;AAAA,UAAC,GAAA;AAAA,UAAA;AAAA,YACC,EAAA,EAAI;AAAA,cACF,OAAA,EAAS,MAAA;AAAA,cACT,cAAA,EAAgB,UAAA;AAAA,cAChB,OAAA,EAAS,cAAc,CAAA,GAAI,CAAA;AAAA,cAC3B,UAAA,EAAY,cAAc,SAAA,GAAY,QAAA;AAAA,cACtC,aAAA,EAAe,cAAc,MAAA,GAAS,MAAA;AAAA,cACtC,EAAA,EAAI,CAAA;AAAA,cACJ,UAAA,EAAY,KAAA,CAAM,WAAA,CAAY,MAAA,CAAO,SAAA,EAAW;AAAA,gBAC9C,QAAA,EAAU,KAAA,CAAM,WAAA,CAAY,QAAA,CAAS;AAAA,eACtC;AAAA,aACH;AAAA,YAEA,QAAA,kBAAA,GAAA,CAAC,WAAQ,OAAA,EAAkB;AAAA;AAAA;AAC7B,OAAA,EAEJ;AAAA;AAAA,GACF;AAEJ;;;;"}
|