mcp-phase-gate 2.0.1 → 2.2.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/README.es.md +146 -59
- package/README.md +130 -52
- package/build/cli.d.ts +14 -0
- package/build/cli.js +98 -0
- package/build/config.d.ts +27 -2
- package/build/config.js +151 -22
- package/build/confirmacion.d.ts +15 -0
- package/build/confirmacion.js +100 -0
- package/build/diagnostico.d.ts +83 -0
- package/build/diagnostico.js +394 -0
- package/build/index.js +28 -365
- package/build/log.d.ts +6 -0
- package/build/log.js +27 -0
- package/build/paths.d.ts +9 -0
- package/build/paths.js +71 -8
- package/build/phases.d.ts +13 -1
- package/build/phases.js +125 -17
- package/build/prompts-mcp.d.ts +33 -0
- package/build/prompts-mcp.js +194 -0
- package/build/recursos.d.ts +8 -0
- package/build/recursos.js +306 -0
- package/build/schemas.d.ts +106 -50
- package/build/schemas.js +151 -75
- package/build/servidor.d.ts +3 -0
- package/build/servidor.js +372 -0
- package/build/tasks.d.ts +8 -2
- package/build/tasks.js +218 -24
- package/package.json +1 -2
- package/prompts/comandos/f1.md +14 -0
- package/prompts/comandos/f2.md +12 -0
- package/prompts/comandos/f3.md +9 -0
- package/prompts/comandos/f4.md +10 -0
- package/prompts/comandos/f5.md +12 -0
- package/prompts/fase-1-descubrimiento.md +22 -6
- package/prompts/fase-2-decisiones.md +34 -5
- package/prompts/fase-3-plan-tecnico.md +77 -22
- package/prompts/fase-4-ejecucion.md +168 -34
- package/prompts/fase-5-auditoria-pr.md +24 -1
- package/prompts/global-rules.md +30 -1
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// Los documentos de las tareas, expuestos como MCP Resources de solo lectura. Un cliente que los
|
|
2
|
+
// muestra (con "@" en Claude Code, Cursor o VS Code) deja a la persona adjuntar al chat el plan
|
|
3
|
+
// técnico o un recibo sin pedírselo al modelo, y al modelo leerlos sin gastar una llamada a
|
|
4
|
+
// read_central_doc.
|
|
5
|
+
//
|
|
6
|
+
// phase-gate://estado el diagnóstico de la instalación
|
|
7
|
+
// phase-gate://fases las fases, con su documento y su capa
|
|
8
|
+
// phase-gate://tareas/{proyecto}/{tarea}/{documento} un archivo de la carpeta de una tarea
|
|
9
|
+
// phase-gate://tareas/{proyecto}/{tarea}/recibos/{recibo} un recibo de lote de la Fase 4
|
|
10
|
+
//
|
|
11
|
+
// Solo lectura, y con las mismas defensas que read_central_doc: cada variable se decodifica y se
|
|
12
|
+
// valida como un segmento portable antes de armar ninguna ruta, la ruta final tiene que quedar
|
|
13
|
+
// dentro de la carpeta de la tarea, y la lectura está acotada a 1 MB de texto.
|
|
14
|
+
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
+
import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
16
|
+
import * as fs from "fs";
|
|
17
|
+
import * as path from "path";
|
|
18
|
+
import { diagnosticar, fasesConCapa, formatearDiagnostico } from "./diagnostico.js";
|
|
19
|
+
import { discoverProjects, estaDentroReal, findProjectFolder, leerTextoAcotado, requireProjectFolder, taskFolderPath, validarSegmento, } from "./paths.js";
|
|
20
|
+
import { discoverPhases, esCarpeta, nombreContextoInicial } from "./phases.js";
|
|
21
|
+
import { listarTareas, tareaActiva } from "./tasks.js";
|
|
22
|
+
export const URI_ESTADO = "phase-gate://estado";
|
|
23
|
+
export const URI_FASES = "phase-gate://fases";
|
|
24
|
+
const MIME = "text/markdown";
|
|
25
|
+
const AUDIENCIA = ["assistant", "user"];
|
|
26
|
+
export function uriDeDocumento(proyecto, tarea, documento) {
|
|
27
|
+
return `phase-gate://tareas/${encodeURIComponent(proyecto)}/${encodeURIComponent(tarea)}/${encodeURIComponent(documento)}`;
|
|
28
|
+
}
|
|
29
|
+
export function uriDeRecibo(proyecto, tarea, recibo) {
|
|
30
|
+
return `phase-gate://tareas/${encodeURIComponent(proyecto)}/${encodeURIComponent(tarea)}/recibos/${encodeURIComponent(recibo)}`;
|
|
31
|
+
}
|
|
32
|
+
// La subcarpeta de recibos la declara una fase en su cabecera (con los prompts de fábrica, la 4).
|
|
33
|
+
function subcarpetaDeRecibos(phases) {
|
|
34
|
+
const conRecibos = [...phases.entries()].sort((a, b) => a[0] - b[0]).find(([, datos]) => datos.recibos);
|
|
35
|
+
return conRecibos?.[1].recibos ?? null;
|
|
36
|
+
}
|
|
37
|
+
// statSync con throwIfNoEntry solo calla el ENOENT; un tramo de la ruta que es un archivo
|
|
38
|
+
// (ENOTDIR) o un permiso denegado no son un error para preguntar "¿es un archivo?".
|
|
39
|
+
function esArchivo(ruta) {
|
|
40
|
+
try {
|
|
41
|
+
return fs.statSync(ruta, { throwIfNoEntry: false })?.isFile() ?? false;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Lo que se lista o se autocompleta pasa por la misma contención que la lectura: un enlace dentro
|
|
48
|
+
// de la tarea que lleva fuera de ella no se lee, y tampoco se enseña su nombre ni su fecha.
|
|
49
|
+
function dentroDeLaTarea(carpetaTarea, ruta) {
|
|
50
|
+
try {
|
|
51
|
+
return estaDentroReal(carpetaTarea, ruta);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Los errores de lectura llegan al cliente con un código que dice qué pasó, no como un error
|
|
58
|
+
// interno: -32002 si el recurso no existe (el que propone la especificación de MCP), -32602 si el
|
|
59
|
+
// URI o lo que apunta no es válido, y -32603 solo para un fallo de E/S inesperado.
|
|
60
|
+
const RECURSO_NO_ENCONTRADO = -32002;
|
|
61
|
+
function conCodigo(leerRecurso) {
|
|
62
|
+
try {
|
|
63
|
+
return leerRecurso();
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (error instanceof McpError)
|
|
67
|
+
throw error;
|
|
68
|
+
const mensaje = error instanceof Error ? error.message : String(error);
|
|
69
|
+
if (/^No existe/.test(mensaje))
|
|
70
|
+
throw new McpError(RECURSO_NO_ENCONTRADO, mensaje);
|
|
71
|
+
if (typeof error?.code === "string")
|
|
72
|
+
throw new McpError(ErrorCode.InternalError, mensaje);
|
|
73
|
+
throw new McpError(ErrorCode.InvalidParams, mensaje);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// El SDK entrega las variables tal como venían en el URI, con su codificación porcentual. Se
|
|
77
|
+
// decodifican aquí y se validan DESPUÉS: un %2F decodificado a "/" lo rechaza validarSegmento.
|
|
78
|
+
function variable(variables, nombre) {
|
|
79
|
+
const crudo = variables[nombre];
|
|
80
|
+
const valor = Array.isArray(crudo) ? crudo.join(",") : String(crudo ?? "");
|
|
81
|
+
try {
|
|
82
|
+
return decodeURIComponent(valor);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
throw new Error(`URI mal codificada: la parte "${nombre}" (${valor}) no es una codificación porcentual válida.`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Ruta de un archivo dentro de una tarea, a partir de las variables ya decodificadas. Las carpetas
|
|
89
|
+
// y archivos con punto no son tareas ni documentos, igual que para write_central_doc.
|
|
90
|
+
function archivoDeTarea(proyecto, tarea, partes) {
|
|
91
|
+
validarSegmento(proyecto, "proyecto");
|
|
92
|
+
validarSegmento(tarea, "tarea");
|
|
93
|
+
for (const parte of partes)
|
|
94
|
+
validarSegmento(parte, "documento");
|
|
95
|
+
if (tarea.startsWith(".") || partes.some((parte) => parte.startsWith("."))) {
|
|
96
|
+
throw new Error("Los archivos y carpetas que empiezan por punto no se exponen como recursos.");
|
|
97
|
+
}
|
|
98
|
+
const carpetaProyecto = requireProjectFolder(proyecto);
|
|
99
|
+
const carpetaTarea = taskFolderPath(carpetaProyecto, tarea);
|
|
100
|
+
if (!esCarpeta(carpetaTarea)) {
|
|
101
|
+
throw new Error(`No existe la tarea "${tarea}" en ${carpetaProyecto}.`);
|
|
102
|
+
}
|
|
103
|
+
const ruta = path.join(carpetaTarea, ...partes);
|
|
104
|
+
if (!estaDentroReal(carpetaTarea, ruta)) {
|
|
105
|
+
throw new Error(`Acceso denegado: el recurso queda fuera de la carpeta de la tarea ${carpetaTarea}.`);
|
|
106
|
+
}
|
|
107
|
+
if (!esArchivo(ruta)) {
|
|
108
|
+
throw new Error(`No existe "${partes.join("/")}" en la tarea "${tarea}" de ${carpetaProyecto}.`);
|
|
109
|
+
}
|
|
110
|
+
return { ruta, tarea: carpetaTarea };
|
|
111
|
+
}
|
|
112
|
+
function leer(uri, ruta) {
|
|
113
|
+
return { contents: [{ uri: uri.href, mimeType: MIME, text: leerTextoAcotado(ruta) }] };
|
|
114
|
+
}
|
|
115
|
+
function recurso(uri, nombre, titulo, ruta) {
|
|
116
|
+
let modificado;
|
|
117
|
+
try {
|
|
118
|
+
modificado = fs.statSync(ruta).mtime.toISOString();
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
modificado = undefined;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
uri,
|
|
125
|
+
name: nombre,
|
|
126
|
+
title: titulo,
|
|
127
|
+
mimeType: MIME,
|
|
128
|
+
annotations: { audience: AUDIENCIA, ...(modificado ? { lastModified: modificado } : {}) },
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// ─── Listado ────────────────────────────────────────────────────────────────
|
|
132
|
+
// Solo los documentos que existen de la tarea ACTIVA de cada proyecto. Listar todas las tareas de
|
|
133
|
+
// todos los proyectos inundaría el selector de "@" del cliente; el resto se alcanza por plantilla,
|
|
134
|
+
// con autocompletado. Si la Documentación no está configurada no hay nada que listar, y el listado
|
|
135
|
+
// no debe fallar por eso: los recursos fijos siguen sirviendo para diagnosticarlo.
|
|
136
|
+
function tareasActivas() {
|
|
137
|
+
try {
|
|
138
|
+
const phases = discoverPhases();
|
|
139
|
+
return [...discoverProjects().values()].sort().flatMap((proyecto) => {
|
|
140
|
+
const activa = tareaActiva(proyecto, phases);
|
|
141
|
+
return activa ? [{ proyecto, tarea: activa.estado.taskName, carpeta: activa.estado.folderPath, phases }] : [];
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function listarDocumentos() {
|
|
149
|
+
const lista = [];
|
|
150
|
+
for (const { proyecto, tarea, carpeta, phases } of tareasActivas()) {
|
|
151
|
+
const nombres = [
|
|
152
|
+
nombreContextoInicial(),
|
|
153
|
+
...[...phases.entries()].sort((a, b) => a[0] - b[0]).flatMap(([, datos]) => (datos.documento ? [datos.documento] : [])),
|
|
154
|
+
];
|
|
155
|
+
for (const documento of nombres) {
|
|
156
|
+
const ruta = path.join(carpeta, documento);
|
|
157
|
+
if (!esArchivo(ruta) || !dentroDeLaTarea(carpeta, ruta))
|
|
158
|
+
continue;
|
|
159
|
+
lista.push(recurso(uriDeDocumento(proyecto, tarea, documento), `${proyecto}/${tarea}/${documento}`, `${tarea} · ${documento}`, ruta));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return lista;
|
|
163
|
+
}
|
|
164
|
+
function recibosDe(carpetaTarea, phases) {
|
|
165
|
+
const subcarpeta = subcarpetaDeRecibos(phases);
|
|
166
|
+
if (!subcarpeta)
|
|
167
|
+
return [];
|
|
168
|
+
const carpeta = path.join(carpetaTarea, subcarpeta);
|
|
169
|
+
if (!esCarpeta(carpeta) || !dentroDeLaTarea(carpetaTarea, carpeta))
|
|
170
|
+
return [];
|
|
171
|
+
return fs
|
|
172
|
+
.readdirSync(carpeta, { withFileTypes: true })
|
|
173
|
+
.filter((entrada) => entrada.isFile() && entrada.name.toLowerCase().endsWith(".md") && !entrada.name.startsWith("."))
|
|
174
|
+
.map((entrada) => entrada.name)
|
|
175
|
+
.filter((nombre) => dentroDeLaTarea(carpetaTarea, path.join(carpeta, nombre)))
|
|
176
|
+
.sort();
|
|
177
|
+
}
|
|
178
|
+
function listarRecibos() {
|
|
179
|
+
const lista = [];
|
|
180
|
+
for (const { proyecto, tarea, carpeta, phases } of tareasActivas()) {
|
|
181
|
+
const subcarpeta = subcarpetaDeRecibos(phases);
|
|
182
|
+
for (const recibo of recibosDe(carpeta, phases)) {
|
|
183
|
+
lista.push(recurso(uriDeRecibo(proyecto, tarea, recibo), `${proyecto}/${tarea}/${subcarpeta}/${recibo}`, `${tarea} · ${recibo}`, path.join(carpeta, subcarpeta, recibo)));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return lista;
|
|
187
|
+
}
|
|
188
|
+
// ─── Autocompletado ─────────────────────────────────────────────────────────
|
|
189
|
+
// Lo que ya se escribió filtra la lista, sin distinguir mayúsculas. Un fallo (Documentación sin
|
|
190
|
+
// configurar, proyecto que no existe) devuelve una lista vacía: autocompletar no es el sitio
|
|
191
|
+
// para explicar errores, eso lo hace la lectura.
|
|
192
|
+
function filtrar(valores, escrito) {
|
|
193
|
+
const prefijo = escrito.toLowerCase();
|
|
194
|
+
return valores.filter((valor) => valor.toLowerCase().startsWith(prefijo));
|
|
195
|
+
}
|
|
196
|
+
function sinFallar(calcular) {
|
|
197
|
+
try {
|
|
198
|
+
return calcular();
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function completarProyecto(escrito) {
|
|
205
|
+
return sinFallar(() => filtrar([...discoverProjects().values()].sort(), escrito));
|
|
206
|
+
}
|
|
207
|
+
function completarTarea(escrito, contexto) {
|
|
208
|
+
return sinFallar(() => {
|
|
209
|
+
const proyecto = findProjectFolder(contexto?.arguments?.proyecto ?? "");
|
|
210
|
+
if (!proyecto)
|
|
211
|
+
return [];
|
|
212
|
+
return filtrar(listarTareas(proyecto, discoverPhases()).map((tarea) => tarea.taskName), escrito);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function carpetaDeTareaPedida(contexto) {
|
|
216
|
+
const proyecto = findProjectFolder(contexto?.arguments?.proyecto ?? "");
|
|
217
|
+
const tarea = contexto?.arguments?.tarea ?? "";
|
|
218
|
+
if (!proyecto || !tarea || tarea.startsWith("."))
|
|
219
|
+
return null;
|
|
220
|
+
validarSegmento(tarea, "tarea");
|
|
221
|
+
const carpeta = taskFolderPath(proyecto, tarea);
|
|
222
|
+
return esCarpeta(carpeta) ? carpeta : null;
|
|
223
|
+
}
|
|
224
|
+
function completarDocumento(escrito, contexto) {
|
|
225
|
+
return sinFallar(() => {
|
|
226
|
+
const carpeta = carpetaDeTareaPedida(contexto);
|
|
227
|
+
if (!carpeta)
|
|
228
|
+
return [];
|
|
229
|
+
const documentos = fs
|
|
230
|
+
.readdirSync(carpeta, { withFileTypes: true })
|
|
231
|
+
.filter((entrada) => entrada.isFile() && entrada.name.toLowerCase().endsWith(".md") && !entrada.name.startsWith("."))
|
|
232
|
+
.map((entrada) => entrada.name)
|
|
233
|
+
.filter((nombre) => dentroDeLaTarea(carpeta, path.join(carpeta, nombre)))
|
|
234
|
+
.sort();
|
|
235
|
+
return filtrar(documentos, escrito);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
function completarRecibo(escrito, contexto) {
|
|
239
|
+
return sinFallar(() => {
|
|
240
|
+
const carpeta = carpetaDeTareaPedida(contexto);
|
|
241
|
+
return carpeta ? filtrar(recibosDe(carpeta, discoverPhases()), escrito) : [];
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
// ─── La tabla de fases ──────────────────────────────────────────────────────
|
|
245
|
+
function celda(texto) {
|
|
246
|
+
return texto.replace(/\r?\n/g, " ").replace(/\|/g, "\\|");
|
|
247
|
+
}
|
|
248
|
+
export function tablaDeFases() {
|
|
249
|
+
const fases = fasesConCapa();
|
|
250
|
+
if (fases.length === 0)
|
|
251
|
+
return "No se encontró ningún prompt de fase.";
|
|
252
|
+
return [
|
|
253
|
+
"| Fase | Título | Documento | Recibos | Capa | Archivo |",
|
|
254
|
+
"|---|---|---|---|---|---|",
|
|
255
|
+
...fases.map((fase) => `| ${fase.numero} | ${celda(fase.titulo)} | ${fase.documento ? `\`${celda(fase.documento)}\`` : "—"} | ` +
|
|
256
|
+
`${fase.recibos ? `\`${celda(fase.recibos)}/\`` : "—"} | ${fase.capa} | \`${celda(fase.archivo)}\` |`),
|
|
257
|
+
].join("\n");
|
|
258
|
+
}
|
|
259
|
+
// ─── Registro ───────────────────────────────────────────────────────────────
|
|
260
|
+
export function registrarRecursos(mcp) {
|
|
261
|
+
mcp.registerResource("estado", URI_ESTADO, {
|
|
262
|
+
title: "Estado de mcp-phase-gate",
|
|
263
|
+
description: "Radiografía de la instalación: variables, prompts, proyectos con su tarea activa y avisos.",
|
|
264
|
+
mimeType: MIME,
|
|
265
|
+
annotations: { audience: AUDIENCIA },
|
|
266
|
+
}, async (uri) => ({ contents: [{ uri: uri.href, mimeType: MIME, text: formatearDiagnostico(diagnosticar(), "markdown") }] }));
|
|
267
|
+
mcp.registerResource("fases", URI_FASES, {
|
|
268
|
+
title: "Fases disponibles",
|
|
269
|
+
description: "Número, título, documento, subcarpeta de recibos y archivo de prompt que gana en cada fase.",
|
|
270
|
+
mimeType: MIME,
|
|
271
|
+
annotations: { audience: AUDIENCIA },
|
|
272
|
+
}, async (uri) => ({ contents: [{ uri: uri.href, mimeType: MIME, text: tablaDeFases() }] }));
|
|
273
|
+
// El de recibos va antes que el de documentos: los dos empiezan igual, y el SDK usa la primera
|
|
274
|
+
// plantilla que encaja. Con variables que no cruzan "/" no se pisan, pero el orden lo deja claro.
|
|
275
|
+
mcp.registerResource("recibo", new ResourceTemplate("phase-gate://tareas/{proyecto}/{tarea}/recibos/{recibo}", {
|
|
276
|
+
list: async () => ({ resources: listarRecibos() }),
|
|
277
|
+
complete: { proyecto: completarProyecto, tarea: completarTarea, recibo: completarRecibo },
|
|
278
|
+
}), {
|
|
279
|
+
title: "Recibo de lote",
|
|
280
|
+
description: "Un recibo de lote de la Fase 4, en la subcarpeta que declara su prompt.",
|
|
281
|
+
mimeType: MIME,
|
|
282
|
+
}, async (uri, variables) => conCodigo(() => {
|
|
283
|
+
const subcarpeta = subcarpetaDeRecibos(discoverPhases());
|
|
284
|
+
if (!subcarpeta)
|
|
285
|
+
throw new Error("No existe ninguna fase que declare una subcarpeta de recibos.");
|
|
286
|
+
const { ruta } = archivoDeTarea(variable(variables, "proyecto"), variable(variables, "tarea"), [
|
|
287
|
+
subcarpeta,
|
|
288
|
+
variable(variables, "recibo"),
|
|
289
|
+
]);
|
|
290
|
+
return leer(uri, ruta);
|
|
291
|
+
}));
|
|
292
|
+
mcp.registerResource("documento", new ResourceTemplate("phase-gate://tareas/{proyecto}/{tarea}/{documento}", {
|
|
293
|
+
list: async () => ({ resources: listarDocumentos() }),
|
|
294
|
+
complete: { proyecto: completarProyecto, tarea: completarTarea, documento: completarDocumento },
|
|
295
|
+
}), {
|
|
296
|
+
title: "Documento de una tarea",
|
|
297
|
+
description: "Un archivo de la carpeta de una tarea: el contexto inicial o el documento de una fase.",
|
|
298
|
+
mimeType: MIME,
|
|
299
|
+
}, async (uri, variables) => conCodigo(() => {
|
|
300
|
+
const { ruta } = archivoDeTarea(variable(variables, "proyecto"), variable(variables, "tarea"), [
|
|
301
|
+
variable(variables, "documento"),
|
|
302
|
+
]);
|
|
303
|
+
return leer(uri, ruta);
|
|
304
|
+
}));
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=recursos.js.map
|
package/build/schemas.d.ts
CHANGED
|
@@ -27,66 +27,122 @@ export declare const readCentralDocShape: {
|
|
|
27
27
|
file_path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
28
28
|
};
|
|
29
29
|
export declare const writeCentralDocShape: {
|
|
30
|
+
file_path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
30
31
|
content: z.ZodString;
|
|
32
|
+
force: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
31
33
|
project: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
32
34
|
task_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
33
35
|
file_name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
34
|
-
file_path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
35
36
|
};
|
|
36
37
|
export declare const readCrossRepoShape: {
|
|
37
38
|
repo_name: z.ZodString;
|
|
38
39
|
file_path: z.ZodString;
|
|
39
40
|
};
|
|
40
|
-
declare const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
41
|
+
export declare const getOrchestratorStatusShape: {};
|
|
42
|
+
export declare const diagnosticoShape: {
|
|
43
|
+
paquete: z.ZodObject<{
|
|
44
|
+
version: z.ZodString;
|
|
45
|
+
ruta: z.ZodString;
|
|
46
|
+
via: z.ZodEnum<{
|
|
47
|
+
npx: "npx";
|
|
48
|
+
global: "global";
|
|
49
|
+
dependencia: "dependencia";
|
|
50
|
+
clon: "clon";
|
|
51
|
+
}>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
node: z.ZodObject<{
|
|
54
|
+
version: z.ZodString;
|
|
55
|
+
plataforma: z.ZodString;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
variables: z.ZodArray<z.ZodObject<{
|
|
58
|
+
logica: z.ZodEnum<{
|
|
59
|
+
DOCS_PATH: "DOCS_PATH";
|
|
60
|
+
REPOS_PATH: "REPOS_PATH";
|
|
61
|
+
TASKS_SUBDIR: "TASKS_SUBDIR";
|
|
62
|
+
PROMPTS_PATH: "PROMPTS_PATH";
|
|
63
|
+
STATE_PATH: "STATE_PATH";
|
|
64
|
+
ELICITATION: "ELICITATION";
|
|
65
|
+
}>;
|
|
66
|
+
valor: z.ZodOptional<z.ZodString>;
|
|
67
|
+
usada: z.ZodNullable<z.ZodString>;
|
|
68
|
+
fuente: z.ZodEnum<{
|
|
69
|
+
".env": ".env";
|
|
70
|
+
entorno: "entorno";
|
|
71
|
+
"sin definir": "sin definir";
|
|
72
|
+
}>;
|
|
73
|
+
discrepancia: z.ZodNullable<z.ZodString>;
|
|
74
|
+
}, z.core.$strip>>;
|
|
75
|
+
rutas: z.ZodObject<{
|
|
76
|
+
docs: z.ZodObject<{
|
|
77
|
+
ruta: z.ZodOptional<z.ZodString>;
|
|
78
|
+
existe: z.ZodBoolean;
|
|
79
|
+
error: z.ZodOptional<z.ZodString>;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
repos: z.ZodObject<{
|
|
82
|
+
ruta: z.ZodOptional<z.ZodString>;
|
|
83
|
+
existe: z.ZodBoolean;
|
|
84
|
+
error: z.ZodOptional<z.ZodString>;
|
|
85
|
+
}, z.core.$strip>;
|
|
86
|
+
}, z.core.$strip>;
|
|
87
|
+
estado: z.ZodObject<{
|
|
88
|
+
archivo: z.ZodString;
|
|
89
|
+
existe: z.ZodBoolean;
|
|
90
|
+
punteros: z.ZodNumber;
|
|
91
|
+
}, z.core.$strip>;
|
|
92
|
+
capas: z.ZodArray<z.ZodObject<{
|
|
93
|
+
ruta: z.ZodString;
|
|
94
|
+
etiqueta: z.ZodEnum<{
|
|
95
|
+
fábrica: "fábrica";
|
|
96
|
+
propia: "propia";
|
|
97
|
+
}>;
|
|
98
|
+
existe: z.ZodBoolean;
|
|
99
|
+
}, z.core.$strip>>;
|
|
100
|
+
reglasGlobales: z.ZodObject<{
|
|
101
|
+
archivo: z.ZodNullable<z.ZodString>;
|
|
102
|
+
capa: z.ZodNullable<z.ZodString>;
|
|
103
|
+
faltan: z.ZodArray<z.ZodString>;
|
|
104
|
+
}, z.core.$strip>;
|
|
105
|
+
fases: z.ZodArray<z.ZodObject<{
|
|
106
|
+
numero: z.ZodNumber;
|
|
107
|
+
titulo: z.ZodString;
|
|
108
|
+
archivo: z.ZodString;
|
|
109
|
+
capa: z.ZodString;
|
|
110
|
+
documento: z.ZodOptional<z.ZodString>;
|
|
111
|
+
recibos: z.ZodOptional<z.ZodString>;
|
|
112
|
+
comando: z.ZodNullable<z.ZodString>;
|
|
113
|
+
}, z.core.$strip>>;
|
|
114
|
+
proyectos: z.ZodArray<z.ZodObject<{
|
|
115
|
+
nombre: z.ZodString;
|
|
116
|
+
tareas: z.ZodNumber;
|
|
117
|
+
activa: z.ZodNullable<z.ZodObject<{
|
|
118
|
+
tarea: z.ZodString;
|
|
119
|
+
origen: z.ZodEnum<{
|
|
120
|
+
puntero: "puntero";
|
|
121
|
+
deducida: "deducida";
|
|
122
|
+
}>;
|
|
123
|
+
fase: z.ZodString;
|
|
124
|
+
}, z.core.$strip>>;
|
|
125
|
+
}, z.core.$strip>>;
|
|
126
|
+
cliente: z.ZodOptional<z.ZodObject<{
|
|
127
|
+
nombre: z.ZodString;
|
|
128
|
+
version: z.ZodString;
|
|
129
|
+
capacidades: z.ZodObject<{
|
|
130
|
+
elicitation: z.ZodBoolean;
|
|
131
|
+
roots: z.ZodBoolean;
|
|
132
|
+
}, z.core.$strip>;
|
|
133
|
+
}, z.core.$strip>>;
|
|
134
|
+
hallazgos: z.ZodArray<z.ZodObject<{
|
|
135
|
+
severidad: z.ZodEnum<{
|
|
136
|
+
error: "error";
|
|
137
|
+
info: "info";
|
|
138
|
+
aviso: "aviso";
|
|
139
|
+
}>;
|
|
140
|
+
codigo: z.ZodString;
|
|
141
|
+
texto: z.ZodString;
|
|
142
|
+
}, z.core.$strip>>;
|
|
79
143
|
};
|
|
80
|
-
type
|
|
81
|
-
type SinNulos<T> = {
|
|
144
|
+
export type SinNulos<T> = {
|
|
82
145
|
[K in keyof T]: Exclude<T[K], null>;
|
|
83
146
|
};
|
|
84
|
-
export
|
|
85
|
-
[K in NombreTool]: {
|
|
86
|
-
tool: K;
|
|
87
|
-
args: SinNulos<z.output<z.ZodObject<(typeof SHAPES)[K]>>>;
|
|
88
|
-
};
|
|
89
|
-
}[NombreTool];
|
|
90
|
-
export declare function validarLlamada(tool: string, args: unknown): LlamadaValidada;
|
|
91
|
-
export {};
|
|
147
|
+
export declare function sinNulos<T extends Record<string, unknown>>(args: T): SinNulos<T>;
|
|
92
148
|
//# sourceMappingURL=schemas.d.ts.map
|