@aleph-alpha/lib-mcp 1.7.0 → 2.1.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.
@@ -15,20 +15,39 @@ import * as path from "node:path";
15
15
  import { fileURLToPath } from "node:url";
16
16
  var __filename = fileURLToPath(import.meta.url);
17
17
  var __dirname = path.dirname(__filename);
18
- function findUiLibraryRoot() {
19
- const possiblePaths = [
20
- // Monorepo development: from packages/lib-mcp/dist/utils -> packages/ui-library
21
- path.resolve(__dirname, "../../../ui-library"),
22
- // Installed as dependency: from node_modules/@aleph-alpha/lib-mcp/dist/utils -> node_modules/@aleph-alpha/ui-library
23
- path.resolve(__dirname, "../../@aleph-alpha/ui-library"),
24
- // Alternative: resolve from cwd
25
- path.join(process.cwd(), "node_modules/@aleph-alpha/ui-library")
18
+ function findInMonorepo(startDir, packageName) {
19
+ let current = startDir;
20
+ for (let i = 0; i < 10; i++) {
21
+ const candidate = path.join(current, "packages", packageName);
22
+ if (fs.existsSync(path.join(candidate, "package.json"))) {
23
+ return candidate;
24
+ }
25
+ const parent = path.dirname(current);
26
+ if (parent === current) break;
27
+ current = parent;
28
+ }
29
+ return null;
30
+ }
31
+ function resolveWorkspacePackage(packageName, scope = "@aleph-alpha") {
32
+ const fromDirname = findInMonorepo(__dirname, packageName);
33
+ if (fromDirname) return fromDirname;
34
+ const fromCwd = findInMonorepo(process.cwd(), packageName);
35
+ if (fromCwd) return fromCwd;
36
+ const nodeModulesCandidates = [
37
+ path.resolve(__dirname, `../../${scope}/${packageName}`),
38
+ path.resolve(__dirname, `../../../${scope}/${packageName}`),
39
+ path.join(process.cwd(), `node_modules/${scope}/${packageName}`)
26
40
  ];
27
- for (const pkgPath of possiblePaths) {
41
+ for (const pkgPath of nodeModulesCandidates) {
28
42
  if (fs.existsSync(path.join(pkgPath, "package.json"))) {
29
43
  return pkgPath;
30
44
  }
31
45
  }
46
+ return null;
47
+ }
48
+ function findUiLibraryRoot() {
49
+ const pkgPath = resolveWorkspacePackage("ui-library");
50
+ if (pkgPath) return pkgPath;
32
51
  throw new Error("Could not find @aleph-alpha/ui-library. Is it installed?");
33
52
  }
34
53
  function getLibrarySourcePath() {
@@ -41,6 +60,21 @@ function getLibrarySourcePath() {
41
60
  "Could not find UI library source directory. Is the package installed correctly?"
42
61
  );
43
62
  }
63
+ function findChatKitRoot() {
64
+ const pkgPath = resolveWorkspacePackage("chat-kit");
65
+ if (pkgPath) return pkgPath;
66
+ throw new Error("Could not find @aleph-alpha/chat-kit. Is it installed?");
67
+ }
68
+ function getChatKitSourcePath() {
69
+ const chatKitRoot = findChatKitRoot();
70
+ const srcPath = path.join(chatKitRoot, "src");
71
+ if (fs.existsSync(srcPath)) {
72
+ return srcPath;
73
+ }
74
+ throw new Error(
75
+ "Could not find chat-kit source directory. Is the package installed correctly?"
76
+ );
77
+ }
44
78
  function getPackageRoot() {
45
79
  const pkgRoot = path.resolve(__dirname, "../..");
46
80
  if (fs.existsSync(path.join(pkgRoot, "package.json"))) {
@@ -52,6 +86,10 @@ function getPackageRoot() {
52
86
  // src/utils/file-utils.ts
53
87
  import * as fs2 from "node:fs";
54
88
 
89
+ // src/utils/constants.ts
90
+ var COMPONENT_PREFIX = "Ui";
91
+ var CHAT_KIT_PREFIX = "Ck";
92
+
55
93
  // src/constants.ts
56
94
  function detectCategoryDirs() {
57
95
  const srcPath = getSrcPath();
@@ -59,11 +97,15 @@ function detectCategoryDirs() {
59
97
  return [];
60
98
  }
61
99
  const entries = fs3.readdirSync(srcPath, { withFileTypes: true });
62
- return entries.filter((entry) => entry.isDirectory()).filter((entry) => !entry.name.startsWith(".") && entry.name !== "node_modules").filter((entry) => {
100
+ return entries.filter((entry) => entry.isDirectory()).filter(
101
+ (entry) => !entry.name.startsWith(".") && entry.name !== "node_modules"
102
+ ).filter((entry) => {
63
103
  try {
64
104
  const dirPath = path2.join(srcPath, entry.name);
65
105
  const subEntries = fs3.readdirSync(dirPath, { withFileTypes: true });
66
- return subEntries.some((sub) => sub.isDirectory() && sub.name.startsWith("Ui"));
106
+ return subEntries.some(
107
+ (sub) => sub.isDirectory() && sub.name.startsWith(COMPONENT_PREFIX)
108
+ );
67
109
  } catch {
68
110
  return false;
69
111
  }
@@ -75,6 +117,47 @@ function getCategoryDirs() {
75
117
  cachedCategoryDirs = detectCategoryDirs();
76
118
  return cachedCategoryDirs;
77
119
  }
120
+ function detectChatKitCategoryDirs() {
121
+ const srcPath = getChatKitSrcPath();
122
+ if (!srcPath || !fs3.existsSync(srcPath)) {
123
+ return [];
124
+ }
125
+ const categories = [];
126
+ const walk = (dir, relative, depth) => {
127
+ let entries;
128
+ try {
129
+ entries = fs3.readdirSync(dir, { withFileTypes: true });
130
+ } catch {
131
+ return;
132
+ }
133
+ const hasChatKitSubdirs = entries.some(
134
+ (sub) => sub.isDirectory() && sub.name.startsWith(CHAT_KIT_PREFIX)
135
+ );
136
+ if (hasChatKitSubdirs && relative) {
137
+ categories.push(relative);
138
+ return;
139
+ }
140
+ if (depth >= 2) return;
141
+ for (const entry of entries) {
142
+ if (!entry.isDirectory()) continue;
143
+ if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
144
+ if (entry.name.startsWith(CHAT_KIT_PREFIX)) continue;
145
+ walk(
146
+ path2.join(dir, entry.name),
147
+ relative ? path2.join(relative, entry.name) : entry.name,
148
+ depth + 1
149
+ );
150
+ }
151
+ };
152
+ walk(srcPath, "", 0);
153
+ return categories;
154
+ }
155
+ var cachedChatKitCategoryDirs = null;
156
+ function getChatKitCategoryDirs() {
157
+ if (cachedChatKitCategoryDirs) return cachedChatKitCategoryDirs;
158
+ cachedChatKitCategoryDirs = detectChatKitCategoryDirs();
159
+ return cachedChatKitCategoryDirs;
160
+ }
78
161
  function getSrcPath() {
79
162
  try {
80
163
  return getLibrarySourcePath();
@@ -82,6 +165,13 @@ function getSrcPath() {
82
165
  return null;
83
166
  }
84
167
  }
168
+ function getChatKitSrcPath() {
169
+ try {
170
+ return getChatKitSourcePath();
171
+ } catch {
172
+ return null;
173
+ }
174
+ }
85
175
 
86
176
  // src/scripts/generate-component-meta.ts
87
177
  function escapeRegex(str) {
@@ -91,6 +181,10 @@ var __filename2 = fileURLToPath2(import.meta.url);
91
181
  var __dirname2 = path3.dirname(__filename2);
92
182
  var PACKAGE_ROOT = getPackageRoot();
93
183
  var OUTPUT_PATH = path3.join(PACKAGE_ROOT, "components-meta.json");
184
+ var CHAT_KIT_OUTPUT_PATH = path3.join(
185
+ PACKAGE_ROOT,
186
+ "chat-kit-components-meta.json"
187
+ );
94
188
  function extractJSDocTags(content, interfaceName) {
95
189
  const declarationRegex = new RegExp(
96
190
  `export\\s+(?:interface|type)\\s+${escapeRegex(interfaceName)}\\b`
@@ -138,12 +232,12 @@ function extractJSDocTags(content, interfaceName) {
138
232
  return { description, useCases, keywords, related, category };
139
233
  }
140
234
  function extractKeywordsFromName(componentName) {
141
- const name = componentName.replace(/^Ui/, "");
235
+ const name = componentName.replace(/^(?:Ui|Ck)/, "");
142
236
  return name.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/\s+/).filter((word) => word.length > 2);
143
237
  }
144
238
  function extractProps(content, interfaceName) {
145
239
  const regex = new RegExp(
146
- `export\\s+interface\\s+${escapeRegex(interfaceName)}\\s*\\{([\\s\\S]*?)\\n\\}`,
240
+ `export\\s+interface\\s+${escapeRegex(interfaceName)}\\s*(?:<(?:\\{[^}]*\\}|[^>])*>)?\\s*\\{([\\s\\S]*?)\\n\\}`,
147
241
  "m"
148
242
  );
149
243
  const match = content.match(regex);
@@ -178,13 +272,17 @@ function processComponent(componentDir, componentName) {
178
272
  typesContent = fs4.readFileSync(typesPath, "utf-8");
179
273
  }
180
274
  const escapedName = escapeRegex(componentName);
181
- const exactPropsRegex = new RegExp(`export\\s+(?:interface|type)\\s+(${escapedName}Props)\\b`);
275
+ const exactPropsRegex = new RegExp(
276
+ `export\\s+(?:interface|type)\\s+(${escapedName}Props)\\b`
277
+ );
182
278
  const exactMatch = typesContent.match(exactPropsRegex);
183
279
  const subComponentPropsRegex = new RegExp(
184
280
  `export\\s+(?:interface|type)\\s+(${escapedName}\\w*Props)\\b`
185
281
  );
186
282
  const subComponentMatch = typesContent.match(subComponentPropsRegex);
187
- const anyPropsMatch = typesContent.match(/export\s+(?:interface|type)\s+(Ui\w+Props)/);
283
+ const anyPropsMatch = typesContent.match(
284
+ /export\s+(?:interface|type)\s+((?:Ui|Ck)\w+Props)/
285
+ );
188
286
  const interfaceName = exactMatch?.[1] || subComponentMatch?.[1] || anyPropsMatch?.[1] || `${componentName}Props`;
189
287
  const jsdocData = extractJSDocTags(typesContent, interfaceName);
190
288
  const nameKeywords = extractKeywordsFromName(componentName);
@@ -217,7 +315,7 @@ function scanComponents() {
217
315
  const entries = fs4.readdirSync(categoryPath, { withFileTypes: true });
218
316
  for (const entry of entries) {
219
317
  if (!entry.isDirectory()) continue;
220
- if (!entry.name.startsWith("Ui")) continue;
318
+ if (!entry.name.startsWith(COMPONENT_PREFIX)) continue;
221
319
  if (entry.name === "shadcn") continue;
222
320
  const componentDir = path3.join(categoryPath, entry.name);
223
321
  const componentMeta = processComponent(componentDir, entry.name);
@@ -228,19 +326,58 @@ function scanComponents() {
228
326
  }
229
327
  return meta;
230
328
  }
329
+ function scanChatKitComponents() {
330
+ const meta = {};
331
+ let srcPath;
332
+ try {
333
+ srcPath = getChatKitSourcePath();
334
+ } catch (e) {
335
+ console.warn(` \u26A0\uFE0F Skipping chat-kit scan: ${e.message}`);
336
+ return meta;
337
+ }
338
+ for (const category of getChatKitCategoryDirs()) {
339
+ const categoryPath = path3.join(srcPath, category);
340
+ if (!fs4.existsSync(categoryPath)) continue;
341
+ const entries = fs4.readdirSync(categoryPath, { withFileTypes: true });
342
+ for (const entry of entries) {
343
+ if (!entry.isDirectory()) continue;
344
+ if (!entry.name.startsWith(CHAT_KIT_PREFIX)) continue;
345
+ const componentDir = path3.join(categoryPath, entry.name);
346
+ const componentMeta = processComponent(componentDir, entry.name);
347
+ if (componentMeta) {
348
+ meta[entry.name] = componentMeta;
349
+ }
350
+ }
351
+ }
352
+ return meta;
353
+ }
354
+ function summarize(label, meta) {
355
+ const total = Object.keys(meta).length;
356
+ const withUseCases = Object.values(meta).filter(
357
+ (m) => m.useCases.length > 0
358
+ ).length;
359
+ const withKeywords = Object.values(meta).filter(
360
+ (m) => m.keywords.length > 0
361
+ ).length;
362
+ console.log(`
363
+ ${label} summary:`);
364
+ console.log(` Components with @useCases: ${withUseCases}/${total}`);
365
+ console.log(` Components with keywords: ${withKeywords}/${total}`);
366
+ }
231
367
  function main() {
232
- console.log("Scanning components...");
368
+ console.log("Scanning ui-library components...");
233
369
  const meta = scanComponents();
234
- console.log(`Found ${Object.keys(meta).length} components`);
370
+ console.log(`Found ${Object.keys(meta).length} ui-library components`);
235
371
  console.log(`Writing to ${OUTPUT_PATH}...`);
236
372
  fs4.writeFileSync(OUTPUT_PATH, JSON.stringify(meta, null, 2));
237
- console.log("Done!");
238
- const withUseCases = Object.values(meta).filter((m) => m.useCases.length > 0).length;
239
- const withKeywords = Object.values(meta).filter((m) => m.keywords.length > 0).length;
240
- console.log(`
241
- Summary:`);
242
- console.log(` Components with @useCases: ${withUseCases}/${Object.keys(meta).length}`);
243
- console.log(` Components with keywords: ${withKeywords}/${Object.keys(meta).length}`);
373
+ console.log("\nScanning chat-kit components...");
374
+ const chatKitMeta = scanChatKitComponents();
375
+ console.log(`Found ${Object.keys(chatKitMeta).length} chat-kit components`);
376
+ console.log(`Writing to ${CHAT_KIT_OUTPUT_PATH}...`);
377
+ fs4.writeFileSync(CHAT_KIT_OUTPUT_PATH, JSON.stringify(chatKitMeta, null, 2));
378
+ console.log("\nDone!");
379
+ summarize("ui-library", meta);
380
+ summarize("chat-kit", chatKitMeta);
244
381
  }
245
382
  var isMain = import.meta.url === `file://${process.argv[1]}`;
246
383
  if (isMain) {