UNPKG

tsai-registry

Version:

Community-driven registry CLI for Mastra/AI agents, workflows, and tools

216 lines (213 loc) 7.93 kB
// @bun var __create = Object.create; var __getProtoOf = Object.getPrototypeOf; var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __toESM = (mod, isNodeMode, target) => { target = mod != null ? __create(__getProtoOf(mod)) : {}; const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target; for (let key of __getOwnPropNames(mod)) if (!__hasOwnProp.call(to, key)) __defProp(to, key, { get: () => mod[key], enumerable: true }); return to; }; var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); var __require = import.meta.require; // utils.ts import fs from "fs"; import path from "path"; async function loadSettings(settingsPath) { let data; let overrideLocalPath; if (!settingsPath) { const localOverride = path.join(process.cwd(), "settings-registry.json"); if (fs.existsSync(localOverride)) { overrideLocalPath = JSON.parse(fs.readFileSync(localOverride, "utf-8")).settings?.local; } settingsPath = process.env.TSAR_SETTINGS_URL || "https://raw.githubusercontent.com/aidalinfo/tsai-registry/refs/heads/main/settings.json"; } if (settingsPath.startsWith("http://") || settingsPath.startsWith("https://")) { const res = await fetch(settingsPath); if (!res.ok) throw new Error(`Erreur lors du chargement distant: ${res.statusText}`); data = await res.text(); } else { const resolvedPath = path.isAbsolute(settingsPath) ? settingsPath : path.join(process.cwd(), settingsPath); if (!fs.existsSync(resolvedPath)) throw new Error(`Fichier introuvable: ${resolvedPath}`); data = fs.readFileSync(resolvedPath, "utf-8"); } const base = JSON.parse(data); if (overrideLocalPath) { base.settings = base.settings || {}; base.settings.local = overrideLocalPath; } if (!base.settings) base.settings = {}; if (!base.settings.local) { let distantSettingsUrl = process.env.TSAR_SETTINGS_URL || "https://raw.githubusercontent.com/aidalinfo/tsai-registry/refs/heads/main/settings.json"; try { let distantData; if (distantSettingsUrl.startsWith("http://") || distantSettingsUrl.startsWith("https://")) { const res = await fetch(distantSettingsUrl); if (res.ok) { distantData = await res.text(); const distantJson = JSON.parse(distantData); if (distantJson.settings && distantJson.settings.local) { base.settings.local = distantJson.settings.local; } } } else if (fs.existsSync(distantSettingsUrl)) { distantData = fs.readFileSync(distantSettingsUrl, "utf-8"); const distantJson = JSON.parse(distantData); if (distantJson.settings && distantJson.settings.local) { base.settings.local = distantJson.settings.local; } } } catch (e) {} if (!base.settings.local) base.settings.local = "src/mastra/registry"; } return base; } async function loadRegistry(registryPath, settingsUrl) { let data; if (!registryPath.startsWith("http://") && !registryPath.startsWith("https://") && settingsUrl) { let repo = settingsUrl.replace("https://github.com/", ""); const branch = "main"; registryPath = `https://raw.githubusercontent.com/${repo}/refs/heads/${branch}/${registryPath}`; } if (registryPath.startsWith("http://") || registryPath.startsWith("https://")) { const res = await fetch(registryPath); if (!res.ok) throw new Error(`Erreur lors du chargement du registry: ${res.statusText}`); data = await res.text(); } else { const resolvedPath = path.isAbsolute(registryPath) ? registryPath : path.join(process.cwd(), registryPath); if (!fs.existsSync(resolvedPath)) throw new Error(`Registry introuvable: ${resolvedPath}`); data = fs.readFileSync(resolvedPath, "utf-8"); } return JSON.parse(data); } // build.ts import fs2 from "fs"; import path2 from "path"; var {write } = globalThis.Bun; (async () => { const settings = await loadSettings(); const ignoreExtensions = settings.build?.ignoreExtensions || []; const registryArg = process.argv[2] || "app/src/mastra/registry"; const REGISTRY_ROOT = path2.isAbsolute(registryArg) ? registryArg : path2.join(process.cwd(), registryArg); const OUTPUT_PATH = path2.join(process.cwd(), "registry.json"); const SUPPORTED_TYPES = ["agents", "workflows", "tools", "mcp"]; function listFilesRecursive(dir) { let results = []; const list = fs2.readdirSync(dir); list.forEach((file) => { const filePath = path2.join(dir, file); const stat = fs2.statSync(filePath); if (stat && stat.isDirectory()) { results = results.concat(listFilesRecursive(filePath)); } else { if (!ignoreExtensions.some((ext) => filePath.endsWith(ext))) { results.push(filePath); } } }); return results; } function extractDependencies(fileContent) { const importRegex = /import\s+(?:[^'\"]+from\s+)?["']([^"']+)["']/g; const deps = new Set; let match; while (match = importRegex.exec(fileContent)) { const dep = match[1]; if (dep && !dep.startsWith(".") && !dep.startsWith("/")) { const depParts = dep.split("/"); if (depParts[0]) { if (depParts[0].startsWith("@")) { if (depParts[1]) deps.add(depParts.slice(0, 2).join("/")); } else { deps.add(depParts[0]); } } } } return Array.from(deps); } function extractEnvs(fileContent) { const envRegex = /process\.env\.([A-Z0-9_]+)/g; const envs = new Set; let match; while (match = envRegex.exec(fileContent)) { if (match[1]) envs.add(match[1]); } return Array.from(envs); } const PROVIDER_MODULES = { "@ai-sdk/xai": "xai", "@ai-sdk/openai": "openai", "@ai-sdk/anthropic": "anthropic", "@ai-sdk/google": "google", "@ai-sdk/azure": "azure", "@ai-sdk/amazon-bedrock": "bedrock", "@ai-sdk/groq": "groq", "@ai-sdk/mistral": "mistral", "@ai-sdk/deepseek": "deepseek" }; function extractAIProviders(fileContent) { const fromRegex = /from\s+['"]([^'"]+)['"]/g; const providers = new Set; let match; while (match = fromRegex.exec(fileContent)) { const mod = match[1]; const provider = PROVIDER_MODULES[mod]; if (provider) providers.add(provider); } return Array.from(providers); } const registry = {}; for (const type of SUPPORTED_TYPES) { const typeDir = path2.join(REGISTRY_ROOT, type); if (!fs2.existsSync(typeDir)) continue; const names = fs2.readdirSync(typeDir); for (const name of names) { const objDir = path2.join(typeDir, name); if (!fs2.statSync(objDir).isDirectory()) continue; const files = listFilesRecursive(objDir); const relFiles = files.map((f) => path2.relative(process.cwd(), f)); let allDeps = []; let allEnvs = []; let providers = []; for (const filePath of files) { const content = fs2.readFileSync(filePath, "utf-8"); allDeps = allDeps.concat(extractDependencies(content)); allEnvs = allEnvs.concat(extractEnvs(content)); providers = providers.concat(extractAIProviders(content)); } allDeps = Array.from(new Set(allDeps)); allEnvs = Array.from(new Set(allEnvs)); providers = Array.from(new Set(providers)); registry[name] = { type, name, files: relFiles, dependencies: allDeps, envs: allEnvs, aiprovider: providers }; } } await write(OUTPUT_PATH, JSON.stringify(registry, null, 2)); console.log("registry.json generate with success."); })();