@eventcatalog/core 3.40.2 → 3.41.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 (138) hide show
  1. package/dist/__mocks__/astro-content.d.cts +1 -1
  2. package/dist/__mocks__/astro-content.d.ts +1 -1
  3. package/dist/analytics/analytics.cjs +1 -1
  4. package/dist/analytics/analytics.js +2 -2
  5. package/dist/analytics/count-resources.cjs +1 -0
  6. package/dist/analytics/count-resources.js +1 -1
  7. package/dist/analytics/log-build.cjs +3 -1
  8. package/dist/analytics/log-build.js +4 -4
  9. package/dist/catalog-to-astro-content-directory.cjs +1 -0
  10. package/dist/catalog-to-astro-content-directory.js +2 -2
  11. package/dist/{chunk-4UVFXLPI.js → chunk-3DVHEVHQ.js} +1 -0
  12. package/dist/{chunk-K3ZVEX2Y.js → chunk-3H2RT3CM.js} +1 -1
  13. package/dist/{chunk-B7LKNRMT.js → chunk-3R6TKNHG.js} +1 -1
  14. package/dist/{chunk-D6UVZABG.js → chunk-DKFIEB24.js} +1 -1
  15. package/dist/{chunk-55D645EH.js → chunk-IR4IAKWS.js} +1 -0
  16. package/dist/{chunk-YDXB3BD2.js → chunk-O6KT4DPL.js} +1 -1
  17. package/dist/{chunk-D6IBLY3O.js → chunk-QMORF42U.js} +1 -0
  18. package/dist/{chunk-HSSCHCQA.js → chunk-QVJGIQYP.js} +1 -1
  19. package/dist/{chunk-PWIB7GLR.js → chunk-TWFS6THS.js} +1 -1
  20. package/dist/{chunk-5FFRK3S5.js → chunk-ZN3JKTWB.js} +3 -2
  21. package/dist/constants.cjs +1 -1
  22. package/dist/constants.js +1 -1
  23. package/dist/eventcatalog.cjs +5 -1
  24. package/dist/eventcatalog.config.d.cts +4 -0
  25. package/dist/eventcatalog.config.d.ts +4 -0
  26. package/dist/eventcatalog.js +10 -10
  27. package/dist/generate.cjs +1 -1
  28. package/dist/generate.js +3 -3
  29. package/dist/map-catalog-to-astro.cjs +1 -0
  30. package/dist/map-catalog-to-astro.js +1 -1
  31. package/dist/search-indexer.cjs +1 -0
  32. package/dist/search-indexer.js +1 -1
  33. package/dist/utils/cli-logger.cjs +1 -1
  34. package/dist/utils/cli-logger.js +2 -2
  35. package/dist/watcher.cjs +1 -0
  36. package/dist/watcher.js +2 -2
  37. package/eventcatalog/public/agents/anthropic-dark.svg +1 -0
  38. package/eventcatalog/public/agents/anthropic-light.svg +1 -0
  39. package/eventcatalog/public/agents/openai-dark.svg +1 -0
  40. package/eventcatalog/public/agents/openai-light.svg +1 -0
  41. package/eventcatalog/public/agents/openai.svg +1 -0
  42. package/eventcatalog/public/icons/agent/anthropic-dark.svg +1 -0
  43. package/eventcatalog/public/icons/agent/anthropic-light.svg +1 -0
  44. package/eventcatalog/public/icons/agent/anthropic.svg +1 -0
  45. package/eventcatalog/public/icons/agent/gemini.svg +1 -0
  46. package/eventcatalog/public/icons/agent/openai-dark.svg +1 -0
  47. package/eventcatalog/public/icons/agent/openai-light.svg +1 -0
  48. package/eventcatalog/public/icons/agent/openai.svg +1 -0
  49. package/eventcatalog/public/icons/agents/anthropic-dark.svg +1 -0
  50. package/eventcatalog/public/icons/agents/anthropic-light.svg +1 -0
  51. package/eventcatalog/public/icons/agents/anthropic.svg +1 -0
  52. package/eventcatalog/public/icons/agents/gemini.svg +1 -0
  53. package/eventcatalog/public/icons/agents/openai-dark.svg +1 -0
  54. package/eventcatalog/public/icons/agents/openai-light.svg +1 -0
  55. package/eventcatalog/public/icons/agents/openai.svg +1 -0
  56. package/eventcatalog/public/icons/protocols/mcp-dark.svg +1 -0
  57. package/eventcatalog/public/icons/protocols/mcp-light.svg +1 -0
  58. package/eventcatalog/public/icons/protocols/mcp.svg +1 -0
  59. package/eventcatalog/public/icons/tools/datadog.svg +1 -0
  60. package/eventcatalog/public/icons/tools/github.svg +1 -0
  61. package/eventcatalog/public/icons/tools/hubspot.svg +1 -0
  62. package/eventcatalog/public/icons/tools/slack.svg +1 -0
  63. package/eventcatalog/public/icons/tools/snowflake.svg +1 -0
  64. package/eventcatalog/public/icons/tools/zendesk.svg +1 -0
  65. package/eventcatalog/src/components/Badge.astro +41 -2
  66. package/eventcatalog/src/components/Grids/MessageGrid.tsx +16 -11
  67. package/eventcatalog/src/components/MDX/AgentTools/AgentTools.astro +132 -0
  68. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +2 -0
  69. package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +8 -3
  70. package/eventcatalog/src/components/MDX/components.tsx +2 -0
  71. package/eventcatalog/src/components/Search/SearchModal.tsx +3 -0
  72. package/eventcatalog/src/components/Search/search-utils.ts +2 -0
  73. package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -0
  74. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +3 -0
  75. package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +165 -0
  76. package/eventcatalog/src/components/Tables/Discover/columns.tsx +132 -7
  77. package/eventcatalog/src/components/Tables/Table.tsx +2 -0
  78. package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +17 -0
  79. package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +17 -0
  80. package/eventcatalog/src/content.config.ts +83 -25
  81. package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +7 -4
  82. package/eventcatalog/src/enterprise/mcp/mcp-server.ts +9 -2
  83. package/eventcatalog/src/enterprise/tools/catalog-tools.ts +62 -28
  84. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +13 -1
  85. package/eventcatalog/src/pages/_index.astro +1 -3
  86. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +5 -5
  87. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +5 -2
  88. package/eventcatalog/src/pages/directory/[type]/index.astro +2 -0
  89. package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -0
  90. package/eventcatalog/src/pages/discover/[type]/index.astro +69 -23
  91. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].mdx.ts +1 -0
  92. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
  93. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +1 -1
  94. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +47 -2
  95. package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +2 -0
  96. package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +2 -0
  97. package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +1 -0
  98. package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +3 -0
  99. package/eventcatalog/src/pages/docs/llm/llms.txt.ts +3 -0
  100. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +24 -1
  101. package/eventcatalog/src/pages/docs/users/[id]/index.astro +24 -1
  102. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +2 -1
  103. package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +141 -0
  104. package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +9 -0
  105. package/eventcatalog/src/stores/sidebar-store/builders/flow.ts +19 -0
  106. package/eventcatalog/src/stores/sidebar-store/builders/message.ts +8 -2
  107. package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +10 -7
  108. package/eventcatalog/src/stores/sidebar-store/state.ts +121 -2
  109. package/eventcatalog/src/types/index.ts +3 -1
  110. package/eventcatalog/src/utils/collection-colors.ts +5 -0
  111. package/eventcatalog/src/utils/collections/agents.ts +163 -0
  112. package/eventcatalog/src/utils/collections/commands.ts +3 -2
  113. package/eventcatalog/src/utils/collections/domains.ts +94 -15
  114. package/eventcatalog/src/utils/collections/events.ts +3 -2
  115. package/eventcatalog/src/utils/collections/flows.ts +20 -3
  116. package/eventcatalog/src/utils/collections/icons.ts +3 -1
  117. package/eventcatalog/src/utils/collections/messages.ts +35 -5
  118. package/eventcatalog/src/utils/collections/queries.ts +3 -2
  119. package/eventcatalog/src/utils/collections/schemas.ts +4 -4
  120. package/eventcatalog/src/utils/collections/services.ts +1 -1
  121. package/eventcatalog/src/utils/collections/teams.ts +5 -1
  122. package/eventcatalog/src/utils/collections/types.ts +1 -0
  123. package/eventcatalog/src/utils/collections/users.ts +5 -1
  124. package/eventcatalog/src/utils/collections/util.ts +2 -0
  125. package/eventcatalog/src/utils/eventcatalog-config/catalog.ts +1 -0
  126. package/eventcatalog/src/utils/llms.ts +1 -1
  127. package/eventcatalog/src/utils/node-graphs/agents-node-graph.ts +4 -0
  128. package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +2 -2
  129. package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +42 -9
  130. package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +20 -0
  131. package/eventcatalog/src/utils/node-graphs/export-node-graph.ts +4 -0
  132. package/eventcatalog/src/utils/node-graphs/flows-node-graph.ts +22 -1
  133. package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +175 -98
  134. package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +117 -23
  135. package/eventcatalog/src/utils/node-graphs/utils/utils.ts +30 -0
  136. package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
  137. package/eventcatalog/src/utils/resource-reference-colors.ts +1 -0
  138. package/package.json +4 -4
@@ -17,7 +17,6 @@ const pageTitle = `${props.type} | ${props.data.name}`.replace(/^\w/, (c) => c.t
17
17
 
18
18
  const type = props.type;
19
19
 
20
- // Get specifications for services
21
20
  const specifications = type === 'services' ? getSpecificationsForService(props) : [];
22
21
  ---
23
22
 
@@ -26,7 +25,11 @@ const specifications = type === 'services' ? getSpecificationsForService(props)
26
25
  <div class="flex docs-layout w-full">
27
26
  <div class="w-full lg:mr-2 pr-24 py-8 bg-[rgb(var(--ec-page-bg))]">
28
27
  {type === 'domains' && <DomainGrid domain={domain} client:load />}
29
- {type === 'services' && <MessageGrid service={props} specifications={specifications} client:load />}
28
+ {
29
+ (type === 'agents' || type === 'services') && (
30
+ <MessageGrid service={props} specifications={specifications} client:load />
31
+ )
32
+ }
30
33
  </div>
31
34
  </div>
32
35
  </main>
@@ -45,6 +45,8 @@ function mapToItem(i: any) {
45
45
  // @ts-ignore
46
46
  associatedTeams: d.data?.associatedTeams?.map(mapToItem) ?? [],
47
47
  // @ts-ignore
48
+ ownedAgents: d.data?.ownedAgents?.map(mapToItem) ?? [],
49
+ // @ts-ignore
48
50
  ownedCommands: d.data?.ownedCommands?.map(mapToItem) ?? [],
49
51
  // @ts-ignore
50
52
  ownedQueries: d.data?.ownedQueries?.map(mapToItem) ?? [],
@@ -10,6 +10,7 @@ export class Page extends HybridPage {
10
10
 
11
11
  static async getStaticPaths(): Promise<Array<{ params: any; props: any }>> {
12
12
  const { getFlows } = await import('@utils/collections/flows');
13
+ const { getAgents } = await import('@utils/collections/agents');
13
14
  const { getServices } = await import('@utils/collections/services');
14
15
  const { getDataProducts } = await import('@utils/collections/data-products');
15
16
 
@@ -18,6 +19,7 @@ export class Page extends HybridPage {
18
19
 
19
20
  const loaders = {
20
21
  ...pageDataLoader,
22
+ agents: getAgents,
21
23
  flows: getFlows,
22
24
  services: getInternalServices,
23
25
  'external-systems': getExternalServices,
@@ -26,6 +28,7 @@ export class Page extends HybridPage {
26
28
 
27
29
  const itemTypes = [
28
30
  'events',
31
+ 'agents',
29
32
  'commands',
30
33
  'queries',
31
34
  'domains',
@@ -56,6 +59,7 @@ export class Page extends HybridPage {
56
59
  }
57
60
 
58
61
  const { getFlows } = await import('@utils/collections/flows');
62
+ const { getAgents } = await import('@utils/collections/agents');
59
63
  const { getServices } = await import('@utils/collections/services');
60
64
  const { getDataProducts } = await import('@utils/collections/data-products');
61
65
 
@@ -64,6 +68,7 @@ export class Page extends HybridPage {
64
68
 
65
69
  const loaders = {
66
70
  ...pageDataLoader,
71
+ agents: getAgents,
67
72
  flows: getFlows,
68
73
  services: getInternalServices,
69
74
  'external-systems': getExternalServices,
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  import { getCommands } from '@utils/collections/commands';
3
- import { getDomains, getDomainsForService } from '@utils/collections/domains';
3
+ import { getAgents } from '@utils/collections/agents';
4
+ import { getDomains, getDomainsForAgent, getDomainsForService } from '@utils/collections/domains';
4
5
  import { getEvents } from '@utils/collections/events';
5
6
  import { getServices } from '@utils/collections/services';
6
7
  import { getQueries } from '@utils/collections/queries';
@@ -22,6 +23,7 @@ const { type, data } = await Page.getData(Astro);
22
23
  const events = await getEvents();
23
24
  const queries = await getQueries();
24
25
  const commands = await getCommands();
26
+ const agents = await getAgents();
25
27
  const services = await getServices();
26
28
  const domains = await getDomains({ getAllVersions: false });
27
29
  const containers = await getContainers();
@@ -94,6 +96,18 @@ const typeConfig: Record<
94
96
  { id: 'isDeprecated', label: 'Is Deprecated' },
95
97
  ],
96
98
  },
99
+ agents: {
100
+ label: 'Agents',
101
+ description: 'Browse AI agents in your catalog and inspect the models, tools, and messages they use.',
102
+ propertyOptions: [
103
+ { id: 'hasModel', label: 'Has Model' },
104
+ { id: 'hasTools', label: 'Has Tools' },
105
+ { id: 'hasOwners', label: 'Has Owners' },
106
+ { id: 'hasRepository', label: 'Has Repository' },
107
+ { id: 'hasDataDependencies', label: 'Has Data Dependencies' },
108
+ { id: 'isDeprecated', label: 'Is Deprecated' },
109
+ ],
110
+ },
97
111
  'external-systems': {
98
112
  label: 'External Systems',
99
113
  description: 'Explore the external systems connected to your architecture and the contracts around them.',
@@ -185,6 +199,7 @@ function hasSpecifications(service: any): boolean {
185
199
 
186
200
  // Build lookup maps for all collections (for resolving data product inputs/outputs)
187
201
  const allCollections = [
202
+ ...agents.map((a) => ({ ...a, collection: 'agents' })),
188
203
  ...services.map((s) => ({ ...s, collection: 'services' })),
189
204
  ...containers.map((c) => ({ ...c, collection: 'containers' })),
190
205
  ...channels.map((c) => ({ ...c, collection: 'channels' })),
@@ -217,16 +232,18 @@ const allSubdomainIds = new Set(
217
232
  domains.flatMap((d: any) => (d.data?.domains || []).map((sd: any) => sd.data?.id || sd.id)).filter(Boolean)
218
233
  );
219
234
 
235
+ const isAgentLike = type === 'agents';
220
236
  const isServiceLike = type === 'services' || type === 'external-systems';
237
+ const isServiceOrAgentLike = isServiceLike || isAgentLike;
221
238
 
222
- // For services and external systems, enrich with domain information
223
- const enrichedData = isServiceLike
239
+ // For services, external systems, and agents, enrich with domain information
240
+ const enrichedData = isServiceOrAgentLike
224
241
  ? await Promise.all(
225
- data.map(async (service: any) => {
226
- const serviceDomains = await getDomainsForService(service);
242
+ data.map(async (resource: any) => {
243
+ const resourceDomains = isAgentLike ? await getDomainsForAgent(resource) : await getDomainsForService(resource);
227
244
  return {
228
- ...service,
229
- enrichedDomains: serviceDomains.map((d: any) => ({
245
+ ...resource,
246
+ enrichedDomains: resourceDomains.map((d: any) => ({
230
247
  id: d.data.id,
231
248
  name: d.data.name,
232
249
  version: d.data.version,
@@ -243,10 +260,12 @@ const tableData = enrichedData.map((d: any) => ({
243
260
  hasServices: type === 'domains' ? (d.data?.services || []).length > 0 : false,
244
261
  isSubdomain: type === 'domains' ? allSubdomainIds.has(d.data.id) : false,
245
262
  // Service-specific properties
246
- domains: isServiceLike ? d.enrichedDomains : undefined,
263
+ domains: isServiceOrAgentLike ? d.enrichedDomains : undefined,
247
264
  hasSpecifications: isServiceLike ? hasSpecifications(d) : false,
248
- hasRepository: isServiceLike ? !!d.data?.repository?.url : false,
249
- hasDataDependencies: isServiceLike ? (d.data?.writesTo || []).length > 0 || (d.data?.readsFrom || []).length > 0 : false,
265
+ hasRepository: isServiceOrAgentLike ? !!d.data?.repository?.url : false,
266
+ hasDataDependencies: isServiceOrAgentLike ? (d.data?.writesTo || []).length > 0 || (d.data?.readsFrom || []).length > 0 : false,
267
+ hasModel: type === 'agents' ? !!d.data?.model : false,
268
+ hasTools: type === 'agents' ? (d.data?.tools || []).length > 0 : false,
250
269
  // Data-product-specific properties
251
270
  hasInputs: type === 'data-products' ? (d.data?.inputs || []).length > 0 : false,
252
271
  hasOutputs: type === 'data-products' ? (d.data?.outputs || []).length > 0 : false,
@@ -264,6 +283,9 @@ const tableData = enrichedData.map((d: any) => ({
264
283
  consumers: d.data?.consumers?.map(mapToItem) ?? [],
265
284
  receives: d.data?.receives?.map(mapToItem) ?? [],
266
285
  sends: d.data?.sends?.map(mapToItem) ?? [],
286
+ model: d.data?.model,
287
+ tools: d.data?.tools ?? [],
288
+ agents: d.data?.agents?.map(mapToItem) ?? [],
267
289
  services: d.data?.services?.map(mapToItem) ?? [],
268
290
  servicesThatWriteToContainer: d.data?.servicesThatWriteToContainer?.map(mapToItem) ?? [],
269
291
  servicesThatReadFromContainer: d.data?.servicesThatReadFromContainer?.map(mapToItem) ?? [],
@@ -279,21 +301,22 @@ const uniqueOwners = Array.from(new Map(tableData.flatMap((d: any) => d.owners |
279
301
 
280
302
  // Get unique producers (services) for message types
281
303
  // Check for duplicate names and add version if needed
282
- const servicesByName = new Map<string, typeof services>();
283
- services.forEach((s) => {
284
- const name = s.data.name;
285
- if (!servicesByName.has(name)) servicesByName.set(name, []);
286
- servicesByName.get(name)!.push(s);
304
+ const producerResources = [...agents, ...services];
305
+ const resourcesByName = new Map<string, typeof producerResources>();
306
+ producerResources.forEach((resource) => {
307
+ const name = resource.data.name;
308
+ if (!resourcesByName.has(name)) resourcesByName.set(name, []);
309
+ resourcesByName.get(name)!.push(resource);
287
310
  });
288
311
 
289
- const uniqueProducers = services
290
- .map((s) => {
291
- const hasDuplicateName = (servicesByName.get(s.data.name)?.length ?? 0) > 1;
292
- const isLatest = s.data.version === s.data.latestVersion;
293
- const versionLabel = isLatest ? 'latest' : `v${s.data.version}`;
312
+ const uniqueProducers = producerResources
313
+ .map((resource) => {
314
+ const hasDuplicateName = (resourcesByName.get(resource.data.name)?.length ?? 0) > 1;
315
+ const isLatest = resource.data.version === resource.data.latestVersion;
316
+ const versionLabel = isLatest ? 'latest' : `v${resource.data.version}`;
294
317
  return {
295
- id: s.data.id,
296
- name: hasDuplicateName ? `${s.data.name} (${versionLabel})` : s.data.name,
318
+ id: resource.data.id,
319
+ name: hasDuplicateName ? `${resource.data.name} (${versionLabel})` : resource.data.name,
297
320
  };
298
321
  })
299
322
  .sort((a, b) => a.name.localeCompare(b.name));
@@ -312,8 +335,29 @@ const uniqueDomains = domains.map((d) => ({
312
335
  version: d.data.version,
313
336
  }));
314
337
 
338
+ const uniqueAgentProviders = Array.from(
339
+ new Map(
340
+ tableData
341
+ .map((d: any) => d.data?.model?.provider)
342
+ .filter(Boolean)
343
+ .map((provider: string) => [provider, { id: provider, name: provider }])
344
+ ).values()
345
+ ).sort((a: any, b: any) => a.name.localeCompare(b.name));
346
+
347
+ const uniqueAgentModels = Array.from(
348
+ new Map(
349
+ tableData
350
+ .map((d: any) => d.data?.model)
351
+ .filter((model: any) => model?.name)
352
+ .map((model: any) => {
353
+ const id = [model.name, model.version].filter(Boolean).join(':');
354
+ return [id, { id, name: model.name }];
355
+ })
356
+ ).values()
357
+ ).sort((a: any, b: any) => a.name.localeCompare(b.name));
358
+
315
359
  // Show domains filter only for services and external systems
316
- const showDomainsFilter = isServiceLike;
360
+ const showDomainsFilter = isServiceOrAgentLike;
317
361
 
318
362
  const title = `${currentTypeConfig.label} (${data.length})`;
319
363
  ---
@@ -338,6 +382,8 @@ const title = `${currentTypeConfig.label} (${data.length})`;
338
382
  owners={uniqueOwners as Array<{ id: string; name: string; type?: 'user' | 'team' }>}
339
383
  producers={uniqueProducers}
340
384
  consumers={uniqueConsumers}
385
+ agentProviders={uniqueAgentProviders as Array<{ id: string; name: string }>}
386
+ agentModels={uniqueAgentModels as Array<{ id: string; name: string }>}
341
387
  propertyOptions={currentTypeConfig.propertyOptions}
342
388
  tableConfiguration={tableConfiguration}
343
389
  showDomainsFilter={showDomainsFilter}
@@ -9,6 +9,7 @@ import { getResourceDocs, getResourceDocsForResource, type ResourceCollection }
9
9
  import { filterMarkdownForAgents } from '@utils/llms';
10
10
 
11
11
  const supportedResourceCollections = new Set<ResourceCollection>([
12
+ 'agents',
12
13
  'domains',
13
14
  'services',
14
15
  'events',
@@ -13,6 +13,7 @@ export class Page extends HybridPage {
13
13
  }
14
14
 
15
15
  const itemTypes: PageTypes[] = [
16
+ 'agents',
16
17
  'events',
17
18
  'commands',
18
19
  'queries',
@@ -14,7 +14,7 @@ export class Page extends HybridPage {
14
14
 
15
15
  const { pageDataLoader } = await import('@utils/page-loaders/page-data-loader');
16
16
 
17
- const itemTypes: PageTypes[] = ['events', 'commands', 'queries', 'services', 'domains', 'flows', 'containers'];
17
+ const itemTypes: PageTypes[] = ['agents', 'events', 'commands', 'queries', 'services', 'domains', 'flows', 'containers'];
18
18
  const allItems = await Promise.all(itemTypes.map((type) => pageDataLoader[type]()));
19
19
 
20
20
  return allItems.flatMap((items, index) =>
@@ -29,7 +29,7 @@ import {
29
29
  ClockIcon,
30
30
  } from '@heroicons/react/24/outline';
31
31
  import { ArrowsRightLeftIcon } from '@heroicons/react/20/solid';
32
- import { Box, Boxes, SquarePenIcon, DatabaseIcon, DatabaseZapIcon, ShieldCheckIcon, AlignLeft, Package } from 'lucide-react';
32
+ import { Bot, Box, Boxes, SquarePenIcon, DatabaseIcon, DatabaseZapIcon, ShieldCheckIcon, AlignLeft, Package } from 'lucide-react';
33
33
 
34
34
  import { getSpecificationsForService } from '@utils/collections/services';
35
35
  import { resourceToCollectionMap, collectionToResourceMap, getDeprecatedDetails } from '@utils/collections/util';
@@ -73,9 +73,54 @@ const getContentBadges = () =>
73
73
  icon: badge.icon ? getIcon(badge.icon) : null,
74
74
  }));
75
75
 
76
- const createResourceBadge = (content: string, icon: any) => ({ content, icon, textColor: 'gray' });
76
+ const createResourceBadge = (content: string, icon: any): any => ({ content, icon, textColor: 'gray' });
77
+
78
+ const getAgentProviderIconURL = (provider: string) => {
79
+ const providerIconName = provider
80
+ .trim()
81
+ .toLowerCase()
82
+ .replace(/\s+/g, '-')
83
+ .replace(/[^a-z0-9-]/g, '');
84
+
85
+ return buildUrl(`/icons/agent/${providerIconName}.svg`, true);
86
+ };
87
+
88
+ const getAgentProviderIconURLs = (provider: string) => {
89
+ const providerIconName = provider
90
+ .trim()
91
+ .toLowerCase()
92
+ .replace(/\s+/g, '-')
93
+ .replace(/[^a-z0-9-]/g, '');
94
+
95
+ const hasThemedIcon = ['openai', 'anthropic'].includes(providerIconName);
96
+
97
+ return hasThemedIcon
98
+ ? {
99
+ iconURLLight: buildUrl(`/icons/agent/${providerIconName}-light.svg`, true),
100
+ iconURLDark: buildUrl(`/icons/agent/${providerIconName}-dark.svg`, true),
101
+ }
102
+ : {
103
+ iconURL: getAgentProviderIconURL(provider),
104
+ };
105
+ };
77
106
 
78
107
  const getBadge = () => {
108
+ if (props.collection === 'agents') {
109
+ const badges = [createResourceBadge('Agent', Bot)];
110
+ if (props.data?.model?.provider) {
111
+ badges.push({
112
+ content: props.data.model.provider,
113
+ ...getAgentProviderIconURLs(props.data.model.provider),
114
+ textColor: 'gray',
115
+ });
116
+ }
117
+ const modelBadge = props.data?.model?.name;
118
+ if (modelBadge) {
119
+ badges.push(createResourceBadge(modelBadge, Bot));
120
+ }
121
+ return badges;
122
+ }
123
+
79
124
  if (props.collection === 'services') {
80
125
  return [createResourceBadge('Service', ServerIcon)];
81
126
  }
@@ -11,6 +11,7 @@ import { isLLMSTxtEnabled } from '@utils/feature';
11
11
  import { filterMarkdownForAgents } from '@utils/llms';
12
12
 
13
13
  const events = await getCollection('events');
14
+ const agents = await getCollection('agents');
14
15
  const commands = await getCollection('commands');
15
16
  const queries = await getCollection('queries');
16
17
  const services = await getCollection('services');
@@ -22,6 +23,7 @@ const containers = await getCollection('containers');
22
23
  const entities = await getEntities();
23
24
 
24
25
  const collections = {
26
+ agents,
25
27
  events,
26
28
  commands,
27
29
  queries,
@@ -9,6 +9,7 @@ import fs from 'fs';
9
9
  import { addSchemaToMarkdown, filterMarkdownForAgents } from '@utils/llms';
10
10
  import { isLLMSTxtEnabled, isSSR } from '@utils/feature';
11
11
  const events = await getCollection('events');
12
+ const agents = await getCollection('agents');
12
13
  const commands = await getCollection('commands');
13
14
  const queries = await getCollection('queries');
14
15
  const services = await getCollection('services');
@@ -22,6 +23,7 @@ const entities = await getCollection('entities');
22
23
  import utils from '@eventcatalog/sdk';
23
24
 
24
25
  const collections = {
26
+ agents,
25
27
  events,
26
28
  commands,
27
29
  queries,
@@ -4,6 +4,7 @@ import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
4
4
  import { isSSR } from '@utils/feature';
5
5
 
6
6
  const itemTypes: PageTypes[] = [
7
+ 'agents',
7
8
  'events',
8
9
  'commands',
9
10
  'queries',
@@ -5,6 +5,7 @@ import { isCustomDocsEnabled, isResourceDocsEnabled, isLLMSTxtEnabled } from '@u
5
5
  import { addSchemaToMarkdown, filterMarkdownForAgents } from '@utils/llms';
6
6
 
7
7
  type AllowedCollections =
8
+ | 'agents'
8
9
  | 'events'
9
10
  | 'commands'
10
11
  | 'queries'
@@ -24,6 +25,7 @@ type AllowedCollections =
24
25
  const events = await getCollection('events');
25
26
  const commands = await getCollection('commands');
26
27
  const queries = await getCollection('queries');
28
+ const agents = await getCollection('agents');
27
29
  const services = await getCollection('services');
28
30
  const dataProducts = await getCollection('data-products');
29
31
  const domains = await getCollection('domains');
@@ -46,6 +48,7 @@ export const GET: APIRoute = async ({ params, request }) => {
46
48
  ...events,
47
49
  ...commands,
48
50
  ...queries,
51
+ ...agents,
49
52
  ...services,
50
53
  ...dataProducts,
51
54
  ...domains,
@@ -10,6 +10,7 @@ const events = await getCollection('events');
10
10
  const commands = await getCollection('commands');
11
11
  const queries = await getCollection('queries');
12
12
 
13
+ const agents = await getCollection('agents');
13
14
  const services = await getCollection('services');
14
15
  const dataProducts = await getCollection('data-products');
15
16
  const domains = await getCollection('domains');
@@ -140,6 +141,8 @@ export const GET: APIRoute = async ({ params, request }) => {
140
141
  commands.map((item) => formatVersionedItem(item, 'commands')).join(''),
141
142
  '\n## Queries',
142
143
  queries.map((item) => formatVersionedItem(item, 'queries')).join(''),
144
+ '\n## Agents',
145
+ agents.map((item) => formatVersionedItem(item, 'agents')).join(''),
143
146
  '\n## Services',
144
147
  services.map((item) => formatVersionedItem(item, 'services')).join(''),
145
148
  '\n## Data Products',
@@ -23,6 +23,7 @@ const membersRaw = props.data.members || [];
23
23
  const members = (await Promise.all(membersRaw.map((m: CollectionEntry<'teams'>) => getEntry(m)))).filter(Boolean);
24
24
 
25
25
  const domains = props.data.ownedDomains as CollectionEntry<'domains'>[];
26
+ const agents = props.data.ownedAgents as CollectionEntry<'agents'>[];
26
27
  const services = props.data.ownedServices as CollectionEntry<'services'>[];
27
28
  const events = props.data.ownedEvents as CollectionEntry<'events'>[];
28
29
  const commands = props.data.ownedCommands as CollectionEntry<'commands'>[];
@@ -51,6 +52,13 @@ const ownedServicesList = services.map((p) => ({
51
52
  tag: `v${p.data.version}`,
52
53
  }));
53
54
 
55
+ const ownedAgentsList = agents.map((p) => ({
56
+ label: `${p.data.name}`,
57
+ href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
58
+ collection: p.collection,
59
+ tag: `v${p.data.version}`,
60
+ }));
61
+
54
62
  const ownedMessagesList = [...events, ...commands, ...queries].map((p) => ({
55
63
  label: `${p.data.name}`,
56
64
  href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
@@ -127,7 +135,7 @@ const pageTitle = `Team | ${props.data.name}`;
127
135
  </div>
128
136
  </div>
129
137
  <div class="border-b border-[rgb(var(--ec-page-border))] py-4" data-pagefind-ignore>
130
- <dl class="grid grid-cols-2 gap-3 sm:grid-cols-4">
138
+ <dl class="grid grid-cols-2 gap-3 sm:grid-cols-5">
131
139
  <div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
132
140
  <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Domains</dt>
133
141
  <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedDomainsList.length}</dd>
@@ -136,6 +144,10 @@ const pageTitle = `Team | ${props.data.name}`;
136
144
  <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Services</dt>
137
145
  <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedServicesList.length}</dd>
138
146
  </div>
147
+ <div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
148
+ <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Agents</dt>
149
+ <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedAgentsList.length}</dd>
150
+ </div>
139
151
  <div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
140
152
  <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Messages</dt>
141
153
  <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedMessagesList.length}</dd>
@@ -177,6 +189,17 @@ const pageTitle = `Team | ${props.data.name}`;
177
189
  />
178
190
  )
179
191
  }
192
+ {
193
+ ownedAgentsList.length > 0 && (
194
+ <PillListFlat
195
+ color="indigo"
196
+ title={`Owned agents (${ownedAgentsList.length})`}
197
+ pills={ownedAgentsList}
198
+ emptyMessage={`This team does not own any agents.`}
199
+ client:load
200
+ />
201
+ )
202
+ }
180
203
  {
181
204
  ownedMessagesList.length > 0 && (
182
205
  <PillListFlat
@@ -20,6 +20,7 @@ const props = await Page.getData(Astro);
20
20
  const { Content } = await render(props);
21
21
 
22
22
  const domains = props.data.ownedDomains as CollectionEntry<'domains'>[];
23
+ const agents = props.data.ownedAgents as CollectionEntry<'agents'>[];
23
24
  const services = props.data.ownedServices as CollectionEntry<'services'>[];
24
25
  const events = props.data.ownedEvents as CollectionEntry<'events'>[];
25
26
  const commands = props.data.ownedCommands as CollectionEntry<'commands'>[];
@@ -40,6 +41,13 @@ const ownedServicesList = services.map((p) => ({
40
41
  tag: `v${p.data.version}`,
41
42
  }));
42
43
 
44
+ const ownedAgentsList = agents.map((p) => ({
45
+ label: `${p.data.name}`,
46
+ href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
47
+ collection: p.collection,
48
+ tag: `v${p.data.version}`,
49
+ }));
50
+
43
51
  const ownedMessageList = [...events, ...commands, ...queries].map((p) => ({
44
52
  label: `${p.data.name}`,
45
53
  badge: p.collection,
@@ -128,7 +136,7 @@ const pageTitle = `User | ${props.data.name}`;
128
136
  </div>
129
137
  </div>
130
138
  <div class="border-b border-[rgb(var(--ec-page-border))] py-4" data-pagefind-ignore>
131
- <dl class="grid grid-cols-2 gap-3 sm:grid-cols-4">
139
+ <dl class="grid grid-cols-2 gap-3 sm:grid-cols-5">
132
140
  <div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
133
141
  <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Domains</dt>
134
142
  <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedDomainsList.length}</dd>
@@ -137,6 +145,10 @@ const pageTitle = `User | ${props.data.name}`;
137
145
  <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Services</dt>
138
146
  <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedServicesList.length}</dd>
139
147
  </div>
148
+ <div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
149
+ <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Agents</dt>
150
+ <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedAgentsList.length}</dd>
151
+ </div>
140
152
  <div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
141
153
  <dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Messages</dt>
142
154
  <dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedMessageList.length}</dd>
@@ -178,6 +190,17 @@ const pageTitle = `User | ${props.data.name}`;
178
190
  />
179
191
  )
180
192
  }
193
+ {
194
+ ownedAgentsList.length > 0 && (
195
+ <PillListFlat
196
+ color="indigo"
197
+ title={`Owned agents (${ownedAgentsList.length})`}
198
+ pills={ownedAgentsList}
199
+ emptyMessage={`${props.data.name} does not own any agents.`}
200
+ client:load
201
+ />
202
+ )
203
+ }
181
204
  {
182
205
  ownedMessageList.length > 0 && (
183
206
  <PillListFlat
@@ -21,10 +21,11 @@ export class Page extends HybridPage {
21
21
  };
22
22
 
23
23
  const itemTypes: PageTypesWithFlows[] = [
24
+ 'agents',
25
+ 'services',
24
26
  'events',
25
27
  'commands',
26
28
  'queries',
27
- 'services',
28
29
  'domains',
29
30
  'flows',
30
31
  'containers',