xonecode 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/apps/web/dist/assets/index-DBZTodio.js +477 -0
  2. package/apps/web/dist/assets/{index-BB3SamhR.css → index-rqecK6s2.css} +1 -1
  3. package/apps/web/dist/assets/{php-D_2--9WK.js → php-BBij3Lhc.js} +1 -1
  4. package/apps/web/dist/assets/{ruby-DSHSDbk1.js → ruby-Dq2YEaLo.js} +1 -1
  5. package/apps/web/dist/index.html +2 -2
  6. package/dist/agent/cloudstudio/cloudstudioClient.js.map +1 -0
  7. package/dist/agent/{cloudstudioMcp.js → cloudstudio/cloudstudioMcp.js} +5 -5
  8. package/dist/agent/cloudstudio/cloudstudioMcp.js.map +1 -0
  9. package/dist/agent/{descarga.js → cloudstudio/descarga.js} +3 -3
  10. package/dist/agent/cloudstudio/descarga.js.map +1 -0
  11. package/dist/agent/cloudstudio/manifiesto.js.map +1 -0
  12. package/dist/agent/{subida.js → cloudstudio/subida.js} +3 -3
  13. package/dist/agent/cloudstudio/subida.js.map +1 -0
  14. package/dist/agent/{zip.js → cloudstudio/zip.js} +1 -1
  15. package/dist/agent/cloudstudio/zip.js.map +1 -0
  16. package/dist/agent/{authEnDisco.js → config/authEnDisco.js} +3 -3
  17. package/dist/agent/config/authEnDisco.js.map +1 -0
  18. package/dist/agent/{catalogoModelos.js → config/catalogoModelos.js} +2 -1
  19. package/dist/agent/config/catalogoModelos.js.map +1 -0
  20. package/dist/agent/{configEnDisco.js → config/configEnDisco.js} +6 -6
  21. package/dist/agent/config/configEnDisco.js.map +1 -0
  22. package/dist/agent/{crearProyecto.js → config/crearProyecto.js} +2 -2
  23. package/dist/agent/config/crearProyecto.js.map +1 -0
  24. package/dist/agent/config/entorno.js.map +1 -0
  25. package/dist/agent/config/gemini.js.map +1 -0
  26. package/dist/agent/{modelos.js → config/modelos.js} +17 -3
  27. package/dist/agent/config/modelos.js.map +1 -0
  28. package/dist/agent/{modelosDeMotor.js → config/modelosDeMotor.js} +1 -1
  29. package/dist/agent/config/modelosDeMotor.js.map +1 -0
  30. package/dist/agent/{persona.js → config/persona.js} +1 -1
  31. package/dist/agent/config/persona.js.map +1 -0
  32. package/dist/agent/{settingsEnDisco.js → config/settingsEnDisco.js} +2 -2
  33. package/dist/agent/config/settingsEnDisco.js.map +1 -0
  34. package/dist/agent/{versionEnDisco.js → config/versionEnDisco.js} +8 -4
  35. package/dist/agent/config/versionEnDisco.js.map +1 -0
  36. package/dist/agent/dispositivos/arranqueDeEmulador.js +146 -0
  37. package/dist/agent/dispositivos/arranqueDeEmulador.js.map +1 -0
  38. package/dist/agent/{dispositivosEnMaquina.js → dispositivos/dispositivosEnMaquina.js} +93 -6
  39. package/dist/agent/dispositivos/dispositivosEnMaquina.js.map +1 -0
  40. package/dist/agent/dispositivos/hotswap.js.map +1 -0
  41. package/dist/agent/dispositivos/instalacionEnMaquina.js.map +1 -0
  42. package/dist/agent/{lanzamientoEnMaquina.js → dispositivos/lanzamientoEnMaquina.js} +1 -1
  43. package/dist/agent/dispositivos/lanzamientoEnMaquina.js.map +1 -0
  44. package/dist/agent/{paqueteDelProyecto.js → dispositivos/paqueteDelProyecto.js} +5 -5
  45. package/dist/agent/dispositivos/paqueteDelProyecto.js.map +1 -0
  46. package/dist/agent/dispositivos/procesosEnMaquina.js.map +1 -0
  47. package/dist/agent/{arbolDeProyecto.js → grafo/arbolDeProyecto.js} +2 -2
  48. package/dist/agent/grafo/arbolDeProyecto.js.map +1 -0
  49. package/dist/agent/{artefactosEnDisco.js → grafo/artefactosEnDisco.js} +2 -2
  50. package/dist/agent/grafo/artefactosEnDisco.js.map +1 -0
  51. package/dist/agent/{busquedaRegex.js → grafo/busquedaRegex.js} +41 -1
  52. package/dist/agent/grafo/busquedaRegex.js.map +1 -0
  53. package/dist/agent/grafo/excluirTools.js +82 -0
  54. package/dist/agent/grafo/excluirTools.js.map +1 -0
  55. package/dist/agent/{memoriaDeProyecto.js → grafo/memoriaDeProyecto.js} +1 -1
  56. package/dist/agent/grafo/memoriaDeProyecto.js.map +1 -0
  57. package/dist/agent/grafo/navegacionXone.js +198 -0
  58. package/dist/agent/grafo/navegacionXone.js.map +1 -0
  59. package/dist/agent/{perfiles.js → grafo/perfiles.js} +51 -8
  60. package/dist/agent/grafo/perfiles.js.map +1 -0
  61. package/dist/agent/{proyecto.js → grafo/proyecto.js} +207 -24
  62. package/dist/agent/grafo/proyecto.js.map +1 -0
  63. package/dist/agent/grafo/skills.js +393 -0
  64. package/dist/agent/grafo/skills.js.map +1 -0
  65. package/dist/agent/{xoneAgent.js → grafo/xoneAgent.js} +196 -67
  66. package/dist/agent/grafo/xoneAgent.js.map +1 -0
  67. package/dist/agent/navegacion/indiceEnDisco.js +21 -0
  68. package/dist/agent/navegacion/indiceEnDisco.js.map +1 -0
  69. package/dist/agent/navegacion/modeloDeProyecto.js +228 -0
  70. package/dist/agent/navegacion/modeloDeProyecto.js.map +1 -0
  71. package/dist/agent/raizDelPaquete.js +56 -0
  72. package/dist/agent/raizDelPaquete.js.map +1 -0
  73. package/dist/agent/{checkpointer.js → sesiones/checkpointer.js} +1 -1
  74. package/dist/agent/sesiones/checkpointer.js.map +1 -0
  75. package/dist/agent/sesiones/git.js.map +1 -0
  76. package/dist/agent/{gitSync.js → sesiones/gitSync.js} +3 -3
  77. package/dist/agent/sesiones/gitSync.js.map +1 -0
  78. package/dist/agent/{sesionGit.js → sesiones/sesionGit.js} +2 -2
  79. package/dist/agent/sesiones/sesionGit.js.map +1 -0
  80. package/dist/agent/{agentesEnDisco.js → subagentes/agentesEnDisco.js} +304 -86
  81. package/dist/agent/subagentes/agentesEnDisco.js.map +1 -0
  82. package/dist/agent/subagentes/consumoExterno.js.map +1 -0
  83. package/dist/agent/subagentes/escrituraDeCodex.js.map +1 -0
  84. package/dist/agent/{escrituraDeOpencode.js → subagentes/escrituraDeOpencode.js} +1 -1
  85. package/dist/agent/subagentes/escrituraDeOpencode.js.map +1 -0
  86. package/dist/agent/{escrituraExterna.js → subagentes/escrituraExterna.js} +6 -6
  87. package/dist/agent/subagentes/escrituraExterna.js.map +1 -0
  88. package/dist/agent/subagentes/subagenteCodex.js.map +1 -0
  89. package/dist/agent/subagentes/subagenteExterno.js.map +1 -0
  90. package/dist/agent/subagentes/subagenteOpencode.js.map +1 -0
  91. package/dist/agent/{aumentador.js → tareas/aumentador.js} +2 -2
  92. package/dist/agent/tareas/aumentador.js.map +1 -0
  93. package/dist/agent/{juezDeTarea.js → tareas/juezDeTarea.js} +5 -5
  94. package/dist/agent/tareas/juezDeTarea.js.map +1 -0
  95. package/dist/agent/{tareasEnDisco.js → tareas/tareasEnDisco.js} +4 -4
  96. package/dist/agent/tareas/tareasEnDisco.js.map +1 -0
  97. package/dist/agent/turno/diagnosticoDeTools.js.map +1 -0
  98. package/dist/agent/{guionizado.js → turno/guionizado.js} +1 -1
  99. package/dist/agent/turno/guionizado.js.map +1 -0
  100. package/dist/agent/turno/informeDeTraza.js +222 -0
  101. package/dist/agent/turno/informeDeTraza.js.map +1 -0
  102. package/dist/agent/turno/inspectorDePrompt.js +205 -0
  103. package/dist/agent/turno/inspectorDePrompt.js.map +1 -0
  104. package/dist/agent/{instantanea.js → turno/instantanea.js} +7 -2
  105. package/dist/agent/turno/instantanea.js.map +1 -0
  106. package/dist/agent/{interrupts.js → turno/interrupts.js} +2 -2
  107. package/dist/agent/turno/interrupts.js.map +1 -0
  108. package/dist/agent/turno/mensajes.js.map +1 -0
  109. package/dist/agent/turno/normalizar.js.map +1 -0
  110. package/dist/agent/{puente.js → turno/puente.js} +47 -3
  111. package/dist/agent/turno/puente.js.map +1 -0
  112. package/dist/agent/turno/resumenDeContexto.js +176 -0
  113. package/dist/agent/turno/resumenDeContexto.js.map +1 -0
  114. package/dist/agent/{resumenDeTool.js → turno/resumenDeTool.js} +15 -0
  115. package/dist/agent/turno/resumenDeTool.js.map +1 -0
  116. package/dist/agent/turno/textoDeTool.js.map +1 -0
  117. package/dist/agent/{turnoReal.js → turno/turnoReal.js} +38 -14
  118. package/dist/agent/turno/turnoReal.js.map +1 -0
  119. package/dist/agent/turno/verificador.js.map +1 -0
  120. package/dist/cli/config.js +1 -1
  121. package/dist/cli/config.js.map +1 -1
  122. package/dist/cli/consola.js +9 -9
  123. package/dist/cli/consola.js.map +1 -1
  124. package/dist/cli/describe.js +2 -2
  125. package/dist/cli/describe.js.map +1 -1
  126. package/dist/cli/doctor.js +1 -1
  127. package/dist/cli/doctor.js.map +1 -1
  128. package/dist/cli/fuentesDeDisco.js +29 -0
  129. package/dist/cli/fuentesDeDisco.js.map +1 -0
  130. package/dist/cli/main.js +37 -28
  131. package/dist/cli/main.js.map +1 -1
  132. package/dist/cli/run.js +32 -10
  133. package/dist/cli/run.js.map +1 -1
  134. package/dist/cli/traza.js +48 -0
  135. package/dist/cli/traza.js.map +1 -0
  136. package/dist/cli/tui/correrTui.js +4 -4
  137. package/dist/cli/tui/correrTui.js.map +1 -1
  138. package/dist/cli/verify.js +1 -1
  139. package/dist/cli/verify.js.map +1 -1
  140. package/dist/core/actos.js +1 -1
  141. package/dist/core/adjuntos.js +2 -2
  142. package/dist/core/agentes.js +145 -7
  143. package/dist/core/agentes.js.map +1 -1
  144. package/dist/core/artefactos.js +4 -4
  145. package/dist/core/config.js +1 -1
  146. package/dist/core/contextos.js +12 -1
  147. package/dist/core/contextos.js.map +1 -1
  148. package/dist/core/descargas.js +1 -1
  149. package/dist/core/dispositivos.js +53 -3
  150. package/dist/core/dispositivos.js.map +1 -1
  151. package/dist/core/esqueleto.js +1 -1
  152. package/dist/core/modelos.js +16 -3
  153. package/dist/core/modelos.js.map +1 -1
  154. package/dist/core/navegacion.js +134 -0
  155. package/dist/core/navegacion.js.map +1 -0
  156. package/dist/core/notify.js +5 -0
  157. package/dist/core/notify.js.map +1 -1
  158. package/dist/core/planDeSubida.js +1 -1
  159. package/dist/core/settings.js +2 -2
  160. package/dist/core/shellDeAgente.js +99 -0
  161. package/dist/core/shellDeAgente.js.map +1 -0
  162. package/dist/core/skills.js +158 -0
  163. package/dist/core/skills.js.map +1 -0
  164. package/dist/core/zipDeSkill.js +107 -0
  165. package/dist/core/zipDeSkill.js.map +1 -0
  166. package/dist/web/servidor/arranque.js +531 -47
  167. package/dist/web/servidor/arranque.js.map +1 -1
  168. package/dist/web/servidor/corredorDeTareas.js +3 -3
  169. package/dist/web/servidor/corredorDeTareas.js.map +1 -1
  170. package/dist/web/servidor/sesiones.js +4 -4
  171. package/dist/web/servidor/transporte.js +1 -1
  172. package/dist/web/servidor/transporte.js.map +1 -1
  173. package/dist/web/servidor/vestibulo.js +7 -7
  174. package/dist/web/servidor/vestibulo.js.map +1 -1
  175. package/package.json +6 -4
  176. package/skills/archify/SKILL.md +25 -2
  177. package/skills/artifacts-builder/SKILL.md +23 -0
  178. package/skills/xone-hotswap/SKILL.md +74 -0
  179. package/skills/xone-hotswap/scripts/xone-arrancar-ios +85 -0
  180. package/skills/xone-hotswap/scripts/xone-desplegar-android +411 -0
  181. package/skills/xone-hotswap/scripts/xone-hotswap +171 -0
  182. package/skills/xone-hotswap/scripts/xone-log-android +102 -0
  183. package/skills/xone-hotswap/scripts/xone-reiniciar-android +104 -0
  184. package/apps/web/dist/assets/index-CFYAoHdw.js +0 -477
  185. package/dist/agent/agentesEnDisco.js.map +0 -1
  186. package/dist/agent/arbolDeProyecto.js.map +0 -1
  187. package/dist/agent/artefactosEnDisco.js.map +0 -1
  188. package/dist/agent/aumentador.js.map +0 -1
  189. package/dist/agent/authEnDisco.js.map +0 -1
  190. package/dist/agent/busquedaRegex.js.map +0 -1
  191. package/dist/agent/catalogoModelos.js.map +0 -1
  192. package/dist/agent/checkpointer.js.map +0 -1
  193. package/dist/agent/cloudstudioClient.js.map +0 -1
  194. package/dist/agent/cloudstudioMcp.js.map +0 -1
  195. package/dist/agent/configEnDisco.js.map +0 -1
  196. package/dist/agent/consumoExterno.js.map +0 -1
  197. package/dist/agent/crearProyecto.js.map +0 -1
  198. package/dist/agent/descarga.js.map +0 -1
  199. package/dist/agent/diagnosticoDeTools.js.map +0 -1
  200. package/dist/agent/dispositivosEnMaquina.js.map +0 -1
  201. package/dist/agent/entorno.js.map +0 -1
  202. package/dist/agent/escrituraDeCodex.js.map +0 -1
  203. package/dist/agent/escrituraDeOpencode.js.map +0 -1
  204. package/dist/agent/escrituraExterna.js.map +0 -1
  205. package/dist/agent/gemini.js.map +0 -1
  206. package/dist/agent/git.js.map +0 -1
  207. package/dist/agent/gitSync.js.map +0 -1
  208. package/dist/agent/guionizado.js.map +0 -1
  209. package/dist/agent/hotswap.js.map +0 -1
  210. package/dist/agent/instalacionEnMaquina.js.map +0 -1
  211. package/dist/agent/instantanea.js.map +0 -1
  212. package/dist/agent/interrupts.js.map +0 -1
  213. package/dist/agent/juezDeTarea.js.map +0 -1
  214. package/dist/agent/lanzamientoEnMaquina.js.map +0 -1
  215. package/dist/agent/manifiesto.js.map +0 -1
  216. package/dist/agent/memoriaDeProyecto.js.map +0 -1
  217. package/dist/agent/mensajes.js.map +0 -1
  218. package/dist/agent/modelos.js.map +0 -1
  219. package/dist/agent/modelosDeMotor.js.map +0 -1
  220. package/dist/agent/normalizar.js.map +0 -1
  221. package/dist/agent/paqueteDelProyecto.js.map +0 -1
  222. package/dist/agent/perfiles.js.map +0 -1
  223. package/dist/agent/persona.js.map +0 -1
  224. package/dist/agent/procesosEnMaquina.js.map +0 -1
  225. package/dist/agent/proyecto.js.map +0 -1
  226. package/dist/agent/puente.js.map +0 -1
  227. package/dist/agent/resumenDeContexto.js +0 -30
  228. package/dist/agent/resumenDeContexto.js.map +0 -1
  229. package/dist/agent/resumenDeTool.js.map +0 -1
  230. package/dist/agent/sesionGit.js.map +0 -1
  231. package/dist/agent/settingsEnDisco.js.map +0 -1
  232. package/dist/agent/skills.js +0 -65
  233. package/dist/agent/skills.js.map +0 -1
  234. package/dist/agent/subagenteCodex.js.map +0 -1
  235. package/dist/agent/subagenteExterno.js.map +0 -1
  236. package/dist/agent/subagenteOpencode.js.map +0 -1
  237. package/dist/agent/subida.js.map +0 -1
  238. package/dist/agent/tareasEnDisco.js.map +0 -1
  239. package/dist/agent/textoDeTool.js.map +0 -1
  240. package/dist/agent/turnoReal.js.map +0 -1
  241. package/dist/agent/verificador.js.map +0 -1
  242. package/dist/agent/versionEnDisco.js.map +0 -1
  243. package/dist/agent/xoneAgent.js.map +0 -1
  244. package/dist/agent/zip.js.map +0 -1
  245. /package/dist/agent/{cloudstudioClient.js → cloudstudio/cloudstudioClient.js} +0 -0
  246. /package/dist/agent/{manifiesto.js → cloudstudio/manifiesto.js} +0 -0
  247. /package/dist/agent/{entorno.js → config/entorno.js} +0 -0
  248. /package/dist/agent/{gemini.js → config/gemini.js} +0 -0
  249. /package/dist/agent/{hotswap.js → dispositivos/hotswap.js} +0 -0
  250. /package/dist/agent/{instalacionEnMaquina.js → dispositivos/instalacionEnMaquina.js} +0 -0
  251. /package/dist/agent/{procesosEnMaquina.js → dispositivos/procesosEnMaquina.js} +0 -0
  252. /package/dist/agent/{git.js → sesiones/git.js} +0 -0
  253. /package/dist/agent/{consumoExterno.js → subagentes/consumoExterno.js} +0 -0
  254. /package/dist/agent/{escrituraDeCodex.js → subagentes/escrituraDeCodex.js} +0 -0
  255. /package/dist/agent/{subagenteCodex.js → subagentes/subagenteCodex.js} +0 -0
  256. /package/dist/agent/{subagenteExterno.js → subagentes/subagenteExterno.js} +0 -0
  257. /package/dist/agent/{subagenteOpencode.js → subagentes/subagenteOpencode.js} +0 -0
  258. /package/dist/agent/{diagnosticoDeTools.js → turno/diagnosticoDeTools.js} +0 -0
  259. /package/dist/agent/{mensajes.js → turno/mensajes.js} +0 -0
  260. /package/dist/agent/{normalizar.js → turno/normalizar.js} +0 -0
  261. /package/dist/agent/{textoDeTool.js → turno/textoDeTool.js} +0 -0
  262. /package/dist/agent/{verificador.js → turno/verificador.js} +0 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * El índice de navegación XOne: qué hay en el proyecto y qué apunta a qué.
3
+ *
4
+ * **Este módulo es PURO**, y esa es la mitad del diseño. Quién lee el disco y quién entiende
5
+ * el XML es `agent/navegacion/` apoyándose en `xone-linter`; aquí solo vive la forma de las
6
+ * respuestas y cómo se consultan. Así la regla se prueba sin un proyecto delante, y el día
7
+ * que la fuente del modelo cambie no cambia nada de esto.
8
+ *
9
+ * **Por qué existe.** Medido sobre un proyecto real (AppDemo, 41 `.xne`): contestar «¿qué
10
+ * colecciones tiene el proyecto?» leyendo ficheros cuesta unos 18.000 tokens —son todos los
11
+ * `.xne`—, y contestarla desde el modelo cuesta 141. La pregunta cara no es leer un fichero
12
+ * (un `.xne` son un par de kilobytes): es **no saber cuál de los cuarenta y uno leer**. Eso
13
+ * es lo que esto contesta, y por eso la primera versión va POR NOMBRE y no por posición.
14
+ *
15
+ * **Por qué no por posición todavía.** Un editor pregunta «¿qué hay bajo el cursor?»; un
16
+ * agente no tiene cursor, tiene nombres. Y saber la posición exacta de un atributo exige
17
+ * conservar su rango al parsear, que hoy `xone-linter` no hace (su `loc()` devuelve solo el
18
+ * fichero). Lo caro está justo en la mitad que no hace falta para lo que se ha medido.
19
+ *
20
+ * **Las rutas que entran aquí son VIRTUALES** (`/Clientes.xne`), nunca de la máquina. Quien
21
+ * traduce es el adaptador, y no es higiene: esto viaja al modelo y de ahí al cable.
22
+ */
23
+ /** Parte `Coll.CAMPO` en sus dos mitades. Sin punto, es una colección a secas. */
24
+ export function partirNombre(nombre) {
25
+ const i = nombre.indexOf(".");
26
+ if (i === -1)
27
+ return { coleccion: nombre.trim() };
28
+ return { coleccion: nombre.slice(0, i).trim(), campo: nombre.slice(i + 1).trim() };
29
+ }
30
+ /**
31
+ * Construye el índice. Puro: el modelo entra ya resuelto y traducido.
32
+ *
33
+ * **No cachea, y quien lo llama tampoco debería.** Construirlo sobre un proyecto real cuesta
34
+ * unas decenas de milisegundos —medido— contra los segundos de una llamada al modelo, así
35
+ * que rehacerlo en cada consulta sale gratis y quita de en medio la pregunta de cuándo
36
+ * invalidarlo. Un índice viejo que dice que un campo existe cuando el agente acaba de
37
+ * borrarlo es peor que no tener índice: es una respuesta con autoridad y equivocada.
38
+ *
39
+ * **La comparación de nombres NO distingue mayúsculas.** En XOne se escribe `NOMBRE` en la
40
+ * declaración y `Nombre` en un `mapfld` con la misma intención, y un índice que conteste «no
41
+ * existe» por la caja manda a buscar un fallo que no está. Lo que se DEVUELVE es siempre el
42
+ * nombre tal como está declarado, no el que se preguntó.
43
+ */
44
+ export function construirIndice(modelo) {
45
+ const igual = (a, b) => a.toLowerCase() === b.toLowerCase();
46
+ const declaracionDeColeccion = (c) => ({
47
+ nombre: c.nombre,
48
+ clase: "coleccion",
49
+ fichero: c.fichero,
50
+ });
51
+ const declaracionDeCampo = (c, campo) => ({
52
+ nombre: campo.nombre,
53
+ clase: "campo",
54
+ fichero: c.fichero,
55
+ coleccion: c.nombre,
56
+ ...(campo.tipo === undefined ? {} : { tipo: campo.tipo }),
57
+ });
58
+ return {
59
+ inventario: () => modelo.colecciones.map(declaracionDeColeccion),
60
+ definicion(nombre) {
61
+ const { coleccion, campo } = partirNombre(nombre);
62
+ const suyas = modelo.colecciones.filter((c) => igual(c.nombre, coleccion));
63
+ // Sin campo, se pregunta por la colección: se devuelven TODAS las que se llamen así.
64
+ // Dos declaraciones con el mismo nombre no es un caso imposible y callarse una sería
65
+ // contestar a medias sobre justo el proyecto que tiene el problema.
66
+ if (campo === undefined || campo === "")
67
+ return suyas.map(declaracionDeColeccion);
68
+ return suyas.flatMap((c) => c.campos.filter((f) => igual(f.nombre, campo)).map((f) => declaracionDeCampo(c, f)));
69
+ },
70
+ referencias(nombre) {
71
+ const { coleccion, campo } = partirNombre(nombre);
72
+ const encaja = (hacia) => {
73
+ const destino = partirNombre(hacia);
74
+ if (!igual(destino.coleccion, coleccion))
75
+ return false;
76
+ // Preguntando por la coll entera valen todas las que apunten a ella, lleven campo o
77
+ // no: quien pregunta «¿quién usa Clientes?» quiere también los `mapfld`.
78
+ if (campo === undefined || campo === "")
79
+ return true;
80
+ return destino.campo !== undefined && igual(destino.campo, campo);
81
+ };
82
+ const salida = [];
83
+ for (const c of modelo.colecciones) {
84
+ for (const r of c.referencias)
85
+ if (encaja(r.hacia))
86
+ salida.push({ ...r, fichero: c.fichero });
87
+ }
88
+ // Y las de script, que ya traen su fichero porque pueden venir de un `.js` suelto.
89
+ for (const r of modelo.referenciasDeScript)
90
+ if (encaja(r.hacia))
91
+ salida.push(r);
92
+ return salida;
93
+ },
94
+ campos(coleccion) {
95
+ const { coleccion: soloColl } = partirNombre(coleccion);
96
+ return modelo.colecciones
97
+ .filter((c) => igual(c.nombre, soloColl))
98
+ .flatMap((c) => c.campos.map((f) => declaracionDeCampo(c, f)));
99
+ },
100
+ app: () => modelo.app,
101
+ detalle(coleccion) {
102
+ const { coleccion: soloColl } = partirNombre(coleccion);
103
+ const c = modelo.colecciones.find((x) => igual(x.nombre, soloColl));
104
+ // `undefined` y no un detalle vacío: «no existe» y «existe y está vacía» son dos cosas,
105
+ // y contestar lo segundo sobre lo primero hace que el agente deje de buscar.
106
+ if (c === undefined)
107
+ return undefined;
108
+ return {
109
+ nombre: c.nombre,
110
+ fichero: c.fichero,
111
+ campos: c.campos.map((f) => declaracionDeCampo(c, f)),
112
+ eventos: c.eventos,
113
+ nodos: c.nodos,
114
+ conexiones: c.conexiones,
115
+ apuntaA: c.referencias.map((r) => ({ ...r, fichero: c.fichero })),
116
+ };
117
+ },
118
+ problemas() {
119
+ const existe = (nombre) => modelo.colecciones.some((c) => igual(c.nombre, nombre));
120
+ const rotas = [];
121
+ const todas = [
122
+ ...modelo.colecciones.flatMap((c) => c.referencias.map((r) => ({ ...r, fichero: c.fichero }))),
123
+ // Las de script cuentan: dos de las tres referencias rotas de un proyecto real solo se
124
+ // ven desde ahí (`appData.getCollection('Login')`, que no existe).
125
+ ...modelo.referenciasDeScript,
126
+ ];
127
+ for (const r of todas)
128
+ if (!existe(partirNombre(r.hacia).coleccion))
129
+ rotas.push(r);
130
+ return { rotas };
131
+ },
132
+ };
133
+ }
134
+ //# sourceMappingURL=navegacion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navegacion.js","sourceRoot":"","sources":["../../src/core/navegacion.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,10 @@ const ICONO = {
25
25
  grep: "✱",
26
26
  regex_search: "✱",
27
27
  task: "⊙",
28
+ // Un icono PROPIO, y no el genérico `⚙`: en un turno donde se lanza una app, la línea del
29
+ // comando es la que dice qué está pasando de verdad — y no puede leerse igual que una tool
30
+ // cualquiera que no está en la tabla.
31
+ execute: "$",
28
32
  };
29
33
  /** El verbo de cada tool conocida, en español. */
30
34
  const VERBO = {
@@ -36,6 +40,7 @@ const VERBO = {
36
40
  grep: "busca",
37
41
  regex_search: "regex",
38
42
  task: "delega en",
43
+ execute: "corre",
39
44
  };
40
45
  /** `→ lee app.xne` para una conocida; `⚙ studio_edit_file` para el resto. */
41
46
  function frase(nombre, detalle) {
@@ -1 +1 @@
1
- {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/core/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,wEAAwE;AACxE,MAAM,KAAK,GAA2B;IACpC,SAAS,EAAE,GAAG;IACd,EAAE,EAAE,GAAG;IACP,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,GAAG;IACd,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,YAAY,EAAE,GAAG;IACjB,IAAI,EAAE,GAAG;CACV,CAAC;AAEF,kDAAkD;AAClD,MAAM,KAAK,GAA2B;IACpC,SAAS,EAAE,KAAK;IAChB,EAAE,EAAE,OAAO;IACX,UAAU,EAAE,SAAS;IACrB,SAAS,EAAE,OAAO;IAClB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,OAAO;IACb,YAAY,EAAE,OAAO;IACrB,IAAI,EAAE,WAAW;CAClB,CAAC;AAsBF,6EAA6E;AAC7E,SAAS,KAAK,CAAC,MAAc,EAAE,OAAgB;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,qFAAqF;IACrF,iFAAiF;IACjF,wFAAwF;IACxF,0DAA0D;IAC1D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,OAAO,EAAE,CAAC;IAC5F,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAE,CAAC;IAC7B,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;AACxG,CAAC;AAED;;;;;GAKG;AACH,SAAS,OAAO,CAAC,QAAkB;IACjC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAChC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC;AACnG,CAAC;AAED,MAAM,OAAO,UAAU;IACb,MAAM,GAAG,EAAE,CAAC;IACZ,MAAM,GAAG,CAAC,CAAC;IACX,QAAQ,GAAa,EAAE,CAAC;IAEhC,wEAAwE;IACxE,MAAM,CAAC,MAAkB;QACvB,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,kEAAkE;YAClE,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,SAAS;gBAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,EAAE;gBAC5E,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrE,OAAO,MAAM,CAAC,CAAC,qBAAqB;QACtC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACpF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,uFAAuF;IACvF,MAAM;QACJ,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;IAEO,WAAW;QACjB,yEAAyE;QACzE,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,KAAK,GACT,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/G,oFAAoF;QACpF,aAAa;QACb,MAAM,MAAM,GAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACrB,CAAC;CACF"}
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/core/notify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,wEAAwE;AACxE,MAAM,KAAK,GAA2B;IACpC,SAAS,EAAE,GAAG;IACd,EAAE,EAAE,GAAG;IACP,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,GAAG;IACd,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,YAAY,EAAE,GAAG;IACjB,IAAI,EAAE,GAAG;IACT,0FAA0F;IAC1F,2FAA2F;IAC3F,sCAAsC;IACtC,OAAO,EAAE,GAAG;CACb,CAAC;AAEF,kDAAkD;AAClD,MAAM,KAAK,GAA2B;IACpC,SAAS,EAAE,KAAK;IAChB,EAAE,EAAE,OAAO;IACX,UAAU,EAAE,SAAS;IACrB,SAAS,EAAE,OAAO;IAClB,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,OAAO;IACb,YAAY,EAAE,OAAO;IACrB,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,OAAO;CACjB,CAAC;AAsBF,6EAA6E;AAC7E,SAAS,KAAK,CAAC,MAAc,EAAE,OAAgB;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,qFAAqF;IACrF,iFAAiF;IACjF,wFAAwF;IACxF,0DAA0D;IAC1D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,OAAO,EAAE,CAAC;IAC5F,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAE,CAAC;IAC7B,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;AACxG,CAAC;AAED;;;;;GAKG;AACH,SAAS,OAAO,CAAC,QAAkB;IACjC,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAChC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC;AACnG,CAAC;AAED,MAAM,OAAO,UAAU;IACb,MAAM,GAAG,EAAE,CAAC;IACZ,MAAM,GAAG,CAAC,CAAC;IACX,QAAQ,GAAa,EAAE,CAAC;IAEhC,wEAAwE;IACxE,MAAM,CAAC,MAAkB;QACvB,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,kEAAkE;YAClE,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,SAAS;gBAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,EAAE;gBAC5E,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrE,OAAO,MAAM,CAAC,CAAC,qBAAqB;QACtC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACrC,IAAI,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACrE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACpF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,uFAAuF;IACvF,MAAM;QACJ,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;IAC5B,CAAC;IAEO,WAAW;QACjB,yEAAyE;QACzE,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,KAAK,GACT,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/G,oFAAoF;QACpF,aAAa;QACb,MAAM,MAAM,GAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3D,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;IACrB,CAAC;CACF"}
@@ -29,7 +29,7 @@ export const extensionDe = (ruta) => {
29
29
  /**
30
30
  * Lo que no sale de esta máquina NUNCA, mire quien lo mire.
31
31
  *
32
- * Es la misma denegación que `agent/perfiles.ts` le impone al AGENTE
32
+ * Es la misma denegación que `agent/grafo/perfiles.ts` le impone al AGENTE
33
33
  * (`permisosDe`/`puedeLeerRuta` deniegan `/.env` y `/.git`, invariante explícito de
34
34
  * `CLAUDE.md`), replicada en la ruta de SUBIDA, que no pasa por aquellos permisos y por
35
35
  * tanto no la heredaba. Que el agente no pueda leer `.env` no sirve de nada si el `/sync`
@@ -6,8 +6,8 @@
6
6
  * de un cliente. Vive en global y no en el proyecto porque un entorno sirve a muchos
7
7
  * proyectos; el proyecto solo guarda a cuál pertenece.
8
8
  *
9
- * TypeScript puro: ni disco ni red. El disco lo pone `agent/settingsEnDisco.ts`, igual
10
- * que `core/config.ts` deja el I/O a `agent/configEnDisco.ts` y `agent/authEnDisco.ts`.
9
+ * TypeScript puro: ni disco ni red. El disco lo pone `agent/config/settingsEnDisco.ts`, igual
10
+ * que `core/config.ts` deja el I/O a `agent/config/configEnDisco.ts` y `agent/config/authEnDisco.ts`.
11
11
  */
12
12
  import { posix } from "node:path";
13
13
  import { CLAVES_DENEGADAS } from "./config.js";
@@ -0,0 +1,99 @@
1
+ /**
2
+ * El ENTORNO con el que corre la shell de un subagente con ejecución.
3
+ *
4
+ * TypeScript puro: aquí se decide QUÉ variables ve esa shell, y quien la monta es
5
+ * `agent/grafo/proyecto.ts`. Separado por lo de siempre —compuesto dentro del montaje, que
6
+ * todos los tests doblan, la regla quedaría escrita y no probada—, y porque esto es una
7
+ * decisión sobre secretos, que es justo lo que no puede depender de acordarse.
8
+ *
9
+ * **Lo que se quita, y por qué es obligatorio quitarlo.** `guardarCredencial` escribe la
10
+ * clave de API TAMBIÉN en `process.env`, a propósito (`agent/config/authEnDisco.ts`). Un
11
+ * `inheritEnv: true` a secas le pasaría esas claves a la shell del modelo, y entonces un
12
+ * `printenv` —que es lo primero que hace cualquiera para orientarse— las deja en el
13
+ * resultado de la tool, o sea en el contexto y en el `.jsonl` de la sesión. No es una fuga
14
+ * hipotética: es la salida normal de un comando normal.
15
+ *
16
+ * Se quitan **por la tabla** (`VARIABLES_POR_PROVEEDOR`, el único sitio donde vive el nombre
17
+ * de la variable de cada proveedor — hubo cuatro copias y ya habían divergido) más el
18
+ * prefijo `XONECODE_CLAVE_`, que es el de los proveedores PERSONALIZADOS y por definición no
19
+ * puede estar en ninguna tabla: el slug lo elige el usuario. Y no se quita todo lo que
20
+ * empiece por `XONECODE_`, que se llevaría `XONECODE_TRACE_TOOLS` y `XONECODE_MODELO` sin
21
+ * que sean secretos de nadie.
22
+ *
23
+ * **Límite declarado, y conviene no engañarse con él**: esto quita NUESTRAS credenciales,
24
+ * las que xonecode puso ahí. El entorno de quien arranca el proceso puede traer un
25
+ * `GITHUB_TOKEN` o un `AWS_SECRET_ACCESS_KEY` suyos, y eso no se filtra — ni se podría con
26
+ * honestidad, porque «lo que parece una clave» es una heurística y una heurística que falla
27
+ * en silencio es peor que una regla declarada. Quien concede ejecución concede leer el
28
+ * entorno y el disco; lo que esto evita es que el harness REGALE lo que él mismo escribió.
29
+ *
30
+ * **Y los scripts de una skill se ponen en el PATH, que es lo que quita el problema en vez de
31
+ * explicarlo.** Medido corriéndolo: el agente tenía DOS espacios de rutas —las virtuales de
32
+ * `read_file` y las reales de sus comandos— y se pasó decenas de llamadas mezclándolos, leyendo
33
+ * con `read_file` rutas absolutas que no existen para esa tool y no van a existir nunca. Con los
34
+ * `scripts/` de cada skill montada en el PATH, un script se llama por su NOMBRE
35
+ * (`xone-hotswap …`) y no hay ninguna ruta que acertar, ni que meter en el prompt, ni que viaje
36
+ * en el evento. Un aparato nuevo mañana trae su skill con sus scripts y quedan disponibles solos.
37
+ *
38
+ * **Se AÑADEN al final, no al principio.** Prepender dejaría que una skill —que puede venir en
39
+ * un `.zip` de cualquier sitio— sombreara un binario del sistema llamando a un script suyo `ls`
40
+ * o `git`. Al final, lo que ya existe gana.
41
+ *
42
+ * **Y lo que se AÑADE además son rutas, una variable por cosa.** Una shell ve el disco de verdad,
43
+ * no nuestras rutas virtuales: `/skills/xone-hotswap/` no existe para ella. Pero meter la
44
+ * ruta absoluta en el prompt tendría dos precios —el comando que el modelo componga sería el
45
+ * `detalle` del evento, y ahí no puede viajar una ruta de la máquina (`sinRutas`), y la
46
+ * raíz no es UNA sino tres con la del proyecto ganando—. Con una variable por skill, el
47
+ * prompt dice `$XONECODE_SKILL_XONE_HOTSWAP/scripts/android.mjs` y ni el contexto ni el
48
+ * cable ven una ruta.
49
+ */
50
+ import { VARIABLES_POR_PROVEEDOR } from "./modelos.js";
51
+ /** El prefijo de las claves de un proveedor personalizado (`core/modelos.ts#variableDeProveedor`). */
52
+ const PREFIJO_DE_CLAVE = "XONECODE_CLAVE_";
53
+ /**
54
+ * La variable que nombra la carpeta donde dejar lo que se quiera enseñar a una persona.
55
+ *
56
+ * Sin ella, un script escribe en el `cwd` —la raíz del proyecto— que es justo lo que
57
+ * `artefactoFueraDeSitio` prohíbe a las tools de fichero, y una shell no pasa por ahí.
58
+ */
59
+ export const VARIABLE_DE_ARTEFACTOS = "XONECODE_ARTEFACTOS";
60
+ /**
61
+ * Cómo se llama la variable que lleva la ruta real de una skill.
62
+ *
63
+ * La MISMA derivación que `variableDeProveedor` para un personalizado (mayúsculas y los
64
+ * guiones a guión bajo): dos formas de convertir un slug en variable son dos formas de
65
+ * discrepar. El prefijo es otro a propósito — `XONECODE_SKILL_` frente a
66
+ * `XONECODE_CLAVE_`—, así que una skill no puede fabricarse el nombre de una credencial.
67
+ */
68
+ export function variableDeSkill(nombre) {
69
+ return `XONECODE_SKILL_${nombre.toUpperCase().replace(/-/g, "_")}`;
70
+ }
71
+ export function entornoDeShell(opciones) {
72
+ const credenciales = new Set(Object.values(VARIABLES_POR_PROVEEDOR));
73
+ const limpio = {};
74
+ for (const [clave, valor] of Object.entries(opciones.entorno)) {
75
+ // Una variable sin valor se DESCARTA en vez de pasarse como cadena vacía: un `PATH=""`
76
+ // no es «no consta», es un PATH roto.
77
+ if (valor === undefined)
78
+ continue;
79
+ if (credenciales.has(clave))
80
+ continue;
81
+ if (clave.startsWith(PREFIJO_DE_CLAVE))
82
+ continue;
83
+ limpio[clave] = valor;
84
+ }
85
+ for (const skill of opciones.skills ?? []) {
86
+ limpio[variableDeSkill(skill.nombre)] = skill.dir;
87
+ }
88
+ const binarios = opciones.binarios ?? [];
89
+ if (binarios.length > 0) {
90
+ // Sin PATH heredado no se parte de vacío: `sh` se inventaría el suyo y perderíamos el del
91
+ // proceso, que es donde están el `adb` y el `node` del usuario.
92
+ const actual = limpio["PATH"];
93
+ limpio["PATH"] = actual === undefined || actual === "" ? binarios.join(":") : [actual, ...binarios].join(":");
94
+ }
95
+ if (opciones.artefactos !== undefined)
96
+ limpio[VARIABLE_DE_ARTEFACTOS] = opciones.artefactos;
97
+ return limpio;
98
+ }
99
+ //# sourceMappingURL=shellDeAgente.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shellDeAgente.js","sourceRoot":"","sources":["../../src/core/shellDeAgente.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,sGAAsG;AACtG,MAAM,gBAAgB,GAAG,iBAAiB,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,qBAAqB,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,kBAAkB,MAAM,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;AACrE,CAAC;AAQD,MAAM,UAAU,cAAc,CAAC,QAW9B;IACC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAC7E,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9D,uFAAuF;QACvF,sCAAsC;QACtC,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QACtC,IAAI,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC;YAAE,SAAS;QACjD,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;IACpD,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC;IACzC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,0FAA0F;QAC1F,gEAAgE;QAChE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS;QAAE,MAAM,CAAC,sBAAsB,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC;IAE5F,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Una skill: el `SKILL.md` que el agente carga bajo demanda, y de quién es.
3
+ *
4
+ * **Este módulo es PURO.** Quién lee el disco es `agent/grafo/skills.ts`; quién las monta
5
+ * para el agente, `agent/grafo/proyecto.ts#backendConSkills`. Aquí solo vive el formato del
6
+ * fichero y la regla de qué nombre vale — las dos cosas que la ventana de Ajustes, el
7
+ * cargador y los tests tienen que entender igual.
8
+ *
9
+ * **Tres orígenes y no dos**, con la misma precedencia que los subagentes y los modelos:
10
+ *
11
+ * | origen | dónde | quién la escribe |
12
+ * |---|---|---|
13
+ * | `serie` | la carpeta `skills/` del PAQUETE | xonecode, y no se toca desde la consola |
14
+ * | `global` | `~/.xonecode/skills/` | el usuario, para todos sus proyectos |
15
+ * | `proyecto` | `<raiz>/.xonecode/skills/` | el usuario, solo para ese proyecto |
16
+ *
17
+ * Las de serie son de SOLO LECTURA y no se borran ni se editan: viven dentro del paquete
18
+ * instalado, así que una edición se la llevaría por delante el siguiente `npm install` sin
19
+ * decir nada. Lo que sí se puede es COPIARLA a las tuyas y cambiarla ahí, que además deja
20
+ * ver de dónde salió. Por eso no hay `.semilla.json` como en los subagentes: nada nuestro
21
+ * se copia nunca a la casa del usuario, así que no hay marca que llevar ni nada que
22
+ * restaurar.
23
+ *
24
+ * El `SKILL.md` es el formato de Claude Code, y eso no es una coincidencia que convenga
25
+ * mantener: es lo que hace que una skill escrita para otro harness se lea aquí tal cual, y
26
+ * que `SkillsMiddleware` de deepagents —que es quien las descubre de verdad— la encuentre
27
+ * sin que xonecode traduzca nada.
28
+ */
29
+ import { motivoDeNombreInaceptable, nombreSugerido } from "./agentes.js";
30
+ /** 4 caracteres por token, la regla de servilleta de siempre. */
31
+ export const tokensDeSkill = (texto) => Math.ceil(texto.length / 4);
32
+ /**
33
+ * El nombre de una skill es un SEGMENTO DE RUTA —la carpeta donde vive— y también lo que el
34
+ * subagente declara en su `.md`, así que vale la MISMA regla que la de un subagente y por la
35
+ * misma razón: `motivoDeNombreInaceptable` (`core/agentes.ts`). No se escribe una segunda
36
+ * aquí porque dos reglas para el mismo tipo de nombre es donde divergen.
37
+ */
38
+ export const motivoDeNombreDeSkillInaceptable = motivoDeNombreInaceptable;
39
+ export const nombreDeSkillSugerido = nombreSugerido;
40
+ /** El texto que sale del frontmatter cuando un campo lleva caracteres que lo romperían. */
41
+ const enUnaLinea = (texto) => texto.replace(/\r?\n/g, " ").trim();
42
+ /** ¿Esta línea abre la clave `clave` en el primer nivel del frontmatter? */
43
+ const abreClave = (linea, clave) => linea.startsWith(`${clave}:`) && !linea.startsWith(" ") && !linea.startsWith("\t");
44
+ /**
45
+ * Compone el `SKILL.md`.
46
+ *
47
+ * El frontmatter es el mínimo que `parseFrontmatter` (`vendor/skillLoaders/catalog.ts`) y
48
+ * deepagents leen: `name` y `description`, una línea cada uno. La descripción se aplana a
49
+ * una línea porque ahí un salto la partiría en dos claves y la segunda mitad se perdería en
50
+ * silencio — el mismo motivo por el que el nombre es un slug.
51
+ *
52
+ * **Y lo demás del frontmatter se CONSERVA**: las claves que no son `name` ni `description`
53
+ * se reescriben tal cual, en su orden. Componer uno nuevo desde cero le borraba a una skill
54
+ * escrita a mano su `license`, su `allowed-tools` o su bloque `metadata` en cuanto alguien
55
+ * abriera la ventana y pulsara Guardar — sin error, sin aviso y sobre un fichero suyo. Las
56
+ * líneas INDENTADAS van con la clave que las abre, que es lo que deja pasar un bloque
57
+ * anidado entero sin entender YAML.
58
+ */
59
+ export function escribirSkill(skill) {
60
+ const cuerpo = skill.cuerpo.replace(/^\n+/, "");
61
+ const resto = [];
62
+ let saltando = false;
63
+ for (const linea of (skill.frontmatter ?? "").split("\n")) {
64
+ if (abreClave(linea, "name") || abreClave(linea, "description")) {
65
+ saltando = true;
66
+ continue;
67
+ }
68
+ // Una línea indentada pertenece a la clave de arriba: si se estaba saltando, se salta.
69
+ const indentada = /^[ \t]/.test(linea);
70
+ if (saltando && indentada)
71
+ continue;
72
+ saltando = false;
73
+ if (linea.trim() !== "")
74
+ resto.push(linea);
75
+ }
76
+ const extra = resto.length === 0 ? "" : `${resto.join("\n")}\n`;
77
+ return `---\nname: ${skill.nombre}\ndescription: ${enUnaLinea(skill.descripcion)}\n${extra}---\n\n${cuerpo}`;
78
+ }
79
+ /**
80
+ * Lee un `SKILL.md`.
81
+ *
82
+ * **El nombre sale de la CARPETA, no del frontmatter**, exactamente como el de un subagente
83
+ * sale del fichero: es lo que la hace direccionable (`/skills/<nombre>/`) y lo que el
84
+ * subagente declara. Un `name:` que diga otra cosa se ignora — mandaría sobre una ruta que
85
+ * ya está decidida, y entonces `rutasDeSkills` apuntaría a una carpeta que no existe.
86
+ *
87
+ * **Sin `description` no se carga.** Es lo que el modelo lee para decidir si esta skill le
88
+ * sirve: sin ella, la skill está en el catálogo y no la usa nadie nunca, que es peor que no
89
+ * estar. Misma regla que la `descripcion` de un subagente.
90
+ */
91
+ export function leerSkill(texto, nombreDeCarpeta, origen, ficheros = []) {
92
+ const { descripcion, frontmatter, cuerpo } = partirFrontmatter(texto);
93
+ if (descripcion === "")
94
+ return { error: "no tiene `description` en el frontmatter" };
95
+ return {
96
+ skill: {
97
+ nombre: nombreDeCarpeta,
98
+ descripcion,
99
+ cuerpo,
100
+ frontmatter,
101
+ origen,
102
+ tokens: tokensDeSkill(texto),
103
+ ficheros,
104
+ },
105
+ };
106
+ }
107
+ /**
108
+ * El frontmatter mínimo, sin traer un parser de YAML.
109
+ *
110
+ * Es el mismo criterio que `core/agentes.ts` y que `vendor/skillLoaders/catalog.ts`: la
111
+ * superficie es `clave: valor` de una línea entre `---`, y un parser entero sería una
112
+ * dependencia para leer dos campos. Lo que no se entiende no se inventa: sin frontmatter,
113
+ * el fichero entero es cuerpo y la descripción sale vacía, que es lo que `leerSkill`
114
+ * rechaza.
115
+ */
116
+ function partirFrontmatter(texto) {
117
+ if (!texto.startsWith("---"))
118
+ return { descripcion: "", frontmatter: "", cuerpo: texto };
119
+ const fin = texto.indexOf("\n---", 3);
120
+ if (fin === -1)
121
+ return { descripcion: "", frontmatter: "", cuerpo: texto };
122
+ // El bloque entero, tal cual, sin los `---` ni el salto que los sigue. Es lo que se enseña
123
+ // y lo que se conserva al guardar: recomponerlo de las claves que entendemos tiraría las
124
+ // que no.
125
+ const frontmatter = texto.slice(3, fin).replace(/^\n/, "");
126
+ let descripcion = "";
127
+ for (const linea of frontmatter.split("\n")) {
128
+ const i = linea.indexOf(":");
129
+ if (i === -1)
130
+ continue;
131
+ if (linea.slice(0, i).trim() === "description")
132
+ descripcion = linea.slice(i + 1).trim();
133
+ }
134
+ const salto = texto.indexOf("\n", fin + 1);
135
+ return {
136
+ descripcion,
137
+ frontmatter,
138
+ cuerpo: salto === -1 ? "" : texto.slice(salto + 1).replace(/^\n+/, ""),
139
+ };
140
+ }
141
+ /**
142
+ * Funde las listas por nombre: la ÚLTIMA gana.
143
+ *
144
+ * Se llama con `serie`, `global`, `proyecto` en ese orden, así que una skill del proyecto
145
+ * tapa a la global del mismo nombre y las dos tapan a la de serie — la misma precedencia
146
+ * que los subagentes y que los modelos, y por lo mismo: lo particular manda sobre lo
147
+ * general. Que una tape a otra NO es un problema que reportar: es la forma de afinar una
148
+ * skill nuestra sin editarla donde el `npm install` la pisaría. Quien lo dice es la ficha,
149
+ * con su origen al lado.
150
+ */
151
+ export function fusionarSkills(...listas) {
152
+ const porNombre = new Map();
153
+ for (const lista of listas)
154
+ for (const skill of lista)
155
+ porNombre.set(skill.nombre, skill);
156
+ return [...porNombre.values()].sort((a, b) => a.nombre.localeCompare(b.nombre));
157
+ }
158
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Instalar una skill desde un `.zip`: QUÉ se acepta y con qué nombre queda.
3
+ *
4
+ * **Este módulo es PURO.** Quién descomprime es `agent/grafo/skills.ts`; aquí vive la regla,
5
+ * que es la parte que hay que poder probar sin un fichero de verdad delante.
6
+ *
7
+ * Un `.zip` que alguien descarga de internet y suelta en esta ventana es la entrada menos
8
+ * de fiar de todo el harness: sus nombres de entrada los eligió quien lo empaquetó. De ahí
9
+ * que la lista de lo que se admite sea BLANCA y no una lista de lo que se rechaza:
10
+ *
11
+ * - **Ninguna entrada puede salir de la carpeta de destino.** Es el «zip slip» de siempre:
12
+ * una entrada llamada `../../.ssh/authorized_keys` escribe donde le da la gana. Se exige
13
+ * una ruta relativa de segmentos llanos, y cualquier otra cosa —`..`, una absoluta, una
14
+ * con `\` (que en Windows ES separador), una con dos puntos de unidad, un byte nulo— se
15
+ * rechaza. No se «normaliza» nada: normalizar es interpretar, e interpretar es donde
16
+ * aparecen los agujeros.
17
+ * - **Tres topes, y los tres son contra un zip BOMBA**: cuánto ocupa descomprimido, cuántas
18
+ * entradas trae y cuánto ocupa la mayor. Un `.zip` de cien kilobytes puede descomprimirse
19
+ * en gigabytes, y el tope del cuerpo HTTP no lo ve.
20
+ * - **Tiene que traer un `SKILL.md`**, porque sin él no es una skill: sería una carpeta de
21
+ * ficheros sueltos que el modelo no puede descubrir.
22
+ *
23
+ * Y el NOMBRE no se pregunta: se DEDUCE, y si no vale se dice cuál valdría. Un campo más en
24
+ * la ventana para algo que el propio `.zip` ya contesta es una pregunta que no lo es.
25
+ */
26
+ import { motivoDeNombreDeSkillInaceptable, nombreDeSkillSugerido } from "./skills.js";
27
+ /** Lo que ocupa el `.zip` que se sube, en bytes. Es el tope del cuerpo HTTP. */
28
+ export const TOPE_DEL_ZIP = 8 * 1024 * 1024;
29
+ /** Lo que puede ocupar DESCOMPRIMIDO. El de arriba no lo ve: un zip bomba cabe en nada. */
30
+ export const TOPE_DESCOMPRIMIDO = 32 * 1024 * 1024;
31
+ /** Cuántos ficheros puede traer. Una skill son unas decenas; mil es otra cosa. */
32
+ export const TOPE_DE_ENTRADAS = 500;
33
+ /**
34
+ * ¿Esta ruta de dentro del zip se puede escribir bajo una carpeta?
35
+ *
36
+ * Lista BLANCA de forma, no un `startsWith` ni un `includes("..")`: es la misma postura que
37
+ * `esRutaDeArtefacto`. Se admite una sucesión de segmentos llanos separados por `/`, y nada
38
+ * más — así lo que no se entiende queda FUERA por omisión en vez de colarse por el hueco que
39
+ * no se pensó.
40
+ */
41
+ export function rutaDeZipAceptable(ruta) {
42
+ if (ruta === "" || ruta.length > 255)
43
+ return false;
44
+ // Un byte nulo trunca la ruta en las capas de C de debajo: lo que el chequeo ve y lo que
45
+ // el sistema abre dejarían de ser lo mismo.
46
+ if (ruta.includes("\0"))
47
+ return false;
48
+ // `\` es separador en Windows, así que una entrada con él no es un segmento llano aquí.
49
+ if (ruta.includes("\\"))
50
+ return false;
51
+ // Absoluta, o con unidad: `/etc/passwd`, `C:/…`.
52
+ if (ruta.startsWith("/") || /^[A-Za-z]:/.test(ruta))
53
+ return false;
54
+ const segmentos = ruta.split("/");
55
+ return segmentos.every((s) => s !== "" && s !== "." && s !== ".." && !/^\s|\s$/.test(s));
56
+ }
57
+ /** El único segmento de primer nivel que comparten TODAS las entradas, si lo hay. */
58
+ function carpetaComun(rutas) {
59
+ const primeros = new Set(rutas.map((r) => r.split("/")[0] ?? ""));
60
+ if (primeros.size !== 1)
61
+ return undefined;
62
+ const unico = [...primeros][0];
63
+ // Solo cuenta como carpeta envolvente si TODAS cuelgan de ella: un zip con un solo
64
+ // fichero en la raíz no tiene carpeta que quitar.
65
+ return rutas.every((r) => r.startsWith(`${unico}/`)) ? unico : undefined;
66
+ }
67
+ /**
68
+ * Decide qué se instala y cómo se va a llamar. Devuelve el motivo si no se puede, nunca lanza.
69
+ *
70
+ * `nombreDelFichero` es el nombre del `.zip` que subió la persona, y solo se usa cuando el
71
+ * zip trae el `SKILL.md` en su raíz — o sea, cuando no hay carpeta dentro de la que sacar el
72
+ * nombre. Es lo que la persona ve en su disco, así que es lo que menos la sorprende.
73
+ */
74
+ export function planDeInstalacion(entradas, nombreDelFichero) {
75
+ if (entradas.length === 0)
76
+ return { error: "el .zip está vacío" };
77
+ if (entradas.length > TOPE_DE_ENTRADAS) {
78
+ return { error: `el .zip trae más de ${TOPE_DE_ENTRADAS} ficheros: eso no es una skill` };
79
+ }
80
+ const mala = entradas.find((e) => !rutaDeZipAceptable(e.ruta));
81
+ if (mala !== undefined) {
82
+ // El nombre de la entrada NO se devuelve: lo eligió quien empaquetó el zip, y esto se
83
+ // pinta en la ventana de alguien. Se dice QUÉ pasa, que es lo accionable.
84
+ return { error: "el .zip trae una ruta que se sale de su carpeta, y no se instala" };
85
+ }
86
+ const total = entradas.reduce((suma, e) => suma + e.bytes, 0);
87
+ if (total > TOPE_DESCOMPRIMIDO) {
88
+ return { error: "el .zip ocupa demasiado descomprimido" };
89
+ }
90
+ const prefijo = carpetaComun(entradas.map((e) => e.ruta));
91
+ const ficheros = prefijo === undefined ? entradas.map((e) => e.ruta) : entradas.map((e) => e.ruta.slice(prefijo.length + 1));
92
+ if (!ficheros.includes("SKILL.md")) {
93
+ return { error: "el .zip no trae ningún SKILL.md: sin él no es una skill" };
94
+ }
95
+ const crudo = prefijo ?? nombreDelFichero.replace(/\.zip$/i, "");
96
+ const motivo = motivoDeNombreDeSkillInaceptable(crudo);
97
+ if (motivo !== undefined) {
98
+ const sugerido = nombreDeSkillSugerido(crudo);
99
+ return {
100
+ error: sugerido === undefined
101
+ ? `«${crudo}» no vale como nombre de skill: ${motivo}`
102
+ : `«${crudo}» no vale como nombre de skill (${motivo}): renombra el .zip o su carpeta a «${sugerido}»`,
103
+ };
104
+ }
105
+ return { nombre: crudo, ficheros, prefijo: prefijo === undefined ? "" : `${prefijo}/` };
106
+ }
107
+ //# sourceMappingURL=zipDeSkill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zipDeSkill.js","sourceRoot":"","sources":["../../src/core/zipDeSkill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,gCAAgC,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEtF,gFAAgF;AAChF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,2FAA2F;AAC3F,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnD,kFAAkF;AAClF,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAmBpC;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IACnD,yFAAyF;IACzF,4CAA4C;IAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,wFAAwF;IACxF,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,iDAAiD;IACjD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,qFAAqF;AACrF,SAAS,YAAY,CAAC,KAAwB;IAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAClE,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAE,CAAC;IAChC,mFAAmF;IACnF,kDAAkD;IAClD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAiC,EACjC,gBAAwB;IAExB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAClE,IAAI,QAAQ,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QACvC,OAAO,EAAE,KAAK,EAAE,uBAAuB,gBAAgB,gCAAgC,EAAE,CAAC;IAC5F,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,sFAAsF;QACtF,0EAA0E;QAC1E,OAAO,EAAE,KAAK,EAAE,kEAAkE,EAAE,CAAC;IACvF,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC9D,IAAI,KAAK,GAAG,kBAAkB,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,EAAE,uCAAuC,EAAE,CAAC;IAC5D,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,MAAM,QAAQ,GACZ,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAE9G,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,KAAK,EAAE,yDAAyD,EAAE,CAAC;IAC9E,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,IAAI,gBAAgB,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,gCAAgC,CAAC,KAAK,CAAC,CAAC;IACvD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO;YACL,KAAK,EACH,QAAQ,KAAK,SAAS;gBACpB,CAAC,CAAC,IAAI,KAAK,mCAAmC,MAAM,EAAE;gBACtD,CAAC,CAAC,IAAI,KAAK,mCAAmC,MAAM,uCAAuC,QAAQ,GAAG;SAC3G,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,EAAE,CAAC;AAC1F,CAAC"}