@nospt/plugin-dev-ai-hub 0.1.0 → 0.2.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.
Files changed (71) hide show
  1. package/dev/index.tsx +17 -217
  2. package/dist/api/DevAiHubClient.esm.js +2 -0
  3. package/dist/api/DevAiHubClient.esm.js.map +1 -1
  4. package/dist/components/AssetCard/AssetCard.esm.js +60 -134
  5. package/dist/components/AssetCard/AssetCard.esm.js.map +1 -1
  6. package/dist/components/AssetCard/AssetCard.module.css.esm.js +8 -0
  7. package/dist/components/AssetCard/AssetCard.module.css.esm.js.map +1 -0
  8. package/dist/components/AssetDetailPanel/AssetDetailPanel.esm.js +175 -281
  9. package/dist/components/AssetDetailPanel/AssetDetailPanel.esm.js.map +1 -1
  10. package/dist/components/AssetDetailPanel/AssetDetailPanel.module.css.esm.js +8 -0
  11. package/dist/components/AssetDetailPanel/AssetDetailPanel.module.css.esm.js.map +1 -0
  12. package/dist/components/AssetFilters/AssetFilters.esm.js +94 -134
  13. package/dist/components/AssetFilters/AssetFilters.esm.js.map +1 -1
  14. package/dist/components/AssetFilters/AssetFilters.module.css.esm.js +8 -0
  15. package/dist/components/AssetFilters/AssetFilters.module.css.esm.js.map +1 -0
  16. package/dist/components/AssetInstallDialog/AssetInstallDialog.esm.js +70 -126
  17. package/dist/components/AssetInstallDialog/AssetInstallDialog.esm.js.map +1 -1
  18. package/dist/components/AssetInstallDialog/AssetInstallDialog.module.css.esm.js +8 -0
  19. package/dist/components/AssetInstallDialog/AssetInstallDialog.module.css.esm.js.map +1 -0
  20. package/dist/components/DevAiHubPage/DevAiHubPage.esm.js +64 -189
  21. package/dist/components/DevAiHubPage/DevAiHubPage.esm.js.map +1 -1
  22. package/dist/components/DevAiHubPage/DevAiHubPage.module.css.esm.js +8 -0
  23. package/dist/components/DevAiHubPage/DevAiHubPage.module.css.esm.js.map +1 -0
  24. package/dist/components/McpConfigPage/McpConfigPage.esm.js +200 -0
  25. package/dist/components/McpConfigPage/McpConfigPage.esm.js.map +1 -0
  26. package/dist/components/McpConfigPage/McpConfigPage.module.css.esm.js +8 -0
  27. package/dist/components/McpConfigPage/McpConfigPage.module.css.esm.js.map +1 -0
  28. package/dist/components/McpConfigPage/index.esm.js +6 -0
  29. package/dist/components/McpConfigPage/index.esm.js.map +1 -0
  30. package/dist/components/ToolIcon/ToolIcon.esm.js +25 -13
  31. package/dist/components/ToolIcon/ToolIcon.esm.js.map +1 -1
  32. package/dist/index.d.ts +10 -5
  33. package/dist/index.esm.js +1 -1
  34. package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js +29 -0
  35. package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js.map +1 -0
  36. package/dist/plugin.esm.js +22 -4
  37. package/dist/plugin.esm.js.map +1 -1
  38. package/dist/routes.esm.js +2 -1
  39. package/dist/routes.esm.js.map +1 -1
  40. package/package.json +24 -14
  41. package/package.json-prepack +24 -14
  42. package/src/components/AssetCard/AssetCard.module.css +153 -0
  43. package/src/components/AssetCard/AssetCard.tsx +79 -148
  44. package/src/components/AssetDetailPanel/AssetDetailPanel.module.css +207 -0
  45. package/src/components/AssetDetailPanel/AssetDetailPanel.tsx +228 -292
  46. package/src/components/AssetFilters/AssetFilters.module.css +67 -0
  47. package/src/components/AssetFilters/AssetFilters.tsx +136 -178
  48. package/src/components/AssetInstallDialog/AssetInstallDialog.module.css +72 -0
  49. package/src/components/AssetInstallDialog/AssetInstallDialog.tsx +95 -135
  50. package/src/components/DevAiHubPage/DevAiHubPage.module.css +105 -0
  51. package/src/components/DevAiHubPage/DevAiHubPage.tsx +73 -222
  52. package/src/components/McpConfigDialog/McpConfigDialog.module.css +111 -0
  53. package/src/components/McpConfigDialog/McpConfigDialog.tsx +178 -208
  54. package/src/components/McpConfigPage/McpConfigPage.module.css +121 -0
  55. package/src/components/McpConfigPage/McpConfigPage.tsx +242 -0
  56. package/src/components/McpConfigPage/index.ts +1 -0
  57. package/src/components/ToolIcon/ToolIcon.tsx +31 -15
  58. package/src/css-modules.d.ts +4 -0
  59. package/src/index.ts +1 -1
  60. package/src/plugin.tsx +21 -1
  61. package/src/routes.ts +1 -0
  62. package/tests/e2e/.auth.json +14 -0
  63. package/tests/e2e/asset-detail.spec.ts +90 -0
  64. package/tests/e2e/asset-filtering.spec.ts +145 -0
  65. package/tests/e2e/asset-installation.spec.ts +74 -0
  66. package/tests/e2e/dev-ai-hub-page.spec.ts +89 -0
  67. package/tests/e2e/fixtures/base.ts +61 -0
  68. package/tests/e2e/fixtures/mock-api.ts +221 -0
  69. package/tests/e2e/mcp-config.spec.ts +88 -0
  70. package/dist/components/McpConfigDialog/McpConfigDialog.esm.js +0 -274
  71. package/dist/components/McpConfigDialog/McpConfigDialog.esm.js.map +0 -1
@@ -0,0 +1,200 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { Text, Tabs, TabList, Tab, TabPanel, Box, Flex, ToggleButton, Switch, TooltipTrigger, ButtonIcon, Tooltip } from '@backstage/ui';
4
+ import { RiDatabase2Line, RiCheckLine, RiFileCopyLine } from '@remixicon/react';
5
+ import { useApi, discoveryApiRef } from '@backstage/core-plugin-api';
6
+ import { ToolIcon } from '../ToolIcon/ToolIcon.esm.js';
7
+ import { useCopyToClipboard, useProviders } from '../../hooks/index.esm.js';
8
+ import styles from './McpConfigPage.module.css.esm.js';
9
+
10
+ const TOOL_CONFIGS = [
11
+ {
12
+ tool: "claude-code",
13
+ label: "Claude Code",
14
+ file: ".mcp.json",
15
+ description: "Add to .mcp.json in your project root (or run via claude mcp add):",
16
+ buildConfig: (url) => JSON.stringify({
17
+ mcpServers: { "dev-ai-hub": { type: "http", url } }
18
+ }, null, 2)
19
+ },
20
+ {
21
+ tool: "github-copilot",
22
+ label: "GitHub Copilot",
23
+ file: ".vscode/settings.json",
24
+ description: "Add to your VS Code settings (.vscode/settings.json or user settings):",
25
+ buildConfig: (url) => JSON.stringify({
26
+ "github.copilot.chat.mcp.servers": { "dev-ai-hub": { type: "http", url } }
27
+ }, null, 2)
28
+ },
29
+ {
30
+ tool: "google-gemini",
31
+ label: "Google Gemini",
32
+ file: "gemini-config.json",
33
+ description: "Add to your Gemini CLI configuration:",
34
+ buildConfig: (url) => JSON.stringify({
35
+ mcpServers: { "dev-ai-hub": { url } }
36
+ }, null, 2)
37
+ }
38
+ ];
39
+ function providerLabel(target) {
40
+ return target.split("/").pop()?.replace(/\.git$/, "") ?? target;
41
+ }
42
+ function McpConfigPage() {
43
+ const discoveryApi = useApi(discoveryApiRef);
44
+ const { copy: copyUrl, copied: copiedUrl } = useCopyToClipboard();
45
+ const { copy: copySnippet, copied: copiedSnippet } = useCopyToClipboard();
46
+ const [selectedToolKey, setSelectedToolKey] = useState("claude-code");
47
+ const [baseUrl, setBaseUrl] = useState("");
48
+ const [selectedProvider, setSelectedProvider] = useState("");
49
+ const [proactiveEnabled, setProactiveEnabled] = useState(false);
50
+ const { providers } = useProviders();
51
+ const showProviderFilter = providers.length > 1;
52
+ useEffect(() => {
53
+ discoveryApi.getBaseUrl("dev-ai-hub").then((url) => setBaseUrl(url));
54
+ }, [discoveryApi]);
55
+ const cfg = TOOL_CONFIGS.find((t) => t.tool === selectedToolKey) ?? TOOL_CONFIGS[0];
56
+ const buildMcpUrl = () => {
57
+ if (!baseUrl) return "loading...";
58
+ const params = new URLSearchParams();
59
+ params.set("tool", cfg.tool);
60
+ if (selectedProvider) params.set("provider", selectedProvider);
61
+ if (proactiveEnabled) params.set("proactive", "true");
62
+ return `${baseUrl}/mcp?${params.toString()}`;
63
+ };
64
+ const mcpUrl = buildMcpUrl();
65
+ const configSnippet = baseUrl ? cfg.buildConfig(mcpUrl) : "";
66
+ const [isDark, setIsDark] = useState(() => {
67
+ if (typeof document === "undefined") return false;
68
+ return document.documentElement.getAttribute("data-theme-mode") === "dark" || document.body.getAttribute("data-theme-mode") === "dark";
69
+ });
70
+ useEffect(() => {
71
+ const getIsDark = () => document.documentElement.getAttribute("data-theme-mode") === "dark" || document.body.getAttribute("data-theme-mode") === "dark";
72
+ const observer = new MutationObserver(() => setIsDark(getIsDark()));
73
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme-mode"] });
74
+ observer.observe(document.body, { attributes: true, attributeFilter: ["data-theme-mode"] });
75
+ return () => observer.disconnect();
76
+ }, []);
77
+ return /* @__PURE__ */ jsxs("div", { className: styles.pageRoot, children: [
78
+ /* @__PURE__ */ jsx(Text, { variant: "title-small", weight: "bold", children: "Configure MCP Server" }),
79
+ /* @__PURE__ */ jsx(Text, { variant: "body-small", color: "secondary", className: styles.subtitle, children: "Connect your AI tool to the Dev AI Hub via Model Context Protocol." }),
80
+ /* @__PURE__ */ jsx("div", { className: styles.configContent, children: /* @__PURE__ */ jsxs(Tabs, { selectedKey: selectedToolKey, onSelectionChange: (key) => setSelectedToolKey(key), children: [
81
+ /* @__PURE__ */ jsx(TabList, { className: styles.tabBar, children: TOOL_CONFIGS.map((t) => /* @__PURE__ */ jsx(Tab, { id: t.tool, children: /* @__PURE__ */ jsxs("span", { className: styles.tabContent, children: [
82
+ /* @__PURE__ */ jsx(ToolIcon, { tool: t.tool, size: 16 }),
83
+ /* @__PURE__ */ jsx("span", { children: t.label })
84
+ ] }) }, t.tool)) }),
85
+ TOOL_CONFIGS.map((t) => /* @__PURE__ */ jsxs(TabPanel, { id: t.tool, children: [
86
+ showProviderFilter && /* @__PURE__ */ jsxs(Box, { className: styles.providerSection, children: [
87
+ /* @__PURE__ */ jsx(Text, { variant: "body-x-small", color: "secondary", className: styles.sectionLabel, children: "Scope to Provider" }),
88
+ /* @__PURE__ */ jsxs(Flex, { className: styles.chipsRow, children: [
89
+ /* @__PURE__ */ jsx(
90
+ ToggleButton,
91
+ {
92
+ id: "all-providers",
93
+ size: "small",
94
+ className: styles.filterChip,
95
+ isSelected: !selectedProvider,
96
+ onChange: () => setSelectedProvider(""),
97
+ style: {
98
+ borderColor: !selectedProvider ? "var(--bui-fg-primary)" : "var(--bui-border-1)",
99
+ backgroundColor: !selectedProvider ? "var(--bui-fg-primary)" : "transparent",
100
+ color: !selectedProvider ? "var(--bui-bg-neutral-1)" : "var(--bui-fg-secondary)"
101
+ },
102
+ children: "All providers"
103
+ }
104
+ ),
105
+ providers.map((p) => {
106
+ const isSelected = selectedProvider === p.id;
107
+ const label = providerLabel(p.target);
108
+ return /* @__PURE__ */ jsx(
109
+ ToggleButton,
110
+ {
111
+ id: p.id,
112
+ size: "small",
113
+ className: styles.filterChip,
114
+ iconStart: /* @__PURE__ */ jsx(RiDatabase2Line, { size: 12, style: { color: isSelected ? "var(--bui-bg-neutral-1)" : "inherit" } }),
115
+ isSelected,
116
+ onChange: () => setSelectedProvider(isSelected ? "" : p.id),
117
+ style: {
118
+ borderColor: isSelected ? "var(--bui-fg-primary)" : "var(--bui-border-1)",
119
+ backgroundColor: isSelected ? "var(--bui-fg-primary)" : "transparent",
120
+ color: isSelected ? "var(--bui-bg-neutral-1)" : "var(--bui-fg-secondary)"
121
+ },
122
+ children: label
123
+ },
124
+ p.id
125
+ );
126
+ })
127
+ ] })
128
+ ] }),
129
+ /* @__PURE__ */ jsx(Flex, { className: styles.proactiveSection, children: /* @__PURE__ */ jsxs(Flex, { className: styles.proactiveRow, children: [
130
+ /* @__PURE__ */ jsx(
131
+ Switch,
132
+ {
133
+ isSelected: proactiveEnabled,
134
+ onChange: setProactiveEnabled,
135
+ "aria-label": "Proactive suggestions"
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsxs(Box, { children: [
139
+ /* @__PURE__ */ jsx(Text, { variant: "body-small", weight: "bold", children: "Proactive suggestions" }),
140
+ /* @__PURE__ */ jsx(Text, { variant: "body-x-small", color: "secondary", children: "The AI will automatically suggest relevant assets based on your project context. Disable if you prefer to search manually." })
141
+ ] })
142
+ ] }) }),
143
+ /* @__PURE__ */ jsxs(Box, { className: styles.urlSection, children: [
144
+ /* @__PURE__ */ jsx(Text, { variant: "body-x-small", color: "secondary", className: styles.sectionLabel, children: "MCP Endpoint" }),
145
+ /* @__PURE__ */ jsxs(Flex, { className: styles.urlBox, children: [
146
+ /* @__PURE__ */ jsx(Text, { variant: "body-small", className: styles.urlText, children: mcpUrl }),
147
+ /* @__PURE__ */ jsxs(TooltipTrigger, { children: [
148
+ /* @__PURE__ */ jsx(
149
+ ButtonIcon,
150
+ {
151
+ "aria-label": copiedUrl ? "Copied!" : "Copy URL",
152
+ icon: copiedUrl ? /* @__PURE__ */ jsx(RiCheckLine, { size: 14, style: { color: "var(--bui-fg-success)" } }) : /* @__PURE__ */ jsx(RiFileCopyLine, { size: 14 }),
153
+ variant: "tertiary",
154
+ onPress: () => copyUrl(mcpUrl)
155
+ }
156
+ ),
157
+ /* @__PURE__ */ jsx(Tooltip, { children: copiedUrl ? "Copied!" : "Copy URL" })
158
+ ] })
159
+ ] })
160
+ ] }),
161
+ /* @__PURE__ */ jsx(Text, { variant: "body-x-small", color: "secondary", className: styles.sectionLabel, children: t.file }),
162
+ /* @__PURE__ */ jsx(Text, { variant: "body-x-small", color: "secondary", style: { display: "block", marginBottom: "var(--bui-space-2)", marginTop: "var(--bui-space-1)" }, children: t.description }),
163
+ /* @__PURE__ */ jsxs("div", { className: styles.snippetContainer, children: [
164
+ /* @__PURE__ */ jsx("pre", { className: `${styles.snippetPre} ${isDark ? styles.snippetPreDark : styles.snippetPreLight}`, children: configSnippet }),
165
+ /* @__PURE__ */ jsxs(TooltipTrigger, { children: [
166
+ /* @__PURE__ */ jsx(
167
+ ButtonIcon,
168
+ {
169
+ "aria-label": "Copy config",
170
+ className: styles.copySnippetButton,
171
+ icon: copiedSnippet ? /* @__PURE__ */ jsx(RiCheckLine, { size: 14, style: { color: "var(--bui-fg-success)" } }) : /* @__PURE__ */ jsx(RiFileCopyLine, { size: 14 }),
172
+ variant: "tertiary",
173
+ onPress: () => copySnippet(configSnippet)
174
+ }
175
+ ),
176
+ /* @__PURE__ */ jsx(Tooltip, { children: copiedSnippet ? "Copied!" : "Copy config" })
177
+ ] })
178
+ ] }),
179
+ /* @__PURE__ */ jsxs(Text, { variant: "body-x-small", color: "secondary", className: styles.hint, children: [
180
+ "\u{1F4A1} Omit ",
181
+ /* @__PURE__ */ jsx("code", { children: "?tool=" }),
182
+ " from the URL to receive assets for all AI tools.",
183
+ showProviderFilter && " Omit ?provider= to receive assets from all repositories.",
184
+ " ",
185
+ "Proactive suggestions add ",
186
+ /* @__PURE__ */ jsx("code", { children: "?proactive=true" }),
187
+ " and register the",
188
+ " ",
189
+ /* @__PURE__ */ jsx("code", { children: "suggest_assets" }),
190
+ " tool and ",
191
+ /* @__PURE__ */ jsx("code", { children: "check_for_assets" }),
192
+ " prompt."
193
+ ] })
194
+ ] }, t.tool))
195
+ ] }) })
196
+ ] });
197
+ }
198
+
199
+ export { McpConfigPage };
200
+ //# sourceMappingURL=McpConfigPage.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpConfigPage.esm.js","sources":["../../../src/components/McpConfigPage/McpConfigPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport {\n Box, Flex, Text, ButtonIcon, ToggleButton, Switch,\n Tabs, TabList, Tab, TabPanel,\n Tooltip, TooltipTrigger,\n} from '@backstage/ui';\nimport { RiFileCopyLine, RiCheckLine, RiDatabase2Line } from '@remixicon/react';\nimport { useApi, discoveryApiRef } from '@backstage/core-plugin-api';\nimport { ToolIcon } from '../ToolIcon';\nimport { useCopyToClipboard, useProviders } from '../../hooks';\nimport type { AiTool } from '@nospt/plugin-dev-ai-hub-common';\nimport styles from './McpConfigPage.module.css';\n\ninterface ToolConfig {\n tool: AiTool;\n label: string;\n file: string;\n description: string;\n buildConfig: (mcpUrl: string) => string;\n}\n\nconst TOOL_CONFIGS: ToolConfig[] = [\n {\n tool: 'claude-code',\n label: 'Claude Code',\n file: '.mcp.json',\n description: 'Add to .mcp.json in your project root (or run via claude mcp add):',\n buildConfig: url => JSON.stringify({\n mcpServers: { 'dev-ai-hub': { type: 'http', url } },\n }, null, 2),\n },\n {\n tool: 'github-copilot',\n label: 'GitHub Copilot',\n file: '.vscode/settings.json',\n description: 'Add to your VS Code settings (.vscode/settings.json or user settings):',\n buildConfig: url => JSON.stringify({\n 'github.copilot.chat.mcp.servers': { 'dev-ai-hub': { type: 'http', url } },\n }, null, 2),\n },\n {\n tool: 'google-gemini',\n label: 'Google Gemini',\n file: 'gemini-config.json',\n description: 'Add to your Gemini CLI configuration:',\n buildConfig: url => JSON.stringify({\n mcpServers: { 'dev-ai-hub': { url } },\n }, null, 2),\n },\n];\n\nfunction providerLabel(target: string): string {\n return target.split('/').pop()?.replace(/\\.git$/, '') ?? target;\n}\n\nexport function McpConfigPage() {\n const discoveryApi = useApi(discoveryApiRef);\n const { copy: copyUrl, copied: copiedUrl } = useCopyToClipboard();\n const { copy: copySnippet, copied: copiedSnippet } = useCopyToClipboard();\n const [selectedToolKey, setSelectedToolKey] = useState<string>('claude-code');\n const [baseUrl, setBaseUrl] = useState('');\n const [selectedProvider, setSelectedProvider] = useState<string>('');\n const [proactiveEnabled, setProactiveEnabled] = useState(false);\n\n const { providers } = useProviders();\n const showProviderFilter = providers.length > 1;\n\n useEffect(() => {\n discoveryApi.getBaseUrl('dev-ai-hub').then(url => setBaseUrl(url));\n }, [discoveryApi]);\n\n const cfg = TOOL_CONFIGS.find(t => t.tool === selectedToolKey) ?? TOOL_CONFIGS[0];\n\n const buildMcpUrl = () => {\n if (!baseUrl) return 'loading...';\n const params = new URLSearchParams();\n params.set('tool', cfg.tool);\n if (selectedProvider) params.set('provider', selectedProvider);\n if (proactiveEnabled) params.set('proactive', 'true');\n return `${baseUrl}/mcp?${params.toString()}`;\n };\n\n const mcpUrl = buildMcpUrl();\n const configSnippet = baseUrl ? cfg.buildConfig(mcpUrl) : '';\n\n const [isDark, setIsDark] = useState(() => {\n if (typeof document === 'undefined') return false;\n return document.documentElement.getAttribute('data-theme-mode') === 'dark' ||\n document.body.getAttribute('data-theme-mode') === 'dark';\n });\n\n useEffect(() => {\n const getIsDark = () =>\n document.documentElement.getAttribute('data-theme-mode') === 'dark' ||\n document.body.getAttribute('data-theme-mode') === 'dark';\n\n const observer = new MutationObserver(() => setIsDark(getIsDark()));\n observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme-mode'] });\n observer.observe(document.body, { attributes: true, attributeFilter: ['data-theme-mode'] });\n return () => observer.disconnect();\n }, []);\n\n return (\n <div className={styles.pageRoot}>\n <Text variant=\"title-small\" weight=\"bold\">Configure MCP Server</Text>\n <Text variant=\"body-small\" color=\"secondary\" className={styles.subtitle}>\n Connect your AI tool to the Dev AI Hub via Model Context Protocol.\n </Text>\n\n <div className={styles.configContent}>\n <Tabs selectedKey={selectedToolKey} onSelectionChange={key => setSelectedToolKey(key as string)}>\n <TabList className={styles.tabBar}>\n {TOOL_CONFIGS.map(t => (\n <Tab key={t.tool} id={t.tool}>\n <span className={styles.tabContent}>\n <ToolIcon tool={t.tool} size={16} />\n <span>{t.label}</span>\n </span>\n </Tab>\n ))}\n </TabList>\n\n {TOOL_CONFIGS.map(t => (\n <TabPanel key={t.tool} id={t.tool}>\n {showProviderFilter && (\n <Box className={styles.providerSection}>\n <Text variant=\"body-x-small\" color=\"secondary\" className={styles.sectionLabel}>\n Scope to Provider\n </Text>\n <Flex className={styles.chipsRow}>\n <ToggleButton\n id=\"all-providers\"\n size=\"small\"\n className={styles.filterChip}\n isSelected={!selectedProvider}\n onChange={() => setSelectedProvider('')}\n style={{\n borderColor: !selectedProvider ? 'var(--bui-fg-primary)' : 'var(--bui-border-1)',\n backgroundColor: !selectedProvider ? 'var(--bui-fg-primary)' : 'transparent',\n color: !selectedProvider ? 'var(--bui-bg-neutral-1)' : 'var(--bui-fg-secondary)',\n }}\n >\n All providers\n </ToggleButton>\n {providers.map(p => {\n const isSelected = selectedProvider === p.id;\n const label = providerLabel(p.target);\n return (\n <ToggleButton\n key={p.id}\n id={p.id}\n size=\"small\"\n className={styles.filterChip}\n iconStart={<RiDatabase2Line size={12} style={{ color: isSelected ? 'var(--bui-bg-neutral-1)' : 'inherit' }} />}\n isSelected={isSelected}\n onChange={() => setSelectedProvider(isSelected ? '' : p.id)}\n style={{\n borderColor: isSelected ? 'var(--bui-fg-primary)' : 'var(--bui-border-1)',\n backgroundColor: isSelected ? 'var(--bui-fg-primary)' : 'transparent',\n color: isSelected ? 'var(--bui-bg-neutral-1)' : 'var(--bui-fg-secondary)',\n }}\n >\n {label}\n </ToggleButton>\n );\n })}\n </Flex>\n </Box>\n )}\n\n <Flex className={styles.proactiveSection}>\n <Flex className={styles.proactiveRow}>\n <Switch\n isSelected={proactiveEnabled}\n onChange={setProactiveEnabled}\n aria-label=\"Proactive suggestions\"\n />\n <Box>\n <Text variant=\"body-small\" weight=\"bold\">Proactive suggestions</Text>\n <Text variant=\"body-x-small\" color=\"secondary\">\n The AI will automatically suggest relevant assets based on your project context.\n Disable if you prefer to search manually.\n </Text>\n </Box>\n </Flex>\n </Flex>\n\n <Box className={styles.urlSection}>\n <Text variant=\"body-x-small\" color=\"secondary\" className={styles.sectionLabel}>\n MCP Endpoint\n </Text>\n <Flex className={styles.urlBox}>\n <Text variant=\"body-small\" className={styles.urlText}>\n {mcpUrl}\n </Text>\n <TooltipTrigger>\n <ButtonIcon\n aria-label={copiedUrl ? 'Copied!' : 'Copy URL'}\n icon={copiedUrl ? <RiCheckLine size={14} style={{ color: 'var(--bui-fg-success)' }} /> : <RiFileCopyLine size={14} />}\n variant=\"tertiary\"\n onPress={() => copyUrl(mcpUrl)}\n />\n <Tooltip>{copiedUrl ? 'Copied!' : 'Copy URL'}</Tooltip>\n </TooltipTrigger>\n </Flex>\n </Box>\n\n <Text variant=\"body-x-small\" color=\"secondary\" className={styles.sectionLabel}>\n {t.file}\n </Text>\n <Text variant=\"body-x-small\" color=\"secondary\" style={{ display: 'block', marginBottom: 'var(--bui-space-2)', marginTop: 'var(--bui-space-1)' }}>\n {t.description}\n </Text>\n <div className={styles.snippetContainer}>\n <pre className={`${styles.snippetPre} ${isDark ? styles.snippetPreDark : styles.snippetPreLight}`}>\n {configSnippet}\n </pre>\n <TooltipTrigger>\n <ButtonIcon\n aria-label=\"Copy config\"\n className={styles.copySnippetButton}\n icon={copiedSnippet ? <RiCheckLine size={14} style={{ color: 'var(--bui-fg-success)' }} /> : <RiFileCopyLine size={14} />}\n variant=\"tertiary\"\n onPress={() => copySnippet(configSnippet)}\n />\n <Tooltip>{copiedSnippet ? 'Copied!' : 'Copy config'}</Tooltip>\n </TooltipTrigger>\n </div>\n\n <Text variant=\"body-x-small\" color=\"secondary\" className={styles.hint}>\n 💡 Omit <code>?tool=</code> from the URL to receive assets for all AI tools.\n {showProviderFilter && ' Omit ?provider= to receive assets from all repositories.'}\n {' '}Proactive suggestions add <code>?proactive=true</code> and register the{' '}\n <code>suggest_assets</code> tool and <code>check_for_assets</code> prompt.\n </Text>\n </TabPanel>\n ))}\n </Tabs>\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAqBA,MAAM,YAAA,GAA6B;AAAA,EACjC;AAAA,IACE,IAAA,EAAM,aAAA;AAAA,IACN,KAAA,EAAO,aAAA;AAAA,IACP,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EAAa,oEAAA;AAAA,IACb,WAAA,EAAa,CAAA,GAAA,KAAO,IAAA,CAAK,SAAA,CAAU;AAAA,MACjC,YAAY,EAAE,YAAA,EAAc,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAI;AAAE,KACpD,EAAG,MAAM,CAAC;AAAA,GACZ;AAAA,EACA;AAAA,IACE,IAAA,EAAM,gBAAA;AAAA,IACN,KAAA,EAAO,gBAAA;AAAA,IACP,IAAA,EAAM,uBAAA;AAAA,IACN,WAAA,EAAa,wEAAA;AAAA,IACb,WAAA,EAAa,CAAA,GAAA,KAAO,IAAA,CAAK,SAAA,CAAU;AAAA,MACjC,mCAAmC,EAAE,YAAA,EAAc,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAI;AAAE,KAC3E,EAAG,MAAM,CAAC;AAAA,GACZ;AAAA,EACA;AAAA,IACE,IAAA,EAAM,eAAA;AAAA,IACN,KAAA,EAAO,eAAA;AAAA,IACP,IAAA,EAAM,oBAAA;AAAA,IACN,WAAA,EAAa,uCAAA;AAAA,IACb,WAAA,EAAa,CAAA,GAAA,KAAO,IAAA,CAAK,SAAA,CAAU;AAAA,MACjC,UAAA,EAAY,EAAE,YAAA,EAAc,EAAE,KAAI;AAAE,KACtC,EAAG,MAAM,CAAC;AAAA;AAEd,CAAA;AAEA,SAAS,cAAc,MAAA,EAAwB;AAC7C,EAAA,OAAO,MAAA,CAAO,MAAM,GAAG,CAAA,CAAE,KAAI,EAAG,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA,IAAK,MAAA;AAC3D;AAEO,SAAS,aAAA,GAAgB;AAC9B,EAAA,MAAM,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,SAAA,KAAc,kBAAA,EAAmB;AAChE,EAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,MAAA,EAAQ,aAAA,KAAkB,kBAAA,EAAmB;AACxE,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,SAAiB,aAAa,CAAA;AAC5E,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,EAAE,CAAA;AACzC,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAiB,EAAE,CAAA;AACnE,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAS,KAAK,CAAA;AAE9D,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,YAAA,EAAa;AACnC,EAAA,MAAM,kBAAA,GAAqB,UAAU,MAAA,GAAS,CAAA;AAE9C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,YAAA,CAAa,WAAW,YAAY,CAAA,CAAE,KAAK,CAAA,GAAA,KAAO,UAAA,CAAW,GAAG,CAAC,CAAA;AAAA,EACnE,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAA,MAAM,GAAA,GAAM,aAAa,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,IAAA,KAAS,eAAe,CAAA,IAAK,YAAA,CAAa,CAAC,CAAA;AAEhF,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,IAAI,CAAC,SAAS,OAAO,YAAA;AACrB,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,IAAA,MAAA,CAAO,GAAA,CAAI,MAAA,EAAQ,GAAA,CAAI,IAAI,CAAA;AAC3B,IAAA,IAAI,gBAAA,EAAkB,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,gBAAgB,CAAA;AAC7D,IAAA,IAAI,gBAAA,EAAkB,MAAA,CAAO,GAAA,CAAI,WAAA,EAAa,MAAM,CAAA;AACpD,IAAA,OAAO,CAAA,EAAG,OAAO,CAAA,KAAA,EAAQ,MAAA,CAAO,UAAU,CAAA,CAAA;AAAA,EAC5C,CAAA;AAEA,EAAA,MAAM,SAAS,WAAA,EAAY;AAC3B,EAAA,MAAM,aAAA,GAAgB,OAAA,GAAU,GAAA,CAAI,WAAA,CAAY,MAAM,CAAA,GAAI,EAAA;AAE1D,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,MAAM;AACzC,IAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,KAAA;AAC5C,IAAA,OAAO,QAAA,CAAS,eAAA,CAAgB,YAAA,CAAa,iBAAiB,CAAA,KAAM,UAClE,QAAA,CAAS,IAAA,CAAK,YAAA,CAAa,iBAAiB,CAAA,KAAM,MAAA;AAAA,EACtD,CAAC,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,SAAA,GAAY,MAChB,QAAA,CAAS,eAAA,CAAgB,YAAA,CAAa,iBAAiB,CAAA,KAAM,MAAA,IAC7D,QAAA,CAAS,IAAA,CAAK,YAAA,CAAa,iBAAiB,CAAA,KAAM,MAAA;AAEpD,IAAA,MAAM,WAAW,IAAI,gBAAA,CAAiB,MAAM,SAAA,CAAU,SAAA,EAAW,CAAC,CAAA;AAClE,IAAA,QAAA,CAAS,OAAA,CAAQ,QAAA,CAAS,eAAA,EAAiB,EAAE,UAAA,EAAY,MAAM,eAAA,EAAiB,CAAC,iBAAiB,CAAA,EAAG,CAAA;AACrG,IAAA,QAAA,CAAS,OAAA,CAAQ,QAAA,CAAS,IAAA,EAAM,EAAE,UAAA,EAAY,MAAM,eAAA,EAAiB,CAAC,iBAAiB,CAAA,EAAG,CAAA;AAC1F,IAAA,OAAO,MAAM,SAAS,UAAA,EAAW;AAAA,EACnC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,QAAA,EACrB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,aAAA,EAAc,MAAA,EAAO,QAAO,QAAA,EAAA,sBAAA,EAAoB,CAAA;AAAA,oBAC9D,GAAA,CAAC,QAAK,OAAA,EAAQ,YAAA,EAAa,OAAM,WAAA,EAAY,SAAA,EAAW,MAAA,CAAO,QAAA,EAAU,QAAA,EAAA,oEAAA,EAEzE,CAAA;AAAA,oBAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,aAAA,EACrB,QAAA,kBAAA,IAAA,CAAC,IAAA,EAAA,EAAK,WAAA,EAAa,eAAA,EAAiB,iBAAA,EAAmB,CAAA,GAAA,KAAO,kBAAA,CAAmB,GAAa,CAAA,EAC5F,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,WAAQ,SAAA,EAAW,MAAA,CAAO,MAAA,EACxB,QAAA,EAAA,YAAA,CAAa,IAAI,CAAA,CAAA,qBAChB,GAAA,CAAC,GAAA,EAAA,EAAiB,EAAA,EAAI,EAAE,IAAA,EACtB,QAAA,kBAAA,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,OAAO,UAAA,EACtB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,QAAA,EAAA,EAAS,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,MAAM,EAAA,EAAI,CAAA;AAAA,wBAClC,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,KAAA,EAAM;AAAA,OAAA,EACjB,CAAA,EAAA,EAJQ,CAAA,CAAE,IAKZ,CACD,CAAA,EACH,CAAA;AAAA,MAEC,aAAa,GAAA,CAAI,CAAA,CAAA,0BACf,QAAA,EAAA,EAAsB,EAAA,EAAI,EAAE,IAAA,EAC1B,QAAA,EAAA;AAAA,QAAA,kBAAA,oBACC,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,eAAA,EACrB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAQ,cAAA,EAAe,KAAA,EAAM,aAAY,SAAA,EAAW,MAAA,CAAO,cAAc,QAAA,EAAA,mBAAA,EAE/E,CAAA;AAAA,0BACA,IAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAW,MAAA,CAAO,QAAA,EACtB,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,YAAA;AAAA,cAAA;AAAA,gBACC,EAAA,EAAG,eAAA;AAAA,gBACH,IAAA,EAAK,OAAA;AAAA,gBACL,WAAW,MAAA,CAAO,UAAA;AAAA,gBAClB,YAAY,CAAC,gBAAA;AAAA,gBACb,QAAA,EAAU,MAAM,mBAAA,CAAoB,EAAE,CAAA;AAAA,gBACtC,KAAA,EAAO;AAAA,kBACL,WAAA,EAAa,CAAC,gBAAA,GAAmB,uBAAA,GAA0B,qBAAA;AAAA,kBAC3D,eAAA,EAAiB,CAAC,gBAAA,GAAmB,uBAAA,GAA0B,aAAA;AAAA,kBAC/D,KAAA,EAAO,CAAC,gBAAA,GAAmB,yBAAA,GAA4B;AAAA,iBACzD;AAAA,gBACD,QAAA,EAAA;AAAA;AAAA,aAED;AAAA,YACC,SAAA,CAAU,IAAI,CAAA,CAAA,KAAK;AAClB,cAAA,MAAM,UAAA,GAAa,qBAAqB,CAAA,CAAE,EAAA;AAC1C,cAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,CAAA,CAAE,MAAM,CAAA;AACpC,cAAA,uBACE,GAAA;AAAA,gBAAC,YAAA;AAAA,gBAAA;AAAA,kBAEC,IAAI,CAAA,CAAE,EAAA;AAAA,kBACN,IAAA,EAAK,OAAA;AAAA,kBACL,WAAW,MAAA,CAAO,UAAA;AAAA,kBAClB,SAAA,kBAAW,GAAA,CAAC,eAAA,EAAA,EAAgB,IAAA,EAAM,EAAA,EAAI,KAAA,EAAO,EAAE,KAAA,EAAO,UAAA,GAAa,yBAAA,GAA4B,SAAA,EAAU,EAAG,CAAA;AAAA,kBAC5G,UAAA;AAAA,kBACA,UAAU,MAAM,mBAAA,CAAoB,UAAA,GAAa,EAAA,GAAK,EAAE,EAAE,CAAA;AAAA,kBAC1D,KAAA,EAAO;AAAA,oBACL,WAAA,EAAa,aAAa,uBAAA,GAA0B,qBAAA;AAAA,oBACpD,eAAA,EAAiB,aAAa,uBAAA,GAA0B,aAAA;AAAA,oBACxD,KAAA,EAAO,aAAa,yBAAA,GAA4B;AAAA,mBAClD;AAAA,kBAEC,QAAA,EAAA;AAAA,iBAAA;AAAA,gBAbI,CAAA,CAAE;AAAA,eAcT;AAAA,YAEJ,CAAC;AAAA,WAAA,EACH;AAAA,SAAA,EACF,CAAA;AAAA,wBAGF,GAAA,CAAC,QAAK,SAAA,EAAW,MAAA,CAAO,kBACtB,QAAA,kBAAA,IAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAW,MAAA,CAAO,YAAA,EACtB,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,UAAA,EAAY,gBAAA;AAAA,cACZ,QAAA,EAAU,mBAAA;AAAA,cACV,YAAA,EAAW;AAAA;AAAA,WACb;AAAA,+BACC,GAAA,EAAA,EACC,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,YAAA,EAAa,MAAA,EAAO,QAAO,QAAA,EAAA,uBAAA,EAAqB,CAAA;AAAA,gCAC7D,IAAA,EAAA,EAAK,OAAA,EAAQ,cAAA,EAAe,KAAA,EAAM,aAAY,QAAA,EAAA,4HAAA,EAG/C;AAAA,WAAA,EACF;AAAA,SAAA,EACF,CAAA,EACF,CAAA;AAAA,wBAEA,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,UAAA,EACrB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAQ,cAAA,EAAe,KAAA,EAAM,aAAY,SAAA,EAAW,MAAA,CAAO,cAAc,QAAA,EAAA,cAAA,EAE/E,CAAA;AAAA,0BACA,IAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAW,MAAA,CAAO,MAAA,EACtB,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,QAAK,OAAA,EAAQ,YAAA,EAAa,SAAA,EAAW,MAAA,CAAO,SAC1C,QAAA,EAAA,MAAA,EACH,CAAA;AAAA,iCACC,cAAA,EAAA,EACC,QAAA,EAAA;AAAA,8BAAA,GAAA;AAAA,gBAAC,UAAA;AAAA,gBAAA;AAAA,kBACC,YAAA,EAAY,YAAY,SAAA,GAAY,UAAA;AAAA,kBACpC,IAAA,EAAM,SAAA,mBAAY,GAAA,CAAC,WAAA,EAAA,EAAY,MAAM,EAAA,EAAI,KAAA,EAAO,EAAE,KAAA,EAAO,yBAAwB,EAAG,CAAA,mBAAK,GAAA,CAAC,cAAA,EAAA,EAAe,MAAM,EAAA,EAAI,CAAA;AAAA,kBACnH,OAAA,EAAQ,UAAA;AAAA,kBACR,OAAA,EAAS,MAAM,OAAA,CAAQ,MAAM;AAAA;AAAA,eAC/B;AAAA,8BACA,GAAA,CAAC,OAAA,EAAA,EAAS,QAAA,EAAA,SAAA,GAAY,SAAA,GAAY,UAAA,EAAW;AAAA,aAAA,EAC/C;AAAA,WAAA,EACF;AAAA,SAAA,EACF,CAAA;AAAA,wBAEA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAQ,cAAA,EAAe,KAAA,EAAM,aAAY,SAAA,EAAW,MAAA,CAAO,YAAA,EAC9D,QAAA,EAAA,CAAA,CAAE,IAAA,EACL,CAAA;AAAA,4BACC,IAAA,EAAA,EAAK,OAAA,EAAQ,cAAA,EAAe,KAAA,EAAM,aAAY,KAAA,EAAO,EAAE,OAAA,EAAS,OAAA,EAAS,cAAc,oBAAA,EAAsB,SAAA,EAAW,oBAAA,EAAqB,EAC3I,YAAE,WAAA,EACL,CAAA;AAAA,wBACA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,gBAAA,EACrB,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,EAAG,MAAA,CAAO,UAAU,CAAA,CAAA,EAAI,MAAA,GAAS,MAAA,CAAO,cAAA,GAAiB,MAAA,CAAO,eAAe,CAAA,CAAA,EAC5F,QAAA,EAAA,aAAA,EACH,CAAA;AAAA,+BACC,cAAA,EAAA,EACC,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,UAAA;AAAA,cAAA;AAAA,gBACC,YAAA,EAAW,aAAA;AAAA,gBACX,WAAW,MAAA,CAAO,iBAAA;AAAA,gBAClB,IAAA,EAAM,aAAA,mBAAgB,GAAA,CAAC,WAAA,EAAA,EAAY,MAAM,EAAA,EAAI,KAAA,EAAO,EAAE,KAAA,EAAO,yBAAwB,EAAG,CAAA,mBAAK,GAAA,CAAC,cAAA,EAAA,EAAe,MAAM,EAAA,EAAI,CAAA;AAAA,gBACvH,OAAA,EAAQ,UAAA;AAAA,gBACR,OAAA,EAAS,MAAM,WAAA,CAAY,aAAa;AAAA;AAAA,aAC1C;AAAA,4BACA,GAAA,CAAC,OAAA,EAAA,EAAS,QAAA,EAAA,aAAA,GAAgB,SAAA,GAAY,aAAA,EAAc;AAAA,WAAA,EACtD;AAAA,SAAA,EACF,CAAA;AAAA,wBAEA,IAAA,CAAC,QAAK,OAAA,EAAQ,cAAA,EAAe,OAAM,WAAA,EAAY,SAAA,EAAW,OAAO,IAAA,EAAM,QAAA,EAAA;AAAA,UAAA,iBAAA;AAAA,0BAC7D,GAAA,CAAC,UAAK,QAAA,EAAA,QAAA,EAAM,CAAA;AAAA,UAAO,mDAAA;AAAA,UAC1B,kBAAA,IAAsB,2DAAA;AAAA,UACtB,GAAA;AAAA,UAAI,4BAAA;AAAA,0BAA0B,GAAA,CAAC,UAAK,QAAA,EAAA,iBAAA,EAAe,CAAA;AAAA,UAAO,mBAAA;AAAA,UAAkB,GAAA;AAAA,0BAC7E,GAAA,CAAC,UAAK,QAAA,EAAA,gBAAA,EAAc,CAAA;AAAA,UAAO,YAAA;AAAA,0BAAU,GAAA,CAAC,UAAK,QAAA,EAAA,kBAAA,EAAgB,CAAA;AAAA,UAAO;AAAA,SAAA,EACpE;AAAA,OAAA,EAAA,EA/Ga,CAAA,CAAE,IAgHjB,CACD;AAAA,KAAA,EACH,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,8 @@
1
+ import styleInject from '../../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = "@layer components {\n .McpConfigPage_pageRoot__fc0e9afedd {\n padding: var(--bui-space-6);\n }\n\n .McpConfigPage_subtitle__fc0e9afedd {\n margin-top: var(--bui-space-1);\n display: block;\n }\n\n .McpConfigPage_configContent__fc0e9afedd {\n margin-top: var(--bui-space-6);\n max-width: 720px;\n }\n\n .McpConfigPage_tabBar__fc0e9afedd {\n margin-bottom: var(--bui-space-4);\n border-bottom: 1px solid var(--bui-border-1);\n }\n\n .McpConfigPage_tabContent__fc0e9afedd {\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n }\n\n .McpConfigPage_sectionLabel__fc0e9afedd {\n text-transform: uppercase;\n letter-spacing: 0.5px;\n display: block;\n margin-bottom: 6px;\n font-weight: 600;\n }\n\n .McpConfigPage_providerSection__fc0e9afedd {\n margin-bottom: var(--bui-space-4);\n }\n\n .McpConfigPage_chipsRow__fc0e9afedd {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n }\n\n .McpConfigPage_filterChip__fc0e9afedd {\n font-weight: 600;\n font-size: 0.75rem;\n border-radius: var(--bui-radius-2);\n border: 1.5px solid;\n transition: all 0.15s ease;\n cursor: pointer;\n }\n\n .McpConfigPage_proactiveSection__fc0e9afedd {\n margin-bottom: var(--bui-space-4);\n }\n\n .McpConfigPage_proactiveRow__fc0e9afedd {\n display: flex;\n align-items: flex-start;\n gap: var(--bui-space-2);\n }\n\n .McpConfigPage_urlSection__fc0e9afedd {\n margin-bottom: var(--bui-space-4);\n }\n\n .McpConfigPage_urlBox__fc0e9afedd {\n display: flex;\n align-items: center;\n gap: var(--bui-space-2);\n margin-top: var(--bui-space-1);\n padding: var(--bui-space-2) var(--bui-space-3);\n border-radius: var(--bui-radius-2);\n border: 1px solid var(--bui-border-1);\n background-color: var(--bui-bg-neutral-1-hover);\n }\n\n .McpConfigPage_urlText__fc0e9afedd {\n flex: 1;\n font-family: monospace;\n font-size: 0.8rem;\n word-break: break-all;\n }\n\n .McpConfigPage_snippetContainer__fc0e9afedd {\n position: relative;\n }\n\n .McpConfigPage_snippetPre__fc0e9afedd {\n margin: 0;\n padding: var(--bui-space-4);\n border-radius: var(--bui-radius-2);\n border: 1px solid var(--bui-border-1);\n font-family: monospace;\n font-size: 0.8rem;\n overflow-x: auto;\n white-space: pre;\n }\n\n .McpConfigPage_snippetPreLight__fc0e9afedd {\n background-color: #f6f8fa;\n color: #24292f;\n }\n\n .McpConfigPage_snippetPreDark__fc0e9afedd {\n background-color: #1E1E1E;\n color: #DCDDE1;\n }\n\n .McpConfigPage_copySnippetButton__fc0e9afedd {\n position: absolute;\n top: 8px;\n right: 8px;\n }\n\n .McpConfigPage_hint__fc0e9afedd {\n display: block;\n margin-top: var(--bui-space-3);\n }\n}\n";
4
+ var styles = {"pageRoot":"McpConfigPage_pageRoot__fc0e9afedd","subtitle":"McpConfigPage_subtitle__fc0e9afedd","configContent":"McpConfigPage_configContent__fc0e9afedd","tabBar":"McpConfigPage_tabBar__fc0e9afedd","tabContent":"McpConfigPage_tabContent__fc0e9afedd","sectionLabel":"McpConfigPage_sectionLabel__fc0e9afedd","providerSection":"McpConfigPage_providerSection__fc0e9afedd","chipsRow":"McpConfigPage_chipsRow__fc0e9afedd","filterChip":"McpConfigPage_filterChip__fc0e9afedd","proactiveSection":"McpConfigPage_proactiveSection__fc0e9afedd","proactiveRow":"McpConfigPage_proactiveRow__fc0e9afedd","urlSection":"McpConfigPage_urlSection__fc0e9afedd","urlBox":"McpConfigPage_urlBox__fc0e9afedd","urlText":"McpConfigPage_urlText__fc0e9afedd","snippetContainer":"McpConfigPage_snippetContainer__fc0e9afedd","snippetPre":"McpConfigPage_snippetPre__fc0e9afedd","snippetPreLight":"McpConfigPage_snippetPreLight__fc0e9afedd","snippetPreDark":"McpConfigPage_snippetPreDark__fc0e9afedd","copySnippetButton":"McpConfigPage_copySnippetButton__fc0e9afedd","hint":"McpConfigPage_hint__fc0e9afedd"};
5
+ styleInject(css_248z);
6
+
7
+ export { styles as default };
8
+ //# sourceMappingURL=McpConfigPage.module.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpConfigPage.module.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,6 @@
1
+ import { McpConfigPage } from './McpConfigPage.esm.js';
2
+
3
+
4
+
5
+ export { McpConfigPage };
6
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,7 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import SvgIcon from '@mui/material/SvgIcon';
3
- import AllInclusiveIcon from '@mui/icons-material/AllInclusive';
4
- import NearMeIcon from '@mui/icons-material/NearMe';
2
+ import { RiInfinityLine, RiNavigationLine } from '@remixicon/react';
5
3
  import { siGooglegemini, siGithub, siAnthropic } from 'simple-icons';
6
4
 
7
5
  const TOOL_ICON = {
@@ -9,29 +7,43 @@ const TOOL_ICON = {
9
7
  "github-copilot": { ...siGithub, label: "GitHub Copilot" },
10
8
  "google-gemini": { ...siGooglegemini, label: "Google Gemini" }
11
9
  };
12
- function ToolIcon({ tool, branded = true, sx, ...props }) {
10
+ function ToolIcon({ tool, branded = true, className, style, size = 20 }) {
13
11
  if (tool === "all") {
14
- return /* @__PURE__ */ jsx(AllInclusiveIcon, { ...props, sx: { color: "text.secondary", ...sx }, titleAccess: "Universal" });
12
+ return /* @__PURE__ */ jsx(
13
+ RiInfinityLine,
14
+ {
15
+ size,
16
+ className,
17
+ style: { color: "var(--bui-fg-secondary)", ...style },
18
+ "aria-label": "Universal"
19
+ }
20
+ );
15
21
  }
16
22
  if (tool === "cursor") {
17
23
  return /* @__PURE__ */ jsx(
18
- NearMeIcon,
24
+ RiNavigationLine,
19
25
  {
20
- ...props,
21
- sx: { color: branded ? "text.primary" : "inherit", ...sx },
22
- titleAccess: "Cursor"
26
+ size,
27
+ className,
28
+ style: { color: branded ? "var(--bui-fg-primary)" : "inherit", ...style },
29
+ "aria-label": "Cursor"
23
30
  }
24
31
  );
25
32
  }
26
33
  const cfg = TOOL_ICON[tool];
27
34
  if (!cfg) return null;
28
35
  return /* @__PURE__ */ jsx(
29
- SvgIcon,
36
+ "svg",
30
37
  {
31
- ...props,
32
- sx: { color: branded ? `#${cfg.hex}` : "inherit", ...sx },
33
- titleAccess: cfg.label,
38
+ xmlns: "http://www.w3.org/2000/svg",
34
39
  viewBox: "0 0 24 24",
40
+ width: size,
41
+ height: size,
42
+ fill: "currentColor",
43
+ className,
44
+ style: { color: branded ? `#${cfg.hex}` : "inherit", ...style },
45
+ "aria-label": cfg.label,
46
+ role: "img",
35
47
  children: /* @__PURE__ */ jsx("path", { d: cfg.path })
36
48
  }
37
49
  );
@@ -1 +1 @@
1
- {"version":3,"file":"ToolIcon.esm.js","sources":["../../../src/components/ToolIcon/ToolIcon.tsx"],"sourcesContent":["import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';\nimport AllInclusiveIcon from '@mui/icons-material/AllInclusive';\nimport NearMeIcon from '@mui/icons-material/NearMe';\nimport { siAnthropic, siGithub, siGooglegemini } from 'simple-icons';\nimport type { AiTool } from '@nospt/plugin-dev-ai-hub-common';\n\ntype SvgTool = Exclude<AiTool, 'all' | 'cursor'>;\n\nconst TOOL_ICON: Record<SvgTool, { path: string; hex: string; label: string }> = {\n 'claude-code': { ...siAnthropic, label: 'Claude Code' },\n 'github-copilot': { ...siGithub, label: 'GitHub Copilot' },\n 'google-gemini': { ...siGooglegemini, label: 'Google Gemini' },\n};\n\ninterface ToolIconProps extends Omit<SvgIconProps, 'color'> {\n tool: AiTool;\n /** Use the brand's official color. Defaults to true. */\n branded?: boolean;\n}\n\nexport function ToolIcon({ tool, branded = true, sx, ...props }: ToolIconProps) {\n if (tool === 'all') {\n return <AllInclusiveIcon {...props} sx={{ color: 'text.secondary', ...sx }} titleAccess=\"Universal\" />;\n }\n\n if (tool === 'cursor') {\n return (\n <NearMeIcon\n {...props}\n sx={{ color: branded ? 'text.primary' : 'inherit', ...sx }}\n titleAccess=\"Cursor\"\n />\n );\n }\n\n const cfg = TOOL_ICON[tool as SvgTool];\n if (!cfg) return null;\n\n return (\n <SvgIcon\n {...props}\n sx={{ color: branded ? `#${cfg.hex}` : 'inherit', ...sx }}\n titleAccess={cfg.label}\n viewBox=\"0 0 24 24\"\n >\n <path d={cfg.path} />\n </SvgIcon>\n );\n}\n"],"names":[],"mappings":";;;;;;AAQA,MAAM,SAAA,GAA2E;AAAA,EAC/E,aAAA,EAAkB,EAAE,GAAG,WAAA,EAAgB,OAAO,aAAA,EAAc;AAAA,EAC5D,gBAAA,EAAkB,EAAE,GAAG,QAAA,EAAgB,OAAO,gBAAA,EAAiB;AAAA,EAC/D,eAAA,EAAkB,EAAE,GAAG,cAAA,EAAgB,OAAO,eAAA;AAChD,CAAA;AAQO,SAAS,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,GAAU,MAAM,EAAA,EAAI,GAAG,OAAM,EAAkB;AAC9E,EAAA,IAAI,SAAS,KAAA,EAAO;AAClB,IAAA,uBAAO,GAAA,CAAC,gBAAA,EAAA,EAAkB,GAAG,KAAA,EAAO,EAAA,EAAI,EAAE,KAAA,EAAO,gBAAA,EAAkB,GAAG,EAAA,EAAG,EAAG,WAAA,EAAY,WAAA,EAAY,CAAA;AAAA,EACtG;AAEA,EAAA,IAAI,SAAS,QAAA,EAAU;AACrB,IAAA,uBACE,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACE,GAAG,KAAA;AAAA,QACJ,IAAI,EAAE,KAAA,EAAO,UAAU,cAAA,GAAiB,SAAA,EAAW,GAAG,EAAA,EAAG;AAAA,QACzD,WAAA,EAAY;AAAA;AAAA,KACd;AAAA,EAEJ;AAEA,EAAA,MAAM,GAAA,GAAM,UAAU,IAAe,CAAA;AACrC,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AAEjB,EAAA,uBACE,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACE,GAAG,KAAA;AAAA,MACJ,EAAA,EAAI,EAAE,KAAA,EAAO,OAAA,GAAU,CAAA,CAAA,EAAI,IAAI,GAAG,CAAA,CAAA,GAAK,SAAA,EAAW,GAAG,EAAA,EAAG;AAAA,MACxD,aAAa,GAAA,CAAI,KAAA;AAAA,MACjB,OAAA,EAAQ,WAAA;AAAA,MAER,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAG,GAAA,CAAI,IAAA,EAAM;AAAA;AAAA,GACrB;AAEJ;;;;"}
1
+ {"version":3,"file":"ToolIcon.esm.js","sources":["../../../src/components/ToolIcon/ToolIcon.tsx"],"sourcesContent":["import type { CSSProperties } from 'react';\nimport { RiInfinityLine, RiNavigationLine } from '@remixicon/react';\nimport { siAnthropic, siGithub, siGooglegemini } from 'simple-icons';\nimport type { AiTool } from '@nospt/plugin-dev-ai-hub-common';\n\ntype SvgTool = Exclude<AiTool, 'all' | 'cursor'>;\n\nconst TOOL_ICON: Record<SvgTool, { path: string; hex: string; label: string }> = {\n 'claude-code': { ...siAnthropic, label: 'Claude Code' },\n 'github-copilot': { ...siGithub, label: 'GitHub Copilot' },\n 'google-gemini': { ...siGooglegemini, label: 'Google Gemini' },\n};\n\ninterface ToolIconProps {\n tool: AiTool;\n /** Use the brand's official color. Defaults to true. */\n branded?: boolean;\n className?: string;\n style?: CSSProperties;\n /** Icon size in pixels. Defaults to 20. */\n size?: number;\n}\n\nexport function ToolIcon({ tool, branded = true, className, style, size = 20 }: ToolIconProps) {\n if (tool === 'all') {\n return (\n <RiInfinityLine\n size={size}\n className={className}\n style={{ color: 'var(--bui-fg-secondary)', ...style }}\n aria-label=\"Universal\"\n />\n );\n }\n\n if (tool === 'cursor') {\n return (\n <RiNavigationLine\n size={size}\n className={className}\n style={{ color: branded ? 'var(--bui-fg-primary)' : 'inherit', ...style }}\n aria-label=\"Cursor\"\n />\n );\n }\n\n const cfg = TOOL_ICON[tool as SvgTool];\n if (!cfg) return null;\n\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"currentColor\"\n className={className}\n style={{ color: branded ? `#${cfg.hex}` : 'inherit', ...style }}\n aria-label={cfg.label}\n role=\"img\"\n >\n <path d={cfg.path} />\n </svg>\n );\n}\n"],"names":[],"mappings":";;;;AAOA,MAAM,SAAA,GAA2E;AAAA,EAC/E,aAAA,EAAkB,EAAE,GAAG,WAAA,EAAgB,OAAO,aAAA,EAAc;AAAA,EAC5D,gBAAA,EAAkB,EAAE,GAAG,QAAA,EAAgB,OAAO,gBAAA,EAAiB;AAAA,EAC/D,eAAA,EAAkB,EAAE,GAAG,cAAA,EAAgB,OAAO,eAAA;AAChD,CAAA;AAYO,SAAS,QAAA,CAAS,EAAE,IAAA,EAAM,OAAA,GAAU,MAAM,SAAA,EAAW,KAAA,EAAO,IAAA,GAAO,EAAA,EAAG,EAAkB;AAC7F,EAAA,IAAI,SAAS,KAAA,EAAO;AAClB,IAAA,uBACE,GAAA;AAAA,MAAC,cAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,SAAA;AAAA,QACA,KAAA,EAAO,EAAE,KAAA,EAAO,yBAAA,EAA2B,GAAG,KAAA,EAAM;AAAA,QACpD,YAAA,EAAW;AAAA;AAAA,KACb;AAAA,EAEJ;AAEA,EAAA,IAAI,SAAS,QAAA,EAAU;AACrB,IAAA,uBACE,GAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,IAAA;AAAA,QACA,SAAA;AAAA,QACA,OAAO,EAAE,KAAA,EAAO,UAAU,uBAAA,GAA0B,SAAA,EAAW,GAAG,KAAA,EAAM;AAAA,QACxE,YAAA,EAAW;AAAA;AAAA,KACb;AAAA,EAEJ;AAEA,EAAA,MAAM,GAAA,GAAM,UAAU,IAAe,CAAA;AACrC,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AAEjB,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO,IAAA;AAAA,MACP,MAAA,EAAQ,IAAA;AAAA,MACR,IAAA,EAAK,cAAA;AAAA,MACL,SAAA;AAAA,MACA,KAAA,EAAO,EAAE,KAAA,EAAO,OAAA,GAAU,CAAA,CAAA,EAAI,IAAI,GAAG,CAAA,CAAA,GAAK,SAAA,EAAW,GAAG,KAAA,EAAM;AAAA,MAC9D,cAAY,GAAA,CAAI,KAAA;AAAA,MAChB,IAAA,EAAK,KAAA;AAAA,MAEL,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAG,GAAA,CAAI,IAAA,EAAM;AAAA;AAAA,GACrB;AAEJ;;;;"}
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { AssetListFilter, AiAssetListResponse, AiAsset, AiHubProvider, AiHubStat
5
5
 
6
6
  declare const devAiHubPlugin: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{
7
7
  root: _backstage_frontend_plugin_api.RouteRef<undefined>;
8
+ mcpConfig: _backstage_frontend_plugin_api.RouteRef<undefined>;
8
9
  }, {}, {
9
10
  "api:dev-ai-hub": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
10
11
  kind: "api";
@@ -18,8 +19,12 @@ declare const devAiHubPlugin: _backstage_frontend_plugin_api.OverridableFrontend
18
19
  "nav-item:dev-ai-hub": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
19
20
  kind: "nav-item";
20
21
  name: undefined;
21
- config: {};
22
- configInput: {};
22
+ config: {
23
+ title: string | undefined;
24
+ };
25
+ configInput: {
26
+ title?: string | undefined;
27
+ };
23
28
  output: _backstage_frontend_plugin_api.ExtensionDataRef<{
24
29
  title: string;
25
30
  icon: _backstage_frontend_plugin_api.IconComponent;
@@ -40,8 +45,8 @@ declare const devAiHubPlugin: _backstage_frontend_plugin_api.OverridableFrontend
40
45
  title: string | undefined;
41
46
  };
42
47
  configInput: {
43
- title?: string | undefined;
44
48
  path?: string | undefined;
49
+ title?: string | undefined;
45
50
  };
46
51
  output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
47
52
  optional: true;
@@ -64,7 +69,6 @@ declare const devAiHubPlugin: _backstage_frontend_plugin_api.OverridableFrontend
64
69
  }>;
65
70
  };
66
71
  params: {
67
- defaultPath?: [Error: `Use the 'path' param instead`];
68
72
  path: string;
69
73
  title?: string;
70
74
  icon?: _backstage_frontend_plugin_api.IconElement;
@@ -99,6 +103,7 @@ interface DevAiHubApi {
99
103
  }
100
104
 
101
105
  declare const rootRouteRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
106
+ declare const mcpConfigRouteRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
102
107
 
103
- export { DevAiHubPage, devAiHubApiRef, devAiHubPlugin, rootRouteRef };
108
+ export { DevAiHubPage, devAiHubApiRef, devAiHubPlugin, mcpConfigRouteRef, rootRouteRef };
104
109
  export type { DevAiHubApi };
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { devAiHubPlugin } from './plugin.esm.js';
2
2
  export { DevAiHubPage } from './pluginLegacy.esm.js';
3
3
  export { devAiHubApiRef } from './api/DevAiHubClient.esm.js';
4
- export { rootRouteRef } from './routes.esm.js';
4
+ export { mcpConfigRouteRef, rootRouteRef } from './routes.esm.js';
5
5
  //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1,29 @@
1
+ function styleInject(css, ref) {
2
+ if ( ref === void 0 ) ref = {};
3
+ var insertAt = ref.insertAt;
4
+
5
+ if (!css || typeof document === 'undefined') { return; }
6
+
7
+ var head = document.head || document.getElementsByTagName('head')[0];
8
+ var style = document.createElement('style');
9
+ style.type = 'text/css';
10
+
11
+ if (insertAt === 'top') {
12
+ if (head.firstChild) {
13
+ head.insertBefore(style, head.firstChild);
14
+ } else {
15
+ head.appendChild(style);
16
+ }
17
+ } else {
18
+ head.appendChild(style);
19
+ }
20
+
21
+ if (style.styleSheet) {
22
+ style.styleSheet.cssText = css;
23
+ } else {
24
+ style.appendChild(document.createTextNode(css));
25
+ }
26
+ }
27
+
28
+ export { styleInject as default };
29
+ //# sourceMappingURL=style-inject.es.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style-inject.es.esm.js","sources":["../../../../../../node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n"],"names":[],"mappings":"AAAA,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,EAAE,KAAK,GAAG,KAAK,MAAM,GAAG,GAAG,GAAG,EAAE;AAChC,EAAE,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ;;AAE7B,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,EAAE,OAAO,CAAC;;AAEzD,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,EAAE,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AAC7C,EAAE,KAAK,CAAC,IAAI,GAAG,UAAU;;AAEzB,EAAE,IAAI,QAAQ,KAAK,KAAK,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC;AAC/C,IAAI,CAAC,MAAM;AACX,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC7B,IAAI;AACJ,EAAE,CAAC,MAAM;AACT,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC3B,EAAE;;AAEF,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE;AACxB,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG;AAClC,EAAE,CAAC,MAAM;AACT,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;AACnD,EAAE;AACF;;;;","x_google_ignoreList":[0]}
@@ -1,13 +1,14 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { createFrontendPlugin, ApiBlueprint, createApiFactory, fetchApiRef, discoveryApiRef, PageBlueprint, NavItemBlueprint } from '@backstage/frontend-plugin-api';
2
+ import { createFrontendPlugin, ApiBlueprint, createApiFactory, fetchApiRef, discoveryApiRef, PageBlueprint, SubPageBlueprint, NavItemBlueprint } from '@backstage/frontend-plugin-api';
3
3
  import HubIcon from '@mui/icons-material/Hub';
4
4
  import { DevAiHubClient, devAiHubApiRef } from './api/DevAiHubClient.esm.js';
5
- import { rootRouteRef } from './routes.esm.js';
5
+ import { mcpConfigRouteRef, rootRouteRef } from './routes.esm.js';
6
6
 
7
7
  const devAiHubPlugin = createFrontendPlugin({
8
8
  pluginId: "dev-ai-hub",
9
9
  routes: {
10
- root: rootRouteRef
10
+ root: rootRouteRef,
11
+ mcpConfig: mcpConfigRouteRef
11
12
  },
12
13
  extensions: [
13
14
  ApiBlueprint.make({
@@ -22,10 +23,27 @@ const devAiHubPlugin = createFrontendPlugin({
22
23
  PageBlueprint.make({
23
24
  params: {
24
25
  path: "/dev-ai-hub",
25
- routeRef: rootRouteRef,
26
+ title: "Dev AI Hub",
27
+ routeRef: rootRouteRef
28
+ }
29
+ }),
30
+ SubPageBlueprint.make({
31
+ name: "browse",
32
+ params: {
33
+ path: "browse",
34
+ title: "Browse",
26
35
  loader: () => import('./components/DevAiHubPage/index.esm.js').then((m) => /* @__PURE__ */ jsx(m.DevAiHubPage, {}))
27
36
  }
28
37
  }),
38
+ SubPageBlueprint.make({
39
+ name: "mcp-config",
40
+ params: {
41
+ path: "mcp-config",
42
+ title: "Configure MCP",
43
+ routeRef: mcpConfigRouteRef,
44
+ loader: () => import('./components/McpConfigPage/index.esm.js').then((m) => /* @__PURE__ */ jsx(m.McpConfigPage, {}))
45
+ }
46
+ }),
29
47
  NavItemBlueprint.make({
30
48
  params: {
31
49
  title: "AI Hub",
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.tsx"],"sourcesContent":["import {\n createFrontendPlugin,\n PageBlueprint,\n ApiBlueprint,\n NavItemBlueprint,\n createApiFactory,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport HubIcon from '@mui/icons-material/Hub';\nimport { devAiHubApiRef, DevAiHubClient } from './api/DevAiHubClient';\nimport { rootRouteRef } from './routes';\n\nexport const devAiHubPlugin = createFrontendPlugin({\n pluginId: 'dev-ai-hub',\n routes: {\n root: rootRouteRef,\n },\n extensions: [\n ApiBlueprint.make({\n params: defineParams =>\n defineParams(\n createApiFactory({\n api: devAiHubApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new DevAiHubClient(discoveryApi, fetchApi),\n }),\n ),\n }),\n PageBlueprint.make({\n params: {\n path: '/dev-ai-hub',\n routeRef: rootRouteRef,\n loader: () =>\n import('./components/DevAiHubPage').then(m => <m.DevAiHubPage />),\n },\n }),\n NavItemBlueprint.make({\n params: {\n title: 'AI Hub',\n routeRef: rootRouteRef,\n icon: HubIcon,\n },\n }),\n ],\n});\n"],"names":[],"mappings":";;;;;;AAaO,MAAM,iBAAiB,oBAAA,CAAqB;AAAA,EACjD,QAAA,EAAU,YAAA;AAAA,EACV,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM;AAAA,GACR;AAAA,EACA,UAAA,EAAY;AAAA,IACV,aAAa,IAAA,CAAK;AAAA,MAChB,QAAQ,CAAA,YAAA,KACN,YAAA;AAAA,QACE,gBAAA,CAAiB;AAAA,UACf,GAAA,EAAK,cAAA;AAAA,UACL,IAAA,EAAM,EAAE,YAAA,EAAc,eAAA,EAAiB,UAAU,WAAA,EAAY;AAAA,UAC7D,OAAA,EAAS,CAAC,EAAE,YAAA,EAAc,UAAS,KACjC,IAAI,cAAA,CAAe,YAAA,EAAc,QAAQ;AAAA,SAC5C;AAAA;AACH,KACH,CAAA;AAAA,IACD,cAAc,IAAA,CAAK;AAAA,MACjB,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,aAAA;AAAA,QACN,QAAA,EAAU,YAAA;AAAA,QACV,MAAA,EAAQ,MACN,OAAO,wCAA2B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,YAAA,EAAF,EAAe,CAAE;AAAA;AACpE,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,MAAA,EAAQ;AAAA,QACN,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,YAAA;AAAA,QACV,IAAA,EAAM;AAAA;AACR,KACD;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.tsx"],"sourcesContent":["import {\n createFrontendPlugin,\n PageBlueprint,\n SubPageBlueprint,\n ApiBlueprint,\n NavItemBlueprint,\n createApiFactory,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport HubIcon from '@mui/icons-material/Hub';\nimport { devAiHubApiRef, DevAiHubClient } from './api/DevAiHubClient';\nimport { rootRouteRef, mcpConfigRouteRef } from './routes';\n\nexport const devAiHubPlugin = createFrontendPlugin({\n pluginId: 'dev-ai-hub',\n routes: {\n root: rootRouteRef,\n mcpConfig: mcpConfigRouteRef,\n },\n extensions: [\n ApiBlueprint.make({\n params: defineParams =>\n defineParams(\n createApiFactory({\n api: devAiHubApiRef,\n deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef },\n factory: ({ discoveryApi, fetchApi }) =>\n new DevAiHubClient(discoveryApi, fetchApi),\n }),\n ),\n }),\n PageBlueprint.make({\n params: {\n path: '/dev-ai-hub',\n title: 'Dev AI Hub',\n routeRef: rootRouteRef,\n },\n }),\n SubPageBlueprint.make({\n name: 'browse',\n params: {\n path: 'browse',\n title: 'Browse',\n loader: () =>\n import('./components/DevAiHubPage').then(m => <m.DevAiHubPage />),\n },\n }),\n SubPageBlueprint.make({\n name: 'mcp-config',\n params: {\n path: 'mcp-config',\n title: 'Configure MCP',\n routeRef: mcpConfigRouteRef,\n loader: () =>\n import('./components/McpConfigPage').then(m => <m.McpConfigPage />),\n },\n }),\n NavItemBlueprint.make({\n params: {\n title: 'AI Hub',\n routeRef: rootRouteRef,\n icon: HubIcon,\n },\n }),\n ],\n});\n"],"names":[],"mappings":";;;;;;AAcO,MAAM,iBAAiB,oBAAA,CAAqB;AAAA,EACjD,QAAA,EAAU,YAAA;AAAA,EACV,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,YAAA;AAAA,IACN,SAAA,EAAW;AAAA,GACb;AAAA,EACA,UAAA,EAAY;AAAA,IACV,aAAa,IAAA,CAAK;AAAA,MAChB,QAAQ,CAAA,YAAA,KACN,YAAA;AAAA,QACE,gBAAA,CAAiB;AAAA,UACf,GAAA,EAAK,cAAA;AAAA,UACL,IAAA,EAAM,EAAE,YAAA,EAAc,eAAA,EAAiB,UAAU,WAAA,EAAY;AAAA,UAC7D,OAAA,EAAS,CAAC,EAAE,YAAA,EAAc,UAAS,KACjC,IAAI,cAAA,CAAe,YAAA,EAAc,QAAQ;AAAA,SAC5C;AAAA;AACH,KACH,CAAA;AAAA,IACD,cAAc,IAAA,CAAK;AAAA,MACjB,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,aAAA;AAAA,QACN,KAAA,EAAO,YAAA;AAAA,QACP,QAAA,EAAU;AAAA;AACZ,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,IAAA,EAAM,QAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,QAAA;AAAA,QACN,KAAA,EAAO,QAAA;AAAA,QACP,MAAA,EAAQ,MACN,OAAO,wCAA2B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,YAAA,EAAF,EAAe,CAAE;AAAA;AACpE,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,YAAA;AAAA,QACN,KAAA,EAAO,eAAA;AAAA,QACP,QAAA,EAAU,iBAAA;AAAA,QACV,MAAA,EAAQ,MACN,OAAO,yCAA4B,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,aAAA,EAAF,EAAgB,CAAE;AAAA;AACtE,KACD,CAAA;AAAA,IACD,iBAAiB,IAAA,CAAK;AAAA,MACpB,MAAA,EAAQ;AAAA,QACN,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,YAAA;AAAA,QACV,IAAA,EAAM;AAAA;AACR,KACD;AAAA;AAEL,CAAC;;;;"}
@@ -1,6 +1,7 @@
1
1
  import { createRouteRef } from '@backstage/frontend-plugin-api';
2
2
 
3
3
  const rootRouteRef = createRouteRef();
4
+ const mcpConfigRouteRef = createRouteRef();
4
5
 
5
- export { rootRouteRef };
6
+ export { mcpConfigRouteRef, rootRouteRef };
6
7
  //# sourceMappingURL=routes.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes.esm.js","sources":["../src/routes.ts"],"sourcesContent":["import { createRouteRef } from '@backstage/frontend-plugin-api';\n\nexport const rootRouteRef = createRouteRef();\n"],"names":[],"mappings":";;AAEO,MAAM,eAAe,cAAA;;;;"}
1
+ {"version":3,"file":"routes.esm.js","sources":["../src/routes.ts"],"sourcesContent":["import { createRouteRef } from '@backstage/frontend-plugin-api';\n\nexport const rootRouteRef = createRouteRef();\nexport const mcpConfigRouteRef = createRouteRef();\n"],"names":[],"mappings":";;AAEO,MAAM,eAAe,cAAA;AACrB,MAAM,oBAAoB,cAAA;;;;"}
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@nospt/plugin-dev-ai-hub",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Frontend plugin for Dev AI Hub",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.esm.js",
7
7
  "types": "./dist/index.d.ts",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/nosportugal/backstage-plugin-dev-ai-hub"
11
+ },
8
12
  "publishConfig": {
9
13
  "access": "public"
10
14
  },
@@ -41,35 +45,41 @@
41
45
  "lint": "backstage-cli package lint",
42
46
  "prepack": "backstage-cli package prepack",
43
47
  "postpack": "backstage-cli package postpack",
44
- "test": "backstage-cli package test --passWithNoTests",
48
+ "test": "backstage-cli package test --passWithNoTests --watchAll=false",
49
+ "test:e2e": "playwright test",
50
+ "test:e2e:ui": "playwright test --ui",
51
+ "test:e2e:debug": "playwright test --debug",
45
52
  "tsc": "tsc --noEmit"
46
53
  },
47
54
  "dependencies": {
48
- "@backstage/core-components": "*",
49
- "@backstage/core-plugin-api": "*",
50
- "@backstage/frontend-plugin-api": "*",
55
+ "@backstage/core-components": "^0.18.9",
56
+ "@backstage/core-plugin-api": "^1.12.5",
57
+ "@backstage/frontend-plugin-api": "^0.16.2",
58
+ "@backstage/ui": "^0.14.3",
51
59
  "@mui/icons-material": "^5.15.0",
52
60
  "@mui/material": "^5.15.0",
53
- "@nospt/plugin-dev-ai-hub-common": "*",
61
+ "@nospt/plugin-dev-ai-hub-common": "^0.2.0",
62
+ "@remixicon/react": "^4.6.0",
54
63
  "react-markdown": "^9.0.0",
55
64
  "react-syntax-highlighter": "^16.1.1",
56
65
  "remark-gfm": "^4.0.1",
57
66
  "simple-icons": "^13.0.0"
58
67
  },
59
68
  "devDependencies": {
60
- "@backstage/cli": "*",
61
- "@backstage/dev-utils": "*",
62
- "@backstage/test-utils": "*",
69
+ "@backstage/cli": "^0.36.1",
70
+ "@backstage/dev-utils": "^1.1.22",
71
+ "@playwright/test": "^1.60.0",
72
+ "@testing-library/dom": "^10.0.0",
63
73
  "@testing-library/jest-dom": "^6.0.0",
64
- "@testing-library/react": "^14.0.0",
65
- "@types/jest": "^29.0.0",
74
+ "@testing-library/react": "^16.3.1",
75
+ "@types/jest": "^30.0.0",
66
76
  "@types/react": "^18.0.0",
67
77
  "@types/react-syntax-highlighter": "^15.0.0",
68
- "jest": "^29.0.0",
69
- "jest-environment-jsdom": "^29.0.0",
78
+ "jest": "^30.2.0",
79
+ "jsdom": "^27.1.0",
70
80
  "react": "^18.0.0",
71
81
  "react-dom": "^18.0.0",
72
- "react-router-dom": "^6.0.0"
82
+ "react-router-dom": "^6.30.2"
73
83
  },
74
84
  "peerDependencies": {
75
85
  "react": "^18.0.0",