@intlayer/chokidar
Version:
Uses chokidar to scan and build Intlayer declaration files into dictionaries based on Intlayer configuration.
1 lines • 15.6 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":["fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { v } from '@intlayer/config/logger';\nimport { getMarkdownMetadata } from '@intlayer/core/markdown';\n\n/**\n * Metadata for each available documentation skill.\n */\nexport const SKILLS_METADATA = {\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n Usage: 'How to use Intlayer in your project',\n CLI: 'Intlayer CLI commands and usage',\n Compiler:\n 'Intlayer Compiler setup and usage for automatic content extraction without .content files',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n React: 'React-specific syntax and hooks usage',\n Vue: 'Vue-specific composables and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n Preact: 'Preact-specific syntax and hooks usage',\n Solid:\n 'Integrates Intlayer internationalization with SolidJS components. Use when the user asks to \"setup SolidJS i18n\", use the \"useIntlayer\" hook in Solid, or manage locales in a SolidJS application.',\n Astro: 'Astro-specific usage and getIntlayer',\n} as const;\n\nexport type Skill = keyof typeof SKILLS_METADATA;\n\nexport const SKILLS = Object.keys(SKILLS_METADATA) as Skill[];\n\nexport const getInitialSkills = (\n deps: Record<string, string>\n): (keyof typeof SKILLS_METADATA)[] => {\n const skills: (keyof typeof SKILLS_METADATA)[] = [\n 'Usage',\n 'Content',\n 'Config',\n 'CLI',\n 'Compiler',\n ];\n\n if (deps.next) skills.push('NextJS');\n if (deps.react || !deps.next) skills.push('React');\n if (deps.preact) skills.push('Preact');\n if (deps['solid-js']) skills.push('Solid');\n if (deps.vue || deps.nuxt) skills.push('Vue');\n if (deps.svelte || deps['@sveltejs/kit']) skills.push('Svelte');\n if (deps.astro) skills.push('Astro');\n\n return skills;\n};\n\nexport interface PlatformMetadata {\n label: string;\n dir: string;\n check?: () => boolean;\n}\n\n/**\n * Metadata and configuration for each supported platform.\n */\nexport const PLATFORMS_METADATA: Record<string, PlatformMetadata> = {\n Cursor: {\n label: 'Cursor',\n dir: '.cursor/skills',\n check: () =>\n process.env.CURSOR === 'true' || process.env.TERM_PROGRAM === 'cursor',\n },\n Windsurf: {\n label: 'Windsurf',\n dir: '.windsurf/skills',\n check: () =>\n process.env.WINDSURF === 'true' ||\n process.env.TERM_PROGRAM === 'windsurf',\n },\n Trae: {\n label: 'Trae',\n dir: '.trae/skills',\n check: () =>\n process.env.TRAE === 'true' || process.env.TERM_PROGRAM === 'trae',\n },\n TraeCN: {\n label: 'Trae CN',\n dir: '.trae/skills',\n check: () => process.env.TRAE_CN === 'true',\n },\n VSCode: {\n label: 'VS Code',\n dir: '.vscode/skills',\n check: () =>\n process.env.VSCODE === 'true' || process.env.TERM_PROGRAM === 'vscode',\n },\n OpenCode: {\n label: 'OpenCode',\n dir: '.opencode/skills',\n check: () => process.env.OPENCODE === 'true',\n },\n Claude: {\n label: 'Claude Code',\n dir: '.claude/skills',\n check: () => process.env.CLAUDE === 'true',\n },\n GitHub: {\n label: 'GitHub Copilot Workspace',\n dir: '.github/skills',\n check: () =>\n process.env.GITHUB_ACTIONS === 'true' || !!process.env.GITHUB_WORKSPACE,\n },\n Antigravity: {\n label: 'Antigravity',\n dir: '.agent/skills',\n },\n Augment: {\n label: 'Augment',\n dir: '.augment/skills',\n },\n OpenClaw: {\n label: 'OpenClaw',\n dir: 'skills',\n },\n Cline: {\n label: 'Cline',\n dir: '.cline/skills',\n },\n CodeBuddy: {\n label: 'CodeBuddy',\n dir: '.codebuddy/skills',\n },\n CommandCode: {\n label: 'Command Code',\n dir: '.commandcode/skills',\n },\n Continue: {\n label: 'Continue',\n dir: '.continue/skills',\n },\n Crush: {\n label: 'Crush',\n dir: '.crush/skills',\n },\n Droid: {\n label: 'Droid',\n dir: '.factory/skills',\n },\n Goose: {\n label: 'Goose',\n dir: '.goose/skills',\n },\n IFlow: {\n label: 'iFlow CLI',\n dir: '.iflow/skills',\n },\n Junie: {\n label: 'Junie',\n dir: '.junie/skills',\n },\n KiloCode: {\n label: 'Kilo Code',\n dir: '.kilocode/skills',\n },\n Kiro: {\n label: 'Kiro CLI',\n dir: '.kiro/skills',\n },\n Kode: {\n label: 'Kode',\n dir: '.kode/skills',\n },\n MCPJam: {\n label: 'MCPJam',\n dir: '.mcpjam/skills',\n },\n MistralVibe: {\n label: 'Mistral Vibe',\n dir: '.vibe/skills',\n },\n Mux: {\n label: 'Mux',\n dir: '.mux/skills',\n },\n OpenHands: {\n label: 'OpenHands',\n dir: '.openhands/skills',\n },\n Pi: {\n label: 'Pi',\n dir: '.pi/skills',\n },\n Qoder: {\n label: 'Qoder',\n dir: '.qoder/skills',\n },\n Qwen: {\n label: 'Qwen Code',\n dir: '.qwen/skills',\n },\n RooCode: {\n label: 'Roo Code',\n dir: '.roo/skills',\n },\n Zencoder: {\n label: 'Zencoder',\n dir: '.zencoder/skills',\n },\n Neovate: {\n label: 'Neovate',\n dir: '.neovate/skills',\n },\n Pochi: {\n label: 'Pochi',\n dir: '.pochi/skills',\n },\n Other: {\n label: 'Other',\n dir: 'skills',\n },\n} as const;\n\nexport type Platform = keyof typeof PLATFORMS_METADATA;\n\nexport const PLATFORMS = Object.keys(PLATFORMS_METADATA) as Platform[];\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to kebab-case for directory naming\n */\nconst camelToKebabCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToKebabCase(skill);\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\nconst ALLOWED_FETCH_HOSTS = new Set(['intlayer.org']);\n\n/**\n * Fetches the content of a URL using native fetch.\n */\nconst fetchUrlContent = async (url: string): Promise<string> => {\n const parsed = new URL(url);\n if (\n parsed.protocol !== 'https:' ||\n !ALLOWED_FETCH_HOSTS.has(parsed.hostname)\n ) {\n throw new Error(`Blocked fetch to disallowed host: ${parsed.hostname}`);\n }\n const response = await fetch(url, { redirect: 'error' });\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}: ${response.statusText}`);\n }\n return response.text();\n};\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n // Determine destination directory\n const relativeDir = PLATFORMS_METADATA[platform].dir ?? 'skills';\n const skillsBaseDir = path.join(projectRoot, relativeDir);\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToKebabCase(skill);\n const skillName = `intlayer-${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n // Extract unique URLs\n const urls = Array.from(\n new Set(skillContent.match(/https:\\/\\/intlayer\\.org\\/[^\\s)]+\\.md/g) || [])\n );\n\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n const referenceDir = path.join(skillDir, 'references');\n\n // Ensure directories exist\n await fs.mkdir(referenceDir, { recursive: true });\n\n // Write License\n if (licenceContent) {\n await fs.writeFile(\n path.join(skillDir, 'LICENCE.md'),\n licenceContent,\n 'utf-8'\n );\n }\n\n let updatedSkillContent = skillContent;\n\n // Parallel download of references\n const downloadPromises = urls.map(async (url) => {\n try {\n const content = await fetchUrlContent(url);\n const metadata = getMarkdownMetadata<{ slugs?: string[] }>(content);\n\n let fileName = '';\n\n // Determine filename from slugs or URL path\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs.filter((slug) => slug !== 'doc').join('_');\n } else {\n const urlPath = new URL(url).pathname;\n fileName = urlPath\n .split('/')\n .filter((part) => part && part !== 'doc')\n .map((part) => part.replace('.md', '')) // Clean extension for joining\n .join('_');\n }\n\n // Ensure it ends with .md\n fileName = fileName ? `${fileName}.md` : 'index.md';\n const localRefPath = `references/${fileName}`;\n\n return {\n url,\n localRefPath,\n fileName,\n content,\n success: true,\n };\n } catch (error) {\n console.warn(\n `Warning: Failed to download ref ${url} for skill ${skill}`,\n error\n );\n return { url, success: false };\n }\n });\n\n const results = await Promise.all(downloadPromises);\n\n // Process results: Write files and update content string\n for (const res of results) {\n if (res.success && res.fileName && res.content && res.localRefPath) {\n // Write the reference file\n await fs.writeFile(\n path.join(referenceDir, res.fileName),\n res.content,\n 'utf-8'\n );\n\n // Update the main content to point to local file\n updatedSkillContent = updatedSkillContent.replaceAll(\n res.url,\n res.localRefPath\n );\n }\n }\n\n // Write the main SKILL.md\n const filePath = path.join(skillDir, 'SKILL.md');\n await fs.writeFile(filePath, updatedSkillContent, 'utf-8');\n createdSkills.push(`${skillName}/SKILL.md`);\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `${v} Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}