xonecode 0.11.0 → 0.13.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 (85) hide show
  1. package/apps/web/dist/assets/index-D8kdTP0Z.css +1 -0
  2. package/apps/web/dist/assets/index-a1EvXQj9.js +485 -0
  3. package/apps/web/dist/assets/{php-DPbDT8rX.js → php-qXN69lAY.js} +1 -1
  4. package/apps/web/dist/assets/{ruby-Bfvws9R8.js → ruby-Cxx7RgZA.js} +1 -1
  5. package/apps/web/dist/iconos/conectores/deepwiki.png +0 -0
  6. package/apps/web/dist/iconos/conectores/jira.png +0 -0
  7. package/apps/web/dist/index.html +2 -2
  8. package/dist/agent/conectores/conectoresEnDisco.js +188 -0
  9. package/dist/agent/conectores/conectoresEnDisco.js.map +1 -0
  10. package/dist/agent/conectores/proveedorDeConector.js +56 -0
  11. package/dist/agent/conectores/proveedorDeConector.js.map +1 -0
  12. package/dist/agent/conectores/servicioDeConectores.js +496 -0
  13. package/dist/agent/conectores/servicioDeConectores.js.map +1 -0
  14. package/dist/agent/config/catalogoModelos.js +2 -0
  15. package/dist/agent/config/catalogoModelos.js.map +1 -1
  16. package/dist/agent/config/modelos.js +27 -0
  17. package/dist/agent/config/modelos.js.map +1 -1
  18. package/dist/agent/config/settingsEnDisco.js +16 -0
  19. package/dist/agent/config/settingsEnDisco.js.map +1 -1
  20. package/dist/agent/dispositivos/procesosEnMaquina.js +24 -2
  21. package/dist/agent/dispositivos/procesosEnMaquina.js.map +1 -1
  22. package/dist/agent/grafo/ejecucionCancelable.js +117 -0
  23. package/dist/agent/grafo/ejecucionCancelable.js.map +1 -0
  24. package/dist/agent/grafo/incorporarAdjunto.js +262 -0
  25. package/dist/agent/grafo/incorporarAdjunto.js.map +1 -0
  26. package/dist/agent/grafo/perfiles.js +12 -5
  27. package/dist/agent/grafo/perfiles.js.map +1 -1
  28. package/dist/agent/grafo/proyecto.js +53 -18
  29. package/dist/agent/grafo/proyecto.js.map +1 -1
  30. package/dist/agent/grafo/xoneAgent.js +25 -0
  31. package/dist/agent/grafo/xoneAgent.js.map +1 -1
  32. package/dist/agent/motores/trueforge/capacidades.js +69 -4
  33. package/dist/agent/motores/trueforge/capacidades.js.map +1 -1
  34. package/dist/agent/motores/trueforge/detencion.js +138 -0
  35. package/dist/agent/motores/trueforge/detencion.js.map +1 -0
  36. package/dist/agent/motores/trueforge/modeloLangchain.js +36 -4
  37. package/dist/agent/motores/trueforge/modeloLangchain.js.map +1 -1
  38. package/dist/agent/motores/trueforge/notas.js +49 -0
  39. package/dist/agent/motores/trueforge/notas.js.map +1 -0
  40. package/dist/agent/motores/trueforge/sesionTrueforge.js +100 -3
  41. package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
  42. package/dist/agent/sesiones/adjuntosDeSesion.js +235 -0
  43. package/dist/agent/sesiones/adjuntosDeSesion.js.map +1 -0
  44. package/dist/agent/subagentes/agentesEnDisco.js +4 -0
  45. package/dist/agent/subagentes/agentesEnDisco.js.map +1 -1
  46. package/dist/agent/trazaDeErroresEnDisco.js +12 -4
  47. package/dist/agent/trazaDeErroresEnDisco.js.map +1 -1
  48. package/dist/agent/turno/depuracion.js +27 -0
  49. package/dist/agent/turno/depuracion.js.map +1 -0
  50. package/dist/agent/turno/diagnosticoDeTools.js +7 -1
  51. package/dist/agent/turno/diagnosticoDeTools.js.map +1 -1
  52. package/dist/agent/turno/informeDeTraza.js +2 -1
  53. package/dist/agent/turno/informeDeTraza.js.map +1 -1
  54. package/dist/agent/turno/interrupts.js +13 -0
  55. package/dist/agent/turno/interrupts.js.map +1 -1
  56. package/dist/agent/turno/resumenDeTool.js +4 -0
  57. package/dist/agent/turno/resumenDeTool.js.map +1 -1
  58. package/dist/agent/turno/turnoReal.js +9 -2
  59. package/dist/agent/turno/turnoReal.js.map +1 -1
  60. package/dist/cli/main.js +52 -10
  61. package/dist/cli/main.js.map +1 -1
  62. package/dist/core/actos.js.map +1 -1
  63. package/dist/core/adjuntos.js +72 -14
  64. package/dist/core/adjuntos.js.map +1 -1
  65. package/dist/core/conectores.js +191 -0
  66. package/dist/core/conectores.js.map +1 -0
  67. package/dist/core/entrega.js.map +1 -1
  68. package/dist/core/modelos.js +23 -1
  69. package/dist/core/modelos.js.map +1 -1
  70. package/dist/core/settings.js +57 -0
  71. package/dist/core/settings.js.map +1 -1
  72. package/dist/web/servidor/arranque.js +336 -6
  73. package/dist/web/servidor/arranque.js.map +1 -1
  74. package/dist/web/servidor/consolaWeb.js +29 -3
  75. package/dist/web/servidor/consolaWeb.js.map +1 -1
  76. package/dist/web/servidor/servidor.js +16 -1
  77. package/dist/web/servidor/servidor.js.map +1 -1
  78. package/dist/web/servidor/transporte.js.map +1 -1
  79. package/dist/web/servidor/vestibulo.js +122 -11
  80. package/dist/web/servidor/vestibulo.js.map +1 -1
  81. package/dist/web/servidor/visorOpenui.js +25 -3
  82. package/dist/web/servidor/visorOpenui.js.map +1 -1
  83. package/package.json +1 -1
  84. package/apps/web/dist/assets/index-BAyybSz-.css +0 -1
  85. package/apps/web/dist/assets/index-BNCMVjWv.js +0 -485
@@ -0,0 +1,138 @@
1
+ /**
2
+ * DETENER y replanificar (IXCODE-4): la persona pulsa el botón mientras el agente trabaja, los
3
+ * especialistas que estaban en marcha cierran con un resumen de lo hecho y lo que les quedaba, y
4
+ * el orquestador recibe esos resúmenes con el mensaje de la persona y replanifica.
5
+ *
6
+ * **No es una `Nota`, y a propósito**: una nota se entrega a CADA hilo como encargo (`notas.ts`),
7
+ * y una orden de parar repartida así haría que el hijo parase y el raíz… volviera a encargar lo
8
+ * mismo. Aquí cada destinatario recibe SU texto: el hijo, «para y resume»; el raíz, «replanifica
9
+ * sin repetir lo hecho».
10
+ *
11
+ * **A quién se detiene**: a los hijos nacidos de una llamada del raíz que empezó ANTES de pulsar.
12
+ * No basta «los vivos al pulsar»: si se pulsa mientras el raíz está decidiendo delegar, el hijo
13
+ * que sale de esa decisión nace después, pero de un plan que la persona ya no quiere. Y los que
14
+ * el raíz delegue DESPUÉS de leer la orden corren normal —son el plan nuevo—.
15
+ *
16
+ * **Cómo para un hijo, sin tocar la librería**: la orden entra por `preLLMProcessors` antes de su
17
+ * siguiente llamada, y SU modelo (`modeloParaTrueforge`, construido por hilo en `crearHijo`) tira
18
+ * las tool calls de esa respuesta: una respuesta sin tool calls cierra el hilo con normalidad
19
+ * (`AGENT_DONE`) y su texto le llega al padre como resultado de `create_sub_agent`. Se FILTRA lo
20
+ * que devuelve el modelo, no se le quitan las tools: con el historial lleno de llamadas, algún
21
+ * proveedor rechaza una petición sin la definición de tools.
22
+ *
23
+ * **Y una llamada EN CURSO se corta** (`corte`): medido con el botón, el analista estaba dentro de
24
+ * una llamada de 60 s generando un informe entero cuando se pulsó, y sin corte esa llamada acababa
25
+ * escribiéndolo. Cada hijo lleva su `AbortController`, que aborta SOLO su stream; el modelo del
26
+ * hijo lo captura y pide el resumen en el acto (`modeloLangchain.ts#corte`). Lo que NO se corta:
27
+ * un comando de shell en curso, que termina primero —la orden llega en la llamada siguiente—.
28
+ */
29
+ /** Lo que llega al padre si el hijo, tras filtrar, no dejó texto. */
30
+ export const RESUMEN_DE_RELLENO = "[Detenido a petición de la persona antes de poder resumir lo hecho.]";
31
+ const cita = (texto) => (texto.trim() === "" ? "" : `: «${texto.trim()}»`);
32
+ export function textoDeDetencionParaHijo(texto) {
33
+ return (`[La persona ha pulsado DETENER${cita(texto)}. Para aquí: no hagas ninguna llamada más —no se ejecutaría—. ` +
34
+ "Contesta YA a quien te delegó con: (1) lo que has hecho y dónde (ficheros leídos o escritos, hallazgos con su fichero), " +
35
+ "(2) lo que te quedaba por hacer. Con eso se replanifica, y lo que digas como hecho no se repetirá.]");
36
+ }
37
+ export function textoDeDetencionParaRaiz(texto) {
38
+ return (`[La persona ha pulsado DETENER y replanificar mientras trabajabas${cita(texto)}. ` +
39
+ "Los especialistas que estaban trabajando han parado; lo que hicieron y lo que les quedaba está en su respuesta. " +
40
+ "Replanifica con esto: lo que ya está hecho NO se repite, y si vuelves a delegar, el encargo nuevo dice qué está hecho y qué cambia.]");
41
+ }
42
+ /** Lleva la cuenta que decide a quién se detiene: cuántas llamadas lleva el raíz, y de cuál nació
43
+ * cada hijo. Uno por sesión; `reiniciar` al empezar cada turno. */
44
+ export function crearControlDeDetencion(hiloRaiz) {
45
+ let llamadasDelRaiz = 0;
46
+ const nacimiento = new Map();
47
+ /** El corte de cada hijo: aborta SOLO su stream en curso. */
48
+ const cortes = new Map();
49
+ let detencion;
50
+ const debeParar = (threadId) => {
51
+ if (detencion === undefined || threadId === hiloRaiz)
52
+ return false;
53
+ const n = nacimiento.get(threadId);
54
+ return n !== undefined && n <= detencion.hastaLlamadaDelRaiz;
55
+ };
56
+ return {
57
+ reiniciar() {
58
+ llamadasDelRaiz = 0;
59
+ nacimiento.clear();
60
+ cortes.clear();
61
+ detencion = undefined;
62
+ },
63
+ /**
64
+ * Cuántos hijos trabajan a la vez AHORA: los nacidos de la última llamada del raíz. Mientras un
65
+ * hijo vive, el raíz espera su resultado y no vuelve a llamar al modelo, así que lo nacido de
66
+ * llamadas anteriores ya terminó. Lo usa el reparto de notas (`notas.ts`).
67
+ */
68
+ hijosVivos() {
69
+ let n = 0;
70
+ for (const nacida of nacimiento.values())
71
+ if (nacida === llamadasDelRaiz)
72
+ n += 1;
73
+ return n;
74
+ },
75
+ /** Al crear un hijo: nace de la llamada del raíz en curso. */
76
+ nacio(threadId) {
77
+ nacimiento.set(threadId, llamadasDelRaiz);
78
+ cortes.set(threadId, new AbortController());
79
+ },
80
+ detener(texto) {
81
+ // Una segunda pulsación en el mismo turno alcanza a lo que haya nacido desde entonces; quien
82
+ // ya recibió la orden no la recibe otra vez. Su texto se JUNTA solo con lo que el raíz aún no
83
+ // leyó: medido, juntarlo con lo ya leído lo volvía a mandar —y tras Parar, como un turno
84
+ // nuevo que nadie pidió—.
85
+ const pendiente = detencion === undefined || detencion.raizAvisado ? "" : detencion.texto;
86
+ detencion = {
87
+ texto: [pendiente, texto].filter((t) => t.trim() !== "").join("\n\n"),
88
+ hastaLlamadaDelRaiz: llamadasDelRaiz,
89
+ avisados: detencion?.avisados ?? new Set(),
90
+ raizAvisado: false,
91
+ };
92
+ // Y a quien esté a mitad de una llamada, se le corta: pedirá el resumen en el acto.
93
+ for (const [hilo, control] of cortes)
94
+ if (debeParar(hilo) && !detencion.avisados.has(hilo))
95
+ control.abort();
96
+ },
97
+ /** Para el modelo de un hijo, al empezar cada llamada: su señal de corte y la orden que se le da
98
+ * si se corta. Darla lo cuenta como avisado —no la recibe otra vez por el procesador—. */
99
+ corte(threadId) {
100
+ const control = cortes.get(threadId);
101
+ if (control === undefined)
102
+ return undefined;
103
+ return {
104
+ senal: control.signal,
105
+ orden: () => {
106
+ detencion.avisados.add(threadId);
107
+ return textoDeDetencionParaHijo(detencion.texto);
108
+ },
109
+ };
110
+ },
111
+ /** Para el modelo de un hijo: si ya recibió la orden, su respuesta no puede llamar tools. */
112
+ soloTexto(threadId) {
113
+ return detencion?.avisados.has(threadId) === true;
114
+ },
115
+ /** Lo que se le mete a ESE hilo antes de su llamada, si algo. Cuenta las llamadas del raíz. */
116
+ antesDeLlamar(threadId) {
117
+ if (threadId === hiloRaiz) {
118
+ llamadasDelRaiz += 1;
119
+ if (detencion === undefined || detencion.raizAvisado)
120
+ return undefined;
121
+ detencion.raizAvisado = true;
122
+ return textoDeDetencionParaRaiz(detencion.texto);
123
+ }
124
+ if (!debeParar(threadId) || detencion.avisados.has(threadId))
125
+ return undefined;
126
+ detencion.avisados.add(threadId);
127
+ return textoDeDetencionParaHijo(detencion.texto);
128
+ },
129
+ /** La orden que NADIE llegó a leer —ni el raíz— sale como el turno siguiente, igual que una
130
+ * nota sobrante. Con texto vacío no queda nada que mandar. */
131
+ sobrante() {
132
+ if (detencion === undefined || detencion.raizAvisado || detencion.texto.trim() === "")
133
+ return undefined;
134
+ return detencion.texto;
135
+ },
136
+ };
137
+ }
138
+ //# sourceMappingURL=detencion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detencion.js","sourceRoot":"","sources":["../../../../src/agent/motores/trueforge/detencion.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,8 @@
17
17
  */
18
18
  import { AIMessage, HumanMessage, SystemMessage, ToolMessage } from "@langchain/core/messages";
19
19
  import { razonamientoDe, razonamientoVisibleDe, textoDe } from "../../turno/puente.js";
20
+ /** Lo que llega al padre si, tras un corte, el resumen no dejó texto. */
21
+ const RELLENO_DEL_CORTE = "[Detenido a petición de la persona a mitad de una llamada, antes de poder resumir lo hecho.]";
20
22
  /** El texto de un `content` de OpenAI, sea cadena o lista de partes. */
21
23
  function textoDeContenido(contenido) {
22
24
  if (typeof contenido === "string")
@@ -75,15 +77,41 @@ export function modeloParaTrueforge(opciones) {
75
77
  const id = `xc-${++secuencia}`;
76
78
  const creado = Math.floor(Date.now() / 1000);
77
79
  const nombre = opciones.nombre ?? "xonecode";
80
+ let relleno = opciones.soloTexto?.();
81
+ const corte = relleno === undefined ? opciones.corte?.() : undefined;
82
+ const senalDelStream = corte === undefined ? senal : senal === undefined ? corte.senal : AbortSignal.any([senal, corte.senal]);
78
83
  let acumulado;
79
- for await (const trozo of await modelo.stream(mensajes, senal === undefined ? {} : { signal: senal })) {
84
+ /** Los trozos de UNA pasada: la normal y, si se corta, la del resumen. */
85
+ const pasada = async function* (lista, s) {
86
+ for await (const trozo of await modelo.stream(lista, s === undefined ? {} : { signal: s }))
87
+ yield trozo;
88
+ };
89
+ let trozos = pasada(mensajes, senalDelStream);
90
+ for (;;) {
91
+ let r;
92
+ try {
93
+ r = await trozos.next();
94
+ }
95
+ catch (e) {
96
+ // Un aborto que es SOLO del corte —no del turno— no es un fallo: se pide el resumen.
97
+ if (corte === undefined || !corte.senal.aborted || senal?.aborted === true || relleno !== undefined)
98
+ throw e;
99
+ relleno = RELLENO_DEL_CORTE;
100
+ const dicho = acumulado === undefined ? "" : textoDe(acumulado);
101
+ acumulado = undefined;
102
+ trozos = pasada([...mensajes, ...(dicho.trim() === "" ? [] : [new AIMessage(dicho)]), new HumanMessage(corte.orden())], senal);
103
+ continue;
104
+ }
105
+ if (r.done === true)
106
+ break;
107
+ const trozo = r.value;
80
108
  acumulado = acumulado === undefined ? trozo : acumulado.concat(trozo);
81
109
  const texto = textoDe(trozo);
82
110
  // En los TROZOS va el razonamiento que se ENSEÑA, DeepSeek incluido: los trozos solo
83
111
  // alimentan los eventos del chat. El mensaje que se guarda en el hilo es el `output` de
84
112
  // abajo, que sigue con `razonamientoDe` — lo de DeepSeek no entra en la memoria.
85
113
  const pensado = razonamientoVisibleDe(trozo);
86
- const llamadas = (trozo.tool_call_chunks ?? []).map((t, i) => ({
114
+ const llamadas = (relleno === undefined ? (trozo.tool_call_chunks ?? []) : []).map((t, i) => ({
87
115
  index: t.index ?? i,
88
116
  ...(t.id === undefined ? {} : { id: t.id, type: "function" }),
89
117
  function: { ...(t.name === undefined ? {} : { name: t.name }), arguments: t.args ?? "" },
@@ -109,13 +137,17 @@ export function modeloParaTrueforge(opciones) {
109
137
  ],
110
138
  };
111
139
  }
112
- const llamadas = acumulado?.tool_calls ?? [];
140
+ const pedidas = acumulado?.tool_calls ?? [];
141
+ const llamadas = relleno === undefined ? pedidas : [];
142
+ if (relleno !== undefined && pedidas.length > 0)
143
+ opciones.alTirarLlamadas?.(pedidas.length);
113
144
  const uso = acumulado?.usage_metadata;
114
145
  const razonamiento = acumulado === undefined ? "" : razonamientoDe(acumulado);
146
+ const contenido = acumulado === undefined ? "" : textoDe(acumulado);
115
147
  return {
116
148
  output: {
117
149
  role: "assistant",
118
- content: acumulado === undefined ? "" : textoDe(acumulado),
150
+ content: relleno !== undefined && contenido.trim() === "" ? relleno : contenido,
119
151
  ...(llamadas.length === 0
120
152
  ? {}
121
153
  : {
@@ -1 +1 @@
1
- {"version":3,"file":"modeloLangchain.js","sourceRoot":"","sources":["../../../../src/agent/motores/trueforge/modeloLangchain.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"modeloLangchain.js","sourceRoot":"","sources":["../../../../src/agent/motores/trueforge/modeloLangchain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ export function crearNota(texto) {
2
+ return { texto, vistaPorElRaiz: false };
3
+ }
4
+ /** Para el raíz: lo que la persona le dijo. */
5
+ export function textoDeNota(texto) {
6
+ return `[la persona escribió mientras trabajabas: «${texto}»]`;
7
+ }
8
+ /** Para un hijo: su interlocutor normal es quien le delegó, así que se dice que viene de fuera, y
9
+ * se le da la salida si no es de su encargo. */
10
+ export function textoDeNotaParaHijo(texto) {
11
+ return (`[la persona escribió mientras trabajabas: «${texto}». Si encaja en tu encargo, incorpóralo. ` +
12
+ "Si no, no lo hagas: termina tu respuesta con «PENDIENTE DE LA PERSONA: …» para que quien te delegó lo replanifique.]");
13
+ }
14
+ /** Para el raíz, cuando la nota ya se la quedó un hijo. */
15
+ export function textoDeNotaYaEntregada(texto, quien) {
16
+ return (`[la persona escribió mientras trabajabas: «${texto}». Se le pasó a ${quien} mientras trabajaba, y su respuesta está arriba: ` +
17
+ "NO la vuelvas a encargar. Actúa solo sobre lo que diga como PENDIENTE DE LA PERSONA o no cubierto.]");
18
+ }
19
+ /** Los textos que se le meten a ESE hilo antes de su llamada, marcando lo entregado. */
20
+ export function entregarNotas(notas, threadId, ctx) {
21
+ const textos = [];
22
+ for (const n of notas) {
23
+ if (threadId === ctx.hiloRaiz) {
24
+ if (n.vistaPorElRaiz)
25
+ continue;
26
+ n.vistaPorElRaiz = true;
27
+ if (n.duenio === undefined) {
28
+ n.duenio = threadId;
29
+ textos.push(textoDeNota(n.texto));
30
+ }
31
+ else {
32
+ textos.push(textoDeNotaYaEntregada(n.texto, ctx.nombreDe(n.duenio)));
33
+ }
34
+ continue;
35
+ }
36
+ if (n.duenio !== undefined || n.vistaPorElRaiz || ctx.hijosVivos !== 1)
37
+ continue;
38
+ n.duenio = threadId;
39
+ textos.push(textoDeNotaParaHijo(n.texto));
40
+ }
41
+ return textos;
42
+ }
43
+ /** Lo que NADIE se quedó, para mandarlo como el turno siguiente. `undefined` si no queda ninguna —
44
+ * así el llamador no confunde "sin sobrantes" con una cadena vacía. */
45
+ export function sobrantes(notas) {
46
+ const sinEntregar = notas.filter((n) => n.duenio === undefined).map((n) => n.texto);
47
+ return sinEntregar.length === 0 ? undefined : sinEntregar.join("\n\n");
48
+ }
49
+ //# sourceMappingURL=notas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notas.js","sourceRoot":"","sources":["../../../../src/agent/motores/trueforge/notas.ts"],"names":[],"mappings":"AA4BA,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AAC1C,CAAC;AAWD,+CAA+C;AAC/C,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,8CAA8C,KAAK,IAAI,CAAC;AACjE,CAAC;AAED;iDACiD;AACjD,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,CACL,8CAA8C,KAAK,2CAA2C;QAC9F,sHAAsH,CACvH,CAAC;AACJ,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,sBAAsB,CAAC,KAAa,EAAE,KAAa;IACjE,OAAO,CACL,8CAA8C,KAAK,mBAAmB,KAAK,mDAAmD;QAC9H,qGAAqG,CACtG,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,KAAsB,EAAE,QAAgB,EAAE,GAAsB;IAC5F,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,QAAQ,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,cAAc;gBAAE,SAAS;YAC/B,CAAC,CAAC,cAAc,GAAG,IAAI,CAAC;YACxB,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC3B,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACvE,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC,UAAU,KAAK,CAAC;YAAE,SAAS;QACjF,CAAC,CAAC,MAAM,GAAG,QAAQ,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;wEACwE;AACxE,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACpF,OAAO,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACzE,CAAC"}
@@ -51,16 +51,22 @@ import { modeloParaTrueforge } from "./modeloLangchain.js";
51
51
  import { TOOLS_DE_LECTURA } from "./toolsDeFichero.js";
52
52
  import { topeAgotadoDe, traducirEvento } from "./eventosTrueforge.js";
53
53
  import { anuncioDeSkills } from "./skillsTrueforge.js";
54
- import { capabilitiesDe, capacidadDeFecha, capacidadDeFicheros, capacidadDeInstrucciones, capacidadDePropias, capacidadDeRecortes, capacidadesDelEspecialista, clasesDeTools, toolsDe, } from "./capacidades.js";
54
+ import { capabilitiesDe, capacidadDeFecha, capacidadDeFicheros, capacidadDeInstrucciones, capacidadDeNotas, capacidadDePropias, capacidadDeRecortes, capacidadesDelEspecialista, clasesDeTools, toolsDe, } from "./capacidades.js";
55
55
  import { crearDiagnosticoDeTools } from "../../turno/diagnosticoDeTools.js";
56
+ import { encenderTrazaDeErrores } from "../../trazaDeErroresEnDisco.js";
57
+ import { anotarPaso } from "../../../core/trazaDeErrores.js";
58
+ import { entornoConDepuracion } from "../../turno/depuracion.js";
56
59
  import { detalleDe, parametrosDe } from "../../turno/resumenDeTool.js";
57
60
  import { apartarMemoria, cargarMemoria, fotoSaneada, guardarMemoria, textoDeMemoriaDescartada } from "./memoriaTrueforge.js";
61
+ import { crearNota, sobrantes } from "./notas.js";
62
+ import { crearControlDeDetencion, RESUMEN_DE_RELLENO } from "./detencion.js";
58
63
  import { crearNavegacionXone } from "../../grafo/navegacionXone.js";
59
64
  import { hechosDelProyectoDe } from "../../navegacion/hechosEnDisco.js";
60
65
  import { conHechosDelProyecto } from "../../../core/hechosDelProyecto.js";
61
66
  import { crearBusquedaRegex } from "../../grafo/busquedaRegex.js";
62
67
  import { crearCopiarArtefacto } from "../../grafo/copiarArtefacto.js";
63
68
  import { crearUnirSecciones } from "../../grafo/unirSecciones.js";
69
+ import { crearIncorporarAdjunto, recibeIncorporarAdjunto } from "../../grafo/incorporarAdjunto.js";
64
70
  import { crearCriticaVisual } from "../../grafo/criticaVisual.js";
65
71
  import { crearTraerDeLaMaquina } from "../../grafo/traerDeLaMaquina.js";
66
72
  import { invocarVisualConModelos } from "../../dispositivos/juezVisual.js";
@@ -151,6 +157,13 @@ function preguntaDeLaFoto(foto) {
151
157
  };
152
158
  }
153
159
  const claveDe = (hilo, id) => `${hilo}:${id}`;
160
+ /**
161
+ * `agregarNota` no vive todavía en `SesionReal` (IXCODE-4, Task 6 se la añade ahí como opcional,
162
+ * compartida con deepagents): se ensancha el tipo de retorno AQUÍ, en vez de esperar a esa task,
163
+ * porque una sesión sin ella tipado como `SesionReal` a secas dejaría `s.agregarNota(...)` en
164
+ * rojo bajo `tsc --noEmit` desde este mismo commit. Sigue siendo un `SesionReal` válido en
165
+ * cualquier sitio que lo espere (`turnoReal.ts#abrirSesionReal`), por ser una intersección.
166
+ */
154
167
  export async function abrirSesionTrueforge(opciones) {
155
168
  const { raiz } = opciones;
156
169
  let modelos = opciones.modelos;
@@ -160,7 +173,14 @@ export async function abrirSesionTrueforge(opciones) {
160
173
  * formato, así que `xonecode traza` compara los dos motores. La omisión es la real —entrar por
161
174
  * parámetro solo sirve para doblarla—, que es lo que evita dejarla escrita y sin montar.
162
175
  */
163
- const diagnostico = opciones.diagnostico ?? crearDiagnosticoDeTools(raiz);
176
+ const entornoDeDiagnostico = entornoConDepuracion(opciones.depurar === true);
177
+ const diagnostico = opciones.diagnostico ?? crearDiagnosticoDeTools(raiz, entornoDeDiagnostico);
178
+ /**
179
+ * La traza de EXCEPCIONES e HITOS, la MISMA de deepagents (`turnoReal.ts`) y que aquí
180
+ * faltaba por completo: TrueForge nunca la encendía, ni siquiera con la variable de entorno
181
+ * puesta a mano.
182
+ */
183
+ encenderTrazaDeErrores(raiz, entornoDeDiagnostico);
164
184
  const tracker = createTokenTracker();
165
185
  const oyentes = new Set();
166
186
  let aborto;
@@ -191,12 +211,30 @@ export async function abrirSesionTrueforge(opciones) {
191
211
  if (a.mime !== undefined && a.mime.startsWith("image/"))
192
212
  capturasDelTurno.push(a);
193
213
  };
214
+ /** Lo que la persona escribió mientras el agente trabajaba, IXCODE-4: se entrega por
215
+ * `capacidadDeNotas`, la MISMA instancia en la raíz y en cada hijo. */
216
+ const notas = [];
217
+ /** DETENER y replanificar (`detencion.ts`): viaja por el mismo procesador que las notas. */
218
+ const detencion = crearControlDeDetencion(HILO_RAIZ);
219
+ /** Tool calls tiradas por DETENER en la sesión: si se queda en cero, el filtro es solo red. */
220
+ let llamadasTiradasPorDetener = 0;
221
+ const capacidadDeNotasDeLaSesion = capacidadDeNotas(notas, {
222
+ detencion,
223
+ nombreDe: (h) => quienEs.get(h) ?? h,
224
+ hiloRaiz: HILO_RAIZ,
225
+ });
226
+ /** Lo que la persona escribió en el turno y nadie leyó: notas y la orden de DETENER. */
227
+ const sinLeerDelTurno = () => {
228
+ const sinLeer = [sobrantes(notas), detencion.sobrante()].filter((t) => t !== undefined);
229
+ return sinLeer.length === 0 ? undefined : sinLeer.join("\n\n");
230
+ };
194
231
  const montarBackend = (ejecucion) => backendDeAgente({
195
232
  raiz,
196
233
  ficheros: ficherosDelProyecto(raiz),
197
234
  ...(opciones.artefactos === undefined
198
235
  ? {}
199
236
  : { artefactos: { carpeta: opciones.artefactos, alEscribir: anotarArtefacto } }),
237
+ ...(opciones.adjuntos === undefined ? {} : { adjuntos: opciones.adjuntos }),
200
238
  ...(ejecucion === undefined ? {} : { ejecucion }),
201
239
  });
202
240
  const backend = montarBackend();
@@ -283,6 +321,12 @@ export async function abrirSesionTrueforge(opciones) {
283
321
  : []),
284
322
  // El mismo reparto que deepagents (`xoneAgent.ts`): a quien declara `escribeEn`.
285
323
  ...((agente.escribeEn ?? []).length > 0 ? [crearUnirSecciones({ raiz, perfil: agente })] : []),
324
+ // Meter un adjunto del chat en el proyecto, con el reparto de deepagents: a quien escribe el
325
+ // proyecto entero y solo con la carpeta montada. Pide aprobación: `capacidadesDelEspecialista`
326
+ // la pone en `requireApprovalForTools`, y `rondasDe` la pregunta con su tarjeta (`cambioDe`).
327
+ ...(opciones.adjuntos !== undefined && recibeIncorporarAdjunto(agente)
328
+ ? [crearIncorporarAdjunto({ raiz, carpetaDeAdjuntos: opciones.adjuntos, perfil: agente })]
329
+ : []),
286
330
  ];
287
331
  /**
288
332
  * **Un cliente de modelo por papel, modelo y esfuerzo, que dura la SESIÓN** —hasta `/modelo`—, y
@@ -354,6 +398,7 @@ export async function abrirSesionTrueforge(opciones) {
354
398
  */
355
399
  const crearHijo = async (params) => {
356
400
  const agente = especialistas().find((a) => a.nombre === params.request.name);
401
+ detencion.nacio(params.threadId);
357
402
  quienEs.set(params.threadId, agente?.nombre ?? params.request.name);
358
403
  if (agente !== undefined)
359
404
  especialistaDeHilo.set(params.threadId, agente.nombre);
@@ -364,7 +409,14 @@ export async function abrirSesionTrueforge(opciones) {
364
409
  const piezas = capacidadesDelEspecialista(agente, params.request.name, {
365
410
  backend: backend,
366
411
  propias: propiasDe,
367
- conShell: () => montarBackend({ entorno: entornoDeLaShellDelProyecto(raiz, opciones.artefactos) }),
412
+ notas: capacidadDeNotasDeLaSesion,
413
+ conShell: () => montarBackend({
414
+ entorno: entornoDeLaShellDelProyecto(raiz, opciones.artefactos),
415
+ // El MISMO patrón que ya usa `modeloParaTrueforge` un poco más arriba en este
416
+ // fichero: un getter que se reevalúa en cada llamada, así siempre lee el
417
+ // `AbortController` de la RONDA en curso y no uno capturado al construir.
418
+ senal: () => aborto?.signal,
419
+ }),
368
420
  });
369
421
  const nombres = toolsDe(piezas);
370
422
  const nota = notaDeTools(nombres, agente === undefined ? LIMITE_DEL_GENERICO : LIMITES_DE[clase]);
@@ -381,6 +433,13 @@ export async function abrirSesionTrueforge(opciones) {
381
433
  ? clienteDe(`papel:${papel}:${agente?.esfuerzo ?? ""}`, () => modelos.paraPapel(papel, agente?.esfuerzo))
382
434
  : clienteDe(`modelo:${agente.modelo}:${agente.esfuerzo ?? ""}`, () => modelos.paraModelo(agente.modelo, agente.esfuerzo)),
383
435
  senal: () => aborto?.signal,
436
+ soloTexto: () => (detencion.soloTexto(params.threadId) ? RESUMEN_DE_RELLENO : undefined),
437
+ corte: () => detencion.corte(params.threadId),
438
+ alTirarLlamadas: (n) => {
439
+ llamadasTiradasPorDetener += n;
440
+ // A la traza de hitos (con «Depurar»): es la medida de si el filtro hace falta o es red.
441
+ anotarPaso("trueforge.detener", `${quienEs.get(params.threadId) ?? params.threadId}: ${n} tool call(s) tiradas`)();
442
+ },
384
443
  }),
385
444
  messages: [{ role: "user", content: params.request.input }],
386
445
  // Los topes MEDIDOS de deepagents: el conductor más, porque cada paso suyo es un comando.
@@ -440,6 +499,7 @@ export async function abrirSesionTrueforge(opciones) {
440
499
  capacidadDePropias(propiasDelRaiz, backend),
441
500
  capacidadDeRecortes(backend),
442
501
  capacidadDeFecha(),
502
+ capacidadDeNotasDeLaSesion,
443
503
  ]),
444
504
  /**
445
505
  * **La conversación se RESUME al mismo umbral que deepagents** (`UMBRAL_RESUMEN_TOKENS`):
@@ -604,6 +664,7 @@ export async function abrirSesionTrueforge(opciones) {
604
664
  throw new Error("la sesión está cerrada");
605
665
  const t0 = Date.now();
606
666
  cancelado = false;
667
+ detencion.reiniciar();
607
668
  const instantanea = await tomarInstantanea(raiz, opciones.entorno.git);
608
669
  const tope = opciones.topeDeRondas ?? MAX_APPROVAL_ROUNDS;
609
670
  const aplicadasSinPreguntar = [];
@@ -924,6 +985,13 @@ export async function abrirSesionTrueforge(opciones) {
924
985
  // deepagents — un aviso que salta cuando no ha pasado nada enseña a ignorarlo.
925
986
  avisos: (b) => [
926
987
  ...(memoriaDescartada === undefined ? [] : [memoriaDescartada]),
988
+ ...(sinLeerDelTurno() === undefined
989
+ ? []
990
+ : cancelado
991
+ ? // PARAR es «para»: lo escrito que nadie leyó no arranca otro turno —medido, lo
992
+ // hacía—, pero tampoco se pierde en silencio: se dice, con su texto, para copiarlo.
993
+ [`⏹ turno parado: no se manda lo que escribiste mientras trabajaba — «${sinLeerDelTurno()}»`]
994
+ : [`⚠ una nota no se pudo entregar a tiempo: se manda como el turno siguiente`]),
927
995
  ...(b.corrio("verify") || !escribioProyecto
928
996
  ? []
929
997
  : [`⚠ el verificador no ha corrido en este turno${motivoSinVerificar === undefined ? "" : ` (${motivoSinVerificar})`}`]),
@@ -1003,6 +1071,13 @@ export async function abrirSesionTrueforge(opciones) {
1003
1071
  }
1004
1072
  }
1005
1073
  const cambios = await instantanea.cambios();
1074
+ // Calculado y VACIADO aquí, DESPUÉS del único `await` que queda entre el `finally` y el
1075
+ // `return`: hacerlo antes (como sugería el borrador) deja una ventana en la que una nota
1076
+ // empujada durante ese `await` cae en una cola ya vacía y sobrevive muda al turno
1077
+ // siguiente — justo lo que este campo existe para impedir.
1078
+ const notasSobrantes = cancelado ? undefined : sinLeerDelTurno();
1079
+ detencion.reiniciar();
1080
+ notas.length = 0; // Se sirvieron o se reportan aquí: no siguen vivas para el próximo turno.
1006
1081
  return {
1007
1082
  bitacora,
1008
1083
  cambios,
@@ -1012,6 +1087,7 @@ export async function abrirSesionTrueforge(opciones) {
1012
1087
  ...(hallazgosDelTurno.length === 0 ? {} : { hallazgos: hallazgosDelTurno }),
1013
1088
  ...(preexistentesDelTurno === undefined ? {} : { preexistentes: preexistentesDelTurno }),
1014
1089
  ...(motivoSinVerificar === undefined ? {} : { motivoSinVerificar }),
1090
+ ...(notasSobrantes === undefined ? {} : { notasSobrantes }),
1015
1091
  };
1016
1092
  },
1017
1093
  async cambiarModelos(nuevos) {
@@ -1042,6 +1118,27 @@ export async function abrirSesionTrueforge(opciones) {
1042
1118
  cancelado = true;
1043
1119
  aborto?.abort(new Error("turno cancelado por el usuario"));
1044
1120
  },
1121
+ /**
1122
+ * Empuja la nota a la cola de la sesión, sin más: no comprueba que haya un turno en marcha
1123
+ * —ese contrato lo sostiene quien llama (`web/servidor/vestibulo.ts`, Task 6)—, así que
1124
+ * llamarlo sin turno en curso no lanza, y la nota queda ahí para la próxima llamada al
1125
+ * modelo que la recoja `capacidadDeNotasDeLaSesion`.
1126
+ */
1127
+ agregarNota(texto) {
1128
+ notas.push(crearNota(texto));
1129
+ },
1130
+ /**
1131
+ * DETENER y replanificar (`detencion.ts`): los especialistas en marcha cierran con su resumen
1132
+ * en su siguiente llamada, y el raíz replanifica con ellos y con `texto`. Solo vale DENTRO de
1133
+ * un turno —el siguiente empieza de cero—, y por eso el servidor solo la manda con uno en vuelo;
1134
+ * si el turno cierra sin que nadie la lea, su texto sale como sobrante.
1135
+ */
1136
+ detener(texto) {
1137
+ detencion.detener(texto);
1138
+ },
1139
+ get llamadasTiradasPorDetener() {
1140
+ return llamadasTiradasPorDetener;
1141
+ },
1045
1142
  consumo() {
1046
1143
  return {
1047
1144
  modelo: { entrada: tracker.input, salida: tracker.output, cache: tracker.cache },