Ctrl K
ComunidadGuías…

scripts/lib/community-skills.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { readdir, readFile, stat } from 'node:fs/promises'
import { join } from 'node:path'
import yaml from 'js-yaml'
import { z } from 'zod'
import { SkillBodySchema } from '../../src/lib/agent-skills/validation'
import type { DiscoveredAtom } from './atom-discovery'

/** Reviewed registry entries and private submissions ultimately use this path. */
export async function discoverCommunitySkills(root: string): Promise<DiscoveredAtom[]> {
  const directory = join(root, 'registry/entries')
  const files = await readdir(directory).catch((error: NodeJS.ErrnoException) => { if (error.code === 'ENOENT') return []; throw error })
  const atoms: DiscoveredAtom[] = []
  for (const file of files.sort()) {
    if (!/^[a-z0-9][a-z0-9-]*\.mdx?$/.test(file)) continue
    const text = await readFile(join(directory, file), 'utf8')
    const frontmatter = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text)
    if (!frontmatter) throw new Error(`Invalid registry frontmatter: ${file}`)
    const entry = yaml.load(frontmatter[1]) as Record<string, unknown>
    const slug = file.replace(/\.mdx?$/, '')
    const bodyPath = `registry/skills/${slug}/SKILL.md`
    const exists = await stat(join(root, bodyPath)).catch((error: NodeJS.ErrnoException) => { if (error.code === 'ENOENT') return null; throw error })
    if (!exists) {
      if (entry.mcp_exposed === true) throw new Error(`Missing skill body: ${bodyPath}`)
      continue
    }
    if (entry.kind !== 'skill' || entry.slug !== slug) throw new Error(`Invalid community skill entry: ${file}`)
    if (entry.mcp_exposed !== undefined && typeof entry.mcp_exposed !== 'boolean') throw new Error(`mcp_exposed must be boolean: ${file}`)
    const reviewedAt = entry.reviewedAt === undefined ? null : z.iso.date().parse(entry.reviewedAt)
    if (entry.mcp_exposed && !reviewedAt) throw new Error(`MCP publication requires reviewedAt: ${file}`)
    const body = SkillBodySchema.parse(await readFile(join(root, bodyPath), 'utf8'))
    atoms.push({ id: `community/${slug}`, tier: 'community', slug,
      title: z.string().min(1).max(120).parse(entry.title), description: z.string().min(1).max(500).parse(entry.description),
      body, body_path: bodyPath, parent_atom_id: null, audience: 'agent', estimated_tokens: Math.ceil(body.length / 4),
      sni_prefixes: [], trigger_signals: {}, frontmatter_version: 1, schema_version: 1,
      mcp_exposed: entry.mcp_exposed === true && entry.status === 'live', reviewed_at: reviewedAt,
    })
  }
  return atoms
}