Files
Alejandro Martinez b86c9f3e3a Add hooks and CLAUDE.md resource types with install/uninstall scripts
Introduces two new resource types (hooks, claude-md) with full CRUD,
   visual hook config editor, section-delimited CLAUDE.md installs,
   uninstall endpoints, and shell injection hardening in sync scripts.
2026-02-16 11:51:33 +01:00

153 lines
6.2 KiB
Markdown

# 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/<type>/<slug>.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