# Plan: Soporte de Skills en formato carpeta (Folder-based resources) ## Contexto El PDF oficial de Anthropic define que una skill puede ser una **carpeta** con subdirectorios: ``` my-skill/ ├── SKILL.md # Requerido ├── scripts/ # Opcional - codigo ejecutable ├── references/ # Opcional - documentacion └── assets/ # Opcional - plantillas, fuentes, iconos ``` Actualmente Skillit almacena cada recurso como un unico `.md` en `data//.md`. Queremos soportar **ambos formatos**: simple (archivo .md) y carpeta (directorio con SKILL.md + subdirectorios). ## Archivos a modificar | Archivo | Cambio | |---------|--------| | `src/lib/registry.ts` | Agregar `mainFileName` por tipo y constante `FOLDER_SUBDIRS` | | `src/lib/resources.ts` | Reescribir CRUD para detectar/manejar ambos formatos; nuevas funciones para sub-archivos | | `src/lib/skills.ts` | Actualizar interfaz `Skill` con `format` y `files` | | `src/lib/sync.ts` | Scripts de sync/push con soporte carpeta | | `src/pages/api/resources/[type]/index.ts` | Aceptar `format` en POST | | `src/pages/api/resources/[type]/[slug].ts` | Manejar carpeta en GET | | `src/pages/[type]/[slug].astro` | Mostrar arbol de archivos | | `src/pages/[type]/[slug]/edit.astro` | Pasar format/files al editor | | `src/pages/[type]/new.astro` | Soporte selector de formato | | `src/pages/[type]/[slug]/i.ts` | Install scripts multi-archivo | | `src/pages/[type]/[slug]/gi.ts` | Install global multi-archivo | | `src/components/ResourceEditor.vue` | Toggle formato + integrar FileManager | ## Archivos nuevos | Archivo | Proposito | |---------|-----------| | `src/pages/api/resources/[type]/[slug]/files/index.ts` | Listar y subir sub-archivos | | `src/pages/api/resources/[type]/[slug]/files/[...filePath].ts` | CRUD individual de sub-archivos | | `src/components/FileManager.vue` | Componente Vue para gestionar sub-archivos | | `src/components/FolderTree.astro` | Componente Astro para mostrar arbol de archivos en detalle | ## Fases de implementacion ### Fase 1: Registry (`registry.ts`) Agregar campo `mainFileName` a `ResourceTypeConfig`: - skills: `SKILL.md` - agents: `AGENT.md` - output-styles: `OUTPUT-STYLE.md` - rules: `RULE.md` Agregar constante `FOLDER_SUBDIRS = ['scripts', 'references', 'assets']`. ### Fase 2: Core CRUD (`resources.ts`) Cambios principales: 1. **Nuevos tipos**: - `ResourceFormat = 'file' | 'folder'` - `ResourceFileEntry = { relativePath: string; size: number }` - Agregar `format` y `files` a interfaz `Resource` 2. **`resolveResource(type, slug)`** (nueva): detecta si el recurso es archivo o carpeta. Carpeta tiene prioridad si ambos existen. 3. **`listResources(type)`**: escanear tanto `*.md` como directorios con el mainFileName. 4. **`getResource(type, slug)`**: usar `resolveResource`, leer mainFile, listar sub-archivos si es carpeta. 5. **`createResource(type, slug, content, format?)`**: parametro `format` opcional (default `'file'`). Si `'folder'`, crear directorio y escribir mainFileName. 6. **`updateResource(type, slug, content)`**: auto-detectar formato, escribir en la ruta correcta. 7. **`deleteResource(type, slug)`**: auto-detectar. Para carpeta usar `fs.rm(dirPath, { recursive: true })`. 8. **Funciones nuevas para sub-archivos**: - `listResourceFiles(type, slug)` - listar archivos auxiliares - `getResourceFile(type, slug, relativePath)` - leer sub-archivo (Buffer) - `addResourceFile(type, slug, relativePath, data: Buffer)` - escribir sub-archivo - `deleteResourceFile(type, slug, relativePath)` - eliminar sub-archivo - `convertToFolder(type, slug)` - convertir simple a carpeta 9. **Seguridad**: validar que `relativePath` no contenga `..`, solo permita rutas dentro de `FOLDER_SUBDIRS`. ### Fase 3: API de sub-archivos **`/api/resources/[type]/[slug]/files/index.ts`**: - GET: lista sub-archivos (JSON) - POST: subir archivo via multipart/form-data **`/api/resources/[type]/[slug]/files/[...filePath].ts`**: - GET: descargar sub-archivo - PUT: subir/reemplazar sub-archivo - DELETE: eliminar sub-archivo **Modificar `/api/resources/[type]/index.ts`**: - POST acepta `format: 'file' | 'folder'` opcional ### Fase 4: Pagina de detalle (`[type]/[slug].astro`) - Comprobar `resource.format` - Para carpeta: renderizar seccion "Files" con `FolderTree.astro` - El raw markdown (para curl) sigue devolviendo solo el mainFile **`FolderTree.astro`**: componente que muestra arbol de archivos con links de descarga. ### Fase 5: Editor UI **`ResourceEditor.vue`**: - Nuevos props: `initialFormat`, `files` - Toggle formato al crear (Simple / Carpeta) - Seccion FileManager al editar recurso tipo carpeta **`FileManager.vue`** (nuevo componente Vue): - Lista archivos con boton eliminar - Boton subir: selector de subdirectorio (scripts/references/assets) + file input - Llamadas fetch a la API de files ### Fase 6: Scripts de instalacion **`[type]/[slug]/i.ts` y `gi.ts`**: - Para formato carpeta: generar script que crea estructura de directorios y descarga cada archivo - URLs de sub-archivos: `${origin}/api/resources/${type}/${slug}/files/${relativePath}` - `chmod +x` para archivos en `scripts/` **`sync.ts`**: - Sync: detectar formato por recurso, generar descarga multi-archivo - Push: iterar tanto `*.md` como directorios; subir main content + sub-archivos ### Fase 7: Backward compat (`skills.ts`) Actualizar interfaz `Skill` con `format` y `files`. El wrapper sigue delegando a `resources.ts`. ## Orden de implementacion 1. Fase 1 (registry) - base 2. Fase 2 (resources.ts CRUD) - critico 3. Fase 3 (API sub-archivos) 4. Fase 4 (pagina detalle) 5. Fase 5 (editor UI) 6. Fase 6 (scripts instalacion) 7. Fase 7 (backward compat) ## Verificacion 1. Crear un skill simple (`test-simple`) via web - verificar que funciona como antes 2. Crear un skill carpeta (`test-folder`) via web - verificar que se crea directorio con SKILL.md 3. Subir archivos a scripts/ y references/ del skill carpeta via FileManager 4. Ver pagina de detalle - verificar arbol de archivos 5. Ejecutar script de instalacion (`curl .../skills/test-folder/i | bash`) - verificar descarga completa 6. Verificar que listado muestra ambos formatos correctamente 7. Editar ambos formatos - verificar que se actualizan 8. Eliminar ambos formatos - verificar limpieza