- Inicio
- Documentation
- Extensiones
- Carga de extensiones (Módulos TypeScript/JavaScript)
Carga de extensiones (Módulos TypeScript/JavaScript)
Este documento cubre cómo el agente de codificación descubre y carga módulos de extensión (.ts/.js) durante el inicio.
No cubre las extensiones de manifiesto gemini-extension.json (documentadas por separado).
Qué hace este subsistema
Sección titulada «Qué hace este subsistema»La carga de extensiones construye una lista de archivos de entrada de módulos, importa cada módulo con Bun, ejecuta su factoría y devuelve:
- definiciones de extensiones cargadas
- errores de carga por ruta (sin abortar toda la carga)
- un objeto compartido de runtime de extensiones utilizado posteriormente por
ExtensionRunner
Archivos de implementación principales
Sección titulada «Archivos de implementación principales»src/extensibility/extensions/loader.ts— descubrimiento de rutas + importación/ejecuciónsrc/extensibility/extensions/index.ts— exportaciones públicassrc/extensibility/extensions/runner.ts— ejecución de runtime/eventos después de la cargasrc/discovery/builtin.ts— proveedor nativo de auto-descubrimiento para módulos de extensiónsrc/config/settings.ts— carga la configuración fusionada deextensions/disabledExtensions
Entradas para la carga de extensiones
Sección titulada «Entradas para la carga de extensiones»1) Módulos de extensión nativos auto-descubiertos
Sección titulada «1) Módulos de extensión nativos auto-descubiertos»discoverAndLoadExtensions() primero solicita a los proveedores de descubrimiento elementos con capacidad extension-module, luego conserva solo los elementos del proveedor native.
Ubicaciones nativas efectivas:
- Proyecto:
<cwd>/.xcsh/extensions - Usuario:
~/.xcsh/agent/extensions
Las rutas raíz provienen del proveedor nativo (SOURCE_PATHS.native).
Notas:
- El auto-descubrimiento nativo actualmente se basa en
.xcsh. - El legado
.pitodavía se acepta en las claves de manifiesto depackage.json(pi.extensions), pero no como raíz nativa aquí.
2) Rutas configuradas explícitamente
Sección titulada «2) Rutas configuradas explícitamente»Después del auto-descubrimiento, las rutas configuradas se agregan y resuelven.
Fuentes de rutas configuradas en la ruta principal de inicio de sesión (sdk.ts):
- Rutas proporcionadas por CLI (
--extension/-e, y--hooktambién se trata como una ruta de extensión) - Array
extensionsde la configuración (configuración global + proyecto fusionadas)
Archivo de configuración global:
~/.xcsh/agent/config.yml(o directorio de agente personalizado víaPI_CODING_AGENT_DIR)
Archivo de configuración del proyecto:
<cwd>/.xcsh/settings.json
Ejemplos:
extensions: - ~/my-exts/safety.ts - ./local/ext-pack{ "extensions": ["./.xcsh/extensions/my-extra"]}Controles de habilitación/deshabilitación
Sección titulada «Controles de habilitación/deshabilitación»Deshabilitar el descubrimiento
Sección titulada «Deshabilitar el descubrimiento»- CLI:
--no-extensions - Opción SDK:
disableExtensionDiscovery
División de comportamiento:
- SDK: cuando
disableExtensionDiscovery=true, aún cargaadditionalExtensionPathsvíaloadExtensions(). - La construcción de rutas del CLI (
main.ts) actualmente limpia las rutas de extensión del CLI cuando se establece--no-extensions, por lo que las opciones explícitas-e/--hookno se reenvían en ese modo.
Deshabilitar módulos de extensión específicos
Sección titulada «Deshabilitar módulos de extensión específicos»La configuración disabledExtensions filtra por formato de id de extensión:
extension-module:<derivedName>
derivedName se basa en la ruta de entrada (getExtensionNameFromPath), por ejemplo:
/x/foo.ts->foo/x/bar/index.ts->bar
Ejemplo:
disabledExtensions: - extension-module:fooResolución de rutas y entradas
Sección titulada «Resolución de rutas y entradas»Normalización de rutas
Sección titulada «Normalización de rutas»Para rutas configuradas:
- Normalizar espacios unicode
- Expandir
~ - Si es relativa, resolver contra el
cwdactual
Si la ruta configurada es un archivo
Sección titulada «Si la ruta configurada es un archivo»Se utiliza directamente como candidata de entrada de módulo.
Si la ruta configurada es un directorio
Sección titulada «Si la ruta configurada es un directorio»Orden de resolución:
package.jsonen ese directorio conxcsh.extensions(o legadopi.extensions) -> usar las entradas declaradasindex.tsindex.js- En caso contrario, escanear un nivel en busca de entradas de extensión:
*.ts/*.jsdirectos- subdirectorio
index.ts/index.js - subdirectorio
package.jsonconxcsh.extensions/pi.extensions
Reglas y restricciones:
- sin descubrimiento recursivo más allá de un nivel de subdirectorio
- las entradas declaradas en el manifiesto
extensionsse resuelven relativas al directorio del paquete - las entradas declaradas se incluyen solo si el archivo existe/el acceso está permitido
- en pares
*/index.{ts,js}, TypeScript se prefiere sobre JavaScript - los enlaces simbólicos se tratan como archivos/directorios elegibles
El comportamiento de ignorar difiere según la fuente
Sección titulada «El comportamiento de ignorar difiere según la fuente»- El auto-descubrimiento nativo (
discoverExtensionModulePathsen los helpers de descubrimiento) usa glob nativo congitignore: trueyhidden: false. - El escaneo de directorios configurados explícitamente en
loader.tsusa reglas dereaddiry no aplica filtrado por gitignore.
Orden de carga y precedencia
Sección titulada «Orden de carga y precedencia»discoverAndLoadExtensions() construye una lista ordenada y luego llama a loadExtensions().
Orden:
- Módulos auto-descubiertos nativos
- Rutas configuradas explícitamente (en el orden proporcionado)
En sdk.ts, el orden configurado es:
- Rutas adicionales del CLI
extensionsde la configuración
Deduplicación:
- basada en ruta absoluta
- la primera ruta encontrada prevalece
- los duplicados posteriores se ignoran
Implicación: si la misma ruta de módulo es tanto auto-descubierta como configurada explícitamente, se carga una sola vez en la primera posición (etapa de auto-descubrimiento).
Importación de módulos y contrato de factoría
Sección titulada «Importación de módulos y contrato de factoría»Cada ruta candidata se carga con importación dinámica:
await import(resolvedPath)- la factoría es
module.default ?? module - la factoría debe ser una función (
ExtensionFactory)
Si la exportación no es una función, esa ruta falla con un error estructurado y la carga continúa.
Manejo de errores y aislamiento
Sección titulada «Manejo de errores y aislamiento»Durante la carga
Sección titulada «Durante la carga»Por cada ruta de extensión, los fallos se capturan como { path, error } y no detienen la carga de otras rutas.
Casos comunes:
- fallo de importación / archivo no encontrado
- exportación de factoría inválida (no es una función)
- excepción lanzada durante la ejecución de la factoría
Modelo de aislamiento en tiempo de ejecución
Sección titulada «Modelo de aislamiento en tiempo de ejecución»- Las extensiones no están aisladas en sandbox (mismo proceso/runtime).
- Comparten un único
EventBusy una única instancia deExtensionRuntime. - Durante la carga, los métodos de acción del runtime lanzan intencionalmente
ExtensionRuntimeNotInitializedError; la conexión de acciones ocurre posteriormente enExtensionRunner.initialize().
Después de la carga
Sección titulada «Después de la carga»Cuando los eventos se ejecutan a través de ExtensionRunner, las excepciones de los manejadores se capturan y se emiten como errores de extensión en lugar de hacer fallar el bucle del runner.
Ejemplos mínimos de estructura a nivel de usuario/proyecto
Sección titulada «Ejemplos mínimos de estructura a nivel de usuario/proyecto»Nivel de usuario
Sección titulada «Nivel de usuario»~/.xcsh/agent/ config.yml extensions/ guardrails.ts audit/ index.tsNivel de proyecto
Sección titulada «Nivel de proyecto»<repo>/ .xcsh/ settings.json extensions/ checks/ package.json lint-gates.tschecks/package.json:
{ "xcsh": { "extensions": ["./src/check-a.ts", "./src/check-b.js"] }}Clave de manifiesto legada aún aceptada:
{ "pi": { "extensions": ["./index.ts"] }}