@terasky/backstage-plugin-ai-rules 0.2.1 → 1.0.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/alpha.d.ts +47 -0
- package/dist/alpha.esm.js +54 -0
- package/dist/alpha.esm.js.map +1 -0
- package/dist/api/AiRulesClient.esm.js +47 -0
- package/dist/api/AiRulesClient.esm.js.map +1 -0
- package/dist/api/types.esm.js +8 -0
- package/dist/api/types.esm.js.map +1 -0
- package/dist/components/AiInstructionsComponent/AiInstructionsComponent.esm.js +65 -0
- package/dist/components/AiInstructionsComponent/AiInstructionsComponent.esm.js.map +1 -0
- package/dist/components/AiRulesComponent/AiRulesComponent.esm.js +38 -20
- package/dist/components/AiRulesComponent/AiRulesComponent.esm.js.map +1 -1
- package/dist/components/MCPServersComponent/MCPServersComponent.esm.js +236 -0
- package/dist/components/MCPServersComponent/MCPServersComponent.esm.js.map +1 -0
- package/dist/hooks/useMCPServers.esm.js +44 -0
- package/dist/hooks/useMCPServers.esm.js.map +1 -0
- package/dist/index.d.ts +62 -4
- package/dist/index.esm.js +4 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +18 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/types.esm.js.map +1 -1
- package/package.json +18 -1
package/dist/alpha.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as _backstage_catalog_model from '@backstage/catalog-model';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
4
|
+
import * as _backstage_plugin_catalog_react_alpha from '@backstage/plugin-catalog-react/alpha';
|
|
5
|
+
|
|
6
|
+
/** @alpha */
|
|
7
|
+
declare const aiRulesPlugin: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{}, {}, {
|
|
8
|
+
"entity-content:ai-rules": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
9
|
+
kind: "entity-content";
|
|
10
|
+
name: undefined;
|
|
11
|
+
config: {
|
|
12
|
+
path: string | undefined;
|
|
13
|
+
title: string | undefined;
|
|
14
|
+
filter: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
15
|
+
group: string | false | undefined;
|
|
16
|
+
};
|
|
17
|
+
configInput: {
|
|
18
|
+
filter?: _backstage_plugin_catalog_react_alpha.EntityPredicate | undefined;
|
|
19
|
+
title?: string | undefined;
|
|
20
|
+
path?: string | undefined;
|
|
21
|
+
group?: string | false | undefined;
|
|
22
|
+
};
|
|
23
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
24
|
+
optional: true;
|
|
25
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
26
|
+
optional: true;
|
|
27
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-filter-expression", {
|
|
28
|
+
optional: true;
|
|
29
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-group", {
|
|
30
|
+
optional: true;
|
|
31
|
+
}>;
|
|
32
|
+
inputs: {};
|
|
33
|
+
params: {
|
|
34
|
+
defaultPath?: [Error: `Use the 'path' param instead`];
|
|
35
|
+
path: string;
|
|
36
|
+
defaultTitle?: [Error: `Use the 'title' param instead`];
|
|
37
|
+
title: string;
|
|
38
|
+
defaultGroup?: [Error: `Use the 'group' param instead`];
|
|
39
|
+
group?: ("development" | "deployment" | "documentation" | "operation" | "overview" | "observability") | (string & {});
|
|
40
|
+
loader: () => Promise<JSX.Element>;
|
|
41
|
+
routeRef?: _backstage_frontend_plugin_api.RouteRef;
|
|
42
|
+
filter?: string | _backstage_plugin_catalog_react_alpha.EntityPredicate | ((entity: _backstage_catalog_model.Entity) => boolean);
|
|
43
|
+
};
|
|
44
|
+
}>;
|
|
45
|
+
}>;
|
|
46
|
+
|
|
47
|
+
export { aiRulesPlugin };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createFrontendPlugin, ApiBlueprint, discoveryApiRef, identityApiRef } from '@backstage/frontend-plugin-api';
|
|
3
|
+
import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';
|
|
4
|
+
import { isAIRulesAvailable } from './components/AiRulesComponent/AiRulesComponent.esm.js';
|
|
5
|
+
import { aiRulesApiRef } from './api/types.esm.js';
|
|
6
|
+
import { AiRulesClient } from './api/AiRulesClient.esm.js';
|
|
7
|
+
|
|
8
|
+
const aiRulesPlugin = createFrontendPlugin({
|
|
9
|
+
pluginId: "ai-rules",
|
|
10
|
+
extensions: [
|
|
11
|
+
EntityContentBlueprint.make({
|
|
12
|
+
params: {
|
|
13
|
+
path: "/ai-rules",
|
|
14
|
+
filter: isAIRulesAvailable,
|
|
15
|
+
title: "AI Rules",
|
|
16
|
+
loader: () => import('./components/AiRulesComponent/AiRulesComponent.esm.js').then((m) => /* @__PURE__ */ jsx(m.AIRulesComponent, {}))
|
|
17
|
+
},
|
|
18
|
+
disabled: true
|
|
19
|
+
}),
|
|
20
|
+
EntityContentBlueprint.make({
|
|
21
|
+
params: {
|
|
22
|
+
path: "/ai-instructions",
|
|
23
|
+
filter: isAIRulesAvailable,
|
|
24
|
+
title: "AI Instructions",
|
|
25
|
+
loader: () => import('./components/AiInstructionsComponent/AiInstructionsComponent.esm.js').then((m) => /* @__PURE__ */ jsx(m.AiInstructionsComponent, {}))
|
|
26
|
+
},
|
|
27
|
+
disabled: false
|
|
28
|
+
}),
|
|
29
|
+
EntityContentBlueprint.make({
|
|
30
|
+
params: {
|
|
31
|
+
path: "/mcp-servers",
|
|
32
|
+
filter: isAIRulesAvailable,
|
|
33
|
+
title: "MCP Servers",
|
|
34
|
+
loader: () => import('./components/MCPServersComponent/MCPServersComponent.esm.js').then((m) => /* @__PURE__ */ jsx(m.MCPServersComponent, {}))
|
|
35
|
+
},
|
|
36
|
+
disabled: true
|
|
37
|
+
}),
|
|
38
|
+
ApiBlueprint.make({
|
|
39
|
+
name: "aiRulesApi",
|
|
40
|
+
params: (defineParams) => defineParams({
|
|
41
|
+
api: aiRulesApiRef,
|
|
42
|
+
deps: {
|
|
43
|
+
discoveryApi: discoveryApiRef,
|
|
44
|
+
identityApi: identityApiRef
|
|
45
|
+
},
|
|
46
|
+
factory: ({ discoveryApi, identityApi }) => new AiRulesClient({ discoveryApi, identityApi })
|
|
47
|
+
}),
|
|
48
|
+
disabled: false
|
|
49
|
+
})
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export { aiRulesPlugin };
|
|
54
|
+
//# sourceMappingURL=alpha.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["import {\n ApiBlueprint,\n createFrontendPlugin,\n discoveryApiRef,\n identityApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';\nimport { isAIRulesAvailable } from './components/AiRulesComponent';\nimport { aiRulesApiRef, AiRulesClient } from './api';\n\n/** @alpha */\nexport const aiRulesPlugin = createFrontendPlugin({\n pluginId: 'ai-rules',\n extensions: [\n EntityContentBlueprint.make({\n params: {\n path: '/ai-rules',\n filter: isAIRulesAvailable,\n title: 'AI Rules',\n loader: () => import('./components/AiRulesComponent/AiRulesComponent').then(m => <m.AIRulesComponent />),\n },\n disabled: true,\n }),\n EntityContentBlueprint.make({\n params: {\n path: '/ai-instructions',\n filter: isAIRulesAvailable,\n title: 'AI Instructions',\n loader: () => import('./components/AiInstructionsComponent/AiInstructionsComponent').then(m => <m.AiInstructionsComponent />),\n },\n disabled: false,\n }),\n EntityContentBlueprint.make({\n params: {\n path: '/mcp-servers',\n filter: isAIRulesAvailable,\n title: 'MCP Servers',\n loader: () => import('./components/MCPServersComponent/MCPServersComponent').then(m => <m.MCPServersComponent />),\n },\n disabled: true,\n }),\n ApiBlueprint.make({\n name: 'aiRulesApi',\n params: defineParams => defineParams({\n api: aiRulesApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n identityApi: identityApiRef,\n },\n factory: ({ discoveryApi, identityApi }) => new AiRulesClient({ discoveryApi, identityApi }),\n }),\n disabled: false,\n }),\n ],\n});"],"names":[],"mappings":";;;;;;;AAWO,MAAM,gBAAgB,oBAAqB,CAAA;AAAA,EAChD,QAAU,EAAA,UAAA;AAAA,EACV,UAAY,EAAA;AAAA,IACV,uBAAuB,IAAK,CAAA;AAAA,MAC1B,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,WAAA;AAAA,QACN,MAAQ,EAAA,kBAAA;AAAA,QACR,KAAO,EAAA,UAAA;AAAA,QACP,MAAA,EAAQ,MAAM,OAAO,uDAAgD,CAAA,CAAE,IAAK,CAAA,CAAA,CAAA,qBAAM,GAAA,CAAA,CAAA,CAAE,gBAAF,EAAA,EAAmB,CAAE;AAAA,OACzG;AAAA,MACA,QAAU,EAAA;AAAA,KACX,CAAA;AAAA,IACD,uBAAuB,IAAK,CAAA;AAAA,MAC1B,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,kBAAA;AAAA,QACN,MAAQ,EAAA,kBAAA;AAAA,QACR,KAAO,EAAA,iBAAA;AAAA,QACP,MAAA,EAAQ,MAAM,OAAO,qEAA8D,CAAA,CAAE,IAAK,CAAA,CAAA,CAAA,qBAAM,GAAA,CAAA,CAAA,CAAE,uBAAF,EAAA,EAA0B,CAAE;AAAA,OAC9H;AAAA,MACA,QAAU,EAAA;AAAA,KACX,CAAA;AAAA,IACD,uBAAuB,IAAK,CAAA;AAAA,MAC1B,MAAQ,EAAA;AAAA,QACN,IAAM,EAAA,cAAA;AAAA,QACN,MAAQ,EAAA,kBAAA;AAAA,QACR,KAAO,EAAA,aAAA;AAAA,QACP,MAAA,EAAQ,MAAM,OAAO,6DAAsD,CAAA,CAAE,IAAK,CAAA,CAAA,CAAA,qBAAM,GAAA,CAAA,CAAA,CAAE,mBAAF,EAAA,EAAsB,CAAE;AAAA,OAClH;AAAA,MACA,QAAU,EAAA;AAAA,KACX,CAAA;AAAA,IACD,aAAa,IAAK,CAAA;AAAA,MAChB,IAAM,EAAA,YAAA;AAAA,MACN,MAAA,EAAQ,kBAAgB,YAAa,CAAA;AAAA,QACnC,GAAK,EAAA,aAAA;AAAA,QACL,IAAM,EAAA;AAAA,UACJ,YAAc,EAAA,eAAA;AAAA,UACd,WAAa,EAAA;AAAA,SACf;AAAA,QACA,OAAA,EAAS,CAAC,EAAE,YAAc,EAAA,WAAA,EAAkB,KAAA,IAAI,aAAc,CAAA,EAAE,YAAc,EAAA,WAAA,EAAa;AAAA,OAC5F,CAAA;AAAA,MACD,QAAU,EAAA;AAAA,KACX;AAAA;AAEL,CAAC;;;;"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
class AiRulesClient {
|
|
2
|
+
discoveryApi;
|
|
3
|
+
identityApi;
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.discoveryApi = options.discoveryApi;
|
|
6
|
+
this.identityApi = options.identityApi;
|
|
7
|
+
}
|
|
8
|
+
async getAuthHeaders() {
|
|
9
|
+
const { token } = await this.identityApi.getCredentials();
|
|
10
|
+
return {
|
|
11
|
+
"Authorization": `Bearer ${token}`
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
cleanGitUrl(url) {
|
|
15
|
+
return url.replace("url:", "").replace(/\/tree\/(?:main|master)\/.*$/, "");
|
|
16
|
+
}
|
|
17
|
+
async getAiRules(ruleTypes) {
|
|
18
|
+
const baseUrl = await this.discoveryApi.getBaseUrl("ai-rules");
|
|
19
|
+
const sourceLocation = window.location.pathname.split("/").includes("catalog") ? new URLSearchParams(window.location.search).get("sourceLocation") || "" : "";
|
|
20
|
+
const gitUrl = this.cleanGitUrl(sourceLocation);
|
|
21
|
+
const queryParams = new URLSearchParams({
|
|
22
|
+
gitUrl,
|
|
23
|
+
ruleTypes: ruleTypes.join(",")
|
|
24
|
+
});
|
|
25
|
+
const response = await fetch(`${baseUrl}/rules?${queryParams}`, {
|
|
26
|
+
headers: await this.getAuthHeaders()
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error("Failed to fetch AI rules");
|
|
30
|
+
}
|
|
31
|
+
return await response.json();
|
|
32
|
+
}
|
|
33
|
+
async getMCPServers(gitUrl) {
|
|
34
|
+
const baseUrl = await this.discoveryApi.getBaseUrl("ai-rules");
|
|
35
|
+
const queryParams = new URLSearchParams({ gitUrl });
|
|
36
|
+
const response = await fetch(`${baseUrl}/mcp-servers?${queryParams}`, {
|
|
37
|
+
headers: await this.getAuthHeaders()
|
|
38
|
+
});
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
throw new Error("Failed to fetch MCP servers");
|
|
41
|
+
}
|
|
42
|
+
return await response.json();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { AiRulesClient };
|
|
47
|
+
//# sourceMappingURL=AiRulesClient.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AiRulesClient.esm.js","sources":["../../src/api/AiRulesClient.ts"],"sourcesContent":["import { AiRulesApi } from './types';\nimport { AIRulesResponse } from '../types';\nimport { MCPServersResponse } from '../types/mcp';\n\n\nexport class AiRulesClient implements AiRulesApi {\n private readonly discoveryApi: { getBaseUrl: (pluginId: string) => Promise<string> };\n private readonly identityApi: { getCredentials(): Promise<{ token?: string }> };\n\n constructor(options: {\n discoveryApi: { getBaseUrl: (pluginId: string) => Promise<string> };\n identityApi: { getCredentials(): Promise<{ token?: string }> };\n }) {\n this.discoveryApi = options.discoveryApi;\n this.identityApi = options.identityApi;\n }\n\n private async getAuthHeaders(): Promise<HeadersInit> {\n const { token } = await this.identityApi.getCredentials();\n return {\n 'Authorization': `Bearer ${token}`,\n };\n }\n\n private cleanGitUrl(url: string): string {\n return url\n .replace('url:', '')\n .replace(/\\/tree\\/(?:main|master)\\/.*$/, '');\n }\n\n async getAiRules(ruleTypes: string[]): Promise<AIRulesResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('ai-rules');\n const sourceLocation = window.location.pathname.split('/').includes('catalog')\n ? new URLSearchParams(window.location.search).get('sourceLocation') || ''\n : '';\n const gitUrl = this.cleanGitUrl(sourceLocation);\n \n const queryParams = new URLSearchParams({\n gitUrl,\n ruleTypes: ruleTypes.join(','),\n });\n\n const response = await fetch(`${baseUrl}/rules?${queryParams}`, {\n headers: await this.getAuthHeaders(),\n });\n if (!response.ok) {\n throw new Error('Failed to fetch AI rules');\n }\n return await response.json();\n }\n\n async getMCPServers(gitUrl: string): Promise<MCPServersResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('ai-rules');\n const queryParams = new URLSearchParams({ gitUrl });\n\n const response = await fetch(`${baseUrl}/mcp-servers?${queryParams}`, {\n headers: await this.getAuthHeaders(),\n });\n if (!response.ok) {\n throw new Error('Failed to fetch MCP servers');\n }\n return await response.json();\n }\n}\n"],"names":[],"mappings":"AAKO,MAAM,aAAoC,CAAA;AAAA,EAC9B,YAAA;AAAA,EACA,WAAA;AAAA,EAEjB,YAAY,OAGT,EAAA;AACD,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,cAAc,OAAQ,CAAA,WAAA;AAAA;AAC7B,EAEA,MAAc,cAAuC,GAAA;AACnD,IAAA,MAAM,EAAE,KAAM,EAAA,GAAI,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA;AACxD,IAAO,OAAA;AAAA,MACL,eAAA,EAAiB,UAAU,KAAK,CAAA;AAAA,KAClC;AAAA;AACF,EAEQ,YAAY,GAAqB,EAAA;AACvC,IAAA,OAAO,IACJ,OAAQ,CAAA,MAAA,EAAQ,EAAE,CAClB,CAAA,OAAA,CAAQ,gCAAgC,EAAE,CAAA;AAAA;AAC/C,EAEA,MAAM,WAAW,SAA+C,EAAA;AAC9D,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,UAAU,CAAA;AAC7D,IAAA,MAAM,iBAAiB,MAAO,CAAA,QAAA,CAAS,SAAS,KAAM,CAAA,GAAG,EAAE,QAAS,CAAA,SAAS,IACzE,IAAI,eAAA,CAAgB,OAAO,QAAS,CAAA,MAAM,EAAE,GAAI,CAAA,gBAAgB,KAAK,EACrE,GAAA,EAAA;AACJ,IAAM,MAAA,MAAA,GAAS,IAAK,CAAA,WAAA,CAAY,cAAc,CAAA;AAE9C,IAAM,MAAA,WAAA,GAAc,IAAI,eAAgB,CAAA;AAAA,MACtC,MAAA;AAAA,MACA,SAAA,EAAW,SAAU,CAAA,IAAA,CAAK,GAAG;AAAA,KAC9B,CAAA;AAED,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,OAAO,CAAA,OAAA,EAAU,WAAW,CAAI,CAAA,EAAA;AAAA,MAC9D,OAAA,EAAS,MAAM,IAAA,CAAK,cAAe;AAAA,KACpC,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,IAAI,MAAM,0BAA0B,CAAA;AAAA;AAE5C,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAC7B,EAEA,MAAM,cAAc,MAA6C,EAAA;AAC/D,IAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,UAAU,CAAA;AAC7D,IAAA,MAAM,WAAc,GAAA,IAAI,eAAgB,CAAA,EAAE,QAAQ,CAAA;AAElD,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,OAAO,CAAA,aAAA,EAAgB,WAAW,CAAI,CAAA,EAAA;AAAA,MACpE,OAAA,EAAS,MAAM,IAAA,CAAK,cAAe;AAAA,KACpC,CAAA;AACD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,IAAI,MAAM,6BAA6B,CAAA;AAAA;AAE/C,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA;AAAA;AAE/B;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.esm.js","sources":["../../src/api/types.ts"],"sourcesContent":["import { AIRulesResponse } from '../types';\nimport { MCPServersResponse } from '../types/mcp';\n\nimport { createApiRef } from '@backstage/core-plugin-api';\n\nexport const aiRulesApiRef = createApiRef<AiRulesApi>({\n id: 'plugin.ai-rules.service',\n});\n\nexport interface AiRulesApi {\n getAiRules(ruleTypes: string[]): Promise<AIRulesResponse>;\n getMCPServers(gitUrl: string): Promise<MCPServersResponse>;\n}\n"],"names":[],"mappings":";;AAKO,MAAM,gBAAgB,YAAyB,CAAA;AAAA,EACpD,EAAI,EAAA;AACN,CAAC;;;;"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
4
|
+
import { Tabs, Tab, Box } from '@material-ui/core';
|
|
5
|
+
import { AIRulesComponent } from '../AiRulesComponent/AiRulesComponent.esm.js';
|
|
6
|
+
import { MCPServersComponent } from '../MCPServersComponent/MCPServersComponent.esm.js';
|
|
7
|
+
|
|
8
|
+
function TabPanel(props) {
|
|
9
|
+
const { children, value, index, ...other } = props;
|
|
10
|
+
return /* @__PURE__ */ jsx(
|
|
11
|
+
"div",
|
|
12
|
+
{
|
|
13
|
+
role: "tabpanel",
|
|
14
|
+
hidden: value !== index,
|
|
15
|
+
id: `ai-instructions-tabpanel-${index}`,
|
|
16
|
+
"aria-labelledby": `ai-instructions-tab-${index}`,
|
|
17
|
+
...other,
|
|
18
|
+
children: value === index && /* @__PURE__ */ jsx(Box, { children })
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
function a11yProps(index) {
|
|
23
|
+
return {
|
|
24
|
+
id: `ai-instructions-tab-${index}`,
|
|
25
|
+
"aria-controls": `ai-instructions-tabpanel-${index}`
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const useStyles = makeStyles((theme) => ({
|
|
29
|
+
root: {
|
|
30
|
+
width: "100%",
|
|
31
|
+
backgroundColor: theme.palette.background.paper
|
|
32
|
+
},
|
|
33
|
+
tabPanel: {
|
|
34
|
+
padding: 0,
|
|
35
|
+
marginTop: theme.spacing(2)
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
const AiInstructionsComponent = ({ title = "AI Instructions" }) => {
|
|
39
|
+
const styles = useStyles();
|
|
40
|
+
const [value, setValue] = useState(0);
|
|
41
|
+
const handleChange = (_event, newValue) => {
|
|
42
|
+
setValue(newValue);
|
|
43
|
+
};
|
|
44
|
+
return /* @__PURE__ */ jsxs("div", { className: styles.root, children: [
|
|
45
|
+
/* @__PURE__ */ jsxs(
|
|
46
|
+
Tabs,
|
|
47
|
+
{
|
|
48
|
+
value,
|
|
49
|
+
onChange: handleChange,
|
|
50
|
+
indicatorColor: "primary",
|
|
51
|
+
textColor: "primary",
|
|
52
|
+
variant: "fullWidth",
|
|
53
|
+
children: [
|
|
54
|
+
/* @__PURE__ */ jsx(Tab, { label: "Agent Rules", ...a11yProps(0) }),
|
|
55
|
+
/* @__PURE__ */ jsx(Tab, { label: "MCP Servers", ...a11yProps(1) })
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
/* @__PURE__ */ jsx(TabPanel, { value, index: 0, children: /* @__PURE__ */ jsx(Box, { className: styles.tabPanel, children: /* @__PURE__ */ jsx(AIRulesComponent, { title }) }) }),
|
|
60
|
+
/* @__PURE__ */ jsx(TabPanel, { value, index: 1, children: /* @__PURE__ */ jsx(Box, { className: styles.tabPanel, children: /* @__PURE__ */ jsx(MCPServersComponent, {}) }) })
|
|
61
|
+
] });
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { AiInstructionsComponent };
|
|
65
|
+
//# sourceMappingURL=AiInstructionsComponent.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AiInstructionsComponent.esm.js","sources":["../../../src/components/AiInstructionsComponent/AiInstructionsComponent.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Tabs,\n Tab,\n Box,\n} from '@material-ui/core';\nimport { AIRulesComponent } from '../AiRulesComponent';\nimport { MCPServersComponent } from '../MCPServersComponent';\n\ninterface TabPanelProps {\n children?: React.ReactNode;\n index: number;\n value: number;\n}\n\nfunction TabPanel(props: TabPanelProps) {\n const { children, value, index, ...other } = props;\n\n return (\n <div\n role=\"tabpanel\"\n hidden={value !== index}\n id={`ai-instructions-tabpanel-${index}`}\n aria-labelledby={`ai-instructions-tab-${index}`}\n {...other}\n >\n {value === index && (\n <Box>\n {children}\n </Box>\n )}\n </div>\n );\n}\n\nfunction a11yProps(index: number) {\n return {\n id: `ai-instructions-tab-${index}`,\n 'aria-controls': `ai-instructions-tabpanel-${index}`,\n };\n}\n\nconst useStyles = makeStyles((theme) => ({\n root: {\n width: '100%',\n backgroundColor: theme.palette.background.paper,\n },\n tabPanel: {\n padding: 0,\n marginTop: theme.spacing(2),\n },\n}));\n\nexport interface AiInstructionsComponentProps {\n title?: string;\n}\n\nexport const AiInstructionsComponent = ({ title = \"AI Instructions\" }: AiInstructionsComponentProps) => {\n const styles = useStyles();\n const [value, setValue] = useState(0);\n\n const handleChange = (_event: React.ChangeEvent<{}>, newValue: number) => {\n setValue(newValue);\n };\n\n return (\n <div className={styles.root}>\n <Tabs\n value={value}\n onChange={handleChange}\n indicatorColor=\"primary\"\n textColor=\"primary\"\n variant=\"fullWidth\"\n >\n <Tab label=\"Agent Rules\" {...a11yProps(0)} />\n <Tab label=\"MCP Servers\" {...a11yProps(1)} />\n </Tabs>\n <TabPanel value={value} index={0}>\n <Box className={styles.tabPanel}>\n <AIRulesComponent title={title} />\n </Box>\n </TabPanel>\n <TabPanel value={value} index={1}>\n <Box className={styles.tabPanel}>\n <MCPServersComponent />\n </Box>\n </TabPanel>\n </div>\n );\n};\n\n\n"],"names":[],"mappings":";;;;;;;AAgBA,SAAS,SAAS,KAAsB,EAAA;AACtC,EAAA,MAAM,EAAE,QAAU,EAAA,KAAA,EAAO,KAAO,EAAA,GAAG,OAAU,GAAA,KAAA;AAE7C,EACE,uBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAK,EAAA,UAAA;AAAA,MACL,QAAQ,KAAU,KAAA,KAAA;AAAA,MAClB,EAAA,EAAI,4BAA4B,KAAK,CAAA,CAAA;AAAA,MACrC,iBAAA,EAAiB,uBAAuB,KAAK,CAAA,CAAA;AAAA,MAC5C,GAAG,KAAA;AAAA,MAEH,QAAU,EAAA,KAAA,KAAA,KAAA,oBACR,GAAA,CAAA,GAAA,EAAA,EACE,QACH,EAAA;AAAA;AAAA,GAEJ;AAEJ;AAEA,SAAS,UAAU,KAAe,EAAA;AAChC,EAAO,OAAA;AAAA,IACL,EAAA,EAAI,uBAAuB,KAAK,CAAA,CAAA;AAAA,IAChC,eAAA,EAAiB,4BAA4B,KAAK,CAAA;AAAA,GACpD;AACF;AAEA,MAAM,SAAA,GAAY,UAAW,CAAA,CAAC,KAAW,MAAA;AAAA,EACvC,IAAM,EAAA;AAAA,IACJ,KAAO,EAAA,MAAA;AAAA,IACP,eAAA,EAAiB,KAAM,CAAA,OAAA,CAAQ,UAAW,CAAA;AAAA,GAC5C;AAAA,EACA,QAAU,EAAA;AAAA,IACR,OAAS,EAAA,CAAA;AAAA,IACT,SAAA,EAAW,KAAM,CAAA,OAAA,CAAQ,CAAC;AAAA;AAE9B,CAAE,CAAA,CAAA;AAMK,MAAM,uBAA0B,GAAA,CAAC,EAAE,KAAA,GAAQ,mBAAsD,KAAA;AACtG,EAAA,MAAM,SAAS,SAAU,EAAA;AACzB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,CAAC,CAAA;AAEpC,EAAM,MAAA,YAAA,GAAe,CAAC,MAAA,EAA+B,QAAqB,KAAA;AACxE,IAAA,QAAA,CAAS,QAAQ,CAAA;AAAA,GACnB;AAEA,EAAA,uBACG,IAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,IACrB,EAAA,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,KAAA;AAAA,QACA,QAAU,EAAA,YAAA;AAAA,QACV,cAAe,EAAA,SAAA;AAAA,QACf,SAAU,EAAA,SAAA;AAAA,QACV,OAAQ,EAAA,WAAA;AAAA,QAER,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,OAAI,KAAM,EAAA,aAAA,EAAe,GAAG,SAAA,CAAU,CAAC,CAAG,EAAA,CAAA;AAAA,8BAC1C,GAAI,EAAA,EAAA,KAAA,EAAM,eAAe,GAAG,SAAA,CAAU,CAAC,CAAG,EAAA;AAAA;AAAA;AAAA,KAC7C;AAAA,oBACC,GAAA,CAAA,QAAA,EAAA,EAAS,KAAc,EAAA,KAAA,EAAO,GAC7B,QAAC,kBAAA,GAAA,CAAA,GAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,QACrB,EAAA,QAAA,kBAAA,GAAA,CAAC,gBAAiB,EAAA,EAAA,KAAA,EAAc,GAClC,CACF,EAAA,CAAA;AAAA,oBACC,GAAA,CAAA,QAAA,EAAA,EAAS,KAAc,EAAA,KAAA,EAAO,CAC7B,EAAA,QAAA,kBAAA,GAAA,CAAC,GAAI,EAAA,EAAA,SAAA,EAAW,MAAO,CAAA,QAAA,EACrB,QAAC,kBAAA,GAAA,CAAA,mBAAA,EAAA,EAAoB,GACvB,CACF,EAAA;AAAA,GACF,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -230,27 +230,45 @@ const RuleComponent = ({ rule }) => {
|
|
|
230
230
|
] }) })
|
|
231
231
|
] });
|
|
232
232
|
};
|
|
233
|
-
const renderCopilotRule = (rule2) =>
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
/* @__PURE__ */ jsxs(
|
|
238
|
-
|
|
239
|
-
rule2.
|
|
233
|
+
const renderCopilotRule = (rule2) => {
|
|
234
|
+
const ruleNumber = rule2.order || (rule2.fileName.match(/Rule (\d+)/) || [])[1] || rule2.id.split("-").pop();
|
|
235
|
+
return /* @__PURE__ */ jsxs(Accordion, { className: styles.ruleCard, children: [
|
|
236
|
+
/* @__PURE__ */ jsx(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), children: /* @__PURE__ */ jsxs("div", { className: styles.ruleHeader, children: [
|
|
237
|
+
/* @__PURE__ */ jsxs("div", { className: styles.ruleHeaderContent, children: [
|
|
238
|
+
/* @__PURE__ */ jsx(RuleTypeIcon, { type: rule2.type }),
|
|
239
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h6", children: rule2.title || `Copilot Rule #${ruleNumber}` }),
|
|
240
|
+
/* @__PURE__ */ jsx(Chip, { label: rule2.type, size: "small", className: styles.ruleType }),
|
|
241
|
+
rule2.applyTo && /* @__PURE__ */ jsx(
|
|
242
|
+
Chip,
|
|
243
|
+
{
|
|
244
|
+
label: `Applies to: ${rule2.applyTo}`,
|
|
245
|
+
size: "small",
|
|
246
|
+
variant: "outlined",
|
|
247
|
+
style: { marginLeft: 8 }
|
|
248
|
+
}
|
|
249
|
+
)
|
|
240
250
|
] }),
|
|
241
|
-
/* @__PURE__ */ jsx(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
251
|
+
rule2.gitUrl && /* @__PURE__ */ jsx(Tooltip, { title: "Open file in repository", children: /* @__PURE__ */ jsx(
|
|
252
|
+
IconButton,
|
|
253
|
+
{
|
|
254
|
+
size: "small",
|
|
255
|
+
onClick: (e) => {
|
|
256
|
+
e.stopPropagation();
|
|
257
|
+
window.open(constructFileUrl(rule2.gitUrl, rule2.filePath), "_blank");
|
|
258
|
+
},
|
|
259
|
+
children: /* @__PURE__ */ jsx(LaunchIcon, { fontSize: "small" })
|
|
260
|
+
}
|
|
261
|
+
) })
|
|
262
|
+
] }) }),
|
|
263
|
+
/* @__PURE__ */ jsx(AccordionDetails, { children: /* @__PURE__ */ jsxs("div", { children: [
|
|
264
|
+
/* @__PURE__ */ jsxs("div", { className: styles.ruleMetadata, children: [
|
|
265
|
+
/* @__PURE__ */ jsx(Chip, { label: `Path: ${rule2.filePath}`, size: "small", variant: "outlined" }),
|
|
266
|
+
rule2.frontmatter && renderFrontmatter(theme, rule2.frontmatter)
|
|
267
|
+
] }),
|
|
268
|
+
/* @__PURE__ */ jsx("div", { className: styles.ruleContent, children: /* @__PURE__ */ jsx(MarkdownContent, { content: rule2.content }) })
|
|
269
|
+
] }) })
|
|
270
|
+
] });
|
|
271
|
+
};
|
|
254
272
|
const renderClineRule = (rule2) => /* @__PURE__ */ jsxs(Accordion, { className: styles.ruleCard, children: [
|
|
255
273
|
/* @__PURE__ */ jsx(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), children: /* @__PURE__ */ jsxs("div", { className: styles.ruleHeader, children: [
|
|
256
274
|
/* @__PURE__ */ jsxs("div", { className: styles.ruleHeaderContent, children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiRulesComponent.esm.js","sources":["../../../src/components/AiRulesComponent/AiRulesComponent.tsx"],"sourcesContent":["import { useAiRules } from '../../hooks/useAiRules';\nimport { InfoCard, Progress, EmptyState, MarkdownContent } from '@backstage/core-components';\nimport { Button, makeStyles, useTheme, Typography, Chip, Card, CardContent, Accordion, AccordionSummary, AccordionDetails, FormControlLabel, Checkbox, IconButton, Tooltip } from '@material-ui/core';\nimport { Entity } from '@backstage/catalog-model';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport CodeIcon from '@material-ui/icons/Code';\nimport LaunchIcon from '@material-ui/icons/Launch';\nimport { AIRuleType, AIRule, CursorRule, CopilotRule, ClineRule, ClaudeCodeRule } from '../../types';\nexport interface AIRulesComponentProps {\n title?: string;\n}\n\nexport const isAIRulesAvailable = (entity: Entity): boolean => {\n const sourceAnnotation = entity.metadata?.annotations?.['backstage.io/source-location'] || '';\n return sourceAnnotation.startsWith('url:');\n};\n\nconst useStyles = makeStyles((theme) => ({\n root: {\n '& .MuiAccordion-root': {\n marginBottom: theme.spacing(1),\n '&:before': {\n display: 'none',\n },\n },\n },\n filterSection: {\n marginBottom: theme.spacing(2),\n padding: theme.spacing(2),\n backgroundColor: theme.palette.background.default,\n borderRadius: theme.shape.borderRadius,\n },\n ruleCard: {\n marginBottom: theme.spacing(1),\n border: `1px solid ${theme.palette.divider}`,\n },\n ruleHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n width: '100%',\n },\n ruleHeaderContent: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n flex: 1,\n },\n ruleType: {\n textTransform: 'uppercase',\n fontWeight: 'bold',\n fontSize: '0.75rem',\n },\n ruleContent: {\n padding: theme.spacing(1),\n borderRadius: theme.shape.borderRadius,\n overflow: 'auto',\n maxHeight: '300px',\n '& > *': {\n backgroundColor: 'transparent !important',\n },\n },\n ruleMetadata: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n marginBottom: theme.spacing(1),\n },\n statsContainer: {\n display: 'flex',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(2),\n },\n statCard: {\n minWidth: '120px',\n textAlign: 'center',\n },\n emptyStateIcon: {\n fontSize: '4rem',\n color: theme.palette.grey[400],\n },\n filterContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n '& > *': {\n marginRight: theme.spacing(1),\n },\n },\n applyFilterButton: {\n marginTop: theme.spacing(1),\n },\n}));\n\nconst RuleTypeIcon = ({ type }: { type: AIRuleType }) => {\n const colors = {\n [AIRuleType.CURSOR]: '#0066CC',\n [AIRuleType.COPILOT]: '#6F42C1', \n [AIRuleType.CLINE]: '#28A745',\n [AIRuleType.CLAUDE_CODE]: '#FF6B35',\n };\n \n return <CodeIcon style={{ color: colors[type] }} />;\n};\n\nconst renderFrontmatter = (theme: any, frontmatter?: Record<string, any>) => {\n if (!frontmatter || Object.keys(frontmatter).length === 0) {\n return null;\n }\n\n // Filter out fields that are already displayed elsewhere (description, globs)\n const filteredEntries = Object.entries(frontmatter).filter(([key]) => \n !['description', 'globs'].includes(key)\n );\n\n if (filteredEntries.length === 0) {\n return null;\n }\n\n return (\n <div style={{ \n marginBottom: '16px', \n padding: '16px', \n backgroundColor: theme.palette.type === 'dark' ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)', \n borderRadius: '8px',\n border: `1px solid ${theme.palette.type === 'dark' ? 'rgba(255,255,255,0.12)' : 'rgba(0,0,0,0.12)'}`\n }}>\n <Typography variant=\"subtitle2\" style={{ \n marginBottom: '12px', \n fontWeight: 'bold',\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n letterSpacing: '0.5px'\n }}>\n Metadata\n </Typography>\n {filteredEntries.map(([key, value], index) => (\n <div key={key} style={{ marginBottom: index < filteredEntries.length - 1 ? '12px' : '0' }}>\n <Typography variant=\"body2\" style={{ \n fontWeight: 'bold',\n textTransform: 'capitalize',\n color: theme.palette.primary.main,\n marginBottom: '4px'\n }}>\n {key}:\n </Typography>\n <Typography variant=\"body2\" style={{ \n lineHeight: '1.5',\n marginLeft: '8px',\n color: theme.palette.text.primary\n }}>\n {Array.isArray(value) ? value.join(', ') : String(value)}\n </Typography>\n </div>\n ))}\n </div>\n );\n};\n\n// Helper function to parse cursor rule content manually\nconst parseCursorContent = (content: string) => {\n return manualParseFrontmatter(content);\n};\n\n// Manual frontmatter parsing as fallback\nconst manualParseFrontmatter = (content: string) => {\n // Check if content starts with ---\n if (!content.trim().startsWith('---')) {\n return {\n frontmatter: undefined,\n content: content\n };\n }\n\n try {\n // Split by lines\n const lines = content.split('\\n');\n let frontmatterEndIndex = -1;\n \n // Find the closing ---\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n frontmatterEndIndex = i;\n break;\n }\n }\n \n if (frontmatterEndIndex === -1) {\n return {\n frontmatter: undefined,\n content: content\n };\n }\n \n // Extract frontmatter lines (between the --- markers)\n const frontmatterLines = lines.slice(1, frontmatterEndIndex);\n const contentLines = lines.slice(frontmatterEndIndex + 1);\n \n // Parse the YAML manually (simple key: value pairs)\n const frontmatter: Record<string, any> = {};\n for (const line of frontmatterLines) {\n const trimmedLine = line.trim();\n if (trimmedLine && trimmedLine.includes(':')) {\n const colonIndex = trimmedLine.indexOf(':');\n const key = trimmedLine.substring(0, colonIndex).trim();\n const value = trimmedLine.substring(colonIndex + 1).trim();\n frontmatter[key] = value;\n }\n }\n \n return {\n frontmatter: Object.keys(frontmatter).length > 0 ? frontmatter : undefined,\n content: contentLines.join('\\n').trim()\n };\n } catch (error) {\n return {\n frontmatter: undefined,\n content: content\n };\n }\n};\n\nconst constructFileUrl = (gitUrl: string, filePath: string): string => {\n // Remove trailing slashes from gitUrl\n const cleanGitUrl = gitUrl.replace(/\\/+$/, '');\n \n // For GitHub URLs, convert to blob view\n if (cleanGitUrl.includes('github.com')) {\n return `${cleanGitUrl}/blob/main/${filePath}`;\n }\n \n // For GitLab URLs, convert to blob view\n if (cleanGitUrl.includes('gitlab.com')) {\n return `${cleanGitUrl}/-/blob/main/${filePath}`;\n }\n \n // For other git providers, try generic blob URL\n return `${cleanGitUrl}/blob/main/${filePath}`;\n};\n\nconst RuleComponent = ({ rule }: { rule: AIRule }) => {\n const styles = useStyles();\n const theme = useTheme();\n \n const renderCursorRule = (rule: CursorRule) => {\n // Parse the raw content to extract frontmatter and clean content\n const { frontmatter, content } = parseCursorContent(rule.content);\n \n return (\n <Accordion className={styles.ruleCard}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">{rule.fileName}</Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n {frontmatter?.description && (\n <Typography variant=\"body2\" style={{ marginLeft: 8, color: theme.palette.text.secondary }}>\n {frontmatter.description}\n </Typography>\n )}\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank');\n }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div>\n <div className={styles.ruleMetadata}>\n <Chip label={`Path: ${rule.filePath}`} size=\"small\" variant=\"outlined\" />\n {frontmatter?.globs && (\n <Chip label={`Globs: ${Array.isArray(frontmatter.globs) ? frontmatter.globs.join(', ') : frontmatter.globs}`} size=\"small\" variant=\"outlined\" />\n )}\n </div>\n {renderFrontmatter(theme, frontmatter)}\n <div className={styles.ruleContent}>\n <MarkdownContent content={content} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n };\n\n const renderCopilotRule = (rule: CopilotRule) => (\n <Card className={styles.ruleCard}>\n <CardContent>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">Copilot Rule #{rule.order}</Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={() => window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank')}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n <div className={styles.ruleContent}>\n {rule.content}\n </div>\n </CardContent>\n </Card>\n );\n\n const renderClineRule = (rule: ClineRule) => (\n <Accordion className={styles.ruleCard}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">{rule.title || rule.fileName}</Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank');\n }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div>\n <div className={styles.ruleMetadata}>\n <Chip label={`Path: ${rule.filePath}`} size=\"small\" variant=\"outlined\" />\n </div>\n <div className={styles.ruleContent}>\n <MarkdownContent content={rule.content} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n\n const renderClaudeCodeRule = (rule: ClaudeCodeRule) => (\n <Accordion className={styles.ruleCard}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">{rule.title || rule.fileName}</Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank');\n }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div>\n <div className={styles.ruleMetadata}>\n <Chip label={`Path: ${rule.filePath}`} size=\"small\" variant=\"outlined\" />\n </div>\n <div className={styles.ruleContent}>\n <MarkdownContent content={rule.content} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n\n switch (rule.type) {\n case AIRuleType.CURSOR:\n return renderCursorRule(rule as CursorRule);\n case AIRuleType.CLAUDE_CODE:\n return renderClaudeCodeRule(rule as ClaudeCodeRule);\n case AIRuleType.COPILOT:\n return renderCopilotRule(rule as CopilotRule);\n case AIRuleType.CLINE:\n return renderClineRule(rule as ClineRule);\n default:\n return null;\n }\n};\n\nexport const AIRulesComponent = ({ title = \"AI Coding Rules\" }: AIRulesComponentProps = {}) => {\n const { rulesByType, loading, error, hasGitUrl, totalRules, allowedRuleTypes, selectedRuleTypes, setSelectedRuleTypes, applyFilters, resetFilters, hasUnappliedChanges, hasSearched } = useAiRules();\n const styles = useStyles();\n \n // Define the desired rendering order\n const ruleTypeDisplayOrder = [AIRuleType.CURSOR, AIRuleType.CLAUDE_CODE, AIRuleType.COPILOT, AIRuleType.CLINE];\n \n // Helper function to format rule type names for display\n const formatRuleTypeName = (type: AIRuleType): string => {\n switch (type) {\n case AIRuleType.CURSOR:\n return 'Cursor';\n case AIRuleType.CLAUDE_CODE:\n return 'Claude Code';\n case AIRuleType.COPILOT:\n return 'Copilot';\n case AIRuleType.CLINE:\n return 'Cline';\n }\n };\n const handleTypeToggle = (type: AIRuleType, checked: boolean) => {\n const newTypes = checked \n ? [...selectedRuleTypes, type]\n : selectedRuleTypes.filter(t => t !== type);\n setSelectedRuleTypes(newTypes);\n };\n\n if (loading) {\n return (\n <InfoCard title={title}>\n <Progress />\n </InfoCard>\n );\n }\n\n if (!hasGitUrl) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"No Git Repository\"\n description=\"This component doesn't have a Git source URL configured.\"\n />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"Error Loading Rules\"\n description={error}\n />\n </InfoCard>\n );\n }\n\n return (\n <InfoCard title={title} className={styles.root}>\n <div className={styles.filterSection}>\n <Typography variant=\"h6\" gutterBottom>\n Filter Rule Types\n </Typography>\n <div className={styles.filterContainer}>\n {allowedRuleTypes.map(type => (\n <FormControlLabel\n key={type}\n control={\n <Checkbox\n checked={selectedRuleTypes.includes(type)}\n onChange={(e) => handleTypeToggle(type, e.target.checked)}\n />\n }\n label={formatRuleTypeName(type)}\n />\n ))}\n </div>\n <div className={styles.applyFilterButton}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={applyFilters}\n disabled={!hasUnappliedChanges}\n >\n Apply Filter\n </Button>\n {hasUnappliedChanges && (\n <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginTop: 8 }}>\n You have unsaved filter changes. Click \"Apply Filter\" to update the results.\n </Typography>\n )}\n {!hasUnappliedChanges && selectedRuleTypes.length === 0 && (\n <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginTop: 8 }}>\n Select at least one rule type to search for AI rules.\n </Typography>\n )}\n </div>\n </div>\n\n {hasSearched && totalRules === 0 ? (\n <EmptyState\n missing=\"content\"\n title=\"No AI Rules Found\"\n description=\"No AI rules were found in this repository for the selected rule types.\"\n action={\n <Button\n variant=\"outlined\"\n onClick={resetFilters}\n >\n Reset Filters\n </Button>\n }\n />\n ) : totalRules > 0 ? (\n <>\n <div className={styles.statsContainer}>\n <Card className={styles.statCard}>\n <CardContent>\n <Typography variant=\"h4\">{totalRules}</Typography>\n <Typography color=\"textSecondary\">Total Rules</Typography>\n </CardContent>\n </Card>\n {ruleTypeDisplayOrder.map(type => {\n const typeRules = rulesByType[type] || [];\n if (typeRules.length === 0) return null;\n return (\n <Card key={type} className={styles.statCard}>\n <CardContent>\n <Typography variant=\"h4\">{typeRules.length}</Typography>\n <Typography color=\"textSecondary\">{formatRuleTypeName(type)}</Typography>\n </CardContent>\n </Card>\n );\n })}\n </div>\n\n {ruleTypeDisplayOrder.map(type => {\n const typeRules = rulesByType[type] || [];\n if (typeRules.length === 0) return null;\n return (\n <div key={type}>\n <Typography variant=\"h5\" gutterBottom style={{ marginTop: 16 }}>\n {formatRuleTypeName(type)} Rules ({typeRules.length})\n </Typography>\n {typeRules.map(rule => (\n <RuleComponent key={rule.id} rule={rule} />\n ))}\n </div>\n );\n })}\n </>\n ) : (\n <div style={{ marginTop: 16 }}>\n <Typography variant=\"body1\" color=\"textSecondary\">\n Select rule types above and click \"Apply Filter\" to search for AI coding rules in this repository.\n </Typography>\n </div>\n )}\n </InfoCard>\n );\n};"],"names":["rule"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AiRulesComponent.esm.js","sources":["../../../src/components/AiRulesComponent/AiRulesComponent.tsx"],"sourcesContent":["import React from 'react';\nimport { useAiRules } from '../../hooks/useAiRules';\nimport { InfoCard, Progress, EmptyState, MarkdownContent } from '@backstage/core-components';\nimport { Button, makeStyles, useTheme, Typography, Chip, Card, CardContent, Accordion, AccordionSummary, AccordionDetails, FormControlLabel, Checkbox, IconButton, Tooltip } from '@material-ui/core';\nimport { Entity } from '@backstage/catalog-model';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport CodeIcon from '@material-ui/icons/Code';\nimport LaunchIcon from '@material-ui/icons/Launch';\nimport { AIRuleType, AIRule, CursorRule, CopilotRule, ClineRule, ClaudeCodeRule } from '../../types';\nexport interface AIRulesComponentProps {\n title?: string;\n}\n\nexport const isAIRulesAvailable = (entity: Entity): boolean => {\n const sourceAnnotation = entity.metadata?.annotations?.['backstage.io/source-location'] || '';\n return sourceAnnotation.startsWith('url:');\n};\n\nconst useStyles = makeStyles((theme) => ({\n root: {\n '& .MuiAccordion-root': {\n marginBottom: theme.spacing(1),\n '&:before': {\n display: 'none',\n },\n },\n },\n filterSection: {\n marginBottom: theme.spacing(2),\n padding: theme.spacing(2),\n backgroundColor: theme.palette.background.default,\n borderRadius: theme.shape.borderRadius,\n },\n ruleCard: {\n marginBottom: theme.spacing(1),\n border: `1px solid ${theme.palette.divider}`,\n },\n ruleHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n width: '100%',\n },\n ruleHeaderContent: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n flex: 1,\n },\n ruleType: {\n textTransform: 'uppercase',\n fontWeight: 'bold',\n fontSize: '0.75rem',\n },\n ruleContent: {\n padding: theme.spacing(1),\n borderRadius: theme.shape.borderRadius,\n overflow: 'auto',\n maxHeight: '300px',\n '& > *': {\n backgroundColor: 'transparent !important',\n },\n },\n ruleMetadata: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n marginBottom: theme.spacing(1),\n },\n statsContainer: {\n display: 'flex',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(2),\n },\n statCard: {\n minWidth: '120px',\n textAlign: 'center',\n },\n emptyStateIcon: {\n fontSize: '4rem',\n color: theme.palette.grey[400],\n },\n filterContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n '& > *': {\n marginRight: theme.spacing(1),\n },\n },\n applyFilterButton: {\n marginTop: theme.spacing(1),\n },\n}));\n\nconst RuleTypeIcon = ({ type }: { type: AIRuleType }) => {\n const colors = {\n [AIRuleType.CURSOR]: '#0066CC',\n [AIRuleType.COPILOT]: '#6F42C1', \n [AIRuleType.CLINE]: '#28A745',\n [AIRuleType.CLAUDE_CODE]: '#FF6B35',\n };\n \n return <CodeIcon style={{ color: colors[type] }} />;\n};\n\nconst renderFrontmatter = (theme: any, frontmatter?: Record<string, any>) => {\n if (!frontmatter || Object.keys(frontmatter).length === 0) {\n return null;\n }\n\n // Filter out fields that are already displayed elsewhere (description, globs)\n const filteredEntries = Object.entries(frontmatter).filter(([key]) => \n !['description', 'globs'].includes(key)\n );\n\n if (filteredEntries.length === 0) {\n return null;\n }\n\n return (\n <div style={{ \n marginBottom: '16px', \n padding: '16px', \n backgroundColor: theme.palette.type === 'dark' ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)', \n borderRadius: '8px',\n border: `1px solid ${theme.palette.type === 'dark' ? 'rgba(255,255,255,0.12)' : 'rgba(0,0,0,0.12)'}`\n }}>\n <Typography variant=\"subtitle2\" style={{ \n marginBottom: '12px', \n fontWeight: 'bold',\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n letterSpacing: '0.5px'\n }}>\n Metadata\n </Typography>\n {filteredEntries.map(([key, value], index) => (\n <div key={key} style={{ marginBottom: index < filteredEntries.length - 1 ? '12px' : '0' }}>\n <Typography variant=\"body2\" style={{ \n fontWeight: 'bold',\n textTransform: 'capitalize',\n color: theme.palette.primary.main,\n marginBottom: '4px'\n }}>\n {key}:\n </Typography>\n <Typography variant=\"body2\" style={{ \n lineHeight: '1.5',\n marginLeft: '8px',\n color: theme.palette.text.primary\n }}>\n {Array.isArray(value) ? value.join(', ') : String(value)}\n </Typography>\n </div>\n ))}\n </div>\n );\n};\n\n// Helper function to parse cursor rule content manually\nconst parseCursorContent = (content: string) => {\n return manualParseFrontmatter(content);\n};\n\n// Manual frontmatter parsing as fallback\nconst manualParseFrontmatter = (content: string) => {\n // Check if content starts with ---\n if (!content.trim().startsWith('---')) {\n return {\n frontmatter: undefined,\n content: content\n };\n }\n\n try {\n // Split by lines\n const lines = content.split('\\n');\n let frontmatterEndIndex = -1;\n \n // Find the closing ---\n for (let i = 1; i < lines.length; i++) {\n if (lines[i].trim() === '---') {\n frontmatterEndIndex = i;\n break;\n }\n }\n \n if (frontmatterEndIndex === -1) {\n return {\n frontmatter: undefined,\n content: content\n };\n }\n \n // Extract frontmatter lines (between the --- markers)\n const frontmatterLines = lines.slice(1, frontmatterEndIndex);\n const contentLines = lines.slice(frontmatterEndIndex + 1);\n \n // Parse the YAML manually (simple key: value pairs)\n const frontmatter: Record<string, any> = {};\n for (const line of frontmatterLines) {\n const trimmedLine = line.trim();\n if (trimmedLine && trimmedLine.includes(':')) {\n const colonIndex = trimmedLine.indexOf(':');\n const key = trimmedLine.substring(0, colonIndex).trim();\n const value = trimmedLine.substring(colonIndex + 1).trim();\n frontmatter[key] = value;\n }\n }\n \n return {\n frontmatter: Object.keys(frontmatter).length > 0 ? frontmatter : undefined,\n content: contentLines.join('\\n').trim()\n };\n } catch (error) {\n return {\n frontmatter: undefined,\n content: content\n };\n }\n};\n\nconst constructFileUrl = (gitUrl: string, filePath: string): string => {\n // Remove trailing slashes from gitUrl\n const cleanGitUrl = gitUrl.replace(/\\/+$/, '');\n \n // For GitHub URLs, convert to blob view\n if (cleanGitUrl.includes('github.com')) {\n return `${cleanGitUrl}/blob/main/${filePath}`;\n }\n \n // For GitLab URLs, convert to blob view\n if (cleanGitUrl.includes('gitlab.com')) {\n return `${cleanGitUrl}/-/blob/main/${filePath}`;\n }\n \n // For other git providers, try generic blob URL\n return `${cleanGitUrl}/blob/main/${filePath}`;\n};\n\nconst RuleComponent = ({ rule }: { rule: AIRule }) => {\n const styles = useStyles();\n const theme = useTheme();\n \n const renderCursorRule = (rule: CursorRule) => {\n // Parse the raw content to extract frontmatter and clean content\n const { frontmatter, content } = parseCursorContent(rule.content);\n \n return (\n <Accordion className={styles.ruleCard}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">{rule.fileName}</Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n {frontmatter?.description && (\n <Typography variant=\"body2\" style={{ marginLeft: 8, color: theme.palette.text.secondary }}>\n {frontmatter.description}\n </Typography>\n )}\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank');\n }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div>\n <div className={styles.ruleMetadata}>\n <Chip label={`Path: ${rule.filePath}`} size=\"small\" variant=\"outlined\" />\n {frontmatter?.globs && (\n <Chip label={`Globs: ${Array.isArray(frontmatter.globs) ? frontmatter.globs.join(', ') : frontmatter.globs}`} size=\"small\" variant=\"outlined\" />\n )}\n </div>\n {renderFrontmatter(theme, frontmatter)}\n <div className={styles.ruleContent}>\n <MarkdownContent content={content} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n };\n\n const renderCopilotRule = (rule: CopilotRule) => {\n // Get rule number from either order (legacy) or extract from filename\n const ruleNumber = rule.order || (rule.fileName.match(/Rule (\\d+)/) || [])[1] || rule.id.split('-').pop();\n \n return (\n <Accordion className={styles.ruleCard}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">\n {rule.title || `Copilot Rule #${ruleNumber}`}\n </Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n {rule.applyTo && (\n <Chip \n label={`Applies to: ${rule.applyTo}`} \n size=\"small\" \n variant=\"outlined\" \n style={{ marginLeft: 8 }}\n />\n )}\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank');\n }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div>\n <div className={styles.ruleMetadata}>\n <Chip label={`Path: ${rule.filePath}`} size=\"small\" variant=\"outlined\" />\n {rule.frontmatter && renderFrontmatter(theme, rule.frontmatter)}\n </div>\n <div className={styles.ruleContent}>\n <MarkdownContent content={rule.content} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n };\n\n const renderClineRule = (rule: ClineRule) => (\n <Accordion className={styles.ruleCard}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">{rule.title || rule.fileName}</Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank');\n }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div>\n <div className={styles.ruleMetadata}>\n <Chip label={`Path: ${rule.filePath}`} size=\"small\" variant=\"outlined\" />\n </div>\n <div className={styles.ruleContent}>\n <MarkdownContent content={rule.content} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n\n const renderClaudeCodeRule = (rule: ClaudeCodeRule) => (\n <Accordion className={styles.ruleCard}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.ruleHeader}>\n <div className={styles.ruleHeaderContent}>\n <RuleTypeIcon type={rule.type} />\n <Typography variant=\"h6\">{rule.title || rule.fileName}</Typography>\n <Chip label={rule.type} size=\"small\" className={styles.ruleType} />\n </div>\n {rule.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n window.open(constructFileUrl(rule.gitUrl!, rule.filePath), '_blank');\n }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div>\n <div className={styles.ruleMetadata}>\n <Chip label={`Path: ${rule.filePath}`} size=\"small\" variant=\"outlined\" />\n </div>\n <div className={styles.ruleContent}>\n <MarkdownContent content={rule.content} />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n\n switch (rule.type) {\n case AIRuleType.CURSOR:\n return renderCursorRule(rule as CursorRule);\n case AIRuleType.CLAUDE_CODE:\n return renderClaudeCodeRule(rule as ClaudeCodeRule);\n case AIRuleType.COPILOT:\n return renderCopilotRule(rule as CopilotRule);\n case AIRuleType.CLINE:\n return renderClineRule(rule as ClineRule);\n default:\n return null;\n }\n};\n\nexport const AIRulesComponent: React.FC<AIRulesComponentProps> = ({ title = \"AI Coding Rules\" } = {}) => {\n const { rulesByType, loading, error, hasGitUrl, totalRules, allowedRuleTypes, selectedRuleTypes, setSelectedRuleTypes, applyFilters, resetFilters, hasUnappliedChanges, hasSearched } = useAiRules();\n const styles = useStyles();\n \n // Define the desired rendering order\n const ruleTypeDisplayOrder = [AIRuleType.CURSOR, AIRuleType.CLAUDE_CODE, AIRuleType.COPILOT, AIRuleType.CLINE];\n \n // Helper function to format rule type names for display\n const formatRuleTypeName = (type: AIRuleType): string => {\n switch (type) {\n case AIRuleType.CURSOR:\n return 'Cursor';\n case AIRuleType.CLAUDE_CODE:\n return 'Claude Code';\n case AIRuleType.COPILOT:\n return 'Copilot';\n case AIRuleType.CLINE:\n return 'Cline';\n }\n };\n const handleTypeToggle = (type: AIRuleType, checked: boolean) => {\n const newTypes = checked \n ? [...selectedRuleTypes, type]\n : selectedRuleTypes.filter(t => t !== type);\n setSelectedRuleTypes(newTypes);\n };\n\n if (loading) {\n return (\n <InfoCard title={title}>\n <Progress />\n </InfoCard>\n );\n }\n\n if (!hasGitUrl) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"No Git Repository\"\n description=\"This component doesn't have a Git source URL configured.\"\n />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"Error Loading Rules\"\n description={error}\n />\n </InfoCard>\n );\n }\n\n return (\n <InfoCard title={title} className={styles.root}>\n <div className={styles.filterSection}>\n <Typography variant=\"h6\" gutterBottom>\n Filter Rule Types\n </Typography>\n <div className={styles.filterContainer}>\n {allowedRuleTypes.map(type => (\n <FormControlLabel\n key={type}\n control={\n <Checkbox\n checked={selectedRuleTypes.includes(type)}\n onChange={(e) => handleTypeToggle(type, e.target.checked)}\n />\n }\n label={formatRuleTypeName(type)}\n />\n ))}\n </div>\n <div className={styles.applyFilterButton}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={applyFilters}\n disabled={!hasUnappliedChanges}\n >\n Apply Filter\n </Button>\n {hasUnappliedChanges && (\n <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginTop: 8 }}>\n You have unsaved filter changes. Click \"Apply Filter\" to update the results.\n </Typography>\n )}\n {!hasUnappliedChanges && selectedRuleTypes.length === 0 && (\n <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginTop: 8 }}>\n Select at least one rule type to search for AI rules.\n </Typography>\n )}\n </div>\n </div>\n\n {hasSearched && totalRules === 0 ? (\n <EmptyState\n missing=\"content\"\n title=\"No AI Rules Found\"\n description=\"No AI rules were found in this repository for the selected rule types.\"\n action={\n <Button\n variant=\"outlined\"\n onClick={resetFilters}\n >\n Reset Filters\n </Button>\n }\n />\n ) : totalRules > 0 ? (\n <>\n <div className={styles.statsContainer}>\n <Card className={styles.statCard}>\n <CardContent>\n <Typography variant=\"h4\">{totalRules}</Typography>\n <Typography color=\"textSecondary\">Total Rules</Typography>\n </CardContent>\n </Card>\n {ruleTypeDisplayOrder.map(type => {\n const typeRules = rulesByType[type] || [];\n if (typeRules.length === 0) return null;\n return (\n <Card key={type} className={styles.statCard}>\n <CardContent>\n <Typography variant=\"h4\">{typeRules.length}</Typography>\n <Typography color=\"textSecondary\">{formatRuleTypeName(type)}</Typography>\n </CardContent>\n </Card>\n );\n })}\n </div>\n\n {ruleTypeDisplayOrder.map(type => {\n const typeRules = rulesByType[type] || [];\n if (typeRules.length === 0) return null;\n return (\n <div key={type}>\n <Typography variant=\"h5\" gutterBottom style={{ marginTop: 16 }}>\n {formatRuleTypeName(type)} Rules ({typeRules.length})\n </Typography>\n {typeRules.map(rule => (\n <RuleComponent key={rule.id} rule={rule} />\n ))}\n </div>\n );\n })}\n </>\n ) : (\n <div style={{ marginTop: 16 }}>\n <Typography variant=\"body1\" color=\"textSecondary\">\n Select rule types above and click \"Apply Filter\" to search for AI coding rules in this repository.\n </Typography>\n </div>\n )}\n </InfoCard>\n );\n};"],"names":["rule"],"mappings":"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"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { InfoCard, Progress, EmptyState, CodeSnippet } from '@backstage/core-components';
|
|
4
|
+
import { makeStyles, Accordion, AccordionSummary, Typography, Chip, AccordionDetails } from '@material-ui/core';
|
|
5
|
+
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
6
|
+
import { useMCPServers } from '../../hooks/useMCPServers.esm.js';
|
|
7
|
+
|
|
8
|
+
const useStyles = makeStyles((theme) => ({
|
|
9
|
+
root: {
|
|
10
|
+
"& .MuiAccordion-root": {
|
|
11
|
+
marginBottom: theme.spacing(1),
|
|
12
|
+
"&:before": {
|
|
13
|
+
display: "none"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
sourceAccordion: {
|
|
18
|
+
backgroundColor: theme.palette.background.default,
|
|
19
|
+
marginBottom: theme.spacing(2),
|
|
20
|
+
width: "100%",
|
|
21
|
+
"& .MuiAccordionSummary-root": {
|
|
22
|
+
borderBottom: `1px solid ${theme.palette.divider}`
|
|
23
|
+
},
|
|
24
|
+
"& .MuiAccordionDetails-root": {
|
|
25
|
+
padding: theme.spacing(2),
|
|
26
|
+
display: "flex",
|
|
27
|
+
flexDirection: "column",
|
|
28
|
+
gap: theme.spacing(2)
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
serversList: {
|
|
32
|
+
display: "flex",
|
|
33
|
+
flexDirection: "column",
|
|
34
|
+
gap: theme.spacing(2),
|
|
35
|
+
width: "100%"
|
|
36
|
+
},
|
|
37
|
+
serverAccordion: {
|
|
38
|
+
backgroundColor: theme.palette.background.paper,
|
|
39
|
+
width: "100%",
|
|
40
|
+
"& .MuiAccordionSummary-root": {
|
|
41
|
+
minHeight: "48px",
|
|
42
|
+
"&.Mui-expanded": {
|
|
43
|
+
minHeight: "48px"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"& .MuiAccordionSummary-content": {
|
|
47
|
+
margin: "12px 0",
|
|
48
|
+
"&.Mui-expanded": {
|
|
49
|
+
margin: "12px 0"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"& .MuiAccordionDetails-root": {
|
|
53
|
+
padding: theme.spacing(3)
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
envContainer: {
|
|
57
|
+
backgroundColor: theme.palette.background.default,
|
|
58
|
+
padding: theme.spacing(2),
|
|
59
|
+
borderRadius: theme.shape.borderRadius
|
|
60
|
+
},
|
|
61
|
+
envGrid: {
|
|
62
|
+
display: "grid",
|
|
63
|
+
gridTemplateColumns: "auto 1fr",
|
|
64
|
+
gap: theme.spacing(1),
|
|
65
|
+
alignItems: "center"
|
|
66
|
+
},
|
|
67
|
+
envKey: {
|
|
68
|
+
fontWeight: "bold",
|
|
69
|
+
color: theme.palette.text.secondary,
|
|
70
|
+
padding: theme.spacing(0.5, 1),
|
|
71
|
+
backgroundColor: theme.palette.background.paper,
|
|
72
|
+
borderRadius: theme.shape.borderRadius,
|
|
73
|
+
fontSize: "0.875rem"
|
|
74
|
+
},
|
|
75
|
+
envValue: {
|
|
76
|
+
wordBreak: "break-word",
|
|
77
|
+
padding: theme.spacing(0.5, 1),
|
|
78
|
+
backgroundColor: theme.palette.background.paper,
|
|
79
|
+
borderRadius: theme.shape.borderRadius,
|
|
80
|
+
fontSize: "0.875rem"
|
|
81
|
+
},
|
|
82
|
+
rawConfig: {
|
|
83
|
+
backgroundColor: theme.palette.background.default,
|
|
84
|
+
padding: theme.spacing(2),
|
|
85
|
+
borderRadius: theme.shape.borderRadius,
|
|
86
|
+
"& pre": {
|
|
87
|
+
margin: 0
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
sectionTitle: {
|
|
91
|
+
marginBottom: theme.spacing(1),
|
|
92
|
+
color: theme.palette.text.secondary,
|
|
93
|
+
fontWeight: 500
|
|
94
|
+
},
|
|
95
|
+
serverContent: {
|
|
96
|
+
display: "flex",
|
|
97
|
+
flexDirection: "column",
|
|
98
|
+
gap: theme.spacing(3),
|
|
99
|
+
width: "100%"
|
|
100
|
+
},
|
|
101
|
+
commandContainer: {
|
|
102
|
+
backgroundColor: theme.palette.background.default,
|
|
103
|
+
padding: theme.spacing(2),
|
|
104
|
+
borderRadius: theme.shape.borderRadius,
|
|
105
|
+
fontFamily: "monospace",
|
|
106
|
+
fontSize: "0.9rem",
|
|
107
|
+
overflowX: "auto",
|
|
108
|
+
whiteSpace: "pre"
|
|
109
|
+
},
|
|
110
|
+
detailsContainer: {
|
|
111
|
+
display: "grid",
|
|
112
|
+
gridTemplateColumns: "1fr 1fr",
|
|
113
|
+
gap: theme.spacing(3)
|
|
114
|
+
}
|
|
115
|
+
}));
|
|
116
|
+
const MCPServersComponent = ({ title = "MCP Servers" }) => {
|
|
117
|
+
const styles = useStyles();
|
|
118
|
+
const { servers, loading, error, hasGitUrl } = useMCPServers();
|
|
119
|
+
if (loading) {
|
|
120
|
+
return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(Progress, {}) });
|
|
121
|
+
}
|
|
122
|
+
if (!hasGitUrl) {
|
|
123
|
+
return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(
|
|
124
|
+
EmptyState,
|
|
125
|
+
{
|
|
126
|
+
missing: "content",
|
|
127
|
+
title: "No Git Repository",
|
|
128
|
+
description: "This component doesn't have a Git source URL configured."
|
|
129
|
+
}
|
|
130
|
+
) });
|
|
131
|
+
}
|
|
132
|
+
if (error) {
|
|
133
|
+
return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(
|
|
134
|
+
EmptyState,
|
|
135
|
+
{
|
|
136
|
+
missing: "content",
|
|
137
|
+
title: "Error Loading MCP Servers",
|
|
138
|
+
description: error
|
|
139
|
+
}
|
|
140
|
+
) });
|
|
141
|
+
}
|
|
142
|
+
if (servers.length === 0) {
|
|
143
|
+
return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(
|
|
144
|
+
EmptyState,
|
|
145
|
+
{
|
|
146
|
+
missing: "content",
|
|
147
|
+
title: "No MCP Servers Found",
|
|
148
|
+
description: "No MCP server configurations were found in this repository."
|
|
149
|
+
}
|
|
150
|
+
) });
|
|
151
|
+
}
|
|
152
|
+
const serversBySource = servers.reduce((acc, server) => {
|
|
153
|
+
const source = server.source;
|
|
154
|
+
if (!acc[source]) {
|
|
155
|
+
acc[source] = [];
|
|
156
|
+
}
|
|
157
|
+
acc[source].push(server);
|
|
158
|
+
return acc;
|
|
159
|
+
}, {});
|
|
160
|
+
const formatSourceName = (source) => {
|
|
161
|
+
switch (source) {
|
|
162
|
+
case "vscode":
|
|
163
|
+
return "VSCode";
|
|
164
|
+
case "cursor":
|
|
165
|
+
return "Cursor";
|
|
166
|
+
case "claude":
|
|
167
|
+
return "Claude";
|
|
168
|
+
default:
|
|
169
|
+
return source;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
return /* @__PURE__ */ jsx(InfoCard, { title, className: styles.root, children: Object.entries(serversBySource).map(([source, sourceServers]) => /* @__PURE__ */ jsxs(Accordion, { defaultExpanded: false, className: styles.sourceAccordion, children: [
|
|
173
|
+
/* @__PURE__ */ jsx(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", width: "100%", gap: "16px" }, children: [
|
|
174
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "h6", children: [
|
|
175
|
+
formatSourceName(source),
|
|
176
|
+
" MCP Servers"
|
|
177
|
+
] }),
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
Chip,
|
|
180
|
+
{
|
|
181
|
+
label: `${sourceServers.length} server${sourceServers.length !== 1 ? "s" : ""}`,
|
|
182
|
+
size: "small",
|
|
183
|
+
color: "primary"
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
] }) }),
|
|
187
|
+
/* @__PURE__ */ jsx(AccordionDetails, { children: /* @__PURE__ */ jsx("div", { className: styles.serversList, children: sourceServers.map((server) => /* @__PURE__ */ jsxs(Accordion, { className: styles.serverAccordion, children: [
|
|
188
|
+
/* @__PURE__ */ jsx(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", width: "100%", gap: "16px" }, children: [
|
|
189
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: server.name }),
|
|
190
|
+
/* @__PURE__ */ jsx(
|
|
191
|
+
Chip,
|
|
192
|
+
{
|
|
193
|
+
label: server.type,
|
|
194
|
+
size: "small",
|
|
195
|
+
color: server.type === "local" ? "default" : "secondary",
|
|
196
|
+
variant: "outlined"
|
|
197
|
+
}
|
|
198
|
+
),
|
|
199
|
+
server.config.command && /* @__PURE__ */ jsx(
|
|
200
|
+
Chip,
|
|
201
|
+
{
|
|
202
|
+
label: `${server.config.command}`,
|
|
203
|
+
size: "small",
|
|
204
|
+
variant: "outlined"
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
] }) }),
|
|
208
|
+
/* @__PURE__ */ jsx(AccordionDetails, { children: /* @__PURE__ */ jsxs("div", { className: styles.serverContent, children: [
|
|
209
|
+
server.config.command && /* @__PURE__ */ jsxs("div", { children: [
|
|
210
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", className: styles.sectionTitle, children: "Command" }),
|
|
211
|
+
/* @__PURE__ */ jsxs("div", { className: styles.commandContainer, children: [
|
|
212
|
+
server.config.command,
|
|
213
|
+
" ",
|
|
214
|
+
server.config.args?.join(" ")
|
|
215
|
+
] })
|
|
216
|
+
] }),
|
|
217
|
+
/* @__PURE__ */ jsxs("div", { className: styles.detailsContainer, children: [
|
|
218
|
+
/* @__PURE__ */ jsx("div", { children: server.config.env && Object.keys(server.config.env).length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
219
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", className: styles.sectionTitle, children: "Environment Variables" }),
|
|
220
|
+
/* @__PURE__ */ jsx("div", { className: styles.envContainer, children: /* @__PURE__ */ jsx("div", { className: styles.envGrid, children: Object.entries(server.config.env).map(([key, value]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
221
|
+
/* @__PURE__ */ jsx(Typography, { className: styles.envKey, children: key }),
|
|
222
|
+
/* @__PURE__ */ jsx(Typography, { className: styles.envValue, children: value })
|
|
223
|
+
] }, key)) }) })
|
|
224
|
+
] }) }),
|
|
225
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
226
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", className: styles.sectionTitle, children: "Raw Configuration" }),
|
|
227
|
+
/* @__PURE__ */ jsx("div", { className: styles.rawConfig, children: /* @__PURE__ */ jsx(CodeSnippet, { text: server.rawConfig, language: "json" }) })
|
|
228
|
+
] })
|
|
229
|
+
] })
|
|
230
|
+
] }) })
|
|
231
|
+
] }, server.name)) }) })
|
|
232
|
+
] }, source)) });
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export { MCPServersComponent };
|
|
236
|
+
//# sourceMappingURL=MCPServersComponent.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MCPServersComponent.esm.js","sources":["../../../src/components/MCPServersComponent/MCPServersComponent.tsx"],"sourcesContent":["import React from 'react';\nimport {\n InfoCard,\n Progress,\n EmptyState,\n CodeSnippet,\n} from '@backstage/core-components';\nimport {\n makeStyles,\n Typography,\n Chip,\n Accordion,\n AccordionSummary,\n AccordionDetails,\n} from '@material-ui/core';\nimport { Theme } from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { MCPServerInfo } from '../../types/mcp';\nimport { useMCPServers } from '../../hooks/useMCPServers';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n root: {\n '& .MuiAccordion-root': {\n marginBottom: theme.spacing(1),\n '&:before': {\n display: 'none',\n },\n },\n },\n sourceAccordion: {\n backgroundColor: theme.palette.background.default,\n marginBottom: theme.spacing(2),\n width: '100%',\n '& .MuiAccordionSummary-root': {\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n '& .MuiAccordionDetails-root': {\n padding: theme.spacing(2),\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(2),\n },\n },\n serversList: {\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(2),\n width: '100%',\n },\n serverAccordion: {\n backgroundColor: theme.palette.background.paper,\n width: '100%',\n '& .MuiAccordionSummary-root': {\n minHeight: '48px',\n '&.Mui-expanded': {\n minHeight: '48px',\n },\n },\n '& .MuiAccordionSummary-content': {\n margin: '12px 0',\n '&.Mui-expanded': {\n margin: '12px 0',\n },\n },\n '& .MuiAccordionDetails-root': {\n padding: theme.spacing(3),\n },\n },\n envContainer: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2),\n borderRadius: theme.shape.borderRadius,\n },\n envGrid: {\n display: 'grid',\n gridTemplateColumns: 'auto 1fr',\n gap: theme.spacing(1),\n alignItems: 'center',\n },\n envKey: {\n fontWeight: 'bold',\n color: theme.palette.text.secondary,\n padding: theme.spacing(0.5, 1),\n backgroundColor: theme.palette.background.paper,\n borderRadius: theme.shape.borderRadius,\n fontSize: '0.875rem',\n },\n envValue: {\n wordBreak: 'break-word',\n padding: theme.spacing(0.5, 1),\n backgroundColor: theme.palette.background.paper,\n borderRadius: theme.shape.borderRadius,\n fontSize: '0.875rem',\n },\n rawConfig: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2),\n borderRadius: theme.shape.borderRadius,\n '& pre': {\n margin: 0,\n },\n },\n sectionTitle: {\n marginBottom: theme.spacing(1),\n color: theme.palette.text.secondary,\n fontWeight: 500,\n },\n serverContent: {\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(3),\n width: '100%',\n },\n commandContainer: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2),\n borderRadius: theme.shape.borderRadius,\n fontFamily: 'monospace',\n fontSize: '0.9rem',\n overflowX: 'auto',\n whiteSpace: 'pre',\n },\n detailsContainer: {\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n gap: theme.spacing(3),\n },\n}));\n\n\nexport interface MCPServersComponentProps {\n title?: string;\n}\n\nexport const MCPServersComponent = ({ title = \"MCP Servers\" }: MCPServersComponentProps) => {\n const styles = useStyles();\n const { servers, loading, error, hasGitUrl } = useMCPServers();\n\n if (loading) {\n return (\n <InfoCard title={title}>\n <Progress />\n </InfoCard>\n );\n }\n\n if (!hasGitUrl) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"No Git Repository\"\n description=\"This component doesn't have a Git source URL configured.\"\n />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"Error Loading MCP Servers\"\n description={error}\n />\n </InfoCard>\n );\n }\n\n if (servers.length === 0) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"No MCP Servers Found\"\n description=\"No MCP server configurations were found in this repository.\"\n />\n </InfoCard>\n );\n }\n\n // Group servers by source\n const serversBySource = servers.reduce((acc, server) => {\n const source = server.source;\n if (!acc[source]) {\n acc[source] = [];\n }\n acc[source].push(server);\n return acc;\n }, {} as Record<string, MCPServerInfo[]>);\n\n const formatSourceName = (source: string) => {\n switch (source) {\n case 'vscode':\n return 'VSCode';\n case 'cursor':\n return 'Cursor';\n case 'claude':\n return 'Claude';\n default:\n return source;\n }\n };\n\n return (\n <InfoCard title={title} className={styles.root}>\n {Object.entries(serversBySource).map(([source, sourceServers]) => (\n <Accordion key={source} defaultExpanded={false} className={styles.sourceAccordion}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div style={{ display: 'flex', alignItems: 'center', width: '100%', gap: '16px' }}>\n <Typography variant=\"h6\">\n {formatSourceName(source)} MCP Servers\n </Typography>\n <Chip\n label={`${sourceServers.length} server${sourceServers.length !== 1 ? 's' : ''}`}\n size=\"small\"\n color=\"primary\"\n />\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div className={styles.serversList}>\n {sourceServers.map((server) => (\n <Accordion key={server.name} className={styles.serverAccordion}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div style={{ display: 'flex', alignItems: 'center', width: '100%', gap: '16px' }}>\n <Typography variant=\"subtitle1\">{server.name}</Typography>\n <Chip \n label={server.type} \n size=\"small\" \n color={server.type === 'local' ? 'default' : 'secondary'}\n variant=\"outlined\"\n />\n {server.config.command && (\n <Chip \n label={`${server.config.command}`}\n size=\"small\"\n variant=\"outlined\"\n />\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div className={styles.serverContent}>\n {server.config.command && (\n <div>\n <Typography variant=\"subtitle2\" className={styles.sectionTitle}>Command</Typography>\n <div className={styles.commandContainer}>\n {server.config.command} {server.config.args?.join(' ')}\n </div>\n </div>\n )}\n <div className={styles.detailsContainer}>\n <div>\n {server.config.env && Object.keys(server.config.env).length > 0 && (\n <>\n <Typography variant=\"subtitle2\" className={styles.sectionTitle}>Environment Variables</Typography>\n <div className={styles.envContainer}>\n <div className={styles.envGrid}>\n {Object.entries(server.config.env).map(([key, value]) => (\n <React.Fragment key={key}>\n <Typography className={styles.envKey}>{key}</Typography>\n <Typography className={styles.envValue}>{value}</Typography>\n </React.Fragment>\n ))}\n </div>\n </div>\n </>\n )}\n </div>\n <div>\n <Typography variant=\"subtitle2\" className={styles.sectionTitle}>Raw Configuration</Typography>\n <div className={styles.rawConfig}>\n <CodeSnippet text={server.rawConfig} language=\"json\" />\n </div>\n </div>\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n ))}\n </div>\n </AccordionDetails>\n </Accordion>\n ))}\n </InfoCard>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
2
|
+
import { useState, useCallback, useEffect } from 'react';
|
|
3
|
+
import { aiRulesApiRef } from '../api/types.esm.js';
|
|
4
|
+
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
5
|
+
|
|
6
|
+
const useMCPServers = () => {
|
|
7
|
+
const api = useApi(aiRulesApiRef);
|
|
8
|
+
const { entity } = useEntity();
|
|
9
|
+
const [loading, setLoading] = useState(false);
|
|
10
|
+
const [error, setError] = useState();
|
|
11
|
+
const [servers, setServers] = useState([]);
|
|
12
|
+
const [hasGitUrl, setHasGitUrl] = useState(true);
|
|
13
|
+
const sourceLocation = entity.metadata?.annotations?.["backstage.io/source-location"];
|
|
14
|
+
const fetchServers = useCallback(async () => {
|
|
15
|
+
if (!sourceLocation) {
|
|
16
|
+
setHasGitUrl(false);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
setLoading(true);
|
|
21
|
+
setError(void 0);
|
|
22
|
+
const gitUrl = sourceLocation.replace("url:", "").replace(/\/tree\/(?:main|master)\/.*$/, "");
|
|
23
|
+
const response = await api.getMCPServers(gitUrl);
|
|
24
|
+
setServers(response.servers);
|
|
25
|
+
} catch (err) {
|
|
26
|
+
setError(err.message);
|
|
27
|
+
} finally {
|
|
28
|
+
setLoading(false);
|
|
29
|
+
}
|
|
30
|
+
}, [api, sourceLocation]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
fetchServers();
|
|
33
|
+
}, [fetchServers]);
|
|
34
|
+
return {
|
|
35
|
+
loading,
|
|
36
|
+
error,
|
|
37
|
+
servers,
|
|
38
|
+
hasGitUrl,
|
|
39
|
+
refetch: fetchServers
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { useMCPServers };
|
|
44
|
+
//# sourceMappingURL=useMCPServers.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMCPServers.esm.js","sources":["../../src/hooks/useMCPServers.ts"],"sourcesContent":["import { useApi } from '@backstage/core-plugin-api';\nimport { useCallback, useEffect, useState } from 'react';\nimport { aiRulesApiRef } from '../api/types';\nimport type { AiRulesApi } from '../api/types';\nimport { MCPServerInfo } from '../types/mcp';\nimport { useEntity } from '@backstage/plugin-catalog-react';\n\nexport const useMCPServers = () => {\n const api = useApi(aiRulesApiRef) as AiRulesApi;\n const { entity } = useEntity();\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string>();\n const [servers, setServers] = useState<MCPServerInfo[]>([]);\n const [hasGitUrl, setHasGitUrl] = useState(true);\n\n const sourceLocation = entity.metadata?.annotations?.['backstage.io/source-location'];\n\n const fetchServers = useCallback(async () => {\n if (!sourceLocation) {\n setHasGitUrl(false);\n return;\n }\n\n try {\n setLoading(true);\n setError(undefined);\n // Clean up the Git URL - remove url: prefix and /tree/main/ or /tree/master/\n const gitUrl = sourceLocation\n .replace('url:', '')\n .replace(/\\/tree\\/(?:main|master)\\/.*$/, '');\n const response = await api.getMCPServers(gitUrl);\n setServers(response.servers);\n } catch (err) {\n setError((err as Error).message);\n } finally {\n setLoading(false);\n }\n }, [api, sourceLocation]);\n\n useEffect(() => {\n fetchServers();\n }, [fetchServers]);\n\n return {\n loading,\n error,\n servers,\n hasGitUrl,\n refetch: fetchServers,\n };\n};\n"],"names":[],"mappings":";;;;;AAOO,MAAM,gBAAgB,MAAM;AACjC,EAAM,MAAA,GAAA,GAAM,OAAO,aAAa,CAAA;AAChC,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAiB,EAAA;AAC3C,EAAA,MAAM,CAAC,OAAS,EAAA,UAAU,CAAI,GAAA,QAAA,CAA0B,EAAE,CAAA;AAC1D,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,IAAI,CAAA;AAE/C,EAAA,MAAM,cAAiB,GAAA,MAAA,CAAO,QAAU,EAAA,WAAA,GAAc,8BAA8B,CAAA;AAEpF,EAAM,MAAA,YAAA,GAAe,YAAY,YAAY;AAC3C,IAAA,IAAI,CAAC,cAAgB,EAAA;AACnB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA;AAAA;AAGF,IAAI,IAAA;AACF,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,QAAA,CAAS,KAAS,CAAA,CAAA;AAElB,MAAM,MAAA,MAAA,GAAS,eACZ,OAAQ,CAAA,MAAA,EAAQ,EAAE,CAClB,CAAA,OAAA,CAAQ,gCAAgC,EAAE,CAAA;AAC7C,MAAA,MAAM,QAAW,GAAA,MAAM,GAAI,CAAA,aAAA,CAAc,MAAM,CAAA;AAC/C,MAAA,UAAA,CAAW,SAAS,OAAO,CAAA;AAAA,aACpB,GAAK,EAAA;AACZ,MAAA,QAAA,CAAU,IAAc,OAAO,CAAA;AAAA,KAC/B,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACC,EAAA,CAAC,GAAK,EAAA,cAAc,CAAC,CAAA;AAExB,EAAA,SAAA,CAAU,MAAM;AACd,IAAa,YAAA,EAAA;AAAA,GACf,EAAG,CAAC,YAAY,CAAC,CAAA;AAEjB,EAAO,OAAA;AAAA,IACL,OAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAS,EAAA;AAAA,GACX;AACF;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import { Entity } from '@backstage/catalog-model';
|
|
3
2
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
3
|
+
import React__default from 'react';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
interface AiInstructionsComponentProps {
|
|
7
|
+
title?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const AiInstructionsComponent: ({ title }: AiInstructionsComponentProps) => react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
interface MCPServersComponentProps {
|
|
12
|
+
title?: string;
|
|
13
|
+
}
|
|
14
|
+
declare const MCPServersComponent: ({ title }: MCPServersComponentProps) => react_jsx_runtime.JSX.Element;
|
|
4
15
|
|
|
5
16
|
interface AIRulesComponentProps {
|
|
6
17
|
title?: string;
|
|
@@ -10,7 +21,7 @@ declare const isAIRulesAvailable: (entity: Entity) => boolean;
|
|
|
10
21
|
declare const aiRulesPlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
11
22
|
root: _backstage_core_plugin_api.RouteRef<undefined>;
|
|
12
23
|
}, {}, {}>;
|
|
13
|
-
declare const AIRulesComponent: (
|
|
24
|
+
declare const AIRulesComponent: (props: any) => React__default.FunctionComponentElement<AIRulesComponentProps>;
|
|
14
25
|
|
|
15
26
|
declare enum AIRuleType {
|
|
16
27
|
CURSOR = "cursor",
|
|
@@ -37,7 +48,10 @@ interface CopilotRule {
|
|
|
37
48
|
fileName: string;
|
|
38
49
|
gitUrl?: string;
|
|
39
50
|
content: string;
|
|
40
|
-
order
|
|
51
|
+
order?: number;
|
|
52
|
+
title?: string;
|
|
53
|
+
applyTo?: string;
|
|
54
|
+
frontmatter?: Record<string, any>;
|
|
41
55
|
}
|
|
42
56
|
interface ClineRule {
|
|
43
57
|
type: AIRuleType.CLINE;
|
|
@@ -71,4 +85,48 @@ interface AIRulesConfig {
|
|
|
71
85
|
allowedRuleTypes?: AIRuleType[];
|
|
72
86
|
}
|
|
73
87
|
|
|
74
|
-
|
|
88
|
+
interface MCPServerConfig {
|
|
89
|
+
type?: 'stdio' | 'remote';
|
|
90
|
+
command?: string;
|
|
91
|
+
args?: string[];
|
|
92
|
+
env?: Record<string, string>;
|
|
93
|
+
url?: string;
|
|
94
|
+
headers?: Record<string, string>;
|
|
95
|
+
}
|
|
96
|
+
interface MCPServerInfo {
|
|
97
|
+
name: string;
|
|
98
|
+
type: 'local' | 'remote';
|
|
99
|
+
config: MCPServerConfig;
|
|
100
|
+
source: 'cursor' | 'vscode' | 'claude';
|
|
101
|
+
rawConfig: string;
|
|
102
|
+
}
|
|
103
|
+
interface MCPServersResponse {
|
|
104
|
+
servers: MCPServerInfo[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
declare const aiRulesApiRef: _backstage_core_plugin_api.ApiRef<AiRulesApi>;
|
|
108
|
+
interface AiRulesApi {
|
|
109
|
+
getAiRules(ruleTypes: string[]): Promise<AIRulesResponse>;
|
|
110
|
+
getMCPServers(gitUrl: string): Promise<MCPServersResponse>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
declare class AiRulesClient implements AiRulesApi {
|
|
114
|
+
private readonly discoveryApi;
|
|
115
|
+
private readonly identityApi;
|
|
116
|
+
constructor(options: {
|
|
117
|
+
discoveryApi: {
|
|
118
|
+
getBaseUrl: (pluginId: string) => Promise<string>;
|
|
119
|
+
};
|
|
120
|
+
identityApi: {
|
|
121
|
+
getCredentials(): Promise<{
|
|
122
|
+
token?: string;
|
|
123
|
+
}>;
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
private getAuthHeaders;
|
|
127
|
+
private cleanGitUrl;
|
|
128
|
+
getAiRules(ruleTypes: string[]): Promise<AIRulesResponse>;
|
|
129
|
+
getMCPServers(gitUrl: string): Promise<MCPServersResponse>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export { type AIRule, AIRuleType, AIRulesComponent, type AIRulesComponentProps, type AIRulesConfig, type AIRulesResponse, AiInstructionsComponent, type AiInstructionsComponentProps, type AiRulesApi, AiRulesClient, type ClaudeCodeRule, type ClineRule, type CopilotRule, type CursorRule, type MCPServerConfig, type MCPServerInfo, MCPServersComponent, type MCPServersComponentProps, type MCPServersResponse, aiRulesApiRef, aiRulesPlugin, isAIRulesAvailable };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export { AIRulesComponent, aiRulesPlugin } from './plugin.esm.js';
|
|
2
2
|
export { AIRuleType } from './types.esm.js';
|
|
3
|
+
export { MCPServersComponent } from './components/MCPServersComponent/MCPServersComponent.esm.js';
|
|
4
|
+
export { AiInstructionsComponent } from './components/AiInstructionsComponent/AiInstructionsComponent.esm.js';
|
|
3
5
|
export { isAIRulesAvailable } from './components/AiRulesComponent/AiRulesComponent.esm.js';
|
|
6
|
+
export { aiRulesApiRef } from './api/types.esm.js';
|
|
7
|
+
export { AiRulesClient } from './api/AiRulesClient.esm.js';
|
|
4
8
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
package/dist/plugin.esm.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createPlugin, createComponentExtension } from '@backstage/core-plugin-api';
|
|
2
2
|
import { rootRouteRef } from './routes.esm.js';
|
|
3
|
+
import React from 'react';
|
|
3
4
|
|
|
4
5
|
const aiRulesPlugin = createPlugin({
|
|
5
6
|
id: "ai-rules",
|
|
@@ -11,7 +12,23 @@ const AIRulesComponent = aiRulesPlugin.provide(
|
|
|
11
12
|
createComponentExtension({
|
|
12
13
|
name: "AIRulesComponent",
|
|
13
14
|
component: {
|
|
14
|
-
lazy: () => import('./components/AiRulesComponent/AiRulesComponent.esm.js').then((m) => m.AIRulesComponent)
|
|
15
|
+
lazy: () => import('./components/AiRulesComponent/AiRulesComponent.esm.js').then((m) => m.AIRulesComponent).then((Component) => (props) => React.createElement(Component, props))
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
aiRulesPlugin.provide(
|
|
20
|
+
createComponentExtension({
|
|
21
|
+
name: "MCPServersComponent",
|
|
22
|
+
component: {
|
|
23
|
+
lazy: () => import('./components/MCPServersComponent/MCPServersComponent.esm.js').then((m) => m.MCPServersComponent).then((Component) => (props) => React.createElement(Component, props))
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
aiRulesPlugin.provide(
|
|
28
|
+
createComponentExtension({
|
|
29
|
+
name: "AiInstructionsComponent",
|
|
30
|
+
component: {
|
|
31
|
+
lazy: () => import('./components/AiInstructionsComponent/AiInstructionsComponent.esm.js').then((m) => m.AiInstructionsComponent).then((Component) => (props) => React.createElement(Component, props))
|
|
15
32
|
}
|
|
16
33
|
})
|
|
17
34
|
);
|
package/dist/plugin.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import { createPlugin, createComponentExtension } from '@backstage/core-plugin-api';\nimport { rootRouteRef } from './routes';\n\nexport const aiRulesPlugin = createPlugin({\n id: 'ai-rules',\n routes: {\n root: rootRouteRef,\n },\n});\n\nexport const AIRulesComponent = aiRulesPlugin.provide(\n createComponentExtension({\n name: 'AIRulesComponent',\n component: {\n lazy: () => import('./components/AiRulesComponent/AiRulesComponent').then(m => m.AIRulesComponent),\n },\n }),\n);"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import { createPlugin, createComponentExtension } from '@backstage/core-plugin-api';\nimport { rootRouteRef } from './routes';\nimport React from 'react';\n\nexport const aiRulesPlugin = createPlugin({\n id: 'ai-rules',\n routes: {\n root: rootRouteRef,\n },\n});\n\nexport const AIRulesComponent = aiRulesPlugin.provide(\n createComponentExtension({\n name: 'AIRulesComponent',\n component: {\n lazy: () => import('./components/AiRulesComponent/AiRulesComponent').then(m => m.AIRulesComponent)\n .then(Component => (props: any) => React.createElement(Component, props)),\n },\n }),\n);\n\nexport const MCPServersComponent = aiRulesPlugin.provide(\n createComponentExtension({\n name: 'MCPServersComponent',\n component: {\n lazy: () => import('./components/MCPServersComponent/MCPServersComponent').then(m => m.MCPServersComponent)\n .then(Component => (props: any) => React.createElement(Component, props)),\n },\n }),\n);\n\nexport const AiInstructionsComponent = aiRulesPlugin.provide(\n createComponentExtension({\n name: 'AiInstructionsComponent',\n component: {\n lazy: () => import('./components/AiInstructionsComponent/AiInstructionsComponent').then(m => m.AiInstructionsComponent)\n .then(Component => (props: any) => React.createElement(Component, props)),\n },\n }),\n);"],"names":[],"mappings":";;;;AAIO,MAAM,gBAAgB,YAAa,CAAA;AAAA,EACxC,EAAI,EAAA,UAAA;AAAA,EACJ,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAEM,MAAM,mBAAmB,aAAc,CAAA,OAAA;AAAA,EAC5C,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,kBAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,MAAM,MAAM,OAAO,uDAAgD,CAAE,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,gBAAgB,CAC9F,CAAA,IAAA,CAAK,eAAa,CAAC,KAAA,KAAe,MAAM,aAAc,CAAA,SAAA,EAAW,KAAK,CAAC;AAAA;AAC5E,GACD;AACH;AAEmC,aAAc,CAAA,OAAA;AAAA,EAC/C,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,qBAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,MAAM,MAAM,OAAO,6DAAsD,CAAE,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,mBAAmB,CACvG,CAAA,IAAA,CAAK,eAAa,CAAC,KAAA,KAAe,MAAM,aAAc,CAAA,SAAA,EAAW,KAAK,CAAC;AAAA;AAC5E,GACD;AACH;AAEuC,aAAc,CAAA,OAAA;AAAA,EACnD,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,yBAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,MAAM,MAAM,OAAO,qEAA8D,CAAE,CAAA,IAAA,CAAK,OAAK,CAAE,CAAA,uBAAuB,CACnH,CAAA,IAAA,CAAK,eAAa,CAAC,KAAA,KAAe,MAAM,aAAc,CAAA,SAAA,EAAW,KAAK,CAAC;AAAA;AAC5E,GACD;AACH;;;;"}
|
package/dist/types.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.esm.js","sources":["../src/types.ts"],"sourcesContent":["export enum AIRuleType {\n CURSOR = 'cursor',\n COPILOT = 'copilot', \n CLINE = 'cline',\n CLAUDE_CODE = 'claude-code',\n}\n\nexport interface CursorRule {\n type: AIRuleType.CURSOR;\n id: string;\n filePath: string;\n fileName: string;\n gitUrl?: string;\n description?: string;\n globs?: string[];\n alwaysApply?: boolean;\n frontmatter?: Record<string, any>;\n content: string;\n}\n\nexport interface CopilotRule {\n type: AIRuleType.COPILOT;\n id: string;\n filePath: string;\n fileName: string;\n gitUrl?: string;\n content: string;\n order
|
|
1
|
+
{"version":3,"file":"types.esm.js","sources":["../src/types.ts"],"sourcesContent":["export enum AIRuleType {\n CURSOR = 'cursor',\n COPILOT = 'copilot', \n CLINE = 'cline',\n CLAUDE_CODE = 'claude-code',\n}\n\nexport interface CursorRule {\n type: AIRuleType.CURSOR;\n id: string;\n filePath: string;\n fileName: string;\n gitUrl?: string;\n description?: string;\n globs?: string[];\n alwaysApply?: boolean;\n frontmatter?: Record<string, any>;\n content: string;\n}\n\nexport interface CopilotRule {\n type: AIRuleType.COPILOT;\n id: string;\n filePath: string;\n fileName: string;\n gitUrl?: string;\n content: string;\n order?: number; // Position in the file (legacy)\n title?: string;\n applyTo?: string;\n frontmatter?: Record<string, any>;\n}\n\nexport interface ClineRule {\n type: AIRuleType.CLINE;\n id: string;\n filePath: string;\n fileName: string;\n gitUrl?: string;\n content: string;\n title?: string;\n sections?: Array<{\n title: string;\n content: string;\n }>;\n}\n\nexport interface ClaudeCodeRule {\n type: AIRuleType.CLAUDE_CODE;\n id: string;\n filePath: string;\n fileName: string;\n gitUrl?: string;\n content: string;\n title?: string;\n}\n\nexport type AIRule = CursorRule | CopilotRule | ClineRule | ClaudeCodeRule;\n\nexport interface AIRulesResponse {\n rules: AIRule[];\n totalCount: number;\n ruleTypes: AIRuleType[];\n}\n\nexport interface AIRulesConfig {\n allowedRuleTypes?: AIRuleType[];\n}"],"names":["AIRuleType"],"mappings":"AAAY,IAAA,UAAA,qBAAAA,WAAL,KAAA;AACL,EAAAA,YAAA,QAAS,CAAA,GAAA,QAAA;AACT,EAAAA,YAAA,SAAU,CAAA,GAAA,SAAA;AACV,EAAAA,YAAA,OAAQ,CAAA,GAAA,OAAA;AACR,EAAAA,YAAA,aAAc,CAAA,GAAA,aAAA;AAJJ,EAAAA,OAAAA,WAAAA;AAAA,CAAA,EAAA,UAAA,IAAA,EAAA;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terasky/backstage-plugin-ai-rules",
|
|
3
3
|
"description": "AI Rules Visualizer Plugin for Backstage",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"main": "dist/index.esm.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"@backstage/catalog-model": "^1.7.5",
|
|
40
40
|
"@backstage/core-components": "^0.17.5",
|
|
41
41
|
"@backstage/core-plugin-api": "^1.10.9",
|
|
42
|
+
"@backstage/frontend-plugin-api": "^0.11.0",
|
|
42
43
|
"@backstage/plugin-catalog-react": "^1.20.1",
|
|
43
44
|
"@backstage/theme": "^0.6.8",
|
|
44
45
|
"@material-ui/core": "^4.12.4",
|
|
@@ -71,8 +72,24 @@
|
|
|
71
72
|
"copilot",
|
|
72
73
|
"cline"
|
|
73
74
|
],
|
|
75
|
+
"exports": {
|
|
76
|
+
".": {
|
|
77
|
+
"import": "./dist/index.esm.js",
|
|
78
|
+
"types": "./dist/index.d.ts",
|
|
79
|
+
"default": "./dist/index.esm.js"
|
|
80
|
+
},
|
|
81
|
+
"./alpha": {
|
|
82
|
+
"import": "./dist/alpha.esm.js",
|
|
83
|
+
"types": "./dist/alpha.d.ts",
|
|
84
|
+
"default": "./dist/alpha.esm.js"
|
|
85
|
+
},
|
|
86
|
+
"./package.json": "./package.json"
|
|
87
|
+
},
|
|
74
88
|
"typesVersions": {
|
|
75
89
|
"*": {
|
|
90
|
+
"alpha": [
|
|
91
|
+
"dist/alpha.d.ts"
|
|
92
|
+
],
|
|
76
93
|
"package.json": [
|
|
77
94
|
"package.json"
|
|
78
95
|
]
|