xonecode 0.8.42 → 0.9.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.
- package/apps/web/dist/assets/{index-CwAAn-xT.css → index-CtfT1BjI.css} +1 -1
- package/apps/web/dist/assets/{index--HvR4hMi.js → index-DqcZ7_Rx.js} +68 -68
- package/apps/web/dist/assets/{php-HCmCEpFP.js → php-DjRQ1K-w.js} +1 -1
- package/apps/web/dist/assets/{ruby-DsWetjbK.js → ruby-BcLyZ3qi.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/dist/agent/config/settingsEnDisco.js +50 -2
- package/dist/agent/config/settingsEnDisco.js.map +1 -1
- package/dist/agent/grafo/arbolDeProyecto.js +1 -1
- package/dist/agent/grafo/arbolDeProyecto.js.map +1 -1
- package/dist/agent/grafo/opcionesDeFicheros.js +24 -0
- package/dist/agent/grafo/opcionesDeFicheros.js.map +1 -0
- package/dist/agent/grafo/perfiles.js +1 -1
- package/dist/agent/grafo/perfiles.js.map +1 -1
- package/dist/agent/grafo/proyecto.js +5 -1
- package/dist/agent/grafo/proyecto.js.map +1 -1
- package/dist/agent/grafo/xoneAgent.js +49 -51
- package/dist/agent/grafo/xoneAgent.js.map +1 -1
- package/dist/agent/motores/trueforge/capacidades.js +138 -0
- package/dist/agent/motores/trueforge/capacidades.js.map +1 -0
- package/dist/agent/motores/trueforge/eventosTrueforge.js +98 -0
- package/dist/agent/motores/trueforge/eventosTrueforge.js.map +1 -0
- package/dist/agent/motores/trueforge/memoriaTrueforge.js +336 -0
- package/dist/agent/motores/trueforge/memoriaTrueforge.js.map +1 -0
- package/dist/agent/motores/trueforge/metricasTrueforge.js +55 -0
- package/dist/agent/motores/trueforge/metricasTrueforge.js.map +1 -0
- package/dist/agent/motores/trueforge/modeloExterno.js +46 -0
- package/dist/agent/motores/trueforge/modeloExterno.js.map +1 -0
- package/dist/agent/motores/trueforge/modeloLangchain.js +149 -0
- package/dist/agent/motores/trueforge/modeloLangchain.js.map +1 -0
- package/dist/agent/motores/trueforge/recortes.js +121 -0
- package/dist/agent/motores/trueforge/recortes.js.map +1 -0
- package/dist/agent/motores/trueforge/sesionTrueforge.js +1045 -0
- package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -0
- package/dist/agent/motores/trueforge/skillsTrueforge.js +14 -0
- package/dist/agent/motores/trueforge/skillsTrueforge.js.map +1 -0
- package/dist/agent/motores/trueforge/toolsDeFichero.js +264 -0
- package/dist/agent/motores/trueforge/toolsDeFichero.js.map +1 -0
- package/dist/agent/motores/trueforge/toolsPropias.js +65 -0
- package/dist/agent/motores/trueforge/toolsPropias.js.map +1 -0
- package/dist/agent/motores/trueforge/trueforge.js +45 -0
- package/dist/agent/motores/trueforge/trueforge.js.map +1 -0
- package/dist/agent/sesiones/memoriaDeHilo.js +24 -0
- package/dist/agent/sesiones/memoriaDeHilo.js.map +1 -0
- package/dist/agent/subagentes/actividadDeCodex.js +60 -0
- package/dist/agent/subagentes/actividadDeCodex.js.map +1 -0
- package/dist/agent/subagentes/agentesEnDisco.js +4 -0
- package/dist/agent/subagentes/agentesEnDisco.js.map +1 -1
- package/dist/agent/subagentes/escrituraExterna.js +2 -0
- package/dist/agent/subagentes/escrituraExterna.js.map +1 -1
- package/dist/agent/subagentes/subagenteCodex.js +20 -0
- package/dist/agent/subagentes/subagenteCodex.js.map +1 -1
- package/dist/agent/subagentes/subagenteExterno.js +269 -202
- package/dist/agent/subagentes/subagenteExterno.js.map +1 -1
- package/dist/agent/subagentes/subagenteOpencode.js +18 -1
- package/dist/agent/subagentes/subagenteOpencode.js.map +1 -1
- package/dist/agent/turno/diagnosticoDeTools.js +3 -0
- package/dist/agent/turno/diagnosticoDeTools.js.map +1 -1
- package/dist/agent/turno/ficherosDelProyecto.js +62 -0
- package/dist/agent/turno/ficherosDelProyecto.js.map +1 -0
- package/dist/agent/turno/informeDeTraza.js +28 -1
- package/dist/agent/turno/informeDeTraza.js.map +1 -1
- package/dist/agent/turno/resumenDeTool.js +3 -0
- package/dist/agent/turno/resumenDeTool.js.map +1 -1
- package/dist/agent/turno/sesionReal.js +2 -0
- package/dist/agent/turno/sesionReal.js.map +1 -0
- package/dist/agent/turno/turnoReal.js +40 -163
- package/dist/agent/turno/turnoReal.js.map +1 -1
- package/dist/agent/turno/verificacion.js +142 -0
- package/dist/agent/turno/verificacion.js.map +1 -0
- package/dist/cli/config.js +19 -0
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/consola.js.map +1 -1
- package/dist/cli/main.js +52 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/tui/correrTui.js +1 -1
- package/dist/cli/tui/correrTui.js.map +1 -1
- package/dist/cli/tui/transcript.js +5 -0
- package/dist/cli/tui/transcript.js.map +1 -1
- package/dist/core/actos.js.map +1 -1
- package/dist/core/config.js +13 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/dispositivoDeSesion.js +49 -0
- package/dist/core/dispositivoDeSesion.js.map +1 -0
- package/dist/core/motor.js +41 -0
- package/dist/core/motor.js.map +1 -0
- package/dist/core/ports.js.map +1 -1
- package/dist/core/settings.js +21 -0
- package/dist/core/settings.js.map +1 -1
- package/dist/core/shellDeAgente.js +3 -0
- package/dist/core/shellDeAgente.js.map +1 -1
- package/dist/core/trazaDeErrores.js +8 -2
- package/dist/core/trazaDeErrores.js.map +1 -1
- package/dist/core/turno.js +10 -0
- package/dist/core/turno.js.map +1 -1
- package/dist/web/servidor/arranque.js +96 -8
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/pielWeb.js +6 -0
- package/dist/web/servidor/pielWeb.js.map +1 -1
- package/dist/web/servidor/sesiones.js +11 -0
- package/dist/web/servidor/sesiones.js.map +1 -1
- package/dist/web/servidor/transporte.js.map +1 -1
- package/dist/web/servidor/vestibulo.js +83 -8
- package/dist/web/servidor/vestibulo.js.map +1 -1
- package/package.json +7 -2
- package/skills/xone-hotswap/SKILL.md +5 -1
- package/skills/xone-hotswap/lib/dispositivo.mjs +72 -0
- package/skills/xone-hotswap/scripts/xone-arrancar-ios +3 -1
- package/skills/xone-hotswap/scripts/xone-captura-android +5 -1
- package/skills/xone-hotswap/scripts/xone-desplegar-android +5 -1
- package/skills/xone-hotswap/scripts/xone-log-android +5 -1
- package/skills/xone-hotswap/scripts/xone-reiniciar-android +5 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Las CAPACIDADES del motor TrueForge: su sistema de plugins (`AgentCapability`), una pieza por
|
|
3
|
+
* responsabilidad —ficheros, tools propias, ejecución, recortes, fecha, instrucciones—.
|
|
4
|
+
*
|
|
5
|
+
* Antes se componían a mano dentro de `abrirSesionTrueforge`, y la nota de «qué tools tienes» de
|
|
6
|
+
* cada hijo se mantenía aparte con una lista escrita: cada tool nueva había que añadirla en dos
|
|
7
|
+
* sitios, y la vez que no se hizo el hijo leía cuatro nombres y veía seis. Aquí **cada pieza
|
|
8
|
+
* declara las tools que añade**, y la nota sale de esa lista (`toolsDe`): hay un solo sitio.
|
|
9
|
+
*
|
|
10
|
+
* Y **qué piezas lleva cada especialista lo decide una función** (`capacidadesDelEspecialista`)
|
|
11
|
+
* sobre lo que declara su `.md`, con la misma partición que deepagents. Es lo que deja probar el
|
|
12
|
+
* reparto sin levantar un hilo.
|
|
13
|
+
*/
|
|
14
|
+
import { NOOP_AGENT_TRACING, ToolSet, currentDateTime } from "./trueforge.js";
|
|
15
|
+
import { permisosDe } from "../../grafo/perfiles.js";
|
|
16
|
+
import { fuenteDeEjecucion, fuenteDeFicheros, TOOLS_DE_FICHERO, TOOLS_DE_LECTURA, TOOLS_QUE_ESCRIBEN, } from "./toolsDeFichero.js";
|
|
17
|
+
import { fuenteDeLangchain } from "./toolsPropias.js";
|
|
18
|
+
import { presupuestoDelPaso } from "./recortes.js";
|
|
19
|
+
/** Las tools que NO piden aprobación: las de lectura, las propias y la shell del conductor. */
|
|
20
|
+
export const SIN_APROBACION = { enableTools: ["@all"], disableTools: [], preloadTools: [], requireApprovalForTools: [] };
|
|
21
|
+
/** Las que escriben PARAN el turno hasta que alguien decida, como el HITL de deepagents. */
|
|
22
|
+
export const CON_APROBACION = { enableTools: ["@all"], disableTools: [], preloadTools: [], requireApprovalForTools: [...TOOLS_QUE_ESCRIBEN] };
|
|
23
|
+
/** Las tools de FICHERO sobre nuestro backend, acotadas por `reglas`. */
|
|
24
|
+
export function capacidadDeFicheros(opciones) {
|
|
25
|
+
return {
|
|
26
|
+
nombre: "ficheros",
|
|
27
|
+
tools: opciones.tools,
|
|
28
|
+
capability: {
|
|
29
|
+
systemToolSets: [
|
|
30
|
+
new ToolSet({
|
|
31
|
+
source: fuenteDeFicheros({ backend: opciones.backend, reglas: opciones.reglas, tools: opciones.tools }),
|
|
32
|
+
selectors: opciones.conAprobacion ? CON_APROBACION : SIN_APROBACION,
|
|
33
|
+
preload: true,
|
|
34
|
+
}),
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Las tools propias de xonecode (`xone_navegacion`, `regex_search`…), adaptadas. */
|
|
40
|
+
export function capacidadDePropias(tools, backend) {
|
|
41
|
+
return {
|
|
42
|
+
nombre: "propias",
|
|
43
|
+
tools: tools.map((t) => t.name),
|
|
44
|
+
capability: {
|
|
45
|
+
systemToolSets: [new ToolSet({ source: fuenteDeLangchain(tools, backend), selectors: SIN_APROBACION, preload: true })],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** `execute`: la shell del que la declara en su `.md`, y de nadie más. */
|
|
50
|
+
export function capacidadDeEjecucion(conShell) {
|
|
51
|
+
return {
|
|
52
|
+
nombre: "ejecucion",
|
|
53
|
+
tools: ["execute"],
|
|
54
|
+
capability: { systemToolSets: [new ToolSet({ source: fuenteDeEjecucion(conShell), selectors: SIN_APROBACION, preload: true })] },
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* El presupuesto de un PASO entero (`recortes.ts#recortarPaso`), que el recorte por resultado no
|
|
59
|
+
* ve: varias respuestas en paralelo que caben solas pero no juntas. No añade tools.
|
|
60
|
+
*/
|
|
61
|
+
export function capacidadDeRecortes(backend) {
|
|
62
|
+
return { nombre: "recortes", tools: [], capability: { toolResponseProcessors: [presupuestoDelPaso(backend)] } };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* `get_current_datetime` de la librería: la fecha en UTC, para que «hoy» o «hace tres días» no se
|
|
66
|
+
* lo invente el modelo. No da la zona horaria local, y no se le atribuye.
|
|
67
|
+
*/
|
|
68
|
+
export function capacidadDeFecha() {
|
|
69
|
+
return { nombre: "fecha", tools: ["get_current_datetime"], capability: currentDateTime({ tracing: NOOP_AGENT_TRACING }) };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Las instrucciones de un HIJO en su prompt de SISTEMA. La librería IGNORA el `instruction` de un
|
|
73
|
+
* hijo (`buildInstruction`, `!this.parent`): a su sistema solo llegan los `instructionBuilders`.
|
|
74
|
+
* En el primer mensaje, una compactación —que sustituye el contexto entero— se las llevaría.
|
|
75
|
+
*/
|
|
76
|
+
export function capacidadDeInstrucciones(texto) {
|
|
77
|
+
return {
|
|
78
|
+
nombre: "instrucciones",
|
|
79
|
+
tools: [],
|
|
80
|
+
capability: {
|
|
81
|
+
instructionBuilders: [(b) => void b.addSection("especialista", texto, true)],
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Las tools que suman unas piezas, en orden: de aquí sale la nota del hijo. */
|
|
86
|
+
export function toolsDe(capacidades) {
|
|
87
|
+
return capacidades.flatMap((c) => [...c.tools]);
|
|
88
|
+
}
|
|
89
|
+
/** Las `AgentCapability` que recibe TrueForge. */
|
|
90
|
+
export function capabilitiesDe(capacidades) {
|
|
91
|
+
return capacidades.map((c) => c.capability);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Qué CLASE de especialista es, por lo que declara su `.md` — la partición de deepagents
|
|
95
|
+
* (`perfiles.ts#toolsDe` y `montajeDeFicheros`):
|
|
96
|
+
* - quien EJECUTA: lectura + `execute`, y nada de escribir (la shell no pasa por los permisos,
|
|
97
|
+
* así que el camino normal de tocar el proyecto sigue siendo el de la aprobación);
|
|
98
|
+
* - quien solo lee: las seis SIN aprobación, porque `permisosDe` lo confina a lo que no es el
|
|
99
|
+
* proyecto —`/artefactos/` y `/planes/`, que es donde el analista deja su plan—: en deepagents
|
|
100
|
+
* `hitlDe` le devuelve `{}` por lo mismo;
|
|
101
|
+
* - el resto: las seis, con `write_file`/`edit_file` pidiendo aprobación y `permisosDe` acotando
|
|
102
|
+
* (`escribeEn` incluido).
|
|
103
|
+
*/
|
|
104
|
+
export function clasesDeTools(agente) {
|
|
105
|
+
if (agente.ejecucion === true)
|
|
106
|
+
return "ejecuta";
|
|
107
|
+
return agente.soloLectura ? "lee" : "escribe";
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Las piezas de un especialista —o del hijo genérico, si el nombre no es de ninguno—, sin sus
|
|
111
|
+
* instrucciones: esas se escriben con la lista de tools que salga de aquí.
|
|
112
|
+
*/
|
|
113
|
+
export function capacidadesDelEspecialista(agente, nombrePedido, deps) {
|
|
114
|
+
// Un nombre inventado da un hijo de SOLO LECTURA sin shell: no tumba el turno ni se lleva la escritura.
|
|
115
|
+
if (agente === undefined) {
|
|
116
|
+
return [
|
|
117
|
+
capacidadDeFicheros({ backend: deps.backend, reglas: permisosDe({ nombre: nombrePedido, soloLectura: true }), tools: TOOLS_DE_LECTURA, conAprobacion: false }),
|
|
118
|
+
capacidadDeRecortes(deps.backend),
|
|
119
|
+
capacidadDeFecha(),
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
const clase = clasesDeTools(agente);
|
|
123
|
+
const reglas = permisosDe(agente);
|
|
124
|
+
const propias = deps.propias(agente);
|
|
125
|
+
return [
|
|
126
|
+
capacidadDeFicheros({
|
|
127
|
+
backend: deps.backend,
|
|
128
|
+
reglas,
|
|
129
|
+
tools: clase === "ejecuta" ? TOOLS_DE_LECTURA : TOOLS_DE_FICHERO,
|
|
130
|
+
conAprobacion: clase === "escribe",
|
|
131
|
+
}),
|
|
132
|
+
...(propias.length > 0 ? [capacidadDePropias(propias, deps.backend)] : []),
|
|
133
|
+
...(clase === "ejecuta" ? [capacidadDeEjecucion(deps.conShell())] : []),
|
|
134
|
+
capacidadDeRecortes(deps.backend),
|
|
135
|
+
capacidadDeFecha(),
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=capacidades.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capacidades.js","sourceRoot":"","sources":["../../../../src/agent/motores/trueforge/capacidades.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { detalleDe } from "../../turno/resumenDeTool.js";
|
|
2
|
+
const HILO_RAIZ = "main";
|
|
3
|
+
/** Las tool calls de un mensaje completo del asistente: nombre y argumentos. */
|
|
4
|
+
function llamadasDe(mensaje) {
|
|
5
|
+
const tc = mensaje?.tool_calls;
|
|
6
|
+
if (!Array.isArray(tc))
|
|
7
|
+
return [];
|
|
8
|
+
return tc.flatMap((t) => {
|
|
9
|
+
const nombre = t.function?.name;
|
|
10
|
+
if (typeof nombre !== "string")
|
|
11
|
+
return [];
|
|
12
|
+
let args = {};
|
|
13
|
+
try {
|
|
14
|
+
args = JSON.parse(t.function?.arguments ?? "{}");
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
args = {};
|
|
18
|
+
}
|
|
19
|
+
return [{ nombre, args }];
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Un evento de TrueForge → cero o más eventos de dominio, y el uso si trae una llamada al modelo
|
|
24
|
+
* terminada (para que quien corre el turno lo sume al contador).
|
|
25
|
+
*/
|
|
26
|
+
export function traducirEvento(evento) {
|
|
27
|
+
const e = (evento ?? {});
|
|
28
|
+
const delRaiz = (e.thread_id ?? HILO_RAIZ) === HILO_RAIZ;
|
|
29
|
+
switch (e.type) {
|
|
30
|
+
case "model.message.delta": {
|
|
31
|
+
if (!delRaiz)
|
|
32
|
+
return { eventos: [] };
|
|
33
|
+
const salida = [];
|
|
34
|
+
if (typeof e.reasoning_content === "string" && e.reasoning_content !== "") {
|
|
35
|
+
salida.push({ tipo: "razonamiento", texto: e.reasoning_content, ...(e.id === undefined ? {} : { msgId: e.id }) });
|
|
36
|
+
}
|
|
37
|
+
if (typeof e.content === "string" && e.content !== "") {
|
|
38
|
+
salida.push({ tipo: "token", texto: e.content, ...(e.id === undefined ? {} : { msgId: e.id }) });
|
|
39
|
+
}
|
|
40
|
+
return { eventos: salida };
|
|
41
|
+
}
|
|
42
|
+
case "internal.agent.context.append": {
|
|
43
|
+
// El mensaje COMPLETO del asistente: de aquí salen sus tools —con los argumentos ya
|
|
44
|
+
// enteros, no a trozos— y el uso de la llamada.
|
|
45
|
+
const salidas = Array.isArray(e.output) ? e.output : [];
|
|
46
|
+
const eventos = [];
|
|
47
|
+
let uso;
|
|
48
|
+
for (const m of salidas) {
|
|
49
|
+
for (const { nombre, args } of llamadasDe(m)) {
|
|
50
|
+
const detalle = detalleDe(nombre, args);
|
|
51
|
+
eventos.push({ tipo: "tool", nombre, ...(detalle === undefined ? {} : { detalle }) });
|
|
52
|
+
}
|
|
53
|
+
const u = m?.usage;
|
|
54
|
+
if (u !== undefined) {
|
|
55
|
+
uso = {
|
|
56
|
+
input: (uso?.input ?? 0) + (u.input_tokens ?? 0),
|
|
57
|
+
output: (uso?.output ?? 0) + (u.output_tokens ?? 0),
|
|
58
|
+
cache: (uso?.cache ?? 0) + (u.cache_read_tokens ?? 0),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { eventos, ...(uso === undefined ? {} : { uso }) };
|
|
63
|
+
}
|
|
64
|
+
case "agent.context.overwrite": {
|
|
65
|
+
// La compactación: una llamada al modelo que también se paga. Su uso viene en el evento y
|
|
66
|
+
// no en un mensaje del contexto, así que sin esto el resumen sería gratis en el contador.
|
|
67
|
+
const u = e.usage;
|
|
68
|
+
if (u === undefined)
|
|
69
|
+
return { eventos: [] };
|
|
70
|
+
return { eventos: [], uso: { input: u.input_tokens ?? 0, output: u.output_tokens ?? 0, cache: u.cache_read_tokens ?? 0 } };
|
|
71
|
+
}
|
|
72
|
+
case "internal.agent.done": {
|
|
73
|
+
// Un subagente que falla lo dice su padre, que recibe el error como respuesta de tool.
|
|
74
|
+
// El RAÍZ que falla se dice aquí: un turno que se rompe no puede cerrar en silencio.
|
|
75
|
+
if (!delRaiz || e.status !== "error")
|
|
76
|
+
return { eventos: [] };
|
|
77
|
+
const detalle = typeof e.error === "string" ? e.error : "error del motor";
|
|
78
|
+
// El TOPE de llamadas no es un fallo del motor: es un corte, y se dice como tal — con cuántas
|
|
79
|
+
// y con lo que se puede hacer. Sin esto se leía «el motor falló» con el texto en inglés.
|
|
80
|
+
const tope = /iteration limit of (\d+)/.exec(detalle);
|
|
81
|
+
if (tope !== null) {
|
|
82
|
+
return {
|
|
83
|
+
eventos: [
|
|
84
|
+
{
|
|
85
|
+
tipo: "aviso",
|
|
86
|
+
texto: `⚠ el orquestador agotó su tope de ${tope[1]} llamadas en este turno: lo hecho hasta aquí se queda como está; pide que siga si hace falta`,
|
|
87
|
+
severidad: "grave",
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return { eventos: [{ tipo: "aviso", texto: `⚠ el motor TrueForge falló: ${detalle}`, severidad: "grave" }] };
|
|
93
|
+
}
|
|
94
|
+
default:
|
|
95
|
+
return { eventos: [] };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=eventosTrueforge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventosTrueforge.js","sourceRoot":"","sources":["../../../../src/agent/motores/trueforge/eventosTrueforge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* La memoria de una conversación de TrueForge, en disco: la FOTO del hilo raíz.
|
|
3
|
+
*
|
|
4
|
+
* Sin esto el árbol de hilos vivía en memoria y reabrir una sesión de este motor empezaba de
|
|
5
|
+
* cero, con la interfaz enseñando la conversación de antes como si el modelo la recordara.
|
|
6
|
+
*
|
|
7
|
+
* **Es la foto del RAÍZ, no la capa `agent-session` de TrueForge, y es a propósito.** Esa capa
|
|
8
|
+
* trae su propio registro de sesiones, turnos y eventos —un segundo índice al lado del nuestro,
|
|
9
|
+
* con su propio «de quién es esto»— y su factoría de subagentes SUSTITUYE el primer mensaje del
|
|
10
|
+
* hijo por el encargo pelado. Lo que hace falta para «reabrir continúa» es menos:
|
|
11
|
+
* `AgentThread.toSnapshot()` y su constructor, que aceptan el contexto de vuelta. Los hijos mueren
|
|
12
|
+
* con su turno por diseño, así que no hay nada suyo que guardar.
|
|
13
|
+
*
|
|
14
|
+
* Tres reglas, las mismas que el checkpoint de deepagents:
|
|
15
|
+
* - **Modo 0600 ANTES de tener contenido**: la foto lleva los mensajes enteros —contenido de
|
|
16
|
+
* ficheros incluido—, igual que `checkpoint.sqlite`.
|
|
17
|
+
* - **Vive en la carpeta de la sesión**, dentro de `.xonecode/`, que no entra en git ni sube.
|
|
18
|
+
* - **Una tool call sin respuesta se SALDA al guardar** (`saldarColgadas`), con una respuesta
|
|
19
|
+
* que dice la verdad: al modelo le llegaría un mensaje con tool calls sin su respuesta detrás, y
|
|
20
|
+
* Gemini y OpenAI contestan 400. El `OpenToolCallCloser` de TrueForge no cubre este caso:
|
|
21
|
+
* se salta a propósito las que crean un hilo (`create_sub_agent`), que es justo la que queda
|
|
22
|
+
* colgada cuando un turno se corta con un hijo esperando aprobación.
|
|
23
|
+
*
|
|
24
|
+
* **Y la foto lleva VERSIÓN, y se lee de forma ESTRICTA** (`interpretarFoto`). Es un fichero que
|
|
25
|
+
* sobrevive a las subidas de XOneCode y de la librería —que es 0.x y no promete nada entre
|
|
26
|
+
* versiones—, así que lo que no se entiende no se carga a medias: un contexto a medio entender
|
|
27
|
+
* es una conversación que el modelo cree recordar y no recuerda. Fail-closed hacia el lado que
|
|
28
|
+
* NO destruye: una foto que no se entiende no tumba la sesión, se abre SIN memoria y se DICE
|
|
29
|
+
* (`textoDeMemoriaDescartada`), y la foto se APARTA con otro nombre (`apartarMemoria`) en vez de
|
|
30
|
+
* borrarse — o el primer guardado del turno siguiente la pisaría.
|
|
31
|
+
*/
|
|
32
|
+
import { chmodSync, existsSync, mkdirSync, openSync, closeSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
33
|
+
import { basename, dirname, join } from "node:path";
|
|
34
|
+
import { VERSION_DE_TRUEFORGE } from "./trueforge.js";
|
|
35
|
+
/** Un id de sesión que se puede usar como nombre de carpeta: segmento llano y nada más. */
|
|
36
|
+
const ID_VALIDO = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
37
|
+
/** Dónde vive la memoria de la sesión `hilo`, o `undefined` si el id no es un segmento llano. */
|
|
38
|
+
export function rutaDeMemoria(raiz, hilo) {
|
|
39
|
+
if (!ID_VALIDO.test(hilo))
|
|
40
|
+
return undefined;
|
|
41
|
+
return join(raiz, ".xonecode", "sesiones", hilo, "memoria-trueforge.json");
|
|
42
|
+
}
|
|
43
|
+
/** El texto con que se salda una tool call que el turno no llegó a contestar. */
|
|
44
|
+
export const RESPUESTA_A_UNA_COLGADA = "No se completó: el turno se cortó antes (quedó sin aprobar, se canceló o se agotó el tope). " +
|
|
45
|
+
"Si sigue haciendo falta, vuelve a pedirlo.";
|
|
46
|
+
/**
|
|
47
|
+
* El contexto con las tool calls del ÚLTIMO mensaje del asistente que no tienen respuesta,
|
|
48
|
+
* saldadas. Solo el último: una anterior sin respuesta ya habría roto la conversación antes.
|
|
49
|
+
* Puro: no toca el contexto que recibe.
|
|
50
|
+
*/
|
|
51
|
+
export function saldarColgadas(context, excepto) {
|
|
52
|
+
const mensajes = context;
|
|
53
|
+
let ultimo = -1;
|
|
54
|
+
for (let i = mensajes.length - 1; i >= 0; i -= 1) {
|
|
55
|
+
const m = mensajes[i];
|
|
56
|
+
if (m?.role === "assistant" && (m.tool_calls?.length ?? 0) > 0) {
|
|
57
|
+
ultimo = i;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (ultimo === -1)
|
|
62
|
+
return [...context];
|
|
63
|
+
const pedidas = new Set((mensajes[ultimo].tool_calls ?? []).map((t) => t.id).filter((id) => typeof id === "string"));
|
|
64
|
+
for (const m of mensajes.slice(ultimo + 1))
|
|
65
|
+
if (m?.role === "tool" && m.tool_call_id !== undefined)
|
|
66
|
+
pedidas.delete(m.tool_call_id);
|
|
67
|
+
// La que espera la respuesta de la persona no está colgada: está esperando, y saldarla la mataría.
|
|
68
|
+
if (excepto !== undefined)
|
|
69
|
+
pedidas.delete(excepto);
|
|
70
|
+
return [...context, ...[...pedidas].map((id) => ({ role: "tool", tool_call_id: id, content: RESPUESTA_A_UNA_COLGADA }))];
|
|
71
|
+
}
|
|
72
|
+
/** La foto lista para guardar o para rehacer el hilo: con las colgadas saldadas. */
|
|
73
|
+
export function fotoSaneada(foto) {
|
|
74
|
+
const pregunta = foto.pregunta_pendiente;
|
|
75
|
+
return { ...foto, context: saldarColgadas(foto.context, pregunta?.id) };
|
|
76
|
+
}
|
|
77
|
+
// ── La versión del FORMATO, y cómo se llega a ella ────────────────────────────────────────────
|
|
78
|
+
/**
|
|
79
|
+
* La versión del formato de la foto en disco. Sube cuando cambia lo que se escribe, y cada subida
|
|
80
|
+
* trae su entrada en `MIGRACIONES`: una foto de antes se MIGRA al leerla, nunca se descarta por
|
|
81
|
+
* vieja. Es NUESTRA, no la de la librería: la de la librería va aparte, en `trueforge`.
|
|
82
|
+
*
|
|
83
|
+
* El formato v1, entero —y nada más, que es lo que hace estricta la lectura—:
|
|
84
|
+
*
|
|
85
|
+
* ```json
|
|
86
|
+
* { "version": 1, "trueforge": "0.2.1", "context": [...],
|
|
87
|
+
* "current_context_usage": {...}, "capability_state": {...} | null,
|
|
88
|
+
* "pregunta_pendiente": { "hilo": "...", "id": "...", "args": {...}, "encargo"?: "..." } }
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* Solo `version` y `context` son obligatorios. `trueforge` es la versión de la librería que
|
|
92
|
+
* escribió el `toSnapshot()`: se APUNTA, no se exige —rechazar por ella tiraría todas las
|
|
93
|
+
* conversaciones en cada subida de la librería—, y está para que una migración futura sepa de
|
|
94
|
+
* dónde parte. Falta en una foto MIGRADA desde v0, porque no se inventa lo que no consta; el
|
|
95
|
+
* guardado siguiente la sella.
|
|
96
|
+
*/
|
|
97
|
+
export const VERSION_DE_MEMORIA = 1;
|
|
98
|
+
/**
|
|
99
|
+
* De cada versión a la SIGUIENTE: devuelve la foto migrada o el MOTIVO por el que no se puede.
|
|
100
|
+
* Puras, y se encadenan (`interpretarFoto`), así que una foto de hace tres versiones pasa por
|
|
101
|
+
* las tres. Una migración no valida el resultado final: eso lo hace UNA vez `validarV1`.
|
|
102
|
+
*/
|
|
103
|
+
export const MIGRACIONES = {
|
|
104
|
+
/**
|
|
105
|
+
* v0 → v1. La v0 es la foto de antes de versionar: `toSnapshot()` del raíz tal cual, más
|
|
106
|
+
* `pregunta_pendiente`. Traía cuatro campos que el constructor del raíz no recibe de vuelta
|
|
107
|
+
* (`thread_id`, `parent`, `agent_info`, `completion`) y aquí se retiran — pero solo con el valor
|
|
108
|
+
* que tiene un RAÍZ: un `parent` o una `completion` puestos serían la foto de un hijo, y
|
|
109
|
+
* retirarlos en silencio sería cargarla a medias.
|
|
110
|
+
*/
|
|
111
|
+
0: (foto) => {
|
|
112
|
+
const { thread_id, parent, agent_info, completion, ...resto } = foto;
|
|
113
|
+
if (thread_id !== undefined && typeof thread_id !== "string")
|
|
114
|
+
return "la foto sin versión trae un `thread_id` que no es texto";
|
|
115
|
+
for (const [campo, valor] of [
|
|
116
|
+
["parent", parent],
|
|
117
|
+
["agent_info", agent_info],
|
|
118
|
+
["completion", completion],
|
|
119
|
+
]) {
|
|
120
|
+
if (valor !== undefined && valor !== null)
|
|
121
|
+
return `la foto sin versión trae \`${campo}\`: no es la de un hilo raíz`;
|
|
122
|
+
}
|
|
123
|
+
return { ...resto, version: 1 };
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
const esObjeto = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
127
|
+
/** Un nombre de campo que sale del FICHERO, recortado: el motivo viaja a la pantalla. */
|
|
128
|
+
const nombreDeCampo = (k) => (k.length > 40 ? `${k.slice(0, 40)}…` : k);
|
|
129
|
+
const CAMPOS_V1 = new Set(["version", "trueforge", "context", "current_context_usage", "capability_state", "pregunta_pendiente"]);
|
|
130
|
+
/**
|
|
131
|
+
* La foto v1, comprobada campo a campo, o el motivo. **Un campo que no se conoce es un NO**, no
|
|
132
|
+
* un campo que se ignora: la v1 la escribe `guardarMemoria` con una lista cerrada, así que uno de
|
|
133
|
+
* más significa que no la escribió este código. Y **un campo conocido y mal formado se lleva la
|
|
134
|
+
* foto ENTERA**: soltar solo la pregunta pendiente, por ejemplo, dejaría una conversación que
|
|
135
|
+
* espera una respuesta que ya nadie sabe a qué va.
|
|
136
|
+
*
|
|
137
|
+
* **Límite declarado**: de cada mensaje del contexto se mira que sea un objeto con `role` o `type`
|
|
138
|
+
* de texto, y no más. Su esquema entero es de la librería (zod, dentro de ella), y repetirlo aquí
|
|
139
|
+
* sería un segundo sitio donde decidir qué es un mensaje.
|
|
140
|
+
*/
|
|
141
|
+
function validarV1(foto) {
|
|
142
|
+
for (const k of Object.keys(foto))
|
|
143
|
+
if (!CAMPOS_V1.has(k))
|
|
144
|
+
return `campo desconocido «${nombreDeCampo(k)}»`;
|
|
145
|
+
if (foto.version !== 1)
|
|
146
|
+
return "la migración no dejó la versión 1";
|
|
147
|
+
if (foto.trueforge !== undefined && typeof foto.trueforge !== "string")
|
|
148
|
+
return "`trueforge` no es texto";
|
|
149
|
+
const { context, current_context_usage, capability_state, pregunta_pendiente } = foto;
|
|
150
|
+
if (!Array.isArray(context))
|
|
151
|
+
return "falta el contexto, o no es una lista";
|
|
152
|
+
const roto = context.findIndex((m) => !esObjeto(m) || (typeof m.role !== "string" && typeof m.type !== "string"));
|
|
153
|
+
if (roto !== -1)
|
|
154
|
+
return `el mensaje ${roto} del contexto no tiene forma de mensaje`;
|
|
155
|
+
if (current_context_usage !== undefined && !esObjeto(current_context_usage))
|
|
156
|
+
return "`current_context_usage` no es un objeto";
|
|
157
|
+
if (capability_state !== undefined && capability_state !== null && !esObjeto(capability_state))
|
|
158
|
+
return "`capability_state` no es un objeto";
|
|
159
|
+
let pregunta;
|
|
160
|
+
if (pregunta_pendiente !== undefined) {
|
|
161
|
+
const p = pregunta_pendiente;
|
|
162
|
+
if (!esObjeto(p) ||
|
|
163
|
+
typeof p.hilo !== "string" ||
|
|
164
|
+
typeof p.id !== "string" ||
|
|
165
|
+
!esObjeto(p.args) ||
|
|
166
|
+
(p.encargo !== undefined && typeof p.encargo !== "string") ||
|
|
167
|
+
Object.keys(p).some((k) => k !== "hilo" && k !== "id" && k !== "args" && k !== "encargo")) {
|
|
168
|
+
return "la pregunta pendiente está mal formada";
|
|
169
|
+
}
|
|
170
|
+
pregunta = { hilo: p.hilo, id: p.id, args: p.args, ...(typeof p.encargo === "string" ? { encargo: p.encargo } : {}) };
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
context,
|
|
174
|
+
...(current_context_usage === undefined ? {} : { current_context_usage }),
|
|
175
|
+
...(capability_state === undefined ? {} : { capability_state: capability_state }),
|
|
176
|
+
...(pregunta === undefined ? {} : { pregunta_pendiente: pregunta }),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* El TEXTO de una foto, entendido: migrado hasta la versión actual y validado, o el motivo por el
|
|
181
|
+
* que no. Pura, y es toda la regla de la lectura. El motivo nunca repite el contenido —un error de
|
|
182
|
+
* `JSON.parse` cita un trozo del fichero, que lleva mensajes enteros— ni ninguna ruta.
|
|
183
|
+
*/
|
|
184
|
+
export function interpretarFoto(texto) {
|
|
185
|
+
let crudo;
|
|
186
|
+
try {
|
|
187
|
+
crudo = JSON.parse(texto);
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
return { estado: "incompatible", motivo: "no es JSON válido" };
|
|
191
|
+
}
|
|
192
|
+
if (!esObjeto(crudo))
|
|
193
|
+
return { estado: "incompatible", motivo: "no es un objeto JSON" };
|
|
194
|
+
// Ausente es v0; `null` NO: no lo escribe nadie, y leerlo como v0 sería adivinar.
|
|
195
|
+
const v = crudo.version === undefined ? 0 : crudo.version;
|
|
196
|
+
if (typeof v !== "number" || !Number.isInteger(v) || v < 0)
|
|
197
|
+
return { estado: "incompatible", motivo: "la versión no es un entero" };
|
|
198
|
+
if (v > VERSION_DE_MEMORIA) {
|
|
199
|
+
return { estado: "incompatible", motivo: `la escribió un XOneCode más nuevo (versión ${v}; este lee hasta la ${VERSION_DE_MEMORIA})` };
|
|
200
|
+
}
|
|
201
|
+
let foto = crudo;
|
|
202
|
+
for (let desde = v; desde < VERSION_DE_MEMORIA; desde += 1) {
|
|
203
|
+
const migrar = MIGRACIONES[desde];
|
|
204
|
+
if (migrar === undefined)
|
|
205
|
+
return { estado: "incompatible", motivo: `no hay migración desde la versión ${desde}` };
|
|
206
|
+
const r = migrar(foto);
|
|
207
|
+
if (typeof r === "string")
|
|
208
|
+
return { estado: "incompatible", motivo: r };
|
|
209
|
+
foto = r;
|
|
210
|
+
}
|
|
211
|
+
const validada = validarV1(foto);
|
|
212
|
+
return typeof validada === "string" ? { estado: "incompatible", motivo: validada } : { estado: "ok", foto: validada };
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Escribe la foto, en el formato ACTUAL: la versión y la de la librería las SELLA aquí quien
|
|
216
|
+
* escribe, no quien llama, y los campos van por lista cerrada —lo que `toSnapshot()` traiga de más
|
|
217
|
+
* no llega a disco, y así la lectura estricta no rechaza lo que este mismo código escribió—.
|
|
218
|
+
* El fichero se CREA con 0600 antes de tener contenido y se reemplaza con `renameSync`, para que
|
|
219
|
+
* un corte a mitad no deje media conversación ni un JSON roto.
|
|
220
|
+
*/
|
|
221
|
+
export function guardarMemoria(raiz, hilo, foto) {
|
|
222
|
+
const ruta = rutaDeMemoria(raiz, hilo);
|
|
223
|
+
if (ruta === undefined)
|
|
224
|
+
return;
|
|
225
|
+
const saneada = fotoSaneada(foto);
|
|
226
|
+
const pregunta = saneada.pregunta_pendiente;
|
|
227
|
+
const enDisco = {
|
|
228
|
+
version: VERSION_DE_MEMORIA,
|
|
229
|
+
trueforge: VERSION_DE_TRUEFORGE,
|
|
230
|
+
context: saneada.context,
|
|
231
|
+
...(saneada.current_context_usage === undefined ? {} : { current_context_usage: saneada.current_context_usage }),
|
|
232
|
+
...(saneada.capability_state === undefined ? {} : { capability_state: saneada.capability_state }),
|
|
233
|
+
...(pregunta === undefined
|
|
234
|
+
? {}
|
|
235
|
+
: {
|
|
236
|
+
pregunta_pendiente: {
|
|
237
|
+
hilo: pregunta.hilo,
|
|
238
|
+
id: pregunta.id,
|
|
239
|
+
args: pregunta.args,
|
|
240
|
+
...(pregunta.encargo === undefined ? {} : { encargo: pregunta.encargo }),
|
|
241
|
+
},
|
|
242
|
+
}),
|
|
243
|
+
};
|
|
244
|
+
mkdirSync(dirname(ruta), { recursive: true });
|
|
245
|
+
const temporal = `${ruta}.${process.pid}.tmp`;
|
|
246
|
+
closeSync(openSync(temporal, "w", 0o600));
|
|
247
|
+
chmodSync(temporal, 0o600);
|
|
248
|
+
writeFileSync(temporal, JSON.stringify(enDisco), { mode: 0o600 });
|
|
249
|
+
renameSync(temporal, ruta);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* La memoria de la sesión, con su estado. No tener fichero es `sin-memoria`, no un fallo; uno que
|
|
253
|
+
* existe y no se puede leer es `incompatible` con el `code` de Node y nada más (su mensaje lleva
|
|
254
|
+
* la ruta absoluta). NO aparta ni borra nada: esto lo llama también quien solo PREGUNTA
|
|
255
|
+
* (`hayMemoria`, la web al reabrir), y preguntar no puede mover ficheros.
|
|
256
|
+
*/
|
|
257
|
+
export function cargarMemoria(raiz, hilo) {
|
|
258
|
+
const ruta = rutaDeMemoria(raiz, hilo);
|
|
259
|
+
if (ruta === undefined || !existsSync(ruta))
|
|
260
|
+
return { estado: "sin-memoria" };
|
|
261
|
+
let texto;
|
|
262
|
+
try {
|
|
263
|
+
texto = readFileSync(ruta, "utf8");
|
|
264
|
+
}
|
|
265
|
+
catch (e) {
|
|
266
|
+
const code = e.code;
|
|
267
|
+
return { estado: "incompatible", motivo: `no se pudo leer${typeof code === "string" ? ` (${code})` : ""}` };
|
|
268
|
+
}
|
|
269
|
+
return interpretarFoto(texto);
|
|
270
|
+
}
|
|
271
|
+
/** La foto guardada y entendida, o `undefined` si no hay o no se entiende (ver `cargarMemoria`). */
|
|
272
|
+
export function leerMemoria(raiz, hilo) {
|
|
273
|
+
const lectura = cargarMemoria(raiz, hilo);
|
|
274
|
+
return lectura.estado === "ok" ? lectura.foto : undefined;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* ¿Hay una conversación de TrueForge que continuar en esta sesión? Solo si la foto se ENTIENDE:
|
|
278
|
+
* una incompatible no se va a cargar, y decir que sí haría que la web presentara como continuada
|
|
279
|
+
* una sesión que empieza de cero.
|
|
280
|
+
*/
|
|
281
|
+
export function hayMemoria(raiz, hilo) {
|
|
282
|
+
return cargarMemoria(raiz, hilo).estado === "ok";
|
|
283
|
+
}
|
|
284
|
+
/** Cómo se llama una foto apartada: la de siempre, con la marca y la hora. */
|
|
285
|
+
const APARTADA = /^memoria-trueforge\.incompatible-\d+(?:-\d+)?\.json$/;
|
|
286
|
+
/**
|
|
287
|
+
* Aparta la foto que no se entiende, con otro nombre y en la MISMA carpeta, y devuelve ese nombre
|
|
288
|
+
* (solo el nombre: viaja a la pantalla). Apartar y no borrar, porque no la entendemos y puede que
|
|
289
|
+
* un XOneCode más nuevo sí; y apartar y no dejarla, porque el guardado del primer turno la pisaría.
|
|
290
|
+
* Un nombre que ya existe nunca se pisa. Si no se puede, devuelve `undefined` y quien llama lo
|
|
291
|
+
* DICE: la foto se queda donde estaba y el siguiente guardado la sustituirá.
|
|
292
|
+
*/
|
|
293
|
+
export function apartarMemoria(raiz, hilo, ahora = Date.now()) {
|
|
294
|
+
const ruta = rutaDeMemoria(raiz, hilo);
|
|
295
|
+
if (ruta === undefined || !existsSync(ruta))
|
|
296
|
+
return undefined;
|
|
297
|
+
try {
|
|
298
|
+
let nombre = `memoria-trueforge.incompatible-${ahora}.json`;
|
|
299
|
+
for (let n = 1; existsSync(join(dirname(ruta), nombre)); n += 1)
|
|
300
|
+
nombre = `memoria-trueforge.incompatible-${ahora}-${n}.json`;
|
|
301
|
+
renameSync(ruta, join(dirname(ruta), nombre));
|
|
302
|
+
return basename(nombre);
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
return undefined;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* El aviso de una memoria que no se cargó, con el motivo y con lo que se hizo con la foto. Se
|
|
310
|
+
* emite UNA vez, en el primer turno: es cuando importa, porque es el turno en que el modelo no
|
|
311
|
+
* recuerda lo que la pantalla enseña. Solo con una foto que EXISTÍA: sin foto no ha pasado nada.
|
|
312
|
+
*/
|
|
313
|
+
export function textoDeMemoriaDescartada(motivo, apartada) {
|
|
314
|
+
return (`⚠ la memoria guardada de esta sesión no se pudo cargar (${motivo}): este turno empieza sin la conversación anterior. ` +
|
|
315
|
+
(apartada === undefined
|
|
316
|
+
? "No se pudo apartar la foto, y el próximo guardado la sustituirá."
|
|
317
|
+
: `La foto no se ha borrado: queda apartada como «${apartada}» en la carpeta de la sesión.`));
|
|
318
|
+
}
|
|
319
|
+
/** Borra la memoria de la sesión, las fotos apartadas incluidas: lo llama el borrado de una sesión. */
|
|
320
|
+
export function olvidarMemoria(raiz, hilo) {
|
|
321
|
+
const ruta = rutaDeMemoria(raiz, hilo);
|
|
322
|
+
if (ruta === undefined)
|
|
323
|
+
return;
|
|
324
|
+
rmSync(ruta, { force: true });
|
|
325
|
+
let nombres = [];
|
|
326
|
+
try {
|
|
327
|
+
nombres = readdirSync(dirname(ruta));
|
|
328
|
+
}
|
|
329
|
+
catch {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
for (const n of nombres)
|
|
333
|
+
if (APARTADA.test(n))
|
|
334
|
+
rmSync(join(dirname(ruta), n), { force: true });
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=memoriaTrueforge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoriaTrueforge.js","sourceRoot":"","sources":["../../../../src/agent/motores/trueforge/memoriaTrueforge.ts"],"names":[],"mappings":"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"}
|