@eventcatalog/core 2.60.0 → 2.61.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 (33) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/{chunk-WASYSRBV.js → chunk-CMVDQ42N.js} +1 -1
  6. package/dist/{chunk-6FRDYEMA.js → chunk-MDWG55PH.js} +1 -1
  7. package/dist/{chunk-QMWI6M2I.js → chunk-RPWUOJ3F.js} +1 -1
  8. package/dist/constants.cjs +1 -1
  9. package/dist/constants.js +1 -1
  10. package/dist/eventcatalog.cjs +2 -2
  11. package/dist/eventcatalog.js +4 -4
  12. package/eventcatalog/astro.config.mjs +1 -0
  13. package/eventcatalog/src/enterprise/eventcatalog-chat/components/Chat.tsx +19 -9
  14. package/eventcatalog/src/enterprise/eventcatalog-chat/components/ChatMessage.tsx +227 -69
  15. package/eventcatalog/src/enterprise/eventcatalog-chat/components/hooks/ChatProvider.tsx +4 -3
  16. package/eventcatalog/src/enterprise/eventcatalog-chat/components/windows/ChatWindow.server.tsx +46 -176
  17. package/eventcatalog/src/enterprise/eventcatalog-chat/pages/api/chat.ts +59 -0
  18. package/eventcatalog/src/enterprise/eventcatalog-chat/pages/chat/index.astro +12 -112
  19. package/eventcatalog/src/enterprise/eventcatalog-chat/providers/ai-provider.ts +83 -4
  20. package/eventcatalog/src/middleware-auth.ts +13 -2
  21. package/eventcatalog/src/pages/chat/feature.astro +24 -16
  22. package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +22 -11
  23. package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +3 -3
  24. package/eventcatalog/src/utils/feature.ts +2 -1
  25. package/eventcatalog/src/utils/url-builder.ts +9 -0
  26. package/package.json +12 -15
  27. package/eventcatalog/src/enterprise/eventcatalog-chat/EventCatalogVectorStore.ts +0 -66
  28. package/eventcatalog/src/enterprise/eventcatalog-chat/components/windows/ChatWindow.client.tsx +0 -540
  29. package/eventcatalog/src/enterprise/eventcatalog-chat/components/workers/document-importer.ts +0 -38
  30. package/eventcatalog/src/enterprise/eventcatalog-chat/components/workers/engine.ts +0 -7
  31. package/eventcatalog/src/enterprise/eventcatalog-chat/pages/api/ai/chat.ts +0 -54
  32. package/eventcatalog/src/enterprise/eventcatalog-chat/pages/api/ai/resources.ts +0 -42
  33. package/eventcatalog/src/enterprise/eventcatalog-chat/utils/ai.ts +0 -112
@@ -3,6 +3,9 @@ import type { MiddlewareHandler } from 'astro';
3
3
  import { getSession } from 'auth-astro/server';
4
4
  import { isAuthEnabled } from '@utils/feature';
5
5
  import jwt from 'jsonwebtoken';
6
+ import { isLLMSTxtEnabled } from '@utils/feature';
7
+
8
+ const isLLMSTextEnabled = isLLMSTxtEnabled();
6
9
 
7
10
  // Define the types in this file
8
11
  export interface NormalizedUser {
@@ -89,13 +92,21 @@ export const authMiddleware: MiddlewareHandler = async (context, next) => {
89
92
 
90
93
  // Skip system/browser requests
91
94
  const systemRoutes = ['/.well-known/', '/favicon.ico', '/robots.txt', '/sitemap.xml', '/_astro/', '/__astro'];
92
- const publicRoutes = ['/auth/login', '/auth/signout', '/auth/error', '/api/auth'];
95
+ let publicRoutes = ['/auth/login', '/auth/signout', '/auth/error', '/api/auth'];
96
+
97
+ const llmsRoutes = ['/docs/llm/llms.txt', '/docs/llm/llms-services.txt', '/docs/llm/llms-full.txt'];
98
+
99
+ if (isLLMSTextEnabled) {
100
+ publicRoutes = [...publicRoutes, ...llmsRoutes];
101
+ }
93
102
 
94
103
  if (
95
104
  pathname.startsWith('/_') ||
96
105
  systemRoutes.some((route) => pathname.startsWith(route)) ||
97
106
  pathname.startsWith('/.well-known/') ||
98
- publicRoutes.some((route) => pathname.startsWith(route))
107
+ publicRoutes.some((route) => pathname.startsWith(route)) ||
108
+ (pathname.endsWith('.mdx') && isLLMSTextEnabled) ||
109
+ (pathname.endsWith('.md') && isLLMSTextEnabled)
99
110
  ) {
100
111
  return next();
101
112
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
3
- import { isEventCatalogChatEnabled as hasEventCatlaogChatLicense } from '@utils/feature';
3
+ import { isEventCatalogChatEnabled as hasEventCatlaogChatLicense, isSSR } from '@utils/feature';
4
4
  import { BotMessageSquare } from 'lucide-react';
5
5
  const hasChatLicense = hasEventCatlaogChatLicense();
6
6
 
@@ -27,20 +27,19 @@ if (hasChatLicense) {
27
27
  <div>
28
28
  <div class="inline-flex items-center px-4 py-2 rounded-full bg-purple-100 text-purple-700 font-medium text-sm mb-6">
29
29
  <BotMessageSquare className="w-4 h-4 mr-2" />
30
- New: Ask your catalog anything
30
+ EventCatalog: Agent
31
31
  </div>
32
32
  <h1 class="text-4xl font-bold text-gray-900 tracking-tight mb-4">Ask. Understand. Ship faster.</h1>
33
33
  <p class="text-xl text-gray-600 mb-8">
34
- Get answers about your events, services, and domains — instantly. Runs entirely in your browser your data never
35
- leaves your machine.
34
+ Get answers about your architecture — instantly. Connect to your own AI models and data.
36
35
  </p>
37
- <div class="flex flex-col sm:flex-row gap-4 mb-8">
36
+ <div class="flex flex-col sm:flex-row gap-4 mb-2">
38
37
  <a
39
- href="https://demo.eventcatalog.dev/chat"
38
+ href="https://www.eventcatalog.dev/docs/development/guides/eventcatlaog-chat/what-is-eventcatalog-chat"
40
39
  target="_blank"
41
40
  class="inline-flex items-center juNot ready for AI chat? You castify-center px-6 py-3 border border-transparent text-base font-medium rounded-lg text-white bg-purple-600 hover:bg-purple-700 transition-colors duration-150"
42
41
  >
43
- Try the demo
42
+ Get Started
44
43
  <svg class="ml-2 w-4 h-4" viewBox="0 0 20 20" fill="currentColor">
45
44
  <path
46
45
  fill-rule="evenodd"
@@ -56,12 +55,19 @@ if (hasChatLicense) {
56
55
  Try for free
57
56
  </a>
58
57
  </div>
59
- <p class="text-sm text-gray-500">
60
- Available with EventCatalog Starter or Scale plans
61
- <a href="https://www.eventcatalog.dev/pricing" class="text-purple-600 font-medium block"
62
- >Try free for 14 days, no credit card required</a
63
- >
64
- </p>
58
+
59
+ <p class="text-sm text-gray-500 italic mb-6">Available with EventCatalog Starter or Scale plans</p>
60
+
61
+ {
62
+ !isSSR() && (
63
+ <p class="text-sm text-gray-500 my-4 bg-yellow-50 p-4 rounded-lg">
64
+ <span class="font-bold">This feature is only available on server side.</span> You can switch to server side by
65
+ setting the <code class="font-mono bg-gray-100 p-0.5 rounded">output</code> property to{' '}
66
+ <code class="font-mono bg-gray-100 p-0.5 rounded">server</code> in your{' '}
67
+ <code class="font-mono bg-gray-100 p-0.5 rounded">eventcatalog.config.js</code> file.
68
+ </p>
69
+ )
70
+ }
65
71
  </div>
66
72
 
67
73
  <div class="relative">
@@ -117,9 +123,9 @@ if (hasChatLicense) {
117
123
  ></path>
118
124
  </svg>
119
125
  </div>
120
- <h3 class="text-lg font-semibold text-gray-900 mb-2">Instant Search</h3>
126
+ <h3 class="text-lg font-semibold text-gray-900 mb-2">Direct Answers</h3>
121
127
  <p class="text-gray-600">
122
- Search and understand complex service relationships in seconds with natural language queries.
128
+ Ask questions about your catalog and get direct answers, using your own models and API keys.
123
129
  </p>
124
130
  </div>
125
131
 
@@ -144,7 +150,9 @@ if (hasChatLicense) {
144
150
  </svg>
145
151
  </div>
146
152
  <h3 class="text-lg font-semibold text-gray-900 mb-2">Privacy First</h3>
147
- <p class="text-gray-600">All processing happens locally in your browser. Your data never leaves your machine.</p>
153
+ <p class="text-gray-600">
154
+ Runs on your own infrastructure, and your own models. Provide your own API keys to get started.
155
+ </p>
148
156
  </div>
149
157
  </div>
150
158
 
@@ -6,8 +6,8 @@ import type { APIRoute } from 'astro';
6
6
  import { getCollection } from 'astro:content';
7
7
  import config from '@config';
8
8
  import fs from 'fs';
9
- import { dirname, join } from 'path';
10
9
  import { addSchemaToMarkdown } from '@utils/llms';
10
+ import { isLLMSTxtEnabled, isSSR } from '@utils/feature';
11
11
  const events = await getCollection('events');
12
12
  const commands = await getCollection('commands');
13
13
  const queries = await getCollection('queries');
@@ -17,12 +17,13 @@ const flows = await getCollection('flows');
17
17
  const channels = await getCollection('channels');
18
18
  const entities = await getCollection('entities');
19
19
 
20
+ import utils from '@eventcatalog/sdk';
21
+
20
22
  export async function getStaticPaths() {
21
23
  // Just return empty array if LLMs are not enabled
22
24
  if (!config.llmsTxt?.enabled) {
23
25
  return [];
24
26
  }
25
-
26
27
  const collections = {
27
28
  events,
28
29
  commands,
@@ -45,20 +46,30 @@ export async function getStaticPaths() {
45
46
 
46
47
  export const GET: APIRoute = async ({ params, props }) => {
47
48
  // Just return empty array if LLMs are not enabled
48
- if (!config.llmsTxt?.enabled) {
49
+ if (!isLLMSTxtEnabled()) {
49
50
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
50
51
  }
51
52
 
52
- if (props?.content?.filePath) {
53
- let file = fs.readFileSync(props.content.filePath, 'utf8');
54
-
55
- try {
56
- file = addSchemaToMarkdown(props.content, file);
57
- } catch (error) {
58
- console.log('Warning: Cant find the schema for', props.content.data.id, props.content.data.version);
53
+ if (isSSR()) {
54
+ const { getResourcePath } = utils(process.env.PROJECT_DIR ?? '');
55
+ const filePath = await getResourcePath(process.env.PROJECT_DIR ?? '', params.id ?? '', params.version ?? '');
56
+ if (!filePath) {
57
+ return new Response('Not found', { status: 404 });
59
58
  }
60
-
59
+ const file = fs.readFileSync(filePath.fullPath, 'utf8');
61
60
  return new Response(file, { status: 200 });
61
+ } else {
62
+ if (props?.content?.filePath) {
63
+ let file = fs.readFileSync(props.content.filePath, 'utf8');
64
+
65
+ try {
66
+ file = addSchemaToMarkdown(props.content, file);
67
+ } catch (error) {
68
+ console.log('Warning: Cant find the schema for', props.content.data.id, props.content.data.version);
69
+ }
70
+
71
+ return new Response(file, { status: 200 });
72
+ }
62
73
  }
63
74
 
64
75
  return new Response('Not found', { status: 404 });
@@ -1,5 +1,4 @@
1
1
  import { getCollection, type CollectionEntry } from 'astro:content';
2
- import config from '@config';
3
2
  import type { APIRoute } from 'astro';
4
3
  import fs from 'fs';
5
4
  import { isCustomDocsEnabled } from '@utils/feature';
@@ -30,11 +29,12 @@ const entities = await getCollection('entities');
30
29
  const channels = await getCollection('channels');
31
30
  const flows = await getCollection('flows');
32
31
  const containers = await getCollection('containers');
33
-
34
32
  const customDocs = await getCollection('customPages');
35
33
 
34
+ import { isLLMSTxtEnabled } from '@utils/feature';
35
+
36
36
  export const GET: APIRoute = async ({ params, request }) => {
37
- if (!config.llmsTxt?.enabled) {
37
+ if (!isLLMSTxtEnabled()) {
38
38
  return new Response('llms.txt is not enabled for this Catalog.', { status: 404 });
39
39
  }
40
40
 
@@ -39,13 +39,14 @@ export const isChangelogEnabled = () => config?.changelog?.enabled ?? true;
39
39
  export const isCustomDocsEnabled = () => isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
40
40
  export const isEventCatalogChatEnabled = () => {
41
41
  const isFeatureEnabledFromPlan = isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
42
- return isFeatureEnabledFromPlan && config?.chat?.enabled;
42
+ return isFeatureEnabledFromPlan && config?.chat?.enabled && isSSR();
43
43
  };
44
44
 
45
45
  export const isEventCatalogUpgradeEnabled = () => !isEventCatalogStarterEnabled() && !isEventCatalogScaleEnabled();
46
46
  export const isCustomLandingPageEnabled = () => isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
47
47
 
48
48
  export const isMarkdownDownloadEnabled = () => config?.llmsTxt?.enabled ?? false;
49
+ export const isLLMSTxtEnabled = () => (config?.llmsTxt?.enabled || isEventCatalogChatEnabled()) ?? false;
49
50
 
50
51
  export const isAuthEnabled = () => {
51
52
  const directory = process.env.PROJECT_DIR || process.cwd();
@@ -1,3 +1,5 @@
1
+ import config from '@config';
2
+
1
3
  const cleanUrl = (url: string) => {
2
4
  return url.replace(/\/+/g, '/');
3
5
  };
@@ -60,3 +62,10 @@ export const toMarkdownUrl = (url: string) => {
60
62
 
61
63
  return url + '.mdx';
62
64
  };
65
+
66
+ export const getBaseURL = () => {
67
+ if (import.meta.env.MODE === 'development') {
68
+ return `http://localhost:${config.port || 3000}`;
69
+ }
70
+ return config.homepageLink || 'https://eventcatalog.dev/';
71
+ };
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "https://github.com/event-catalog/eventcatalog.git"
7
7
  },
8
8
  "type": "module",
9
- "version": "2.60.0",
9
+ "version": "2.61.1",
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
@@ -21,13 +21,15 @@
21
21
  "default-files-for-collections/"
22
22
  ],
23
23
  "dependencies": {
24
- "@ai-sdk/anthropic": "^1.2.11",
25
- "@ai-sdk/google": "^1.2.17",
26
- "@ai-sdk/openai": "^1.3.16",
27
- "@astrojs/markdown-remark": "^6.3.6",
28
- "@astrojs/mdx": "^4.3.5",
29
- "@astrojs/node": "^9.4.3",
30
- "@astrojs/react": "^4.3.1",
24
+ "@ai-sdk/anthropic": "^2.0.23",
25
+ "@ai-sdk/google": "^2.0.17",
26
+ "@ai-sdk/openai": "^2.0.42",
27
+ "@ai-sdk/react": "^2.0.60",
28
+ "@ai-sdk/rsc": "^1.0.60",
29
+ "@astrojs/markdown-remark": "^6.3.7",
30
+ "@astrojs/mdx": "^4.3.6",
31
+ "@astrojs/node": "^9.4.4",
32
+ "@astrojs/react": "^4.4.0",
31
33
  "@astrojs/rss": "^4.0.12",
32
34
  "@astrojs/tailwind": "^6.0.2",
33
35
  "@asyncapi/avro-schema-parser": "^3.0.24",
@@ -42,11 +44,7 @@
42
44
  "@fontsource/inter": "^5.2.5",
43
45
  "@headlessui/react": "^2.0.3",
44
46
  "@heroicons/react": "^2.1.3",
45
- "@huggingface/transformers": "^3.3.3",
46
47
  "@iconify-json/logos": "^1.2.4",
47
- "@langchain/community": "^0.3.32",
48
- "@langchain/openai": "^0.5.6",
49
- "@mlc-ai/web-llm": "^0.2.78",
50
48
  "@parcel/watcher": "^2.4.1",
51
49
  "@radix-ui/react-context-menu": "^2.2.6",
52
50
  "@radix-ui/react-dialog": "^1.1.6",
@@ -57,8 +55,8 @@
57
55
  "@tanstack/react-query": "^5.74.3",
58
56
  "@tanstack/react-table": "^8.17.3",
59
57
  "@xyflow/react": "^12.3.6",
60
- "ai": "^4.3.9",
61
- "astro": "^5.13.8",
58
+ "ai": "^5.0.60",
59
+ "astro": "^5.14.1",
62
60
  "astro-compress": "^2.3.8",
63
61
  "astro-expressive-code": "^0.41.3",
64
62
  "astro-seo": "^0.8.4",
@@ -80,7 +78,6 @@
80
78
  "js-yaml": "^4.1.0",
81
79
  "jsonpath": "^1.1.1",
82
80
  "jsonwebtoken": "^9.0.2",
83
- "langchain": "^0.3.19",
84
81
  "lodash.debounce": "^4.0.8",
85
82
  "lodash.merge": "4.6.2",
86
83
  "lucide-react": "^0.453.0",
@@ -1,66 +0,0 @@
1
- import { HuggingFaceTransformersEmbeddings } from '@langchain/community/embeddings/huggingface_transformers';
2
- import { MemoryVectorStore } from 'langchain/vectorstores/memory';
3
- import { Document as LangChainDocument } from 'langchain/document';
4
- import { OpenAIEmbeddings } from '@langchain/openai';
5
-
6
- import { getConfigurationForGivenGenerator } from '@utils/generators';
7
-
8
- const aiGeneratorConfiguration = getConfigurationForGivenGenerator('@eventcatalog/generator-ai');
9
- const embedding = aiGeneratorConfiguration?.embedding || {};
10
-
11
- export interface Resource {
12
- id: string;
13
- type: string;
14
- url: string;
15
- title?: string;
16
- schema?: string;
17
- }
18
-
19
- export class EventCatalogVectorStore {
20
- private vectorStore: MemoryVectorStore;
21
-
22
- // Make the constructor private so it can only be called from within the class
23
- private constructor(vectorStore: MemoryVectorStore) {
24
- this.vectorStore = vectorStore;
25
- }
26
-
27
- // Static async factory method
28
- public static async create(documents: LangChainDocument[], embeddings: number[][]): Promise<EventCatalogVectorStore> {
29
- let embeddingsInstance: any;
30
-
31
- if (embedding.provider === 'openai') {
32
- const model = embedding.model || 'text-embedding-3-large';
33
- embeddingsInstance = new OpenAIEmbeddings({ model });
34
- } else {
35
- const model = embedding.model || 'all-MiniLM-L6-v2';
36
- embeddingsInstance = new HuggingFaceTransformersEmbeddings({ model });
37
- }
38
-
39
- const vectorStore = new MemoryVectorStore(embeddingsInstance);
40
- await vectorStore.addVectors(embeddings, documents);
41
- return new EventCatalogVectorStore(vectorStore);
42
- }
43
-
44
- async search(query: string) {
45
- return this.vectorStore.similaritySearch(query, 10);
46
- }
47
-
48
- async getEventCatalogResources(query: string): Promise<Resource[]> {
49
- const results = await this.vectorStore.similaritySearchWithScore(query, 50);
50
- return Array.from(
51
- new Map(
52
- results.map((result: any) => {
53
- const metadata = result[0].metadata;
54
- const resource: Resource = {
55
- id: metadata.id,
56
- type: metadata.type,
57
- url: `/docs/${metadata.type}s/${metadata.id}`,
58
- title: metadata.title || metadata.id,
59
- ...(metadata.schema && { schema: metadata.schema }),
60
- };
61
- return [metadata.id, resource]; // Use ID as key for Map
62
- })
63
- ).values()
64
- );
65
- }
66
- }