@sweetoburrito/backstage-plugin-ai-assistant 0.6.0 → 0.7.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/dist/api/chat.esm.js +20 -1
- package/dist/api/chat.esm.js.map +1 -1
- package/dist/api/mcp.esm.js +73 -0
- package/dist/api/mcp.esm.js.map +1 -0
- package/dist/api/summarizer.esm.js +47 -0
- package/dist/api/summarizer.esm.js.map +1 -0
- package/dist/components/AiAssistantChatModal/AiAssistantChatModal.esm.js +194 -0
- package/dist/components/AiAssistantChatModal/AiAssistantChatModal.esm.js.map +1 -0
- package/dist/components/AiAssistantChatModal/index.esm.js +2 -0
- package/dist/components/AiAssistantChatModal/index.esm.js.map +1 -0
- package/dist/components/AiAssistantPage/AiAssistantPage.esm.js +31 -8
- package/dist/components/AiAssistantPage/AiAssistantPage.esm.js.map +1 -1
- package/dist/components/Conversation/Conversation.esm.js +28 -6
- package/dist/components/Conversation/Conversation.esm.js.map +1 -1
- package/dist/components/Conversation/McpServersTab.esm.js +303 -0
- package/dist/components/Conversation/McpServersTab.esm.js.map +1 -0
- package/dist/components/Conversation/SettingsModal.esm.js +134 -0
- package/dist/components/Conversation/SettingsModal.esm.js.map +1 -0
- package/dist/components/MessageCard/FeedbackButtons.esm.js +64 -0
- package/dist/components/MessageCard/FeedbackButtons.esm.js.map +1 -0
- package/dist/components/MessageCard/MessageCard.esm.js +63 -10
- package/dist/components/MessageCard/MessageCard.esm.js.map +1 -1
- package/dist/hooks/use-chat-settings.esm.js +24 -0
- package/dist/hooks/use-chat-settings.esm.js.map +1 -0
- package/dist/hooks/use-page-summary.esm.js +27 -0
- package/dist/hooks/use-page-summary.esm.js.map +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.esm.js +1 -1
- package/dist/plugin.esm.js +33 -2
- package/dist/plugin.esm.js.map +1 -1
- package/package.json +4 -3
package/dist/api/chat.esm.js
CHANGED
|
@@ -53,7 +53,26 @@ const createChatService = ({
|
|
|
53
53
|
const data = await response.json();
|
|
54
54
|
return data.conversations;
|
|
55
55
|
};
|
|
56
|
-
|
|
56
|
+
const scoreMessage = async (messageId, score) => {
|
|
57
|
+
const assistantBaseUrl = await discoveryApi.getBaseUrl("ai-assistant");
|
|
58
|
+
await fetchApi.fetch(
|
|
59
|
+
`${assistantBaseUrl}/chat/message/${messageId}/score`,
|
|
60
|
+
{
|
|
61
|
+
method: "POST",
|
|
62
|
+
body: JSON.stringify({ score }),
|
|
63
|
+
headers: {
|
|
64
|
+
"Content-Type": "application/json"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
getModels,
|
|
71
|
+
getConversation,
|
|
72
|
+
sendMessage,
|
|
73
|
+
getConversations,
|
|
74
|
+
scoreMessage
|
|
75
|
+
};
|
|
57
76
|
};
|
|
58
77
|
|
|
59
78
|
export { chatApiRef, createChatService };
|
package/dist/api/chat.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.esm.js","sources":["../../src/api/chat.ts"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\nimport {\n Conversation,\n Message,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\ntype SendMessageOptions = {\n conversationId?: string;\n modelId: string;\n messages: Message[];\n stream?: boolean;\n};\n\nexport type ChatApi = {\n getModels: () => Promise<string[]>;\n getConversation: (id?: string) => Promise<Message[]>;\n sendMessage: (options: SendMessageOptions) => Promise<{\n messages: Message[];\n conversationId: string;\n }>;\n getConversations: () => Promise<Conversation[]>;\n};\n\ntype ChatApiOptions = {\n fetchApi: FetchApi;\n discoveryApi: DiscoveryApi;\n};\n\nexport const chatApiRef = createApiRef<ChatApi>({\n id: 'plugin.ai-assistant.chat',\n});\n\nexport const createChatService = ({\n fetchApi,\n discoveryApi,\n}: ChatApiOptions): ChatApi => {\n const getModels: ChatApi['getModels'] = async (): Promise<string[]> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(`${assistantBaseUrl}/models`);\n const data = await response.json();\n return data.models;\n };\n\n const getConversation: ChatApi['getConversation'] = async id => {\n if (!id) return [];\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(`${assistantBaseUrl}/chat/${id}`);\n\n const data = await response.json();\n\n return data.conversation as Message[];\n };\n\n const sendMessage: ChatApi['sendMessage'] = async ({\n conversationId,\n modelId,\n messages,\n stream,\n }) => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n const response = await fetchApi.fetch(`${assistantBaseUrl}/chat/message`, {\n method: 'POST',\n body: JSON.stringify({\n conversationId,\n modelId,\n messages,\n stream,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n const data = await response.json();\n\n return {\n messages: data.messages as Message[],\n conversationId: data.conversationId as string,\n };\n };\n\n const getConversations: ChatApi['getConversations'] = async () => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(\n `${assistantBaseUrl}/chat/conversations`,\n );\n\n const data = await response.json();\n\n return data.conversations as Conversation[];\n };\n\n
|
|
1
|
+
{"version":3,"file":"chat.esm.js","sources":["../../src/api/chat.ts"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\nimport {\n Conversation,\n Message,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\ntype SendMessageOptions = {\n conversationId?: string;\n modelId: string;\n messages: Message[];\n stream?: boolean;\n};\n\nexport type ChatApi = {\n getModels: () => Promise<string[]>;\n getConversation: (id?: string) => Promise<Message[]>;\n sendMessage: (options: SendMessageOptions) => Promise<{\n messages: Message[];\n conversationId: string;\n }>;\n getConversations: () => Promise<Conversation[]>;\n scoreMessage: (messageId: string, score: number) => Promise<void>;\n};\n\ntype ChatApiOptions = {\n fetchApi: FetchApi;\n discoveryApi: DiscoveryApi;\n};\n\nexport const chatApiRef = createApiRef<ChatApi>({\n id: 'plugin.ai-assistant.chat',\n});\n\nexport const createChatService = ({\n fetchApi,\n discoveryApi,\n}: ChatApiOptions): ChatApi => {\n const getModels: ChatApi['getModels'] = async (): Promise<string[]> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(`${assistantBaseUrl}/models`);\n const data = await response.json();\n return data.models;\n };\n\n const getConversation: ChatApi['getConversation'] = async id => {\n if (!id) return [];\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(`${assistantBaseUrl}/chat/${id}`);\n\n const data = await response.json();\n\n return data.conversation as Message[];\n };\n\n const sendMessage: ChatApi['sendMessage'] = async ({\n conversationId,\n modelId,\n messages,\n stream,\n }) => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n const response = await fetchApi.fetch(`${assistantBaseUrl}/chat/message`, {\n method: 'POST',\n body: JSON.stringify({\n conversationId,\n modelId,\n messages,\n stream,\n }),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n const data = await response.json();\n\n return {\n messages: data.messages as Message[],\n conversationId: data.conversationId as string,\n };\n };\n\n const getConversations: ChatApi['getConversations'] = async () => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(\n `${assistantBaseUrl}/chat/conversations`,\n );\n\n const data = await response.json();\n\n return data.conversations as Conversation[];\n };\n\n const scoreMessage: ChatApi['scoreMessage'] = async (messageId, score) => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n await fetchApi.fetch(\n `${assistantBaseUrl}/chat/message/${messageId}/score`,\n {\n method: 'POST',\n body: JSON.stringify({ score }),\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n );\n };\n\n return {\n getModels,\n getConversation,\n sendMessage,\n getConversations,\n scoreMessage,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { createApiRef } from '@backstage/core-plugin-api';
|
|
2
|
+
|
|
3
|
+
const mcpApiRef = createApiRef({
|
|
4
|
+
id: "plugin.ai-assistant.mcp"
|
|
5
|
+
});
|
|
6
|
+
const createMcpService = ({ fetchApi, discoveryApi }) => {
|
|
7
|
+
const getUserDefinedMcpConfigs = async () => {
|
|
8
|
+
const assistantBaseUrl = await discoveryApi.getBaseUrl("ai-assistant");
|
|
9
|
+
const response = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`);
|
|
10
|
+
const data = await response.json();
|
|
11
|
+
return data;
|
|
12
|
+
};
|
|
13
|
+
const createMcpConfig = async (config) => {
|
|
14
|
+
const assistantBaseUrl = await discoveryApi.getBaseUrl("ai-assistant");
|
|
15
|
+
const res = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`, {
|
|
16
|
+
method: "POST",
|
|
17
|
+
body: JSON.stringify(config),
|
|
18
|
+
headers: {
|
|
19
|
+
"Content-Type": "application/json"
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
const errorData = await res.json();
|
|
24
|
+
const { error } = errorData;
|
|
25
|
+
throw new Error(
|
|
26
|
+
`Failed to create MCP config: ${error || res.statusText}`
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const updateMcpConfig = async (config) => {
|
|
31
|
+
const assistantBaseUrl = await discoveryApi.getBaseUrl("ai-assistant");
|
|
32
|
+
const res = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`, {
|
|
33
|
+
method: "PATCH",
|
|
34
|
+
body: JSON.stringify(config),
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/json"
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
if (!res.ok) {
|
|
40
|
+
const errorData = await res.json();
|
|
41
|
+
const { error } = errorData;
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Failed to update MCP config: ${error || res.statusText}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const deleteMcpConfig = async (configName) => {
|
|
48
|
+
const assistantBaseUrl = await discoveryApi.getBaseUrl("ai-assistant");
|
|
49
|
+
const res = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`, {
|
|
50
|
+
method: "DELETE",
|
|
51
|
+
body: JSON.stringify({ name: configName }),
|
|
52
|
+
headers: {
|
|
53
|
+
"Content-Type": "application/json"
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
const errorData = await res.json();
|
|
58
|
+
const { error } = errorData;
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Failed to delete MCP config: ${error || res.statusText}`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
getUserDefinedMcpConfigs,
|
|
66
|
+
createMcpConfig,
|
|
67
|
+
updateMcpConfig,
|
|
68
|
+
deleteMcpConfig
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export { createMcpService, mcpApiRef };
|
|
73
|
+
//# sourceMappingURL=mcp.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.esm.js","sources":["../../src/api/mcp.ts"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\nimport { McpServerConfig } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\nexport type McpApi = Awaited<ReturnType<typeof createMcpService>>;\n\ntype McpApiOptions = {\n fetchApi: FetchApi;\n discoveryApi: DiscoveryApi;\n};\n\nexport const mcpApiRef = createApiRef<McpApi>({\n id: 'plugin.ai-assistant.mcp',\n});\n\nexport const createMcpService = ({ fetchApi, discoveryApi }: McpApiOptions) => {\n const getUserDefinedMcpConfigs = async (): Promise<{ names: string[] }> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`);\n const data = await response.json();\n return data;\n };\n\n const createMcpConfig = async (config: McpServerConfig): Promise<void> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const res = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`, {\n method: 'POST',\n body: JSON.stringify(config),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!res.ok) {\n const errorData = await res.json();\n\n const { error } = errorData;\n\n throw new Error(\n `Failed to create MCP config: ${error || res.statusText}`,\n );\n }\n };\n\n const updateMcpConfig = async (config: McpServerConfig): Promise<void> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const res = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`, {\n method: 'PATCH',\n body: JSON.stringify(config),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!res.ok) {\n const errorData = await res.json();\n\n const { error } = errorData;\n\n throw new Error(\n `Failed to update MCP config: ${error || res.statusText}`,\n );\n }\n };\n\n const deleteMcpConfig = async (configName: string): Promise<void> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const res = await fetchApi.fetch(`${assistantBaseUrl}/mcp/config`, {\n method: 'DELETE',\n body: JSON.stringify({ name: configName }),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!res.ok) {\n const errorData = await res.json();\n\n const { error } = errorData;\n\n throw new Error(\n `Failed to delete MCP config: ${error || res.statusText}`,\n );\n }\n };\n\n return {\n getUserDefinedMcpConfigs,\n createMcpConfig,\n updateMcpConfig,\n deleteMcpConfig,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createApiRef } from '@backstage/core-plugin-api';
|
|
2
|
+
|
|
3
|
+
const summarizerApiRef = createApiRef({
|
|
4
|
+
id: "plugin.ai-assistant.summarizer"
|
|
5
|
+
});
|
|
6
|
+
const createSummarizerService = ({
|
|
7
|
+
fetchApi,
|
|
8
|
+
discoveryApi
|
|
9
|
+
}) => {
|
|
10
|
+
const summarizeContent = async (content) => {
|
|
11
|
+
const assistantBaseUrl = await discoveryApi.getBaseUrl("ai-assistant");
|
|
12
|
+
const response = await fetchApi.fetch(
|
|
13
|
+
`${assistantBaseUrl}/summary/content`,
|
|
14
|
+
{
|
|
15
|
+
method: "POST",
|
|
16
|
+
body: JSON.stringify({ content }),
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
return data.summary;
|
|
24
|
+
};
|
|
25
|
+
const summarizeConversation = async (messages) => {
|
|
26
|
+
const assistantBaseUrl = await discoveryApi.getBaseUrl("ai-assistant");
|
|
27
|
+
const response = await fetchApi.fetch(
|
|
28
|
+
`${assistantBaseUrl}/summary/conversation`,
|
|
29
|
+
{
|
|
30
|
+
method: "POST",
|
|
31
|
+
body: JSON.stringify({ messages }),
|
|
32
|
+
headers: {
|
|
33
|
+
"Content-Type": "application/json"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
return data.summary;
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
summarizeContent,
|
|
42
|
+
summarizeConversation
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export { createSummarizerService, summarizerApiRef };
|
|
47
|
+
//# sourceMappingURL=summarizer.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarizer.esm.js","sources":["../../src/api/summarizer.ts"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\nexport type SummarizerApi = Awaited<ReturnType<typeof createSummarizerService>>;\n\ntype SummarizerApiOptions = {\n fetchApi: FetchApi;\n discoveryApi: DiscoveryApi;\n};\n\nexport const summarizerApiRef = createApiRef<SummarizerApi>({\n id: 'plugin.ai-assistant.summarizer',\n});\n\nexport const createSummarizerService = ({\n fetchApi,\n discoveryApi,\n}: SummarizerApiOptions) => {\n const summarizeContent = async (content: string): Promise<string> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n\n const response = await fetchApi.fetch(\n `${assistantBaseUrl}/summary/content`,\n {\n method: 'POST',\n body: JSON.stringify({ content }),\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n );\n\n const data = await response.json();\n return data.summary as string;\n };\n\n const summarizeConversation = async (\n messages: Message[],\n ): Promise<string> => {\n const assistantBaseUrl = await discoveryApi.getBaseUrl('ai-assistant');\n const response = await fetchApi.fetch(\n `${assistantBaseUrl}/summary/conversation`,\n {\n method: 'POST',\n body: JSON.stringify({ messages }),\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n );\n\n const data = await response.json();\n return data.summary as string;\n };\n\n return {\n summarizeContent,\n summarizeConversation,\n };\n};\n"],"names":[],"mappings":";;AAWO,MAAM,mBAAmB,YAAA,CAA4B;AAAA,EAC1D,EAAA,EAAI;AACN,CAAC;AAEM,MAAM,0BAA0B,CAAC;AAAA,EACtC,QAAA;AAAA,EACA;AACF,CAAA,KAA4B;AAC1B,EAAA,MAAM,gBAAA,GAAmB,OAAO,OAAA,KAAqC;AACnE,IAAA,MAAM,gBAAA,GAAmB,MAAM,YAAA,CAAa,UAAA,CAAW,cAAc,CAAA;AAErE,IAAA,MAAM,QAAA,GAAW,MAAM,QAAA,CAAS,KAAA;AAAA,MAC9B,GAAG,gBAAgB,CAAA,gBAAA,CAAA;AAAA,MACnB;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,SAAS,CAAA;AAAA,QAChC,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB;AAAA;AAClB;AACF,KACF;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd,CAAA;AAEA,EAAA,MAAM,qBAAA,GAAwB,OAC5B,QAAA,KACoB;AACpB,IAAA,MAAM,gBAAA,GAAmB,MAAM,YAAA,CAAa,UAAA,CAAW,cAAc,CAAA;AACrE,IAAA,MAAM,QAAA,GAAW,MAAM,QAAA,CAAS,KAAA;AAAA,MAC9B,GAAG,gBAAgB,CAAA,qBAAA,CAAA;AAAA,MACnB;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,UAAU,CAAA;AAAA,QACjC,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB;AAAA;AAClB;AACF,KACF;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,gBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect, useMemo } from 'react';
|
|
3
|
+
import { Conversation } from '../Conversation/Conversation.esm.js';
|
|
4
|
+
import '@mui/material/Dialog';
|
|
5
|
+
import '@mui/material/DialogTitle';
|
|
6
|
+
import '@mui/material/DialogContent';
|
|
7
|
+
import '@mui/material/DialogActions';
|
|
8
|
+
import Button from '@mui/material/Button';
|
|
9
|
+
import '@mui/material/Tab';
|
|
10
|
+
import '@mui/material/Tabs';
|
|
11
|
+
import Box from '@mui/material/Box';
|
|
12
|
+
import Typography from '@mui/material/Typography';
|
|
13
|
+
import Stack from '@mui/material/Stack';
|
|
14
|
+
import IconButton from '@mui/material/IconButton';
|
|
15
|
+
import '@mui/icons-material/Close';
|
|
16
|
+
import '@mui/icons-material/Settings';
|
|
17
|
+
import '@backstage/core-plugin-api';
|
|
18
|
+
import 'react-use';
|
|
19
|
+
import '@mui/material/TextField';
|
|
20
|
+
import '@mui/material/Paper';
|
|
21
|
+
import '@mui/material/Divider';
|
|
22
|
+
import '@mui/material/Card';
|
|
23
|
+
import '@mui/material/CardContent';
|
|
24
|
+
import '@mui/material/CardActions';
|
|
25
|
+
import '@mui/material/Alert';
|
|
26
|
+
import '@mui/icons-material/Delete';
|
|
27
|
+
import AddIcon from '@mui/icons-material/Add';
|
|
28
|
+
import Tooltip from '@mui/material/Tooltip';
|
|
29
|
+
import '../../api/mcp.esm.js';
|
|
30
|
+
import Modal from '@mui/material/Modal';
|
|
31
|
+
import Chip from '@mui/material/Chip';
|
|
32
|
+
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
|
|
33
|
+
import { useChatSettings } from '../../hooks/use-chat-settings.esm.js';
|
|
34
|
+
import { useLocation } from 'react-router-dom';
|
|
35
|
+
import { usePageSummary } from '../../hooks/use-page-summary.esm.js';
|
|
36
|
+
|
|
37
|
+
const AiAssistantChatModal = ({
|
|
38
|
+
open: controlledOpen,
|
|
39
|
+
onClose: controlledOnClose,
|
|
40
|
+
conversationId: controlledConversationId,
|
|
41
|
+
setConversationId: controlledSetConversationId
|
|
42
|
+
}) => {
|
|
43
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
44
|
+
const [modalConversationId, setModalConversationId] = useState();
|
|
45
|
+
const { modalVisible, setModalVisible, setSummaryEnabled, summaryEnabled } = useChatSettings();
|
|
46
|
+
const location = useLocation();
|
|
47
|
+
const { summary, loading, error } = usePageSummary();
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
setModalVisible(true);
|
|
50
|
+
}, [location, setModalVisible, setSummaryEnabled]);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
if (!modalOpen) return;
|
|
53
|
+
setSummaryEnabled(true);
|
|
54
|
+
}, [modalOpen, setSummaryEnabled]);
|
|
55
|
+
const additionalSystemMessages = useMemo(() => {
|
|
56
|
+
if (!summaryEnabled || !summary) return [];
|
|
57
|
+
const path = location.pathname;
|
|
58
|
+
const title = document.title;
|
|
59
|
+
const content = `The user is currently on the page titled "${title}" located at "${path}". The page has the following context: ${summary}. Use this context to inform your responses where relevant.`;
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
role: "system",
|
|
63
|
+
content,
|
|
64
|
+
metadata: {},
|
|
65
|
+
score: 0
|
|
66
|
+
}
|
|
67
|
+
];
|
|
68
|
+
}, [summaryEnabled, summary, location.pathname]);
|
|
69
|
+
if (!modalVisible) {
|
|
70
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
71
|
+
}
|
|
72
|
+
const getChipColor = () => {
|
|
73
|
+
if (loading) return "primary";
|
|
74
|
+
if (error) return "error";
|
|
75
|
+
if (summary) return "success";
|
|
76
|
+
return void 0;
|
|
77
|
+
};
|
|
78
|
+
const getChipLabel = () => {
|
|
79
|
+
if (loading) return "Loading page context...";
|
|
80
|
+
if (error) return "Error loading page context";
|
|
81
|
+
if (summary) return "Page Context Loaded";
|
|
82
|
+
return "No page context available";
|
|
83
|
+
};
|
|
84
|
+
const isOpen = controlledOpen !== void 0 ? controlledOpen : modalOpen;
|
|
85
|
+
const conversationId = controlledConversationId !== void 0 ? controlledConversationId : modalConversationId;
|
|
86
|
+
const setConversationId = controlledSetConversationId || setModalConversationId;
|
|
87
|
+
const handleModalOpen = () => {
|
|
88
|
+
if (controlledOpen === void 0) {
|
|
89
|
+
setModalOpen(true);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const handleModalClose = () => {
|
|
93
|
+
if (controlledOnClose) {
|
|
94
|
+
controlledOnClose();
|
|
95
|
+
} else {
|
|
96
|
+
setModalOpen(false);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const openNewModalChat = () => {
|
|
100
|
+
setConversationId(void 0);
|
|
101
|
+
};
|
|
102
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
103
|
+
/* @__PURE__ */ jsx(
|
|
104
|
+
Box,
|
|
105
|
+
{
|
|
106
|
+
sx: {
|
|
107
|
+
position: "absolute",
|
|
108
|
+
bottom: (theme) => theme.spacing(2),
|
|
109
|
+
right: (theme) => theme.spacing(2),
|
|
110
|
+
borderRadius: "50%",
|
|
111
|
+
boxShadow: (theme) => theme.shadows[4],
|
|
112
|
+
bgcolor: (theme) => theme.palette.background.paper,
|
|
113
|
+
border: (theme) => `1px solid ${theme.palette.primary.main}`,
|
|
114
|
+
width: 50,
|
|
115
|
+
height: 50,
|
|
116
|
+
padding: (theme) => theme.spacing(1),
|
|
117
|
+
display: "flex",
|
|
118
|
+
justifyContent: "center",
|
|
119
|
+
alignItems: "center",
|
|
120
|
+
zIndex: (theme) => theme.zIndex.modal - 1,
|
|
121
|
+
":hover": {
|
|
122
|
+
cursor: "pointer",
|
|
123
|
+
boxShadow: (theme) => theme.shadows[6],
|
|
124
|
+
bgcolor: (theme) => theme.palette.background.default
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
onClick: handleModalOpen,
|
|
128
|
+
children: /* @__PURE__ */ jsx(AutoAwesomeIcon, {})
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
/* @__PURE__ */ jsx(Modal, { open: isOpen, onClose: handleModalClose, children: /* @__PURE__ */ jsx(
|
|
132
|
+
Box,
|
|
133
|
+
{
|
|
134
|
+
sx: {
|
|
135
|
+
position: "absolute",
|
|
136
|
+
top: "50%",
|
|
137
|
+
left: "50%",
|
|
138
|
+
transform: "translate(-50%, -50%)",
|
|
139
|
+
width: "60vw",
|
|
140
|
+
height: "60vh",
|
|
141
|
+
bgcolor: "background.paper",
|
|
142
|
+
border: "1px solid #000",
|
|
143
|
+
padding: 2,
|
|
144
|
+
display: "flex",
|
|
145
|
+
flexDirection: "column"
|
|
146
|
+
},
|
|
147
|
+
children: /* @__PURE__ */ jsxs(Stack, { spacing: 2, flex: 1, height: "100%", children: [
|
|
148
|
+
/* @__PURE__ */ jsxs(
|
|
149
|
+
Stack,
|
|
150
|
+
{
|
|
151
|
+
direction: "row",
|
|
152
|
+
spacing: 2,
|
|
153
|
+
justifyContent: "space-between",
|
|
154
|
+
alignItems: "center",
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h6", component: "h2", children: "AI Assistant" }),
|
|
157
|
+
summaryEnabled && /* @__PURE__ */ jsx(
|
|
158
|
+
Tooltip,
|
|
159
|
+
{
|
|
160
|
+
title: summary ?? "No summary available",
|
|
161
|
+
placement: "bottom",
|
|
162
|
+
children: /* @__PURE__ */ jsx(
|
|
163
|
+
Chip,
|
|
164
|
+
{
|
|
165
|
+
label: getChipLabel(),
|
|
166
|
+
color: getChipColor(),
|
|
167
|
+
variant: "outlined"
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
/* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, children: [
|
|
173
|
+
/* @__PURE__ */ jsx(Tooltip, { title: "New Chat", placement: "bottom", children: /* @__PURE__ */ jsx(IconButton, { onClick: openNewModalChat, children: /* @__PURE__ */ jsx(AddIcon, {}) }) }),
|
|
174
|
+
/* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: handleModalClose, children: "Close" })
|
|
175
|
+
] })
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
),
|
|
179
|
+
/* @__PURE__ */ jsx(
|
|
180
|
+
Conversation,
|
|
181
|
+
{
|
|
182
|
+
conversationId,
|
|
183
|
+
setConversationId,
|
|
184
|
+
additionalSystemMessages
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
] })
|
|
188
|
+
}
|
|
189
|
+
) })
|
|
190
|
+
] });
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export { AiAssistantChatModal };
|
|
194
|
+
//# sourceMappingURL=AiAssistantChatModal.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AiAssistantChatModal.esm.js","sources":["../../../src/components/AiAssistantChatModal/AiAssistantChatModal.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport { Conversation } from '../Conversation';\nimport Stack from '@mui/material/Stack';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport Modal from '@mui/material/Modal';\nimport Button from '@mui/material/Button';\nimport Chip from '@mui/material/Chip';\nimport AddIcon from '@mui/icons-material/Add';\nimport AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';\nimport { useChatSettings } from '../../hooks/use-chat-settings';\nimport { useLocation } from 'react-router-dom';\nimport { usePageSummary } from '../../hooks/use-page-summary';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\nexport interface AiAssistantChatModalProps {\n open?: boolean;\n onClose?: () => void;\n conversationId?: string;\n setConversationId?: (id: string | undefined) => void;\n}\n\nexport const AiAssistantChatModal = ({\n open: controlledOpen,\n onClose: controlledOnClose,\n conversationId: controlledConversationId,\n setConversationId: controlledSetConversationId,\n}: AiAssistantChatModalProps) => {\n const [modalOpen, setModalOpen] = useState(false);\n const [modalConversationId, setModalConversationId] = useState<string>();\n\n const { modalVisible, setModalVisible, setSummaryEnabled, summaryEnabled } =\n useChatSettings();\n\n const location = useLocation();\n\n const { summary, loading, error } = usePageSummary();\n\n // Update visibility based on route changes\n useEffect(() => {\n setModalVisible(true);\n }, [location, setModalVisible, setSummaryEnabled]);\n\n useEffect(() => {\n if (!modalOpen) return;\n setSummaryEnabled(true);\n }, [modalOpen, setSummaryEnabled]);\n\n const additionalSystemMessages: Message[] = useMemo(() => {\n if (!summaryEnabled || !summary) return [];\n\n const path = location.pathname;\n const title = document.title;\n const content = `The user is currently on the page titled \"${title}\" located at \"${path}\". The page has the following context: ${summary}. Use this context to inform your responses where relevant.`;\n\n return [\n {\n role: 'system',\n content,\n metadata: {},\n score: 0,\n },\n ];\n }, [summaryEnabled, summary, location.pathname]);\n\n // If the context says the modal is not visible, don't render anything\n if (!modalVisible) {\n return <></>;\n }\n\n const getChipColor = () => {\n if (loading) return 'primary';\n if (error) return 'error';\n if (summary) return 'success';\n return undefined;\n };\n\n const getChipLabel = () => {\n if (loading) return 'Loading page context...';\n if (error) return 'Error loading page context';\n if (summary) return 'Page Context Loaded';\n return 'No page context available';\n };\n\n // Use controlled props if provided, otherwise use internal state\n const isOpen = controlledOpen !== undefined ? controlledOpen : modalOpen;\n const conversationId =\n controlledConversationId !== undefined\n ? controlledConversationId\n : modalConversationId;\n const setConversationId =\n controlledSetConversationId || setModalConversationId;\n\n const handleModalOpen = () => {\n if (controlledOpen === undefined) {\n setModalOpen(true);\n }\n };\n\n const handleModalClose = () => {\n if (controlledOnClose) {\n controlledOnClose();\n } else {\n setModalOpen(false);\n }\n };\n\n const openNewModalChat = () => {\n setConversationId(undefined);\n };\n\n return (\n <>\n <Box\n sx={{\n position: 'absolute',\n bottom: theme => theme.spacing(2),\n right: theme => theme.spacing(2),\n borderRadius: '50%',\n boxShadow: theme => theme.shadows[4],\n bgcolor: theme => theme.palette.background.paper,\n border: theme => `1px solid ${theme.palette.primary.main}`,\n width: 50,\n height: 50,\n padding: theme => theme.spacing(1),\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n zIndex: theme => theme.zIndex.modal - 1,\n ':hover': {\n cursor: 'pointer',\n boxShadow: theme => theme.shadows[6],\n bgcolor: theme => theme.palette.background.default,\n },\n }}\n onClick={handleModalOpen}\n >\n <AutoAwesomeIcon />\n </Box>\n\n <Modal open={isOpen} onClose={handleModalClose}>\n <Box\n sx={{\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: '60vw',\n height: '60vh',\n bgcolor: 'background.paper',\n border: '1px solid #000',\n padding: 2,\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n <Stack spacing={2} flex={1} height=\"100%\">\n <Stack\n direction=\"row\"\n spacing={2}\n justifyContent=\"space-between\"\n alignItems=\"center\"\n >\n <Typography variant=\"h6\" component=\"h2\">\n AI Assistant\n </Typography>\n {summaryEnabled && (\n <Tooltip\n title={summary ?? 'No summary available'}\n placement=\"bottom\"\n >\n <Chip\n label={getChipLabel()}\n color={getChipColor()}\n variant=\"outlined\"\n />\n </Tooltip>\n )}\n <Stack direction=\"row\" spacing={1}>\n <Tooltip title=\"New Chat\" placement=\"bottom\">\n <IconButton onClick={openNewModalChat}>\n <AddIcon />\n </IconButton>\n </Tooltip>\n <Button variant=\"outlined\" onClick={handleModalClose}>\n Close\n </Button>\n </Stack>\n </Stack>\n <Conversation\n conversationId={conversationId}\n setConversationId={setConversationId}\n additionalSystemMessages={additionalSystemMessages}\n />\n </Stack>\n </Box>\n </Modal>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -1,27 +1,50 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
3
|
import { Conversation } from '../Conversation/Conversation.esm.js';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
4
|
+
import '@mui/material/Dialog';
|
|
5
|
+
import '@mui/material/DialogTitle';
|
|
6
|
+
import '@mui/material/DialogContent';
|
|
7
|
+
import '@mui/material/DialogActions';
|
|
8
|
+
import '@mui/material/Button';
|
|
9
|
+
import '@mui/material/Tab';
|
|
10
|
+
import '@mui/material/Tabs';
|
|
11
|
+
import Box from '@mui/material/Box';
|
|
12
|
+
import Typography from '@mui/material/Typography';
|
|
7
13
|
import Stack from '@mui/material/Stack';
|
|
8
14
|
import IconButton from '@mui/material/IconButton';
|
|
15
|
+
import '@mui/icons-material/Close';
|
|
16
|
+
import '@mui/icons-material/Settings';
|
|
17
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
18
|
+
import { useAsync, useList } from 'react-use';
|
|
19
|
+
import '@mui/material/TextField';
|
|
20
|
+
import '@mui/material/Paper';
|
|
21
|
+
import '@mui/material/Divider';
|
|
22
|
+
import '@mui/material/Card';
|
|
23
|
+
import '@mui/material/CardContent';
|
|
24
|
+
import '@mui/material/CardActions';
|
|
25
|
+
import '@mui/material/Alert';
|
|
26
|
+
import '@mui/icons-material/Delete';
|
|
27
|
+
import AddIcon from '@mui/icons-material/Add';
|
|
9
28
|
import Tooltip from '@mui/material/Tooltip';
|
|
29
|
+
import '../../api/mcp.esm.js';
|
|
30
|
+
import { chatApiRef } from '../../api/chat.esm.js';
|
|
31
|
+
import { useTheme } from '@mui/material/styles';
|
|
10
32
|
import Drawer from '@mui/material/Drawer';
|
|
11
33
|
import List from '@mui/material/List';
|
|
12
34
|
import ListItemButton from '@mui/material/ListItemButton';
|
|
13
35
|
import ListItem from '@mui/material/ListItem';
|
|
14
|
-
import Box from '@mui/material/Box';
|
|
15
|
-
import Typography from '@mui/material/Typography';
|
|
16
36
|
import MenuIcon from '@mui/icons-material/Menu';
|
|
17
|
-
import AddIcon from '@mui/icons-material/Add';
|
|
18
|
-
import { useApi } from '@backstage/core-plugin-api';
|
|
19
37
|
import { signalApiRef } from '@backstage/plugin-signals-react';
|
|
38
|
+
import { useChatSettings } from '../../hooks/use-chat-settings.esm.js';
|
|
20
39
|
|
|
21
40
|
const AiAssistantPage = () => {
|
|
22
41
|
const chatApi = useApi(chatApiRef);
|
|
23
42
|
const signalApi = useApi(signalApiRef);
|
|
24
43
|
const theme = useTheme();
|
|
44
|
+
const chatSettings = useChatSettings();
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
chatSettings.setModalVisible(false);
|
|
47
|
+
}, [chatSettings]);
|
|
25
48
|
const [conversationId, setConversationId] = useState();
|
|
26
49
|
const { value: conversationHistory } = useAsync(
|
|
27
50
|
() => chatApi.getConversations(),
|
|
@@ -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';\n\nexport const AiAssistantPage = () => {\n const chatApi = useApi(chatApiRef);\n const signalApi = useApi(signalApiRef);\n\n const theme = useTheme();\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":"
|
|
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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"}
|
|
@@ -10,12 +10,15 @@ import Stack from '@mui/material/Stack';
|
|
|
10
10
|
import Autocomplete from '@mui/material/Autocomplete';
|
|
11
11
|
import Paper from '@mui/material/Paper';
|
|
12
12
|
import NorthIcon from '@mui/icons-material/North';
|
|
13
|
+
import SettingsIcon from '@mui/icons-material/Settings';
|
|
13
14
|
import Button from '@mui/material/Button';
|
|
14
15
|
import { MessageCard } from '../MessageCard/MessageCard.esm.js';
|
|
16
|
+
import { SettingsModal } from './SettingsModal.esm.js';
|
|
15
17
|
|
|
16
18
|
const Conversation = ({
|
|
17
19
|
conversationId,
|
|
18
|
-
setConversationId
|
|
20
|
+
setConversationId,
|
|
21
|
+
additionalSystemMessages
|
|
19
22
|
}) => {
|
|
20
23
|
const chatApi = useApi(chatApiRef);
|
|
21
24
|
const errorApi = useApi(errorApiRef);
|
|
@@ -26,6 +29,7 @@ const Conversation = ({
|
|
|
26
29
|
"modelId",
|
|
27
30
|
void 0
|
|
28
31
|
);
|
|
32
|
+
const [settingsModalOpen, setSettingsModalOpen] = useState(false);
|
|
29
33
|
const { value: models, loading: loadingModels } = useAsync(
|
|
30
34
|
() => chatApi.getModels(),
|
|
31
35
|
[chatApi]
|
|
@@ -84,7 +88,7 @@ const Conversation = ({
|
|
|
84
88
|
}, [models, modelId, setModelId]);
|
|
85
89
|
const [{ loading: sending }, sendMessage] = useAsyncFn(async () => {
|
|
86
90
|
const newMessages = [
|
|
87
|
-
{ role: "human", content: input, metadata: {} }
|
|
91
|
+
{ role: "human", content: input, metadata: {}, score: 0 }
|
|
88
92
|
];
|
|
89
93
|
if (!modelId) {
|
|
90
94
|
errorApi.post({
|
|
@@ -99,7 +103,7 @@ const Conversation = ({
|
|
|
99
103
|
const response = await chatApi.sendMessage({
|
|
100
104
|
conversationId,
|
|
101
105
|
modelId,
|
|
102
|
-
messages: newMessages
|
|
106
|
+
messages: additionalSystemMessages ? [...additionalSystemMessages, ...newMessages] : newMessages
|
|
103
107
|
});
|
|
104
108
|
setConversationId(response.conversationId);
|
|
105
109
|
return response;
|
|
@@ -157,10 +161,10 @@ const Conversation = ({
|
|
|
157
161
|
},
|
|
158
162
|
message.id ?? idx
|
|
159
163
|
)),
|
|
160
|
-
|
|
164
|
+
messages[messages.length - 1] && messages[messages.length - 1]?.role !== "ai" && /* @__PURE__ */ jsx(
|
|
161
165
|
MessageCard,
|
|
162
166
|
{
|
|
163
|
-
message: { content: "", role: "ai", metadata: {} },
|
|
167
|
+
message: { content: "", role: "ai", metadata: {}, score: 0 },
|
|
164
168
|
loading: true
|
|
165
169
|
}
|
|
166
170
|
),
|
|
@@ -205,6 +209,17 @@ const Conversation = ({
|
|
|
205
209
|
renderInput: (params) => /* @__PURE__ */ jsx(TextField, { ...params, label: "Models" })
|
|
206
210
|
}
|
|
207
211
|
),
|
|
212
|
+
/* @__PURE__ */ jsx(
|
|
213
|
+
Button,
|
|
214
|
+
{
|
|
215
|
+
disabled: sending,
|
|
216
|
+
variant: "contained",
|
|
217
|
+
color: "info",
|
|
218
|
+
title: "Settings",
|
|
219
|
+
onClick: () => setSettingsModalOpen(true),
|
|
220
|
+
children: /* @__PURE__ */ jsx(SettingsIcon, {})
|
|
221
|
+
}
|
|
222
|
+
),
|
|
208
223
|
/* @__PURE__ */ jsx(
|
|
209
224
|
Button,
|
|
210
225
|
{
|
|
@@ -216,7 +231,14 @@ const Conversation = ({
|
|
|
216
231
|
)
|
|
217
232
|
]
|
|
218
233
|
}
|
|
219
|
-
) })
|
|
234
|
+
) }),
|
|
235
|
+
/* @__PURE__ */ jsx(
|
|
236
|
+
SettingsModal,
|
|
237
|
+
{
|
|
238
|
+
open: settingsModalOpen,
|
|
239
|
+
onClose: () => setSettingsModalOpen(false)
|
|
240
|
+
}
|
|
241
|
+
)
|
|
220
242
|
]
|
|
221
243
|
}
|
|
222
244
|
);
|