- Inicio
- Documentation
- Extensiones
- Gestión de plugins e instalación interna
Gestión de plugins e instalación interna
Este documento describe cómo las operaciones xcsh plugin modifican el estado de los plugins en disco y cómo los plugins instalados se convierten en capacidades en tiempo de ejecución (herramientas hoy en día, con resolución de rutas para hooks/comandos disponible).
Alcance y arquitectura
Sección titulada «Alcance y arquitectura»Existen dos implementaciones de gestión de plugins en el código base:
- Ruta activa utilizada por los comandos CLI:
PluginManager(src/extensibility/plugins/manager.ts) - Módulo auxiliar heredado: funciones del instalador (
src/extensibility/plugins/installer.ts)
La ejecución del comando xcsh plugin ... pasa por PluginManager.
installer.ts sigue documentando verificaciones de seguridad importantes y comportamiento del sistema de archivos, pero no es la ruta utilizada por src/commands/plugin.ts + src/cli/plugin-cli.ts.
Ciclo de vida: desde la invocación CLI hasta la disponibilidad en tiempo de ejecución
Sección titulada «Ciclo de vida: desde la invocación CLI hasta la disponibilidad en tiempo de ejecución»xcsh plugin <action> ... -> src/commands/plugin.ts -> runPluginCommand(...) in src/cli/plugin-cli.ts -> PluginManager method (install/list/uninstall/link/...) -> mutate ~/.xcsh/plugins/{package.json,node_modules,xcsh-plugins.lock.json} -> runtime discovery: discoverAndLoadCustomTools(...) -> getAllPluginToolPaths(cwd) -> custom tool loader imports tool modulesPuntos de entrada de comandos
Sección titulada «Puntos de entrada de comandos»src/commands/plugin.tsdefine el comando/indicadores y reenvía arunPluginCommand.src/cli/plugin-cli.tsmapea los subcomandos a los métodos dePluginManager:install,uninstall,list,link,doctor,features,config,enable,disable
- No existe una acción
updateexplícita; la actualización se realiza volviendo a ejecutarinstallcon una nueva especificación de paquete/versión.
Modelo en disco
Sección titulada «Modelo en disco»El estado global de los plugins reside en ~/.xcsh/plugins:
package.json— manifiesto de dependencias utilizado porbun install/bun uninstallnode_modules/— paquetes de plugins instalados o enlaces simbólicosxcsh-plugins.lock.json— estado en tiempo de ejecución:- habilitado/deshabilitado por plugin
- conjunto de características seleccionadas por plugin
- configuraciones de plugin persistidas
Las anulaciones locales del proyecto residen en:
<cwd>/.xcsh/plugin-overrides.json
Las anulaciones son de solo lectura desde la perspectiva del gestor/cargador (no existe ruta de escritura aquí) y pueden deshabilitar plugins o anular características/configuraciones para este proyecto.
Análisis de especificaciones de plugins e interpretación de metadatos
Sección titulada «Análisis de especificaciones de plugins e interpretación de metadatos»Gramática de especificaciones de instalación
Sección titulada «Gramática de especificaciones de instalación»parsePluginSpec (parser.ts) admite:
pkg->features: null(comportamiento predeterminado)pkg[*]-> habilitar todas las características del manifiestopkg[]-> no habilitar características opcionalespkg[a,b]-> habilitar características con nombre@scope/pkg@1.2.3[feat]-> paquete con ámbito + versión con selección explícita de características
extractPackageName elimina el sufijo de versión para la búsqueda de rutas en disco después de la instalación.
Fuente del manifiesto y campos requeridos
Sección titulada «Fuente del manifiesto y campos requeridos»El manifiesto se resuelve como:
package.json.xcsh- alternativa
package.json.pi - alternativa
{ version: package.version }
Implicaciones:
- No existe validación de esquema estricta en el gestor/cargador.
- Un paquete sin manifiesto
xcsh/pisigue siendo instalable y listable. - La carga de plugins en tiempo de ejecución (
getEnabledPlugins) omite los paquetes sin manifiestoxcsh/pi. manifest.versionsiempre se sobreescribe desde laversiondel paquete.
Un JSON malformado en package.json es un error grave en el momento de la lectura; una forma de manifiesto malformada puede fallar más adelante solo cuando se consumen campos específicos.
Flujo de instalación/actualización (PluginManager.install)
Sección titulada «Flujo de instalación/actualización (PluginManager.install)»- Analizar la sintaxis de corchetes de características de la especificación de instalación.
- Validar el nombre del paquete contra la expresión regular + lista de denegación de metacaracteres de shell.
- Asegurarse de que
package.jsondel plugin exista (xcsh-plugins, mapa de dependencias privadas). - Ejecutar
bun install <packageSpec>en~/.xcsh/plugins. - Leer el
node_modules/<name>/package.jsondel paquete instalado. - Resolver el manifiesto y calcular
enabledFeatures:[*]: todas las características declaradas (onullsi no hay mapa de características)[a,b]: valida que cada característica exista en el mapa de características del manifiesto[]: lista de características vacía- especificación simple:
null(usar la política de valores predeterminados más adelante en el cargador)
- Actualizar el estado en tiempo de ejecución del archivo de bloqueo:
{ version, enabledFeatures, enabled: true }.
Semántica de actualización
Sección titulada «Semántica de actualización»Dado que la actualización está basada en la instalación:
xcsh plugin install pkg@newVersionactualiza la dependencia y la versión del archivo de bloqueo.- La configuración existente se preserva; la entrada de estado se sobreescribe para versión/características/habilitado.
- No existe lógica separada de “verificar actualizaciones” ni de migración transaccional.
Flujo de eliminación (PluginManager.uninstall)
Sección titulada «Flujo de eliminación (PluginManager.uninstall)»- Validar el nombre del paquete.
- Ejecutar
bun uninstall <name>en el directorio de plugins. - Eliminar el estado en tiempo de ejecución del plugin del archivo de bloqueo:
config.plugins[name]config.settings[name]
Si el comando de desinstalación falla, el estado en tiempo de ejecución no se modifica.
Flujo de listado (PluginManager.list)
Sección titulada «Flujo de listado (PluginManager.list)»- Leer el mapa de dependencias de plugins desde
~/.xcsh/plugins/package.json. - Cargar la configuración en tiempo de ejecución del archivo de bloqueo (archivo faltante -> valores predeterminados vacíos).
- Cargar las anulaciones del proyecto (
<cwd>/.xcsh/plugin-overrides.json, errores de análisis/lectura -> objeto vacío con advertencia). - Para cada dependencia con un
package.jsonresoluble:- construir el registro
InstalledPlugin - combinar el estado de características/habilitación:
- base desde el archivo de bloqueo (o valores predeterminados)
- las anulaciones del proyecto pueden reemplazar la selección de características
- la lista
disableddel proyecto enmascara el plugin como deshabilitado
- construir el registro
Este es el estado efectivo utilizado por la salida de estado del CLI y las operaciones de configuración/características.
Flujo de enlace (PluginManager.link)
Sección titulada «Flujo de enlace (PluginManager.link)»link admite el desarrollo local de plugins creando un enlace simbólico de un paquete local en ~/.xcsh/plugins/node_modules/<pkg.name>.
Comportamiento:
- Resolver
localPathcontra el cwd del gestor. - Requerir
package.jsonlocal y el camponame. - Asegurarse de que existan los directorios del plugin.
- Para nombres con ámbito, crear el directorio de ámbito.
- Eliminar la ruta existente en la ubicación del enlace de destino.
- Crear el enlace simbólico.
- Agregar una entrada al archivo de bloqueo en tiempo de ejecución habilitada con características predeterminadas (
null).
Advertencia: el PluginManager.link actual no aplica la verificación de límite de ruta cwd presente en el installer.ts heredado (normalizedPath.startsWith(normalizedCwd)), por lo que la confianza es responsabilidad del llamador.
Carga en tiempo de ejecución: del plugin instalado a las capacidades invocables
Sección titulada «Carga en tiempo de ejecución: del plugin instalado a las capacidades invocables»Puerta de descubrimiento
Sección titulada «Puerta de descubrimiento»getEnabledPlugins(cwd) (plugins/loader.ts) lee:
- manifiesto de dependencias del plugin (
package.json) - estado en tiempo de ejecución del archivo de bloqueo
- anulaciones del proyecto mediante
getConfigDirPaths("plugin-overrides.json", { user: false, cwd })
Filtrado:
- omitir si no hay
package.jsondel plugin - omitir si el manifiesto (
xcsh/pi) está ausente - omitir si está deshabilitado globalmente en el archivo de bloqueo
- omitir si está deshabilitado por el proyecto
Resolución de rutas de capacidades
Sección titulada «Resolución de rutas de capacidades»Para cada plugin habilitado:
resolvePluginToolPaths(plugin)resolvePluginHookPaths(plugin)resolvePluginCommandPaths(plugin)
Cada resolvedor incluye entradas base más entradas de características:
- lista de características explícita -> solo las características seleccionadas
enabledFeatures === null-> habilitar las características marcadas comodefault: true
Los archivos faltantes se omiten silenciosamente (protección con existsSync).
Diferencias actuales en el cableado en tiempo de ejecución
Sección titulada «Diferencias actuales en el cableado en tiempo de ejecución»- Las herramientas están conectadas al tiempo de ejecución hoy mediante
discoverAndLoadCustomTools(custom-tools/loader.ts), que llama agetAllPluginToolPaths(cwd). - Las rutas se deduplicarán por ruta absoluta resuelta en el descubrimiento de herramientas personalizadas (conjunto
seen, la primera ruta gana). - Los resolutores de hooks/comandos existen y se exportan, pero esta ruta de código actualmente no los conecta a un registro en tiempo de ejecución de la misma manera en que se conectan las herramientas.
Detalles de gestión de bloqueo/estado
Sección titulada «Detalles de gestión de bloqueo/estado»PluginManager almacena en caché la configuración en tiempo de ejecución en memoria por instancia (#runtimeConfig) y la carga de forma diferida una vez.
Comportamiento de carga:
- archivo de bloqueo faltante ->
{ plugins: {}, settings: {} } - fallo de lectura/análisis del archivo de bloqueo -> advertencia + mismos valores predeterminados vacíos
Comportamiento de guardado:
- escribe el JSON completo del archivo de bloqueo con formato de sangría en cada mutación
No existe bloqueo entre procesos ni estrategia de fusión; los escritores concurrentes pueden sobreescribirse mutuamente.
Verificaciones de seguridad y límites de confianza
Sección titulada «Verificaciones de seguridad y límites de confianza»Validación de entrada/paquetes
Sección titulada «Validación de entrada/paquetes»La ruta del gestor activo aplica la validación del nombre del paquete:
- expresión regular para especificaciones de paquetes con o sin ámbito (opcionalmente con versión)
- lista de denegación explícita de metacaracteres de shell (
[;&|$(){}[]<>\]`)
Esto limita el riesgo de inyección de comandos al invocar bun install/uninstall.
Límite de confianza del sistema de archivos
Sección titulada «Límite de confianza del sistema de archivos»- El código del plugin se ejecuta en proceso cuando se importan los módulos de herramientas personalizadas; no existe aislamiento.
- Las rutas relativas del manifiesto se unen al directorio del paquete del plugin y solo se verifica su existencia.
- El paquete del plugin en sí es código de confianza una vez instalado.
Verificaciones exclusivas del instalador heredado
Sección titulada «Verificaciones exclusivas del instalador heredado»installer.ts incluye verificaciones adicionales en el momento del enlace que no se replican en PluginManager.link:
- la ruta local debe resolverse dentro del cwd del proyecto
- protecciones adicionales de nombre de paquete/recorrido de ruta para la denominación del destino del enlace simbólico
Dado que el CLI utiliza PluginManager, estas protecciones de enlace más estrictas no están actualmente en la ruta principal.
Comportamiento ante fallos, éxito parcial y reversión
Sección titulada «Comportamiento ante fallos, éxito parcial y reversión»El gestor de plugins no es transaccional.
| Etapa de la operación | Comportamiento ante fallo | Reversión |
|---|---|---|
bun install falla | la instalación se interrumpe con stderr | N/A (aún no se han escrito estados) |
| La instalación tiene éxito, luego falla la validación del manifiesto/características | el comando falla | Sin reversión de desinstalación; la dependencia puede permanecer en node_modules/package.json |
| La instalación tiene éxito, luego falla la escritura del archivo de bloqueo | el comando falla | Sin reversión del paquete instalado |
bun uninstall tiene éxito, falla la escritura del archivo de bloqueo | el comando falla | Paquete eliminado, puede quedar estado en tiempo de ejecución obsoleto |
link elimina el destino anterior y luego falla la creación del enlace simbólico | el comando falla | Sin restauración del enlace/directorio anterior |
Operativamente, doctor --fix puede reparar algunas desviaciones (bun install, limpieza de configuración huérfana, limpieza de características inválidas), pero es de mejor esfuerzo.
Resumen del comportamiento ante manifiestos malformados o faltantes
Sección titulada «Resumen del comportamiento ante manifiestos malformados o faltantes»- Campo
xcsh/pifaltante:- instalación/listado: tolerado (manifiesto mínimo)
- descubrimiento de plugins habilitados en tiempo de ejecución: omitido como no-plugin
- Característica faltante referenciada por la especificación de instalación o
features --set/--enable: error grave con la lista de características disponibles plugin-overrides.jsoninválido: ignorado con alternativa a{}tanto en las rutas del gestor como del cargador- Rutas de archivos de herramientas/hooks/comandos faltantes referenciadas por el manifiesto: ignoradas silenciosamente durante la expansión del resolvedor; señaladas como errores solo por
doctor
Diferencias de modo y precedencia
Sección titulada «Diferencias de modo y precedencia»--dry-run(install): devuelve un resultado de instalación sintético, sin escrituras en el sistema de archivos/red/estado.--json: solo formato de salida, sin cambio de comportamiento.- Las anulaciones del proyecto siempre tienen precedencia sobre el archivo de bloqueo global para la vista de características/configuración.
- La habilitación efectiva es
runtimeEnabled && !projectDisabled.
Archivos de implementación
Sección titulada «Archivos de implementación»src/commands/plugin.ts— declaración del comando CLI y mapeo de indicadoressrc/cli/plugin-cli.ts— despacho de acciones, manejadores de comandos orientados al usuariosrc/extensibility/plugins/manager.ts— implementación activa de instalación/eliminación/listado/enlace/estado/doctorsrc/extensibility/plugins/installer.ts— ayudantes del instalador heredado y verificaciones adicionales de seguridad de enlacesrc/extensibility/plugins/loader.ts— descubrimiento de plugins habilitados y resolución de rutas de herramientas/hooks/comandossrc/extensibility/plugins/parser.ts— ayudantes de análisis de especificaciones de instalación y nombres de paquetessrc/extensibility/plugins/types.ts— contratos de tipos de manifiesto/tiempo de ejecución/anulaciónsrc/extensibility/custom-tools/loader.ts— cableado en tiempo de ejecución para módulos de herramientas proporcionados por plugins