@eventcatalog/core 3.40.2 → 3.41.1

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 (175) 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-PWIB7GLR.js → chunk-6C2H2YLW.js} +1 -1
  14. package/dist/{chunk-D6UVZABG.js → chunk-GNLFCESR.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-5FFRK3S5.js → chunk-UGNBEYJJ.js} +3 -2
  19. package/dist/{chunk-HSSCHCQA.js → chunk-X5JM6SAH.js} +1 -1
  20. package/dist/{chunk-B7LKNRMT.js → chunk-Z5A2F2DN.js} +1 -1
  21. package/dist/constants.cjs +1 -1
  22. package/dist/constants.js +1 -1
  23. package/dist/docs/development/components/components/04-agent-tools.md +43 -0
  24. package/dist/docs/development/guides/agents/01-introduction.md +43 -0
  25. package/dist/docs/development/guides/agents/02-adding-agents.md +152 -0
  26. package/dist/docs/development/guides/agents/03-adding-tools.md +92 -0
  27. package/dist/docs/development/guides/agents/04-model-metadata.md +96 -0
  28. package/dist/docs/development/guides/agents/_category_.json +11 -0
  29. package/dist/docs/development/guides/agents/adding-to-agents/01-messages.md +122 -0
  30. package/dist/docs/development/guides/agents/adding-to-agents/02-datastores.md +62 -0
  31. package/dist/docs/development/guides/agents/adding-to-agents/_category_.json +10 -0
  32. package/dist/docs/development/guides/agents/ownership/01-owners.md +67 -0
  33. package/dist/docs/development/guides/agents/ownership/_category_.json +11 -0
  34. package/dist/docs/development/guides/agents/versioning-and-lifecycle/01-versioning.md +48 -0
  35. package/dist/docs/development/guides/agents/versioning-and-lifecycle/02-changelog.md +40 -0
  36. package/dist/docs/development/guides/agents/versioning-and-lifecycle/03-deprecating.md +41 -0
  37. package/dist/docs/development/guides/agents/versioning-and-lifecycle/_category_.json +11 -0
  38. package/dist/docs/development/guides/domains/02-creating-domains/03-adding-services-to-domains.md +27 -0
  39. package/dist/docs/development/guides/flows/03-flow-nodes.md +30 -0
  40. package/dist/eventcatalog.cjs +5 -1
  41. package/dist/eventcatalog.config.d.cts +4 -0
  42. package/dist/eventcatalog.config.d.ts +4 -0
  43. package/dist/eventcatalog.js +10 -10
  44. package/dist/generate.cjs +1 -1
  45. package/dist/generate.js +3 -3
  46. package/dist/map-catalog-to-astro.cjs +1 -0
  47. package/dist/map-catalog-to-astro.js +1 -1
  48. package/dist/search-indexer.cjs +1 -0
  49. package/dist/search-indexer.js +1 -1
  50. package/dist/utils/cli-logger.cjs +1 -1
  51. package/dist/utils/cli-logger.js +2 -2
  52. package/dist/watcher.cjs +1 -0
  53. package/dist/watcher.js +2 -2
  54. package/eventcatalog/public/agents/anthropic-dark.svg +1 -0
  55. package/eventcatalog/public/agents/anthropic-light.svg +1 -0
  56. package/eventcatalog/public/agents/openai-dark.svg +1 -0
  57. package/eventcatalog/public/agents/openai-light.svg +1 -0
  58. package/eventcatalog/public/agents/openai.svg +1 -0
  59. package/eventcatalog/public/icons/agent/anthropic-dark.svg +1 -0
  60. package/eventcatalog/public/icons/agent/anthropic-light.svg +1 -0
  61. package/eventcatalog/public/icons/agent/anthropic.svg +1 -0
  62. package/eventcatalog/public/icons/agent/gemini.svg +1 -0
  63. package/eventcatalog/public/icons/agent/openai-dark.svg +1 -0
  64. package/eventcatalog/public/icons/agent/openai-light.svg +1 -0
  65. package/eventcatalog/public/icons/agent/openai.svg +1 -0
  66. package/eventcatalog/public/icons/agents/anthropic-dark.svg +1 -0
  67. package/eventcatalog/public/icons/agents/anthropic-light.svg +1 -0
  68. package/eventcatalog/public/icons/agents/anthropic.svg +1 -0
  69. package/eventcatalog/public/icons/agents/gemini.svg +1 -0
  70. package/eventcatalog/public/icons/agents/openai-dark.svg +1 -0
  71. package/eventcatalog/public/icons/agents/openai-light.svg +1 -0
  72. package/eventcatalog/public/icons/agents/openai.svg +1 -0
  73. package/eventcatalog/public/icons/protocols/mcp-dark.svg +1 -0
  74. package/eventcatalog/public/icons/protocols/mcp-light.svg +1 -0
  75. package/eventcatalog/public/icons/protocols/mcp.svg +1 -0
  76. package/eventcatalog/public/icons/tools/datadog.svg +1 -0
  77. package/eventcatalog/public/icons/tools/github.svg +1 -0
  78. package/eventcatalog/public/icons/tools/hubspot.svg +1 -0
  79. package/eventcatalog/public/icons/tools/slack.svg +1 -0
  80. package/eventcatalog/public/icons/tools/snowflake.svg +1 -0
  81. package/eventcatalog/public/icons/tools/zendesk.svg +1 -0
  82. package/eventcatalog/src/components/Badge.astro +41 -2
  83. package/eventcatalog/src/components/Grids/MessageGrid.tsx +16 -11
  84. package/eventcatalog/src/components/MDX/AgentTools/AgentTools.astro +132 -0
  85. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +2 -0
  86. package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +8 -3
  87. package/eventcatalog/src/components/MDX/components.tsx +2 -0
  88. package/eventcatalog/src/components/Search/SearchModal.tsx +3 -0
  89. package/eventcatalog/src/components/Search/search-utils.ts +2 -0
  90. package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -0
  91. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +3 -0
  92. package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +165 -0
  93. package/eventcatalog/src/components/Tables/Discover/columns.tsx +132 -7
  94. package/eventcatalog/src/components/Tables/Table.tsx +2 -0
  95. package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +17 -0
  96. package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +17 -0
  97. package/eventcatalog/src/content.config.ts +83 -25
  98. package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +7 -4
  99. package/eventcatalog/src/enterprise/mcp/mcp-server.ts +9 -2
  100. package/eventcatalog/src/enterprise/tools/catalog-tools.ts +62 -28
  101. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +13 -1
  102. package/eventcatalog/src/pages/_index.astro +1 -3
  103. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +5 -5
  104. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +5 -2
  105. package/eventcatalog/src/pages/directory/[type]/index.astro +2 -0
  106. package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -0
  107. package/eventcatalog/src/pages/discover/[type]/index.astro +69 -23
  108. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId].mdx.ts +1 -0
  109. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
  110. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +1 -1
  111. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +47 -2
  112. package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +2 -0
  113. package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +2 -0
  114. package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +1 -0
  115. package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +3 -0
  116. package/eventcatalog/src/pages/docs/llm/llms.txt.ts +3 -0
  117. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +24 -1
  118. package/eventcatalog/src/pages/docs/users/[id]/index.astro +24 -1
  119. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +2 -1
  120. package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +141 -0
  121. package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +9 -0
  122. package/eventcatalog/src/stores/sidebar-store/builders/flow.ts +19 -0
  123. package/eventcatalog/src/stores/sidebar-store/builders/message.ts +8 -2
  124. package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +10 -7
  125. package/eventcatalog/src/stores/sidebar-store/state.ts +121 -2
  126. package/eventcatalog/src/types/index.ts +3 -1
  127. package/eventcatalog/src/utils/collection-colors.ts +5 -0
  128. package/eventcatalog/src/utils/collections/agents.ts +163 -0
  129. package/eventcatalog/src/utils/collections/commands.ts +3 -2
  130. package/eventcatalog/src/utils/collections/domains.ts +94 -15
  131. package/eventcatalog/src/utils/collections/events.ts +3 -2
  132. package/eventcatalog/src/utils/collections/flows.ts +20 -3
  133. package/eventcatalog/src/utils/collections/icons.ts +3 -1
  134. package/eventcatalog/src/utils/collections/messages.ts +35 -5
  135. package/eventcatalog/src/utils/collections/queries.ts +3 -2
  136. package/eventcatalog/src/utils/collections/schemas.ts +4 -4
  137. package/eventcatalog/src/utils/collections/services.ts +1 -1
  138. package/eventcatalog/src/utils/collections/teams.ts +5 -1
  139. package/eventcatalog/src/utils/collections/types.ts +1 -0
  140. package/eventcatalog/src/utils/collections/users.ts +5 -1
  141. package/eventcatalog/src/utils/collections/util.ts +2 -0
  142. package/eventcatalog/src/utils/eventcatalog-config/catalog.ts +1 -0
  143. package/eventcatalog/src/utils/llms.ts +1 -1
  144. package/eventcatalog/src/utils/node-graphs/agents-node-graph.ts +4 -0
  145. package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +2 -2
  146. package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +42 -9
  147. package/eventcatalog/src/utils/node-graphs/export-mermaid.ts +20 -0
  148. package/eventcatalog/src/utils/node-graphs/export-node-graph.ts +4 -0
  149. package/eventcatalog/src/utils/node-graphs/flows-node-graph.ts +22 -1
  150. package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +175 -98
  151. package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +117 -23
  152. package/eventcatalog/src/utils/node-graphs/utils/utils.ts +30 -0
  153. package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
  154. package/eventcatalog/src/utils/resource-reference-colors.ts +1 -0
  155. package/package.json +4 -4
  156. /package/dist/docs/development/components/components/{04-attachments.md → 05-attachments.md} +0 -0
  157. /package/dist/docs/development/components/components/{05-channel-information.md → 06-channel-information.md} +0 -0
  158. /package/dist/docs/development/components/components/{06-design.md → 07-design.md} +0 -0
  159. /package/dist/docs/development/components/components/{07-entitymap.md → 08-entitymap.md} +0 -0
  160. /package/dist/docs/development/components/components/{08-flow.md → 09-flow.md} +0 -0
  161. /package/dist/docs/development/components/components/{09-link.md → 10-link.md} +0 -0
  162. /package/dist/docs/development/components/components/{10-mermaid-file-loader.md → 11-mermaid-file-loader.md} +0 -0
  163. /package/dist/docs/development/components/components/{11-message-table.md → 12-message-table.md} +0 -0
  164. /package/dist/docs/development/components/components/{12-nodegraph.md → 13-nodegraph.md} +0 -0
  165. /package/dist/docs/development/components/components/{13-openapi.md → 14-openapi.md} +0 -0
  166. /package/dist/docs/development/components/components/{14-prompt.md → 15-prompt.md} +0 -0
  167. /package/dist/docs/development/components/components/{15-remote-schema.md → 16-remote-schema.md} +0 -0
  168. /package/dist/docs/development/components/components/{16-resource-group-table.md → 17-resource-group-table.md} +0 -0
  169. /package/dist/docs/development/components/components/{17-resource-link.md → 18-resource-link.md} +0 -0
  170. /package/dist/docs/development/components/components/{18-schema.md → 19-schema.md} +0 -0
  171. /package/dist/docs/development/components/components/{19-schema-viewer.md → 20-schema-viewer.md} +0 -0
  172. /package/dist/docs/development/components/components/{20-steps.md → 21-steps.md} +0 -0
  173. /package/dist/docs/development/components/components/{21-tabs.md → 22-tabs.md} +0 -0
  174. /package/dist/docs/development/components/components/{22-tiles.md → 23-tiles.md} +0 -0
  175. /package/dist/docs/development/components/components/{23-visibility.md → 24-visibility.md} +0 -0
@@ -6,6 +6,7 @@ import {
6
6
  generatedIdForEdge,
7
7
  calculatedNodes,
8
8
  createEdge,
9
+ buildContextMenuForAgent,
9
10
  buildContextMenuForService,
10
11
  buildContextMenuForResource,
11
12
  versionMatches,
@@ -16,6 +17,16 @@ import {
16
17
  } from '@utils/node-graphs/utils/utils';
17
18
 
18
19
  const sanitizeGroupId = (name: string) => name.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase();
20
+ const sanitizeToolId = (name: string) =>
21
+ name
22
+ .replace(/[^a-zA-Z0-9]+/g, '-')
23
+ .replace(/(^-|-$)/g, '')
24
+ .toLowerCase();
25
+
26
+ const generateIdForAgentToolNode = (
27
+ agent: CollectionEntry<'agents'> | CollectionEntry<'services'>,
28
+ tool: { name: string; type: string }
29
+ ) => `${generateIdForNode(agent)}-tool-${sanitizeToolId(`${tool.name}-${tool.type}`)}`;
19
30
 
20
31
  import { findMatchingNodes, findInMap, createVersionedMap } from '@utils/collections/util';
21
32
  import { MarkerType, type Node, type Edge } from '@xyflow/react';
@@ -35,6 +46,7 @@ const precomputeGroupExpansion = (
35
46
  opts: {
36
47
  serviceNodeId: string;
37
48
  services: any;
49
+ agents: any;
38
50
  service: any;
39
51
  mode: string;
40
52
  channels: any;
@@ -57,6 +69,7 @@ const precomputeGroupExpansion = (
57
69
  message: msg as any,
58
70
  targetChannels: channelRefs,
59
71
  services: opts.services,
72
+ agents: opts.agents,
60
73
  currentNodes: [...opts.existingNodes, ...expandedNodes],
61
74
  target: opts.service,
62
75
  mode: opts.mode,
@@ -67,6 +80,7 @@ const precomputeGroupExpansion = (
67
80
  message: msg as any,
68
81
  sourceChannels: channelRefs,
69
82
  services: opts.services,
83
+ agents: opts.agents,
70
84
  currentNodes: [...opts.existingNodes, ...expandedNodes],
71
85
  source: opts.service,
72
86
  currentEdges: [...opts.existingEdges, ...expandedEdges],
@@ -104,8 +118,32 @@ interface Props {
104
118
  renderAllEdges?: boolean;
105
119
  channelRenderMode?: 'single' | 'flat';
106
120
  renderMessages?: boolean;
121
+ collection?: 'agents' | 'services';
107
122
  }
108
123
 
124
+ const getResourceContextMenu = (resource: CollectionEntry<'agents'> | CollectionEntry<'services'>) => {
125
+ if (resource.collection === 'agents') {
126
+ return buildContextMenuForAgent({
127
+ id: resource.data.id,
128
+ version: resource.data.version,
129
+ repository: resource.data.repository as { url: string },
130
+ });
131
+ }
132
+
133
+ return buildContextMenuForService({
134
+ id: resource.data.id,
135
+ version: resource.data.version,
136
+ specifications: (resource.data as any).specifications as { type: string; path: string }[],
137
+ repository: resource.data.repository as { url: string },
138
+ });
139
+ };
140
+
141
+ const getResourceNodeData = (resource: CollectionEntry<'agents'> | CollectionEntry<'services'>, mode: 'simple' | 'full') => ({
142
+ mode,
143
+ ...(resource.collection === 'agents' ? { agent: { ...resource.data } } : { service: { ...resource.data } }),
144
+ contextMenu: getResourceContextMenu(resource),
145
+ });
146
+
109
147
  const getSendsMessageByMessageType = (messageType: string) => {
110
148
  switch (messageType) {
111
149
  case 'events':
@@ -139,14 +177,16 @@ export const getNodesAndEdges = async ({
139
177
  renderAllEdges = false,
140
178
  channelRenderMode = 'flat',
141
179
  renderMessages = true,
180
+ collection = 'services',
142
181
  }: Props) => {
143
182
  const flow = defaultFlow || createDagreGraph({ ranksep: 300, nodesep: 50 });
144
183
  let nodes = [] as any,
145
184
  edges = [] as any;
146
185
 
147
186
  // Fetch all collections in parallel
148
- const [services, events, commands, queries, channels, containers] = await Promise.all([
187
+ const [services, agents, events, commands, queries, channels, containers] = await Promise.all([
149
188
  getCollection('services'),
189
+ getCollection('agents'),
150
190
  getCollection('events'),
151
191
  getCollection('commands'),
152
192
  getCollection('queries'),
@@ -154,7 +194,8 @@ export const getNodesAndEdges = async ({
154
194
  getCollection('containers'),
155
195
  ]);
156
196
 
157
- const service = services.find((service) => service.data.id === id && service.data.version === version);
197
+ const resources = collection === 'agents' ? agents : services;
198
+ const service = resources.find((service) => service.data.id === id && service.data.version === version);
158
199
 
159
200
  // Nothing found...
160
201
  if (!service) {
@@ -174,6 +215,7 @@ export const getNodesAndEdges = async ({
174
215
  const sendsRaw = service?.data.sends || [];
175
216
  const writesToRaw = service?.data.writesTo || [];
176
217
  const readsFromRaw = service?.data.readsFrom || [];
218
+ const toolsRaw = collection === 'agents' ? (service?.data as any).tools || [] : [];
177
219
 
178
220
  const receivesHydrated = receivesRaw
179
221
  .map((message) => findInMap(messageMap, message.id, message.version))
@@ -233,7 +275,7 @@ export const getNodesAndEdges = async ({
233
275
  groupData.messages,
234
276
  groupData.messages.map((msg: any) => findPointerForMessage(msg)?.from || []),
235
277
  'receives',
236
- { serviceNodeId, services, service, mode, channels, channelMap, existingNodes: nodes, existingEdges: edges }
278
+ { serviceNodeId, services, agents, service, mode, channels, channelMap, existingNodes: nodes, existingEdges: edges }
237
279
  );
238
280
 
239
281
  nodes.push({
@@ -285,6 +327,7 @@ export const getNodesAndEdges = async ({
285
327
  message: receive as any,
286
328
  targetChannels: targetChannels,
287
329
  services,
330
+ agents,
288
331
  currentNodes: nodes,
289
332
  target: service,
290
333
  mode,
@@ -302,16 +345,7 @@ export const getNodesAndEdges = async ({
302
345
  id: generateIdForNode(service),
303
346
  sourcePosition: 'right',
304
347
  targetPosition: 'left',
305
- data: {
306
- mode,
307
- service: { ...service.data },
308
- contextMenu: buildContextMenuForService({
309
- id: service.data.id,
310
- version: service.data.version,
311
- specifications: service.data.specifications as { type: string; path: string }[],
312
- repository: service.data.repository as { url: string },
313
- }),
314
- },
348
+ data: getResourceNodeData(service, mode),
315
349
  type: service.collection,
316
350
  });
317
351
 
@@ -349,6 +383,57 @@ export const getNodesAndEdges = async ({
349
383
  }
350
384
  });
351
385
 
386
+ if (collection === 'agents') {
387
+ toolsRaw.forEach((tool) => {
388
+ const toolNodeId = generateIdForAgentToolNode(service, tool);
389
+
390
+ nodes.push({
391
+ id: toolNodeId,
392
+ sourcePosition: 'right',
393
+ targetPosition: 'left',
394
+ data: {
395
+ mode,
396
+ agentTool: {
397
+ id: sanitizeToolId(`${tool.name}-${tool.type}`),
398
+ name: tool.name,
399
+ type: tool.type,
400
+ icon: tool.icon,
401
+ url: tool.url,
402
+ description: tool.description,
403
+ },
404
+ contextMenu: tool.url
405
+ ? [
406
+ {
407
+ label: 'Open tool endpoint',
408
+ href: tool.url,
409
+ external: true,
410
+ },
411
+ ]
412
+ : undefined,
413
+ },
414
+ type: 'agentTool',
415
+ });
416
+
417
+ edges.push(
418
+ createEdge({
419
+ id: `${serviceNodeId}-${toolNodeId}`,
420
+ source: serviceNodeId,
421
+ target: toolNodeId,
422
+ label: 'calls tool',
423
+ type: 'step',
424
+ animated: false,
425
+ data: { animated: false },
426
+ markerEnd: {
427
+ type: MarkerType.ArrowClosed,
428
+ color: '#666',
429
+ width: 20,
430
+ height: 20,
431
+ },
432
+ })
433
+ );
434
+ });
435
+ }
436
+
352
437
  // Any containers the service reads from
353
438
  readsFrom.forEach((readFrom) => {
354
439
  nodes.push({
@@ -401,7 +486,7 @@ export const getNodesAndEdges = async ({
401
486
  groupData.messages,
402
487
  groupData.messages.map((msg: any) => findPointerForMessage(msg)?.to || []),
403
488
  'sends',
404
- { serviceNodeId, services, service, mode, channels, channelMap, existingNodes: nodes, existingEdges: edges }
489
+ { serviceNodeId, services, agents, service, mode, channels, channelMap, existingNodes: nodes, existingEdges: edges }
405
490
  );
406
491
 
407
492
  nodes.push({
@@ -453,6 +538,7 @@ export const getNodesAndEdges = async ({
453
538
  message: send as any,
454
539
  sourceChannels: sourceChannels,
455
540
  services,
541
+ agents,
456
542
  currentNodes: nodes,
457
543
  source: service,
458
544
  currentEdges: edges,
@@ -512,7 +598,11 @@ export const getNodesAndEdges = async ({
512
598
  });
513
599
  });
514
600
 
515
- nodes.forEach((node: any) => {
601
+ const uniqueNodes = nodes.filter(
602
+ (node: any, index: number, self: any[]) => index === self.findIndex((n: any) => n.id === node.id)
603
+ );
604
+
605
+ uniqueNodes.forEach((node: any) => {
516
606
  flow.setNode(node.id, { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT });
517
607
  });
518
608
 
@@ -527,13 +617,17 @@ export const getNodesAndEdges = async ({
527
617
  const uniqueEdges = edges.reduce((acc: any[], edge: any) => {
528
618
  const existingEdge = acc.find((e: any) => e.id === edge.id);
529
619
  if (existingEdge) {
530
- // existingEdge.label = `${existingEdge.label} & ${edge.label}`;
531
- // Add the custom colors to the existing edge which can be an array of strings
532
- const value = Array.isArray(edge.data.customColor) ? edge.data.customColor : [edge.data.customColor];
533
- const existingValue = Array.isArray(existingEdge.data.customColor)
534
- ? existingEdge.data.customColor
535
- : [existingEdge.data.customColor];
536
- existingEdge.data.customColor = [...value, ...existingValue];
620
+ if (edge.data?.customColor || existingEdge.data?.customColor) {
621
+ // Add custom colors to the existing edge when grouped message paths converge.
622
+ const value = Array.isArray(edge.data?.customColor) ? edge.data.customColor : [edge.data?.customColor].filter(Boolean);
623
+ const existingValue = Array.isArray(existingEdge.data?.customColor)
624
+ ? existingEdge.data.customColor
625
+ : [existingEdge.data?.customColor].filter(Boolean);
626
+ existingEdge.data = {
627
+ ...existingEdge.data,
628
+ customColor: [...value, ...existingValue],
629
+ };
630
+ }
537
631
  } else {
538
632
  acc.push(edge);
539
633
  }
@@ -541,7 +635,7 @@ export const getNodesAndEdges = async ({
541
635
  }, []);
542
636
 
543
637
  return {
544
- nodes: calculatedNodes(flow, nodes),
638
+ nodes: calculatedNodes(flow, uniqueNodes),
545
639
  edges: uniqueEdges,
546
640
  };
547
641
  };
@@ -274,6 +274,36 @@ export const buildContextMenuForService = ({
274
274
  return items;
275
275
  };
276
276
 
277
+ export const buildContextMenuForAgent = ({
278
+ id,
279
+ version,
280
+ repository,
281
+ }: {
282
+ id: string;
283
+ version: string;
284
+ repository?: { url: string };
285
+ }): ContextMenuItem[] => {
286
+ const items: ContextMenuItem[] = [{ label: 'Read documentation', href: buildUrl(`/docs/agents/${id}/${version}`) }];
287
+
288
+ if (repository?.url) {
289
+ items.push({
290
+ label: 'View code repository',
291
+ href: repository.url,
292
+ external: true,
293
+ separator: true,
294
+ });
295
+ }
296
+
297
+ items.push({
298
+ label: 'Read changelog',
299
+ href: buildUrl(`/docs/agents/${id}/${version}/changelog`),
300
+ external: true,
301
+ separator: !repository?.url,
302
+ });
303
+
304
+ return items;
305
+ };
306
+
277
307
  export const buildContextMenuForResource = ({
278
308
  collection,
279
309
  id,
@@ -1,4 +1,5 @@
1
1
  import type { CollectionTypes, PageTypes } from '@types';
2
+ import { getAgents } from '@utils/collections/agents';
2
3
  import { getChannels } from '@utils/collections/channels';
3
4
  import { getDomains } from '@utils/collections/domains';
4
5
  import { getCommands, getEvents } from '@utils/collections/messages';
@@ -15,6 +16,7 @@ type PageDataLoaderOptions = { getAllVersions?: boolean };
15
16
 
16
17
  export const pageDataLoader: Record<PageTypes, (options?: PageDataLoaderOptions) => Promise<CollectionEntry<CollectionTypes>[]>> =
17
18
  {
19
+ agents: getAgents,
18
20
  events: getEvents,
19
21
  commands: getCommands,
20
22
  queries: getQueries,
@@ -2,6 +2,7 @@ import { getColorForCollection, tailwind500RgbByColor, type CollectionColor } fr
2
2
  import { resourceToCollectionMap } from './collections/util';
3
3
 
4
4
  export type ResourceReferenceType =
5
+ | 'agent'
5
6
  | 'entity'
6
7
  | 'service'
7
8
  | 'event'
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "3.40.2",
10
+ "version": "3.41.1",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -113,9 +113,9 @@
113
113
  "update-notifier": "^7.3.1",
114
114
  "uuid": "^10.0.0",
115
115
  "zod": "^4.3.6",
116
- "@eventcatalog/linter": "1.0.24",
117
- "@eventcatalog/visualiser": "^3.21.0",
118
- "@eventcatalog/sdk": "2.21.2"
116
+ "@eventcatalog/linter": "1.0.26",
117
+ "@eventcatalog/sdk": "2.23.0",
118
+ "@eventcatalog/visualiser": "^3.22.0"
119
119
  },
120
120
  "devDependencies": {
121
121
  "@astrojs/check": "^0.9.9",