@terasky/backstage-plugin-ai-rules 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/config.d.ts +11 -9
  2. package/dist/alpha.esm.js +30 -0
  3. package/dist/alpha.esm.js.map +1 -1
  4. package/dist/api/AiRulesClient.esm.js +27 -19
  5. package/dist/api/AiRulesClient.esm.js.map +1 -1
  6. package/dist/api/types.esm.js.map +1 -1
  7. package/dist/components/AgentConfigsComponent/AgentConfigsComponent.esm.js +91 -0
  8. package/dist/components/AgentConfigsComponent/AgentConfigsComponent.esm.js.map +1 -0
  9. package/dist/components/AgentSkillsComponent/AgentSkillsComponent.esm.js +225 -0
  10. package/dist/components/AgentSkillsComponent/AgentSkillsComponent.esm.js.map +1 -0
  11. package/dist/components/AiInstructionsComponent/AiInstructionsComponent.esm.js +13 -3
  12. package/dist/components/AiInstructionsComponent/AiInstructionsComponent.esm.js.map +1 -1
  13. package/dist/components/AiRulesComponent/AiRulesComponent.esm.js +327 -248
  14. package/dist/components/AiRulesComponent/AiRulesComponent.esm.js.map +1 -1
  15. package/dist/components/IgnoreFilesComponent/IgnoreFilesComponent.esm.js +86 -0
  16. package/dist/components/IgnoreFilesComponent/IgnoreFilesComponent.esm.js.map +1 -0
  17. package/dist/components/MCPServersComponent/MCPServersComponent.esm.js +4 -0
  18. package/dist/components/MCPServersComponent/MCPServersComponent.esm.js.map +1 -1
  19. package/dist/hooks/useAgentConfigs.esm.js +38 -0
  20. package/dist/hooks/useAgentConfigs.esm.js.map +1 -0
  21. package/dist/hooks/useAiRules.esm.js +13 -1
  22. package/dist/hooks/useAiRules.esm.js.map +1 -1
  23. package/dist/hooks/useIgnoreFiles.esm.js +38 -0
  24. package/dist/hooks/useIgnoreFiles.esm.js.map +1 -0
  25. package/dist/hooks/useSkills.esm.js +38 -0
  26. package/dist/hooks/useSkills.esm.js.map +1 -0
  27. package/dist/index.d.ts +143 -7
  28. package/dist/index.esm.js +3 -0
  29. package/dist/index.esm.js.map +1 -1
  30. package/dist/plugin.esm.js +24 -0
  31. package/dist/plugin.esm.js.map +1 -1
  32. package/dist/types.esm.js +7 -0
  33. package/dist/types.esm.js.map +1 -1
  34. package/package.json +11 -11
package/config.d.ts CHANGED
@@ -6,18 +6,20 @@ export interface Config {
6
6
  */
7
7
  aiRules?: {
8
8
  /**
9
- * Allowed rule types to search for in repositories
10
- * Defaults to ["cursor", "copilot", "cline", "claude-code"] if not specified
9
+ * Allowed rule types to search for in repositories.
10
+ * Supported values: "cursor", "copilot", "cline", "claude-code",
11
+ * "windsurf", "roo-code", "codex", "gemini", "amazon-q", "continue", "aider"
12
+ * Defaults to all supported types if not specified.
11
13
  * @visibility frontend
12
14
  */
13
- allowedRuleTypes: string[]; // e.g. ["cursor", "copilot", "cline", "claude-code"]
15
+ allowedRuleTypes: string[];
14
16
  /**
15
- * Default rule types to be pre-selected when the component loads
16
- * If not provided, defaults to empty array (no rules pre-selected)
17
- * If empty array, no rule types are pre-selected
18
- * If specific array, those rule types are pre-selected
17
+ * Default rule types to be pre-selected when the component loads.
18
+ * If not provided, defaults to empty array (no rules pre-selected).
19
+ * If empty array, no rule types are pre-selected.
20
+ * If specific array, those rule types are pre-selected.
19
21
  * @visibility frontend
20
22
  */
21
- defaultRuleTypes?: string[]; // e.g. ["cursor", "copilot"]
23
+ defaultRuleTypes?: string[];
22
24
  }
23
- }
25
+ }
package/dist/alpha.esm.js CHANGED
@@ -38,6 +38,36 @@ const aiRulesPlugin = createFrontendPlugin({
38
38
  },
39
39
  disabled: true
40
40
  }),
41
+ EntityContentBlueprint.make({
42
+ name: "ignoreFiles",
43
+ params: {
44
+ path: "/ignore-files",
45
+ filter: isAIRulesAvailable,
46
+ title: "Ignore Files",
47
+ loader: () => import('./components/IgnoreFilesComponent/IgnoreFilesComponent.esm.js').then((m) => /* @__PURE__ */ jsx(m.IgnoreFilesComponent, {}))
48
+ },
49
+ disabled: true
50
+ }),
51
+ EntityContentBlueprint.make({
52
+ name: "agentConfigs",
53
+ params: {
54
+ path: "/agent-configs",
55
+ filter: isAIRulesAvailable,
56
+ title: "Agent Configs",
57
+ loader: () => import('./components/AgentConfigsComponent/AgentConfigsComponent.esm.js').then((m) => /* @__PURE__ */ jsx(m.AgentConfigsComponent, {}))
58
+ },
59
+ disabled: true
60
+ }),
61
+ EntityContentBlueprint.make({
62
+ name: "agentSkills",
63
+ params: {
64
+ path: "/agent-skills",
65
+ filter: isAIRulesAvailable,
66
+ title: "Agent Skills",
67
+ loader: () => import('./components/AgentSkillsComponent/AgentSkillsComponent.esm.js').then((m) => /* @__PURE__ */ jsx(m.AgentSkillsComponent, {}))
68
+ },
69
+ disabled: true
70
+ }),
41
71
  ApiBlueprint.make({
42
72
  name: "aiRulesApi",
43
73
  params: (defineParams) => defineParams({
@@ -1 +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 name: 'aiRules',\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 name: 'aiInstructions',\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 name: 'mcpServers',\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});\nexport default aiRulesPlugin;"],"names":[],"mappings":";;;;;;;AAWO,MAAM,gBAAgB,oBAAA,CAAqB;AAAA,EAChD,QAAA,EAAU,UAAA;AAAA,EACV,UAAA,EAAY;AAAA,IACV,uBAAuB,IAAA,CAAK;AAAA,MAC1B,IAAA,EAAM,SAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,WAAA;AAAA,QACN,MAAA,EAAQ,kBAAA;AAAA,QACR,KAAA,EAAO,UAAA;AAAA,QACP,MAAA,EAAQ,MAAM,OAAO,uDAAgD,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,gBAAA,EAAF,EAAmB,CAAE;AAAA,OACzG;AAAA,MACA,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,IACD,uBAAuB,IAAA,CAAK;AAAA,MAC1B,IAAA,EAAM,gBAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,kBAAA;AAAA,QACN,MAAA,EAAQ,kBAAA;AAAA,QACR,KAAA,EAAO,iBAAA;AAAA,QACP,MAAA,EAAQ,MAAM,OAAO,qEAA8D,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,uBAAA,EAAF,EAA0B,CAAE;AAAA,OAC9H;AAAA,MACA,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,IACD,uBAAuB,IAAA,CAAK;AAAA,MAC1B,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,cAAA;AAAA,QACN,MAAA,EAAQ,kBAAA;AAAA,QACR,KAAA,EAAO,aAAA;AAAA,QACP,MAAA,EAAQ,MAAM,OAAO,6DAAsD,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,qBAAK,GAAA,CAAC,CAAA,CAAE,mBAAA,EAAF,EAAsB,CAAE;AAAA,OAClH;AAAA,MACA,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,IACD,aAAa,IAAA,CAAK;AAAA,MAChB,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ,kBAAgB,YAAA,CAAa;AAAA,QACnC,GAAA,EAAK,aAAA;AAAA,QACL,IAAA,EAAM;AAAA,UACJ,YAAA,EAAc,eAAA;AAAA,UACd,WAAA,EAAa;AAAA,SACf;AAAA,QACA,OAAA,EAAS,CAAC,EAAE,YAAA,EAAc,WAAA,EAAY,KAAM,IAAI,aAAA,CAAc,EAAE,YAAA,EAAc,WAAA,EAAa;AAAA,OAC5F,CAAA;AAAA,MACD,QAAA,EAAU;AAAA,KACX;AAAA;AAEL,CAAC;;;;"}
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 name: 'aiRules',\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 name: 'aiInstructions',\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 name: 'mcpServers',\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 EntityContentBlueprint.make({\n name: 'ignoreFiles',\n params: {\n path: '/ignore-files',\n filter: isAIRulesAvailable,\n title: 'Ignore Files',\n loader: () => import('./components/IgnoreFilesComponent/IgnoreFilesComponent').then(m => <m.IgnoreFilesComponent />),\n },\n disabled: true,\n }),\n EntityContentBlueprint.make({\n name: 'agentConfigs',\n params: {\n path: '/agent-configs',\n filter: isAIRulesAvailable,\n title: 'Agent Configs',\n loader: () => import('./components/AgentConfigsComponent/AgentConfigsComponent').then(m => <m.AgentConfigsComponent />),\n },\n disabled: true,\n }),\n EntityContentBlueprint.make({\n name: 'agentSkills',\n params: {\n path: '/agent-skills',\n filter: isAIRulesAvailable,\n title: 'Agent Skills',\n loader: () => import('./components/AgentSkillsComponent/AgentSkillsComponent').then(m => <m.AgentSkillsComponent />),\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});\nexport default aiRulesPlugin;\n"],"names":[],"mappings":"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"}
@@ -7,9 +7,7 @@ class AiRulesClient {
7
7
  }
8
8
  async getAuthHeaders() {
9
9
  const { token } = await this.identityApi.getCredentials();
10
- return {
11
- "Authorization": `Bearer ${token}`
12
- };
10
+ return { "Authorization": `Bearer ${token}` };
13
11
  }
14
12
  cleanGitUrl(url) {
15
13
  return url.replace("url:", "").replace(/\/tree\/(?:main|master)\/.*$/, "");
@@ -18,27 +16,37 @@ class AiRulesClient {
18
16
  const baseUrl = await this.discoveryApi.getBaseUrl("ai-rules");
19
17
  const sourceLocation = window.location.pathname.split("/").includes("catalog") ? new URLSearchParams(window.location.search).get("sourceLocation") || "" : "";
20
18
  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
- }
19
+ const queryParams = new URLSearchParams({ gitUrl, ruleTypes: ruleTypes.join(",") });
20
+ const response = await fetch(`${baseUrl}/rules?${queryParams}`, { headers: await this.getAuthHeaders() });
21
+ if (!response.ok) throw new Error("Failed to fetch AI rules");
31
22
  return await response.json();
32
23
  }
33
24
  async getMCPServers(gitUrl) {
34
25
  const baseUrl = await this.discoveryApi.getBaseUrl("ai-rules");
35
26
  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
- }
27
+ const response = await fetch(`${baseUrl}/mcp-servers?${queryParams}`, { headers: await this.getAuthHeaders() });
28
+ if (!response.ok) throw new Error("Failed to fetch MCP servers");
29
+ return await response.json();
30
+ }
31
+ async getIgnoreFiles(gitUrl) {
32
+ const baseUrl = await this.discoveryApi.getBaseUrl("ai-rules");
33
+ const queryParams = new URLSearchParams({ gitUrl });
34
+ const response = await fetch(`${baseUrl}/ignore-files?${queryParams}`, { headers: await this.getAuthHeaders() });
35
+ if (!response.ok) throw new Error("Failed to fetch ignore files");
36
+ return await response.json();
37
+ }
38
+ async getAgentConfigs(gitUrl) {
39
+ const baseUrl = await this.discoveryApi.getBaseUrl("ai-rules");
40
+ const queryParams = new URLSearchParams({ gitUrl });
41
+ const response = await fetch(`${baseUrl}/agent-configs?${queryParams}`, { headers: await this.getAuthHeaders() });
42
+ if (!response.ok) throw new Error("Failed to fetch agent configs");
43
+ return await response.json();
44
+ }
45
+ async getSkills(gitUrl) {
46
+ const baseUrl = await this.discoveryApi.getBaseUrl("ai-rules");
47
+ const queryParams = new URLSearchParams({ gitUrl });
48
+ const response = await fetch(`${baseUrl}/skills?${queryParams}`, { headers: await this.getAuthHeaders() });
49
+ if (!response.ok) throw new Error("Failed to fetch agent skills");
42
50
  return await response.json();
43
51
  }
44
52
  }
@@ -1 +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,aAAA,CAAoC;AAAA,EAC9B,YAAA;AAAA,EACA,WAAA;AAAA,EAEjB,YAAY,OAAA,EAGT;AACD,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,YAAA;AAC5B,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,WAAA;AAAA,EAC7B;AAAA,EAEA,MAAc,cAAA,GAAuC;AACnD,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,YAAY,cAAA,EAAe;AACxD,IAAA,OAAO;AAAA,MACL,eAAA,EAAiB,UAAU,KAAK,CAAA;AAAA,KAClC;AAAA,EACF;AAAA,EAEQ,YAAY,GAAA,EAAqB;AACvC,IAAA,OAAO,IACJ,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAClB,OAAA,CAAQ,gCAAgC,EAAE,CAAA;AAAA,EAC/C;AAAA,EAEA,MAAM,WAAW,SAAA,EAA+C;AAC9D,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,YAAA,CAAa,WAAW,UAAU,CAAA;AAC7D,IAAA,MAAM,iBAAiB,MAAA,CAAO,QAAA,CAAS,SAAS,KAAA,CAAM,GAAG,EAAE,QAAA,CAAS,SAAS,IACzE,IAAI,eAAA,CAAgB,OAAO,QAAA,CAAS,MAAM,EAAE,GAAA,CAAI,gBAAgB,KAAK,EAAA,GACrE,EAAA;AACJ,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,cAAc,CAAA;AAE9C,IAAA,MAAM,WAAA,GAAc,IAAI,eAAA,CAAgB;AAAA,MACtC,MAAA;AAAA,MACA,SAAA,EAAW,SAAA,CAAU,IAAA,CAAK,GAAG;AAAA,KAC9B,CAAA;AAED,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,OAAO,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA,EAAI;AAAA,MAC9D,OAAA,EAAS,MAAM,IAAA,CAAK,cAAA;AAAe,KACpC,CAAA;AACD,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,IAC5C;AACA,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC7B;AAAA,EAEA,MAAM,cAAc,MAAA,EAA6C;AAC/D,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,YAAA,CAAa,WAAW,UAAU,CAAA;AAC7D,IAAA,MAAM,WAAA,GAAc,IAAI,eAAA,CAAgB,EAAE,QAAQ,CAAA;AAElD,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,OAAO,CAAA,aAAA,EAAgB,WAAW,CAAA,CAAA,EAAI;AAAA,MACpE,OAAA,EAAS,MAAM,IAAA,CAAK,cAAA;AAAe,KACpC,CAAA;AACD,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAAA,IAC/C;AACA,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC7B;AACF;;;;"}
1
+ {"version":3,"file":"AiRulesClient.esm.js","sources":["../../src/api/AiRulesClient.ts"],"sourcesContent":["import { AiRulesApi } from './types';\nimport { AIRulesResponse, IgnoreFilesResponse, AgentConfigsResponse, SkillsResponse } from '../types';\nimport { MCPServersResponse } from '../types/mcp';\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 { 'Authorization': `Bearer ${token}` };\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 const queryParams = new URLSearchParams({ gitUrl, ruleTypes: ruleTypes.join(',') });\n const response = await fetch(`${baseUrl}/rules?${queryParams}`, { headers: await this.getAuthHeaders() });\n if (!response.ok) throw new Error('Failed to fetch AI rules');\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 const response = await fetch(`${baseUrl}/mcp-servers?${queryParams}`, { headers: await this.getAuthHeaders() });\n if (!response.ok) throw new Error('Failed to fetch MCP servers');\n return await response.json();\n }\n\n async getIgnoreFiles(gitUrl: string): Promise<IgnoreFilesResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('ai-rules');\n const queryParams = new URLSearchParams({ gitUrl });\n const response = await fetch(`${baseUrl}/ignore-files?${queryParams}`, { headers: await this.getAuthHeaders() });\n if (!response.ok) throw new Error('Failed to fetch ignore files');\n return await response.json();\n }\n\n async getAgentConfigs(gitUrl: string): Promise<AgentConfigsResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('ai-rules');\n const queryParams = new URLSearchParams({ gitUrl });\n const response = await fetch(`${baseUrl}/agent-configs?${queryParams}`, { headers: await this.getAuthHeaders() });\n if (!response.ok) throw new Error('Failed to fetch agent configs');\n return await response.json();\n }\n\n async getSkills(gitUrl: string): Promise<SkillsResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('ai-rules');\n const queryParams = new URLSearchParams({ gitUrl });\n const response = await fetch(`${baseUrl}/skills?${queryParams}`, { headers: await this.getAuthHeaders() });\n if (!response.ok) throw new Error('Failed to fetch agent skills');\n return await response.json();\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +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,YAAA,CAAyB;AAAA,EACpD,EAAA,EAAI;AACN,CAAC;;;;"}
1
+ {"version":3,"file":"types.esm.js","sources":["../../src/api/types.ts"],"sourcesContent":["import { AIRulesResponse, IgnoreFilesResponse, AgentConfigsResponse, SkillsResponse } 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 getIgnoreFiles(gitUrl: string): Promise<IgnoreFilesResponse>;\n getAgentConfigs(gitUrl: string): Promise<AgentConfigsResponse>;\n getSkills(gitUrl: string): Promise<SkillsResponse>;\n}\n"],"names":[],"mappings":";;AAKO,MAAM,gBAAgB,YAAA,CAAyB;AAAA,EACpD,EAAA,EAAI;AACN,CAAC;;;;"}
@@ -0,0 +1,91 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { InfoCard, Progress, EmptyState, CodeSnippet } from '@backstage/core-components';
3
+ import { makeStyles, Typography, Accordion, AccordionSummary, Chip, Tooltip, IconButton, AccordionDetails } from '@material-ui/core';
4
+ import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
5
+ import LaunchIcon from '@material-ui/icons/Launch';
6
+ import { useAgentConfigs } from '../../hooks/useAgentConfigs.esm.js';
7
+
8
+ const useStyles = makeStyles((theme) => ({
9
+ root: {
10
+ "& .MuiAccordion-root": {
11
+ marginBottom: theme.spacing(1),
12
+ "&:before": { display: "none" }
13
+ }
14
+ },
15
+ configAccordion: {
16
+ backgroundColor: theme.palette.background.paper,
17
+ border: `1px solid ${theme.palette.divider}`
18
+ },
19
+ summaryRow: {
20
+ display: "flex",
21
+ alignItems: "center",
22
+ width: "100%",
23
+ gap: theme.spacing(1)
24
+ },
25
+ codeContainer: {
26
+ backgroundColor: theme.palette.background.default,
27
+ borderRadius: theme.shape.borderRadius,
28
+ "& pre": { margin: 0 }
29
+ }
30
+ }));
31
+ const constructFileUrl = (gitUrl, filePath) => {
32
+ const cleanGitUrl = gitUrl.replace(/\/+$/, "");
33
+ if (cleanGitUrl.includes("github.com")) return `${cleanGitUrl}/blob/main/${filePath}`;
34
+ if (cleanGitUrl.includes("gitlab.com")) return `${cleanGitUrl}/-/blob/main/${filePath}`;
35
+ return `${cleanGitUrl}/blob/main/${filePath}`;
36
+ };
37
+ const LANGUAGE_LABEL = {
38
+ yaml: "YAML",
39
+ json: "JSON",
40
+ typescript: "TypeScript"
41
+ };
42
+ const ConfigAccordion = ({ config }) => {
43
+ const styles = useStyles();
44
+ return /* @__PURE__ */ jsxs(Accordion, { className: styles.configAccordion, children: [
45
+ /* @__PURE__ */ jsx(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), children: /* @__PURE__ */ jsxs("div", { className: styles.summaryRow, children: [
46
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: config.agent }),
47
+ /* @__PURE__ */ jsx(Chip, { label: config.filePath, size: "small", variant: "outlined" }),
48
+ /* @__PURE__ */ jsx(Chip, { label: LANGUAGE_LABEL[config.language], size: "small", color: "primary" }),
49
+ config.gitUrl && /* @__PURE__ */ jsx(Tooltip, { title: "Open file in repository", children: /* @__PURE__ */ jsx(
50
+ IconButton,
51
+ {
52
+ size: "small",
53
+ style: { marginLeft: "auto" },
54
+ onClick: (e) => {
55
+ e.stopPropagation();
56
+ window.open(constructFileUrl(config.gitUrl, config.filePath), "_blank");
57
+ },
58
+ children: /* @__PURE__ */ jsx(LaunchIcon, { fontSize: "small" })
59
+ }
60
+ ) })
61
+ ] }) }),
62
+ /* @__PURE__ */ jsx(AccordionDetails, { children: /* @__PURE__ */ jsx("div", { style: { width: "100%" }, children: /* @__PURE__ */ jsx("div", { className: styles.codeContainer, children: /* @__PURE__ */ jsx(CodeSnippet, { text: config.content, language: config.language, showLineNumbers: true }) }) }) })
63
+ ] });
64
+ };
65
+ const AgentConfigsComponent = ({ title = "Agent Configurations" }) => {
66
+ const styles = useStyles();
67
+ const { configs, loading, error, hasGitUrl } = useAgentConfigs();
68
+ if (loading) return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(Progress, {}) });
69
+ if (!hasGitUrl) {
70
+ return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(EmptyState, { missing: "content", title: "No Git Repository", description: "This component doesn't have a Git source URL configured." }) });
71
+ }
72
+ if (error) {
73
+ return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(EmptyState, { missing: "content", title: "Error Loading Agent Configs", description: error }) });
74
+ }
75
+ if (configs.length === 0) {
76
+ return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(EmptyState, { missing: "content", title: "No Agent Configs Found", description: "No agent configuration files were found (.aider.conf.yml, .continue/config.yaml, .cursor/settings.json, .zed/assistant.json)." }) });
77
+ }
78
+ return /* @__PURE__ */ jsxs(InfoCard, { title, className: styles.root, children: [
79
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", style: { marginBottom: 16 }, children: [
80
+ "Found ",
81
+ configs.length,
82
+ " agent configuration file",
83
+ configs.length !== 1 ? "s" : "",
84
+ "."
85
+ ] }),
86
+ configs.map((config) => /* @__PURE__ */ jsx(ConfigAccordion, { config }, config.filePath))
87
+ ] });
88
+ };
89
+
90
+ export { AgentConfigsComponent };
91
+ //# sourceMappingURL=AgentConfigsComponent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentConfigsComponent.esm.js","sources":["../../../src/components/AgentConfigsComponent/AgentConfigsComponent.tsx"],"sourcesContent":["import {\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 IconButton,\n Tooltip,\n} from '@material-ui/core';\nimport { Theme } from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport LaunchIcon from '@material-ui/icons/Launch';\nimport { useAgentConfigs } from '../../hooks/useAgentConfigs';\nimport { AgentConfig } from '../../types';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n root: {\n '& .MuiAccordion-root': {\n marginBottom: theme.spacing(1),\n '&:before': { display: 'none' },\n },\n },\n configAccordion: {\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n },\n summaryRow: {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n gap: theme.spacing(1),\n },\n codeContainer: {\n backgroundColor: theme.palette.background.default,\n borderRadius: theme.shape.borderRadius,\n '& pre': { margin: 0 },\n },\n}));\n\nconst constructFileUrl = (gitUrl: string, filePath: string): string => {\n const cleanGitUrl = gitUrl.replace(/\\/+$/, '');\n if (cleanGitUrl.includes('github.com')) return `${cleanGitUrl}/blob/main/${filePath}`;\n if (cleanGitUrl.includes('gitlab.com')) return `${cleanGitUrl}/-/blob/main/${filePath}`;\n return `${cleanGitUrl}/blob/main/${filePath}`;\n};\n\nconst LANGUAGE_LABEL: Record<AgentConfig['language'], string> = {\n yaml: 'YAML',\n json: 'JSON',\n typescript: 'TypeScript',\n};\n\nconst ConfigAccordion = ({ config }: { config: AgentConfig }) => {\n const styles = useStyles();\n return (\n <Accordion className={styles.configAccordion}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.summaryRow}>\n <Typography variant=\"subtitle1\">{config.agent}</Typography>\n <Chip label={config.filePath} size=\"small\" variant=\"outlined\" />\n <Chip label={LANGUAGE_LABEL[config.language]} size=\"small\" color=\"primary\" />\n {config.gitUrl && (\n <Tooltip title=\"Open file in repository\">\n <IconButton\n size=\"small\"\n style={{ marginLeft: 'auto' }}\n onClick={(e) => { e.stopPropagation(); window.open(constructFileUrl(config.gitUrl!, config.filePath), '_blank'); }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div style={{ width: '100%' }}>\n <div className={styles.codeContainer}>\n <CodeSnippet text={config.content} language={config.language} showLineNumbers />\n </div>\n </div>\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport interface AgentConfigsComponentProps {\n title?: string;\n}\n\nexport const AgentConfigsComponent = ({ title = 'Agent Configurations' }: AgentConfigsComponentProps) => {\n const styles = useStyles();\n const { configs, loading, error, hasGitUrl } = useAgentConfigs();\n\n if (loading) return <InfoCard title={title}><Progress /></InfoCard>;\n\n if (!hasGitUrl) {\n return (\n <InfoCard title={title}>\n <EmptyState missing=\"content\" title=\"No Git Repository\" description=\"This component doesn't have a Git source URL configured.\" />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title={title}>\n <EmptyState missing=\"content\" title=\"Error Loading Agent Configs\" description={error} />\n </InfoCard>\n );\n }\n\n if (configs.length === 0) {\n return (\n <InfoCard title={title}>\n <EmptyState missing=\"content\" title=\"No Agent Configs Found\" description=\"No agent configuration files were found (.aider.conf.yml, .continue/config.yaml, .cursor/settings.json, .zed/assistant.json).\" />\n </InfoCard>\n );\n }\n\n return (\n <InfoCard title={title} className={styles.root}>\n <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginBottom: 16 }}>\n Found {configs.length} agent configuration file{configs.length !== 1 ? 's' : ''}.\n </Typography>\n {configs.map(config => (\n <ConfigAccordion key={config.filePath} config={config} />\n ))}\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAsBA,MAAM,SAAA,GAAY,UAAA,CAAW,CAAC,KAAA,MAAkB;AAAA,EAC9C,IAAA,EAAM;AAAA,IACJ,sBAAA,EAAwB;AAAA,MACtB,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,MAC7B,UAAA,EAAY,EAAE,OAAA,EAAS,MAAA;AAAO;AAChC,GACF;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,KAAA;AAAA,IAC1C,MAAA,EAAQ,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA;AAAA,GAC5C;AAAA,EACA,UAAA,EAAY;AAAA,IACV,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,KAAA,EAAO,MAAA;AAAA,IACP,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA,GACtB;AAAA,EACA,aAAA,EAAe;AAAA,IACb,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,OAAA;AAAA,IAC1C,YAAA,EAAc,MAAM,KAAA,CAAM,YAAA;AAAA,IAC1B,OAAA,EAAS,EAAE,MAAA,EAAQ,CAAA;AAAE;AAEzB,CAAA,CAAE,CAAA;AAEF,MAAM,gBAAA,GAAmB,CAAC,MAAA,EAAgB,QAAA,KAA6B;AACrE,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAC7C,EAAA,IAAI,WAAA,CAAY,SAAS,YAAY,CAAA,SAAU,CAAA,EAAG,WAAW,cAAc,QAAQ,CAAA,CAAA;AACnF,EAAA,IAAI,WAAA,CAAY,SAAS,YAAY,CAAA,SAAU,CAAA,EAAG,WAAW,gBAAgB,QAAQ,CAAA,CAAA;AACrF,EAAA,OAAO,CAAA,EAAG,WAAW,CAAA,WAAA,EAAc,QAAQ,CAAA,CAAA;AAC7C,CAAA;AAEA,MAAM,cAAA,GAA0D;AAAA,EAC9D,IAAA,EAAM,MAAA;AAAA,EACN,IAAA,EAAM,MAAA;AAAA,EACN,UAAA,EAAY;AACd,CAAA;AAEA,MAAM,eAAA,GAAkB,CAAC,EAAE,MAAA,EAAO,KAA+B;AAC/D,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,uBACE,IAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAW,MAAA,CAAO,eAAA,EAC3B,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,gBAAA,EAAA,EAAiB,4BAAY,GAAA,CAAC,cAAA,EAAA,EAAe,GAC5C,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,UAAA,EACrB,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,WAAA,EAAa,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM,CAAA;AAAA,sBAC9C,GAAA,CAAC,QAAK,KAAA,EAAO,MAAA,CAAO,UAAU,IAAA,EAAK,OAAA,EAAQ,SAAQ,UAAA,EAAW,CAAA;AAAA,sBAC9D,GAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAO,cAAA,CAAe,MAAA,CAAO,QAAQ,CAAA,EAAG,IAAA,EAAK,OAAA,EAAQ,KAAA,EAAM,SAAA,EAAU,CAAA;AAAA,MAC1E,MAAA,CAAO,MAAA,oBACN,GAAA,CAAC,OAAA,EAAA,EAAQ,OAAM,yBAAA,EACb,QAAA,kBAAA,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,OAAA;AAAA,UACL,KAAA,EAAO,EAAE,UAAA,EAAY,MAAA,EAAO;AAAA,UAC5B,OAAA,EAAS,CAAC,CAAA,KAAM;AAAE,YAAA,CAAA,CAAE,eAAA,EAAgB;AAAG,YAAA,MAAA,CAAO,KAAK,gBAAA,CAAiB,MAAA,CAAO,QAAS,MAAA,CAAO,QAAQ,GAAG,QAAQ,CAAA;AAAA,UAAG,CAAA;AAAA,UAEjH,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,QAAA,EAAS,OAAA,EAAQ;AAAA;AAAA,OAC/B,EACF;AAAA,KAAA,EAEJ,CAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,gBAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,EAAE,KAAA,EAAO,MAAA,EAAO,EAC1B,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,MAAA,CAAO,eACrB,QAAA,kBAAA,GAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,MAAA,CAAO,OAAA,EAAS,QAAA,EAAU,MAAA,CAAO,QAAA,EAAU,eAAA,EAAe,IAAA,EAAC,CAAA,EAChF,CAAA,EACF,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ,CAAA;AAMO,MAAM,qBAAA,GAAwB,CAAC,EAAE,KAAA,GAAQ,wBAAuB,KAAkC;AACvG,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAS,KAAA,EAAO,SAAA,KAAc,eAAA,EAAgB;AAE/D,EAAA,IAAI,SAAS,uBAAO,GAAA,CAAC,YAAS,KAAA,EAAc,QAAA,kBAAA,GAAA,CAAC,YAAS,CAAA,EAAE,CAAA;AAExD,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EACR,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,mBAAA,EAAoB,WAAA,EAAY,0DAAA,EAA2D,CAAA,EACjI,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EACR,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,6BAAA,EAA8B,WAAA,EAAa,KAAA,EAAO,CAAA,EACxF,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EACR,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,wBAAA,EAAyB,WAAA,EAAY,+HAAA,EAAgI,CAAA,EAC3M,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACE,IAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAc,SAAA,EAAW,OAAO,IAAA,EACxC,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,UAAA,EAAA,EAAW,SAAQ,OAAA,EAAQ,KAAA,EAAM,iBAAgB,KAAA,EAAO,EAAE,YAAA,EAAc,EAAA,EAAG,EAAG,QAAA,EAAA;AAAA,MAAA,QAAA;AAAA,MACtE,OAAA,CAAQ,MAAA;AAAA,MAAO,2BAAA;AAAA,MAA0B,OAAA,CAAQ,MAAA,KAAW,CAAA,GAAI,GAAA,GAAM,EAAA;AAAA,MAAG;AAAA,KAAA,EAClF,CAAA;AAAA,IACC,OAAA,CAAQ,IAAI,CAAA,MAAA,qBACX,GAAA,CAAC,mBAAsC,MAAA,EAAA,EAAjB,MAAA,CAAO,QAA0B,CACxD;AAAA,GAAA,EACH,CAAA;AAEJ;;;;"}
@@ -0,0 +1,225 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { InfoCard, Progress, EmptyState, MarkdownContent, CodeSnippet } from '@backstage/core-components';
4
+ import { makeStyles, Card, CardContent, Typography, Accordion, AccordionSummary, Chip, AccordionDetails, Tooltip, IconButton } from '@material-ui/core';
5
+ import { ToggleButtonGroup, ToggleButton } from '@material-ui/lab';
6
+ import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
7
+ import LaunchIcon from '@material-ui/icons/Launch';
8
+ import { useSkills } from '../../hooks/useSkills.esm.js';
9
+
10
+ const useStyles = makeStyles((theme) => ({
11
+ root: {
12
+ "& .MuiAccordion-root": {
13
+ marginBottom: theme.spacing(1),
14
+ "&:before": { display: "none" }
15
+ }
16
+ },
17
+ statsContainer: {
18
+ display: "flex",
19
+ flexWrap: "wrap",
20
+ gap: theme.spacing(2),
21
+ marginBottom: theme.spacing(2)
22
+ },
23
+ statCard: {
24
+ minWidth: "120px",
25
+ textAlign: "center"
26
+ },
27
+ sourceAccordion: {
28
+ backgroundColor: theme.palette.background.default,
29
+ marginBottom: theme.spacing(2),
30
+ "& .MuiAccordionSummary-root": {
31
+ borderBottom: `1px solid ${theme.palette.divider}`
32
+ }
33
+ },
34
+ skillAccordion: {
35
+ backgroundColor: theme.palette.background.paper,
36
+ border: `1px solid ${theme.palette.divider}`,
37
+ marginBottom: theme.spacing(1)
38
+ },
39
+ summaryRow: {
40
+ display: "flex",
41
+ alignItems: "center",
42
+ width: "100%",
43
+ gap: theme.spacing(1),
44
+ flexWrap: "wrap"
45
+ },
46
+ summaryActions: {
47
+ marginLeft: "auto",
48
+ display: "flex",
49
+ alignItems: "center",
50
+ gap: theme.spacing(0.5),
51
+ flexShrink: 0
52
+ },
53
+ skillContent: {
54
+ display: "flex",
55
+ flexDirection: "column",
56
+ gap: theme.spacing(2),
57
+ width: "100%"
58
+ },
59
+ viewToggle: {
60
+ marginBottom: theme.spacing(1)
61
+ },
62
+ resourcesSection: {
63
+ backgroundColor: theme.palette.background.default,
64
+ borderRadius: theme.shape.borderRadius,
65
+ padding: theme.spacing(2)
66
+ },
67
+ resourceGroup: {
68
+ marginBottom: theme.spacing(1),
69
+ "&:last-child": { marginBottom: 0 }
70
+ },
71
+ resourceList: {
72
+ display: "flex",
73
+ flexWrap: "wrap",
74
+ gap: theme.spacing(0.5),
75
+ marginTop: theme.spacing(0.5)
76
+ },
77
+ contentViewer: {
78
+ maxHeight: 400,
79
+ overflow: "auto",
80
+ "& > *": { backgroundColor: "transparent !important" }
81
+ }
82
+ }));
83
+ const SOURCE_LABELS = {
84
+ "cross-client": "Cross-Client (.agents/skills/)",
85
+ "claude": "Claude Code (.claude/skills/)",
86
+ "cursor": "Cursor (.cursor/skills/)"
87
+ };
88
+ const constructFileUrl = (gitUrl, filePath) => {
89
+ const cleanGitUrl = gitUrl.replace(/\/+$/, "");
90
+ if (cleanGitUrl.includes("github.com")) return `${cleanGitUrl}/blob/main/${filePath}`;
91
+ if (cleanGitUrl.includes("gitlab.com")) return `${cleanGitUrl}/-/blob/main/${filePath}`;
92
+ return `${cleanGitUrl}/blob/main/${filePath}`;
93
+ };
94
+ const SkillContentViewer = ({ content }) => {
95
+ const styles = useStyles();
96
+ const [view, setView] = useState("rendered");
97
+ return /* @__PURE__ */ jsxs("div", { children: [
98
+ /* @__PURE__ */ jsxs(
99
+ ToggleButtonGroup,
100
+ {
101
+ size: "small",
102
+ value: view,
103
+ exclusive: true,
104
+ onChange: (_e, v) => {
105
+ if (v) setView(v);
106
+ },
107
+ className: styles.viewToggle,
108
+ children: [
109
+ /* @__PURE__ */ jsx(ToggleButton, { value: "rendered", children: "Rendered" }),
110
+ /* @__PURE__ */ jsx(ToggleButton, { value: "raw", children: "Raw" })
111
+ ]
112
+ }
113
+ ),
114
+ view === "rendered" ? /* @__PURE__ */ jsx("div", { className: styles.contentViewer, children: /* @__PURE__ */ jsx(MarkdownContent, { content }) }) : /* @__PURE__ */ jsx(CodeSnippet, { text: content, language: "markdown" })
115
+ ] });
116
+ };
117
+ const ResourcesSection = ({ resources }) => {
118
+ const styles = useStyles();
119
+ const hasResources = resources.scripts.length > 0 || resources.references.length > 0 || resources.assets.length > 0;
120
+ if (!hasResources) return null;
121
+ return /* @__PURE__ */ jsxs("div", { className: styles.resourcesSection, children: [
122
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", color: "textSecondary", gutterBottom: true, children: "Bundled Resources" }),
123
+ resources.scripts.length > 0 && /* @__PURE__ */ jsxs("div", { className: styles.resourceGroup, children: [
124
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: "Scripts" }),
125
+ /* @__PURE__ */ jsx("div", { className: styles.resourceList, children: resources.scripts.map((f) => /* @__PURE__ */ jsx(Chip, { label: f, size: "small", variant: "outlined" }, f)) })
126
+ ] }),
127
+ resources.references.length > 0 && /* @__PURE__ */ jsxs("div", { className: styles.resourceGroup, children: [
128
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: "References" }),
129
+ /* @__PURE__ */ jsx("div", { className: styles.resourceList, children: resources.references.map((f) => /* @__PURE__ */ jsx(Chip, { label: f, size: "small", variant: "outlined" }, f)) })
130
+ ] }),
131
+ resources.assets.length > 0 && /* @__PURE__ */ jsxs("div", { className: styles.resourceGroup, children: [
132
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: "Assets" }),
133
+ /* @__PURE__ */ jsx("div", { className: styles.resourceList, children: resources.assets.map((f) => /* @__PURE__ */ jsx(Chip, { label: f, size: "small", variant: "outlined" }, f)) })
134
+ ] })
135
+ ] });
136
+ };
137
+ const SkillAccordion = ({ skill }) => {
138
+ const styles = useStyles();
139
+ return /* @__PURE__ */ jsxs(Accordion, { className: styles.skillAccordion, children: [
140
+ /* @__PURE__ */ jsx(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), children: /* @__PURE__ */ jsxs("div", { className: styles.summaryRow, children: [
141
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", style: { fontWeight: 600 }, children: skill.name }),
142
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", style: { flex: 1 }, children: skill.description }),
143
+ skill.compatibility && /* @__PURE__ */ jsx(Chip, { label: skill.compatibility, size: "small", variant: "outlined" }),
144
+ skill.license && /* @__PURE__ */ jsx(Chip, { label: `License: ${skill.license}`, size: "small" }),
145
+ skill.metadata?.author && /* @__PURE__ */ jsx(Chip, { label: `by ${skill.metadata.author}`, size: "small", variant: "outlined" }),
146
+ skill.metadata?.version && /* @__PURE__ */ jsx(Chip, { label: `v${skill.metadata.version}`, size: "small", variant: "outlined" }),
147
+ /* @__PURE__ */ jsx("div", { className: styles.summaryActions, children: skill.gitUrl && /* @__PURE__ */ jsx(Tooltip, { title: "Open SKILL.md in repository", children: /* @__PURE__ */ jsx(
148
+ IconButton,
149
+ {
150
+ size: "small",
151
+ onClick: (e) => {
152
+ e.stopPropagation();
153
+ window.open(constructFileUrl(skill.gitUrl, skill.filePath), "_blank");
154
+ },
155
+ children: /* @__PURE__ */ jsx(LaunchIcon, { fontSize: "small" })
156
+ }
157
+ ) }) })
158
+ ] }) }),
159
+ /* @__PURE__ */ jsx(AccordionDetails, { children: /* @__PURE__ */ jsxs("div", { className: styles.skillContent, children: [
160
+ skill.allowedTools && skill.allowedTools.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
161
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: "Pre-approved tools" }),
162
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, marginTop: 4 }, children: skill.allowedTools.map((t) => /* @__PURE__ */ jsx(Chip, { label: t, size: "small" }, t)) })
163
+ ] }),
164
+ /* @__PURE__ */ jsx(SkillContentViewer, { content: skill.content }),
165
+ /* @__PURE__ */ jsx(ResourcesSection, { resources: skill.resources })
166
+ ] }) })
167
+ ] });
168
+ };
169
+ const AgentSkillsComponent = ({ title = "Agent Skills" }) => {
170
+ const styles = useStyles();
171
+ const { skills, loading, error, hasGitUrl } = useSkills();
172
+ if (loading) return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(Progress, {}) });
173
+ if (!hasGitUrl) {
174
+ return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(EmptyState, { missing: "content", title: "No Git Repository", description: "This component doesn't have a Git source URL configured." }) });
175
+ }
176
+ if (error) {
177
+ return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(EmptyState, { missing: "content", title: "Error Loading Skills", description: error }) });
178
+ }
179
+ if (skills.length === 0) {
180
+ return /* @__PURE__ */ jsx(InfoCard, { title, children: /* @__PURE__ */ jsx(
181
+ EmptyState,
182
+ {
183
+ missing: "content",
184
+ title: "No Agent Skills Found",
185
+ description: "No Agent Skills (agentskills.io) were found in this repository. Skills are discovered in .agents/skills/, .claude/skills/, and .cursor/skills/."
186
+ }
187
+ ) });
188
+ }
189
+ const skillsBySource = skills.reduce((acc, skill) => {
190
+ if (!acc[skill.source]) acc[skill.source] = [];
191
+ acc[skill.source].push(skill);
192
+ return acc;
193
+ }, {});
194
+ const sourceOrder = ["cross-client", "claude", "cursor"];
195
+ return /* @__PURE__ */ jsxs(InfoCard, { title, className: styles.root, children: [
196
+ /* @__PURE__ */ jsxs("div", { className: styles.statsContainer, children: [
197
+ /* @__PURE__ */ jsx(Card, { className: styles.statCard, children: /* @__PURE__ */ jsxs(CardContent, { children: [
198
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", children: skills.length }),
199
+ /* @__PURE__ */ jsx(Typography, { color: "textSecondary", children: "Total Skills" })
200
+ ] }) }),
201
+ sourceOrder.map((source) => {
202
+ const sourceSkills = skillsBySource[source];
203
+ if (!sourceSkills || sourceSkills.length === 0) return null;
204
+ return /* @__PURE__ */ jsx(Card, { className: styles.statCard, children: /* @__PURE__ */ jsxs(CardContent, { children: [
205
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", children: sourceSkills.length }),
206
+ /* @__PURE__ */ jsx(Typography, { color: "textSecondary", children: source === "cross-client" ? "Cross-Client" : source === "claude" ? "Claude" : "Cursor" })
207
+ ] }) }, source);
208
+ })
209
+ ] }),
210
+ sourceOrder.map((source) => {
211
+ const sourceSkills = skillsBySource[source];
212
+ if (!sourceSkills || sourceSkills.length === 0) return null;
213
+ return /* @__PURE__ */ jsxs(Accordion, { defaultExpanded: true, className: styles.sourceAccordion, children: [
214
+ /* @__PURE__ */ jsx(AccordionSummary, { expandIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 16 }, children: [
215
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", children: SOURCE_LABELS[source] }),
216
+ /* @__PURE__ */ jsx(Chip, { label: `${sourceSkills.length} skill${sourceSkills.length !== 1 ? "s" : ""}`, size: "small", color: "primary" })
217
+ ] }) }),
218
+ /* @__PURE__ */ jsx(AccordionDetails, { style: { flexDirection: "column" }, children: sourceSkills.map((skill) => /* @__PURE__ */ jsx(SkillAccordion, { skill }, skill.filePath)) })
219
+ ] }, source);
220
+ })
221
+ ] });
222
+ };
223
+
224
+ export { AgentSkillsComponent };
225
+ //# sourceMappingURL=AgentSkillsComponent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AgentSkillsComponent.esm.js","sources":["../../../src/components/AgentSkillsComponent/AgentSkillsComponent.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n InfoCard,\n Progress,\n EmptyState,\n MarkdownContent,\n CodeSnippet,\n} from '@backstage/core-components';\nimport {\n makeStyles,\n Typography,\n Chip,\n Card,\n CardContent,\n Accordion,\n AccordionSummary,\n AccordionDetails,\n IconButton,\n Tooltip,\n} from '@material-ui/core';\nimport { ToggleButton, ToggleButtonGroup } from '@material-ui/lab';\nimport { Theme } from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport LaunchIcon from '@material-ui/icons/Launch';\nimport { useSkills } from '../../hooks/useSkills';\nimport { AgentSkill } from '../../types';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n root: {\n '& .MuiAccordion-root': {\n marginBottom: theme.spacing(1),\n '&:before': { display: 'none' },\n },\n },\n statsContainer: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(2),\n marginBottom: theme.spacing(2),\n },\n statCard: {\n minWidth: '120px',\n textAlign: 'center',\n },\n sourceAccordion: {\n backgroundColor: theme.palette.background.default,\n marginBottom: theme.spacing(2),\n '& .MuiAccordionSummary-root': {\n borderBottom: `1px solid ${theme.palette.divider}`,\n },\n },\n skillAccordion: {\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n marginBottom: theme.spacing(1),\n },\n summaryRow: {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n gap: theme.spacing(1),\n flexWrap: 'wrap',\n },\n summaryActions: {\n marginLeft: 'auto',\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n flexShrink: 0,\n },\n skillContent: {\n display: 'flex',\n flexDirection: 'column',\n gap: theme.spacing(2),\n width: '100%',\n },\n viewToggle: {\n marginBottom: theme.spacing(1),\n },\n resourcesSection: {\n backgroundColor: theme.palette.background.default,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(2),\n },\n resourceGroup: {\n marginBottom: theme.spacing(1),\n '&:last-child': { marginBottom: 0 },\n },\n resourceList: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(0.5),\n },\n contentViewer: {\n maxHeight: 400,\n overflow: 'auto',\n '& > *': { backgroundColor: 'transparent !important' },\n },\n}));\n\nconst SOURCE_LABELS: Record<AgentSkill['source'], string> = {\n 'cross-client': 'Cross-Client (.agents/skills/)',\n 'claude': 'Claude Code (.claude/skills/)',\n 'cursor': 'Cursor (.cursor/skills/)',\n};\n\nconst constructFileUrl = (gitUrl: string, filePath: string): string => {\n const cleanGitUrl = gitUrl.replace(/\\/+$/, '');\n if (cleanGitUrl.includes('github.com')) return `${cleanGitUrl}/blob/main/${filePath}`;\n if (cleanGitUrl.includes('gitlab.com')) return `${cleanGitUrl}/-/blob/main/${filePath}`;\n return `${cleanGitUrl}/blob/main/${filePath}`;\n};\n\nconst SkillContentViewer = ({ content }: { content: string }) => {\n const styles = useStyles();\n const [view, setView] = useState<'rendered' | 'raw'>('rendered');\n return (\n <div>\n <ToggleButtonGroup\n size=\"small\"\n value={view}\n exclusive\n onChange={(_e: any, v: any) => { if (v) setView(v); }}\n className={styles.viewToggle}\n >\n <ToggleButton value=\"rendered\">Rendered</ToggleButton>\n <ToggleButton value=\"raw\">Raw</ToggleButton>\n </ToggleButtonGroup>\n {view === 'rendered' ? (\n <div className={styles.contentViewer}>\n <MarkdownContent content={content} />\n </div>\n ) : (\n <CodeSnippet text={content} language=\"markdown\" />\n )}\n </div>\n );\n};\n\nconst ResourcesSection = ({ resources }: { resources: AgentSkill['resources'] }) => {\n const styles = useStyles();\n const hasResources =\n resources.scripts.length > 0 ||\n resources.references.length > 0 ||\n resources.assets.length > 0;\n\n if (!hasResources) return null;\n\n return (\n <div className={styles.resourcesSection}>\n <Typography variant=\"subtitle2\" color=\"textSecondary\" gutterBottom>\n Bundled Resources\n </Typography>\n {resources.scripts.length > 0 && (\n <div className={styles.resourceGroup}>\n <Typography variant=\"caption\" color=\"textSecondary\">Scripts</Typography>\n <div className={styles.resourceList}>\n {resources.scripts.map(f => <Chip key={f} label={f} size=\"small\" variant=\"outlined\" />)}\n </div>\n </div>\n )}\n {resources.references.length > 0 && (\n <div className={styles.resourceGroup}>\n <Typography variant=\"caption\" color=\"textSecondary\">References</Typography>\n <div className={styles.resourceList}>\n {resources.references.map(f => <Chip key={f} label={f} size=\"small\" variant=\"outlined\" />)}\n </div>\n </div>\n )}\n {resources.assets.length > 0 && (\n <div className={styles.resourceGroup}>\n <Typography variant=\"caption\" color=\"textSecondary\">Assets</Typography>\n <div className={styles.resourceList}>\n {resources.assets.map(f => <Chip key={f} label={f} size=\"small\" variant=\"outlined\" />)}\n </div>\n </div>\n )}\n </div>\n );\n};\n\nconst SkillAccordion = ({ skill }: { skill: AgentSkill }) => {\n const styles = useStyles();\n return (\n <Accordion className={styles.skillAccordion}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div className={styles.summaryRow}>\n <Typography variant=\"subtitle1\" style={{ fontWeight: 600 }}>\n {skill.name}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\" style={{ flex: 1 }}>\n {skill.description}\n </Typography>\n {skill.compatibility && (\n <Chip label={skill.compatibility} size=\"small\" variant=\"outlined\" />\n )}\n {skill.license && (\n <Chip label={`License: ${skill.license}`} size=\"small\" />\n )}\n {skill.metadata?.author && (\n <Chip label={`by ${skill.metadata.author}`} size=\"small\" variant=\"outlined\" />\n )}\n {skill.metadata?.version && (\n <Chip label={`v${skill.metadata.version}`} size=\"small\" variant=\"outlined\" />\n )}\n <div className={styles.summaryActions}>\n {skill.gitUrl && (\n <Tooltip title=\"Open SKILL.md in repository\">\n <IconButton\n size=\"small\"\n onClick={(e) => { e.stopPropagation(); window.open(constructFileUrl(skill.gitUrl!, skill.filePath), '_blank'); }}\n >\n <LaunchIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n </div>\n </div>\n </AccordionSummary>\n <AccordionDetails>\n <div className={styles.skillContent}>\n {skill.allowedTools && skill.allowedTools.length > 0 && (\n <div>\n <Typography variant=\"caption\" color=\"textSecondary\">Pre-approved tools</Typography>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 4 }}>\n {skill.allowedTools.map(t => <Chip key={t} label={t} size=\"small\" />)}\n </div>\n </div>\n )}\n <SkillContentViewer content={skill.content} />\n <ResourcesSection resources={skill.resources} />\n </div>\n </AccordionDetails>\n </Accordion>\n );\n};\n\nexport interface AgentSkillsComponentProps {\n title?: string;\n}\n\nexport const AgentSkillsComponent = ({ title = 'Agent Skills' }: AgentSkillsComponentProps) => {\n const styles = useStyles();\n const { skills, loading, error, hasGitUrl } = useSkills();\n\n if (loading) return <InfoCard title={title}><Progress /></InfoCard>;\n\n if (!hasGitUrl) {\n return (\n <InfoCard title={title}>\n <EmptyState missing=\"content\" title=\"No Git Repository\" description=\"This component doesn't have a Git source URL configured.\" />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title={title}>\n <EmptyState missing=\"content\" title=\"Error Loading Skills\" description={error} />\n </InfoCard>\n );\n }\n\n if (skills.length === 0) {\n return (\n <InfoCard title={title}>\n <EmptyState\n missing=\"content\"\n title=\"No Agent Skills Found\"\n description=\"No Agent Skills (agentskills.io) were found in this repository. Skills are discovered in .agents/skills/, .claude/skills/, and .cursor/skills/.\"\n />\n </InfoCard>\n );\n }\n\n // Group by source\n const skillsBySource = skills.reduce((acc, skill) => {\n if (!acc[skill.source]) acc[skill.source] = [];\n acc[skill.source].push(skill);\n return acc;\n }, {} as Record<AgentSkill['source'], AgentSkill[]>);\n\n const sourceOrder: AgentSkill['source'][] = ['cross-client', 'claude', 'cursor'];\n\n return (\n <InfoCard title={title} className={styles.root}>\n {/* Stats */}\n <div className={styles.statsContainer}>\n <Card className={styles.statCard}>\n <CardContent>\n <Typography variant=\"h4\">{skills.length}</Typography>\n <Typography color=\"textSecondary\">Total Skills</Typography>\n </CardContent>\n </Card>\n {sourceOrder.map(source => {\n const sourceSkills = skillsBySource[source];\n if (!sourceSkills || sourceSkills.length === 0) return null;\n return (\n <Card key={source} className={styles.statCard}>\n <CardContent>\n <Typography variant=\"h4\">{sourceSkills.length}</Typography>\n <Typography color=\"textSecondary\">\n {source === 'cross-client' ? 'Cross-Client' : source === 'claude' ? 'Claude' : 'Cursor'}\n </Typography>\n </CardContent>\n </Card>\n );\n })}\n </div>\n\n {/* Grouped by source */}\n {sourceOrder.map(source => {\n const sourceSkills = skillsBySource[source];\n if (!sourceSkills || sourceSkills.length === 0) return null;\n return (\n <Accordion key={source} defaultExpanded className={styles.sourceAccordion}>\n <AccordionSummary expandIcon={<ExpandMoreIcon />}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>\n <Typography variant=\"h6\">{SOURCE_LABELS[source]}</Typography>\n <Chip label={`${sourceSkills.length} skill${sourceSkills.length !== 1 ? 's' : ''}`} size=\"small\" color=\"primary\" />\n </div>\n </AccordionSummary>\n <AccordionDetails style={{ flexDirection: 'column' }}>\n {sourceSkills.map(skill => (\n <SkillAccordion key={skill.filePath} skill={skill} />\n ))}\n </AccordionDetails>\n </Accordion>\n );\n })}\n </InfoCard>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -4,6 +4,9 @@ import { makeStyles } from '@material-ui/core/styles';
4
4
  import { Tabs, Tab, Box } from '@material-ui/core';
5
5
  import { AIRulesComponent } from '../AiRulesComponent/AiRulesComponent.esm.js';
6
6
  import { MCPServersComponent } from '../MCPServersComponent/MCPServersComponent.esm.js';
7
+ import { IgnoreFilesComponent } from '../IgnoreFilesComponent/IgnoreFilesComponent.esm.js';
8
+ import { AgentConfigsComponent } from '../AgentConfigsComponent/AgentConfigsComponent.esm.js';
9
+ import { AgentSkillsComponent } from '../AgentSkillsComponent/AgentSkillsComponent.esm.js';
7
10
 
8
11
  function TabPanel(props) {
9
12
  const { children, value, index, ...other } = props;
@@ -49,15 +52,22 @@ const AiInstructionsComponent = ({ title = "AI Instructions" }) => {
49
52
  onChange: handleChange,
50
53
  indicatorColor: "primary",
51
54
  textColor: "primary",
52
- variant: "fullWidth",
55
+ variant: "scrollable",
56
+ scrollButtons: "auto",
53
57
  children: [
54
58
  /* @__PURE__ */ jsx(Tab, { label: "Agent Rules", ...a11yProps(0) }),
55
- /* @__PURE__ */ jsx(Tab, { label: "MCP Servers", ...a11yProps(1) })
59
+ /* @__PURE__ */ jsx(Tab, { label: "MCP Servers", ...a11yProps(1) }),
60
+ /* @__PURE__ */ jsx(Tab, { label: "Ignore Files", ...a11yProps(2) }),
61
+ /* @__PURE__ */ jsx(Tab, { label: "Agent Configs", ...a11yProps(3) }),
62
+ /* @__PURE__ */ jsx(Tab, { label: "Agent Skills", ...a11yProps(4) })
56
63
  ]
57
64
  }
58
65
  ),
59
66
  /* @__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, {}) }) })
67
+ /* @__PURE__ */ jsx(TabPanel, { value, index: 1, children: /* @__PURE__ */ jsx(Box, { className: styles.tabPanel, children: /* @__PURE__ */ jsx(MCPServersComponent, {}) }) }),
68
+ /* @__PURE__ */ jsx(TabPanel, { value, index: 2, children: /* @__PURE__ */ jsx(Box, { className: styles.tabPanel, children: /* @__PURE__ */ jsx(IgnoreFilesComponent, {}) }) }),
69
+ /* @__PURE__ */ jsx(TabPanel, { value, index: 3, children: /* @__PURE__ */ jsx(Box, { className: styles.tabPanel, children: /* @__PURE__ */ jsx(AgentConfigsComponent, {}) }) }),
70
+ /* @__PURE__ */ jsx(TabPanel, { value, index: 4, children: /* @__PURE__ */ jsx(Box, { className: styles.tabPanel, children: /* @__PURE__ */ jsx(AgentSkillsComponent, {}) }) })
61
71
  ] });
62
72
  };
63
73