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.
153 lines
6.2 KiB
Markdown
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
|