@tacuchi/agent-workflow-cli 23.0.0 → 25.0.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.md +37 -1
- package/dist/adapters/postgres-readonly-tools.js +277 -0
- package/dist/adapters/postgres-readonly-tools.js.map +1 -0
- package/dist/application/checkpoint/markdown.js +85 -5
- package/dist/application/checkpoint/markdown.js.map +1 -1
- package/dist/application/checkpoint-service.js +7 -6
- package/dist/application/checkpoint-service.js.map +1 -1
- package/dist/application/checkpoint-write-service.js +270 -16
- package/dist/application/checkpoint-write-service.js.map +1 -1
- package/dist/application/database-mcp-server.js +168 -0
- package/dist/application/database-mcp-server.js.map +1 -0
- package/dist/application/database-mcp-stdio.js +137 -0
- package/dist/application/database-mcp-stdio.js.map +1 -0
- package/dist/application/database-tool-catalog.js +226 -0
- package/dist/application/database-tool-catalog.js.map +1 -0
- package/dist/application/dsn-reader-service.js +1 -1
- package/dist/application/flow/advance.js +60 -10
- package/dist/application/flow/advance.js.map +1 -1
- package/dist/application/flow/internal-actions.js +1 -1
- package/dist/application/flow/internal-actions.js.map +1 -1
- package/dist/application/flow/submit.js +256 -9
- package/dist/application/flow/submit.js.map +1 -1
- package/dist/application/lifecycle-target.js +16 -19
- package/dist/application/lifecycle-target.js.map +1 -1
- package/dist/application/lock-service.js +96 -31
- package/dist/application/lock-service.js.map +1 -1
- package/dist/application/logging/log-events.js +19 -3
- package/dist/application/logging/log-events.js.map +1 -1
- package/dist/application/logging/logger.js +2 -2
- package/dist/application/logging/logger.js.map +1 -1
- package/dist/application/markdown.js +6 -2
- package/dist/application/markdown.js.map +1 -1
- package/dist/application/mcp-connections-service.js +115 -41
- package/dist/application/mcp-connections-service.js.map +1 -1
- package/dist/application/mcp-doctor-service.js +98 -54
- package/dist/application/mcp-doctor-service.js.map +1 -1
- package/dist/application/mcp-entry-classification.js +60 -0
- package/dist/application/mcp-entry-classification.js.map +1 -0
- package/dist/application/mcp-host-reader.js +102 -86
- package/dist/application/mcp-host-reader.js.map +1 -1
- package/dist/application/mcp-host-receipt-service.js +399 -0
- package/dist/application/mcp-host-receipt-service.js.map +1 -0
- package/dist/application/mcp-host-receipt-store.js +122 -0
- package/dist/application/mcp-host-receipt-store.js.map +1 -0
- package/dist/application/mcp-host-receipts.js +28 -0
- package/dist/application/mcp-host-receipts.js.map +1 -0
- package/dist/application/mcp-host-writer.js +209 -38
- package/dist/application/mcp-host-writer.js.map +1 -1
- package/dist/application/mcp-launch-probe-service.js +142 -0
- package/dist/application/mcp-launch-probe-service.js.map +1 -0
- package/dist/application/mcp-migration-service.js +351 -0
- package/dist/application/mcp-migration-service.js.map +1 -0
- package/dist/application/mcp-native-host-check-service.js +154 -0
- package/dist/application/mcp-native-host-check-service.js.map +1 -0
- package/dist/application/mcp-receipt-registration-service.js +105 -0
- package/dist/application/mcp-receipt-registration-service.js.map +1 -0
- package/dist/application/mcp-receipt-removal-service.js +62 -0
- package/dist/application/mcp-receipt-removal-service.js.map +1 -0
- package/dist/application/mcp-remove-service.js +83 -24
- package/dist/application/mcp-remove-service.js.map +1 -1
- package/dist/application/mcp-scope-common.js +1 -1
- package/dist/application/mcp-scope-common.js.map +1 -1
- package/dist/application/mcp-setup-service.js +59 -24
- package/dist/application/mcp-setup-service.js.map +1 -1
- package/dist/application/mcp-stdio-probe.js +526 -0
- package/dist/application/mcp-stdio-probe.js.map +1 -0
- package/dist/application/mcp-test-connection-service.js +23 -50
- package/dist/application/mcp-test-connection-service.js.map +1 -1
- package/dist/application/parsers/spec-functional.js +220 -0
- package/dist/application/parsers/spec-functional.js.map +1 -0
- package/dist/application/parsers/spec-relation.js +142 -5
- package/dist/application/parsers/spec-relation.js.map +1 -1
- package/dist/application/paths-service.js +13 -0
- package/dist/application/paths-service.js.map +1 -1
- package/dist/application/plan-exec-decision-service.js +57 -4
- package/dist/application/plan-exec-decision-service.js.map +1 -1
- package/dist/application/reseal-service.js +300 -0
- package/dist/application/reseal-service.js.map +1 -0
- package/dist/application/self/host-states.js.map +1 -1
- package/dist/application/self/install-skill.js +4 -34
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/mcp-config.js +369 -59
- package/dist/application/self/mcp-config.js.map +1 -1
- package/dist/application/self/mcp-via-state.js +9 -6
- package/dist/application/self/mcp-via-state.js.map +1 -1
- package/dist/application/self/uninstall-skill.js +3 -18
- package/dist/application/self/uninstall-skill.js.map +1 -1
- package/dist/application/self/uninstall.js +4 -23
- package/dist/application/self/uninstall.js.map +1 -1
- package/dist/application/workline-index-service.js +64 -6
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/application/workspace-init-service.js +4 -6
- package/dist/application/workspace-init-service.js.map +1 -1
- package/dist/cli/commands/checkpoint-write.js +24 -22
- package/dist/cli/commands/checkpoint-write.js.map +1 -1
- package/dist/cli/commands/index.js +7 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/mcp.js +642 -55
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/reseal.js +140 -0
- package/dist/cli/commands/reseal.js.map +1 -0
- package/dist/cli/commands/status.js +5 -1
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/tool.js +141 -0
- package/dist/cli/commands/tool.js.map +1 -0
- package/dist/cli/help-groups.js +7 -1
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/main.js +189 -57
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/parser.js +5 -1
- package/dist/cli/parser.js.map +1 -1
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli/render.js +15 -2
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/tui/components/host-admin-section.js +2 -46
- package/dist/cli/tui/components/host-admin-section.js.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab-helpers.js +71 -0
- package/dist/cli/tui/tabs/mcp-tab-helpers.js.map +1 -1
- package/dist/cli/tui/tabs/mcp-tab.js +101 -42
- package/dist/cli/tui/tabs/mcp-tab.js.map +1 -1
- package/dist/domain/database-tools.js +445 -0
- package/dist/domain/database-tools.js.map +1 -0
- package/dist/domain/effective-contract.js +10 -2
- package/dist/domain/effective-contract.js.map +1 -1
- package/dist/domain/flow/answer.js +4 -0
- package/dist/domain/flow/answer.js.map +1 -1
- package/dist/domain/flow/authority.js +103 -14
- package/dist/domain/flow/authority.js.map +1 -1
- package/dist/domain/flow/directive.js +2 -0
- package/dist/domain/flow/directive.js.map +1 -1
- package/dist/domain/flow/run-state.js +42 -0
- package/dist/domain/flow/run-state.js.map +1 -1
- package/dist/domain/lineage.js +38 -11
- package/dist/domain/lineage.js.map +1 -1
- package/dist/domain/mcp-entry.js +131 -17
- package/dist/domain/mcp-entry.js.map +1 -1
- package/dist/domain/postgres-object-search.js +320 -0
- package/dist/domain/postgres-object-search.js.map +1 -0
- package/dist/domain/redaction.js +47 -0
- package/dist/domain/redaction.js.map +1 -0
- package/dist/domain/workline-mcp-entry.js +6 -9
- package/dist/domain/workline-mcp-entry.js.map +1 -1
- package/dist/ports/postgres-tools.js +10 -0
- package/dist/ports/postgres-tools.js.map +1 -0
- package/package.json +5 -1
- package/skills/w/commands/plan-exec.md +1 -1
- package/skills/w/commands/spec-new.md +6 -5
- package/skills/w/context/MANIFEST.json +1 -1
- package/skills/w/harness/HARNESS.md +1 -1
- package/skills/w/hooks/README.md +13 -9
- package/skills/w/hooks/hooks.template.json +2 -2
- package/skills/w/loops/CHASSIS.md +1 -1
- package/skills/w/loops/plan-exec-loop/LOOP.md +7 -5
- package/skills/w/loops/plan-new-loop/LOOP.md +46 -41
- package/skills/w/loops/plan-refine-loop/LOOP.md +4 -4
- package/skills/w/loops/quick-loop/LOOP.md +12 -13
- package/skills/w/loops/spec-refine-loop/LOOP.md +7 -3
- package/skills/w/modules/COMPACTION.md +1 -1
- package/skills/w/modules/PLAN-INPUT.md +3 -3
- package/skills/w/modules/PROMPT-CONTINUITY.md +1 -1
- package/dist/application/mcp-dbhub-launcher.js +0 -216
- package/dist/application/mcp-dbhub-launcher.js.map +0 -1
- package/dist/application/self/mcp-offer.js +0 -96
- package/dist/application/self/mcp-offer.js.map +0 -1
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
3
|
+
import { StringDecoder } from "node:string_decoder";
|
|
4
|
+
import { isDeepStrictEqual } from "node:util";
|
|
5
|
+
import { MAX_TOOL_RESULT_BYTES } from "../domain/database-tools.js";
|
|
6
|
+
/** The protocol revision used by the local Workline MCP server. */
|
|
7
|
+
export const MCP_STDIO_PROBE_PROTOCOL_VERSION = "2025-06-18";
|
|
8
|
+
/**
|
|
9
|
+
* `content[0].text` JSON-escapes the already bounded canonical response. A
|
|
10
|
+
* control-character-heavy result can expand close to sixfold before JSON-RPC
|
|
11
|
+
* framing, so the probe must not reject a valid 4 MiB tool contract.
|
|
12
|
+
*/
|
|
13
|
+
export const DEFAULT_MCP_STDIO_PROBE_MAX_FRAME_BYTES = MAX_TOOL_RESULT_BYTES * 6 + 64 * 1024;
|
|
14
|
+
export const DEFAULT_MCP_STDIO_PROBE_TIMEOUTS = {
|
|
15
|
+
spawn: 10_000,
|
|
16
|
+
initialize: 10_000,
|
|
17
|
+
initialized: 10_000,
|
|
18
|
+
toolsList: 10_000,
|
|
19
|
+
toolsCall: 30_000,
|
|
20
|
+
};
|
|
21
|
+
class ProbeFailure extends Error {
|
|
22
|
+
phase;
|
|
23
|
+
code;
|
|
24
|
+
constructor(phase, code, message) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.phase = phase;
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.name = "ProbeFailure";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Launches a persisted stdio descriptor without a shell and proves the MCP
|
|
33
|
+
* lifecycle. It never prints child stdout/stderr and deliberately returns no
|
|
34
|
+
* tool payload, so a faulty server cannot put DSNs, SQL or rows into a doctor
|
|
35
|
+
* report by echoing them.
|
|
36
|
+
*/
|
|
37
|
+
export async function runMcpStdioProbe(input, deps = {}) {
|
|
38
|
+
const mode = input.mode ?? "launch";
|
|
39
|
+
const normalized = normalizeInput(input, mode);
|
|
40
|
+
if (normalized instanceof ProbeFailure)
|
|
41
|
+
return toFailure(mode, normalized);
|
|
42
|
+
let child = null;
|
|
43
|
+
let session = null;
|
|
44
|
+
try {
|
|
45
|
+
const spawner = deps.spawn ?? defaultSpawner;
|
|
46
|
+
const options = {
|
|
47
|
+
// The server uses this marker to keep a local launch probe separate from
|
|
48
|
+
// an actual host `initialized` notification in its receipt ledger.
|
|
49
|
+
env: {
|
|
50
|
+
...(deps.environment ?? process.env),
|
|
51
|
+
...normalized.descriptor.env,
|
|
52
|
+
AW_MCP_PROBE: "1",
|
|
53
|
+
},
|
|
54
|
+
shell: false,
|
|
55
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
56
|
+
windowsHide: true,
|
|
57
|
+
...(normalized.cwd === undefined ? {} : { cwd: normalized.cwd }),
|
|
58
|
+
};
|
|
59
|
+
child = spawner(normalized.descriptor.command, normalized.descriptor.args, options);
|
|
60
|
+
if (child.stdin === null || child.stdout === null || child.stderr === null) {
|
|
61
|
+
throw new ProbeFailure("spawn", "SPAWN_FAILED", "No se pudo abrir el transporte stdio del servidor MCP.");
|
|
62
|
+
}
|
|
63
|
+
session = new McpStdioProbeSession(child, normalized);
|
|
64
|
+
return await session.run();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (error instanceof ProbeFailure)
|
|
68
|
+
return toFailure(mode, error);
|
|
69
|
+
return toFailure(mode, new ProbeFailure("spawn", "SPAWN_FAILED", "No se pudo iniciar el servidor MCP configurado."));
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
session?.terminate();
|
|
73
|
+
if (session === null && child !== null)
|
|
74
|
+
terminateChild(child);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
class McpStdioProbeSession {
|
|
78
|
+
child;
|
|
79
|
+
input;
|
|
80
|
+
decoder = new StringDecoder("utf8");
|
|
81
|
+
failureWaiters = new Set();
|
|
82
|
+
lineBuffer = "";
|
|
83
|
+
stdoutBufferedBytes = 0;
|
|
84
|
+
nextId = 1;
|
|
85
|
+
pending = null;
|
|
86
|
+
failure = null;
|
|
87
|
+
currentPhase = "spawn";
|
|
88
|
+
finished = false;
|
|
89
|
+
constructor(child, input) {
|
|
90
|
+
this.child = child;
|
|
91
|
+
this.input = input;
|
|
92
|
+
}
|
|
93
|
+
async run() {
|
|
94
|
+
this.attachListeners();
|
|
95
|
+
await this.waitForSpawn();
|
|
96
|
+
const initialized = await this.request("initialize", "initialize", {
|
|
97
|
+
protocolVersion: this.input.protocolVersion,
|
|
98
|
+
capabilities: {},
|
|
99
|
+
clientInfo: { name: "agent-workflow-mcp-probe", version: "1" },
|
|
100
|
+
});
|
|
101
|
+
const protocolVersion = readProtocolVersion(initialized.result);
|
|
102
|
+
if (protocolVersion === null) {
|
|
103
|
+
throw new ProbeFailure("initialize", "INVALID_INITIALIZE_RESPONSE", "El servidor MCP devolvió una inicialización inválida.");
|
|
104
|
+
}
|
|
105
|
+
if (protocolVersion !== this.input.protocolVersion) {
|
|
106
|
+
throw new ProbeFailure("initialize", "PROTOCOL_VERSION_MISMATCH", "El servidor MCP negoció una versión de protocolo incompatible.");
|
|
107
|
+
}
|
|
108
|
+
await this.notify("initialized", "notifications/initialized");
|
|
109
|
+
const listed = await this.request("tools/list", "tools/list", {});
|
|
110
|
+
const tools = readPublishedTools(listed.result);
|
|
111
|
+
if (tools === null) {
|
|
112
|
+
throw new ProbeFailure("tools/list", "INVALID_TOOLS_RESPONSE", "El servidor MCP devolvió una lista de tools inválida.");
|
|
113
|
+
}
|
|
114
|
+
if (!sameToolSchemas(tools, this.input.expectedTools)) {
|
|
115
|
+
throw new ProbeFailure("tools/list", "TOOL_SCHEMA_MISMATCH", "Las tools publicadas no coinciden con el catálogo esperado.");
|
|
116
|
+
}
|
|
117
|
+
if (this.input.mode === "data") {
|
|
118
|
+
if (!tools.some((tool) => tool.name === "execute_sql")) {
|
|
119
|
+
throw new ProbeFailure("tools/call", "TOOL_MISSING", "El servidor MCP no publicó la tool requerida para la verificación de datos.");
|
|
120
|
+
}
|
|
121
|
+
const called = await this.request("tools/call", "tools/call", {
|
|
122
|
+
name: "execute_sql",
|
|
123
|
+
// Kept only on stdin. It is never included in any result or error.
|
|
124
|
+
arguments: { sql: "SELECT 1 AS ok" },
|
|
125
|
+
});
|
|
126
|
+
const dataState = readDataProbeResult(called.result);
|
|
127
|
+
if (dataState === "invalid") {
|
|
128
|
+
throw new ProbeFailure("tools/call", "INVALID_DATA_RESPONSE", "El servidor MCP devolvió una respuesta de datos inválida.");
|
|
129
|
+
}
|
|
130
|
+
if (dataState === "failure") {
|
|
131
|
+
throw new ProbeFailure("tools/call", "TOOL_CALL_FAILED", "La verificación de datos del servidor MCP no se pudo completar.");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
this.finished = true;
|
|
135
|
+
return {
|
|
136
|
+
ok: true,
|
|
137
|
+
mode: this.input.mode,
|
|
138
|
+
protocol_version: protocolVersion,
|
|
139
|
+
tool_count: tools.length,
|
|
140
|
+
...(this.input.mode === "data" ? { data_verified: true } : {}),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
terminate() {
|
|
144
|
+
this.finished = true;
|
|
145
|
+
terminateChild(this.child);
|
|
146
|
+
}
|
|
147
|
+
attachListeners() {
|
|
148
|
+
const stdout = this.child.stdout;
|
|
149
|
+
const stderr = this.child.stderr;
|
|
150
|
+
if (stdout === null || stderr === null) {
|
|
151
|
+
this.fail(new ProbeFailure("spawn", "SPAWN_FAILED", "No se pudo abrir el transporte stdio del servidor MCP."));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
stdout.on("data", (chunk) => this.onStdout(chunk));
|
|
155
|
+
stdout.on("end", () => this.onStdoutEnd());
|
|
156
|
+
stdout.on("error", () => {
|
|
157
|
+
this.fail(new ProbeFailure(this.currentPhase, "PROCESS_EXITED", "El servidor MCP cerró su salida."));
|
|
158
|
+
});
|
|
159
|
+
// Stderr can contain a driver error with credentials. Drain it, never store
|
|
160
|
+
// or forward it.
|
|
161
|
+
stderr.resume();
|
|
162
|
+
stderr.on("error", () => { });
|
|
163
|
+
this.child.on("error", () => {
|
|
164
|
+
this.fail(new ProbeFailure(this.currentPhase, "SPAWN_FAILED", "No se pudo iniciar el servidor MCP configurado."));
|
|
165
|
+
});
|
|
166
|
+
this.child.on("exit", () => {
|
|
167
|
+
this.fail(new ProbeFailure(this.currentPhase, "PROCESS_EXITED", "El servidor MCP terminó antes de completar el probe."));
|
|
168
|
+
});
|
|
169
|
+
this.child.on("close", () => {
|
|
170
|
+
this.fail(new ProbeFailure(this.currentPhase, "PROCESS_EXITED", "El servidor MCP cerró antes de completar el probe."));
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
async waitForSpawn() {
|
|
174
|
+
// Node assigns pid before emitting `spawn`. Treat that as launched so a
|
|
175
|
+
// synchronous test double cannot lose the event between spawn() and this
|
|
176
|
+
// listener; a later child error still fails the active protocol phase.
|
|
177
|
+
if (this.child.pid !== undefined)
|
|
178
|
+
return;
|
|
179
|
+
const spawned = new Promise((resolve) => {
|
|
180
|
+
this.child.once("spawn", resolve);
|
|
181
|
+
});
|
|
182
|
+
await this.withPhaseTimeout("spawn", this.input.timeouts.spawn, spawned);
|
|
183
|
+
}
|
|
184
|
+
async request(phase, method, params) {
|
|
185
|
+
const id = this.nextId;
|
|
186
|
+
this.nextId += 1;
|
|
187
|
+
const response = new Promise((resolve, reject) => {
|
|
188
|
+
const pending = { id, resolve, reject };
|
|
189
|
+
this.pending = pending;
|
|
190
|
+
this.write({ jsonrpc: "2.0", id, method, params }, phase, pending);
|
|
191
|
+
});
|
|
192
|
+
try {
|
|
193
|
+
return await this.withPhaseTimeout(phase, timeoutFor(this.input.timeouts, phase), response);
|
|
194
|
+
}
|
|
195
|
+
finally {
|
|
196
|
+
if (this.pending?.id === id)
|
|
197
|
+
this.pending = null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async notify(phase, method) {
|
|
201
|
+
const write = new Promise((resolve, reject) => {
|
|
202
|
+
this.write({ jsonrpc: "2.0", method }, phase, null, resolve, reject);
|
|
203
|
+
});
|
|
204
|
+
await this.withPhaseTimeout(phase, this.input.timeouts.initialized, write);
|
|
205
|
+
}
|
|
206
|
+
write(message, phase, pending, onWritten, onWriteFailure) {
|
|
207
|
+
const stdin = this.child.stdin;
|
|
208
|
+
if (stdin === null) {
|
|
209
|
+
const failure = new ProbeFailure(phase, "STDIN_WRITE_FAILED", "No se pudo escribir al servidor MCP.");
|
|
210
|
+
if (pending !== null)
|
|
211
|
+
pending.reject(failure);
|
|
212
|
+
else
|
|
213
|
+
onWriteFailure?.(failure);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
stdin.write(`${JSON.stringify(message)}\n`, (error) => {
|
|
218
|
+
if (error === undefined || error === null) {
|
|
219
|
+
onWritten?.();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const failure = new ProbeFailure(phase, "STDIN_WRITE_FAILED", "No se pudo escribir al servidor MCP.");
|
|
223
|
+
if (pending !== null && this.pending === pending)
|
|
224
|
+
pending.reject(failure);
|
|
225
|
+
else
|
|
226
|
+
onWriteFailure?.(failure);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
const failure = new ProbeFailure(phase, "STDIN_WRITE_FAILED", "No se pudo escribir al servidor MCP.");
|
|
231
|
+
if (pending !== null)
|
|
232
|
+
pending.reject(failure);
|
|
233
|
+
else
|
|
234
|
+
onWriteFailure?.(failure);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
async withPhaseTimeout(phase, timeoutMs, operation) {
|
|
238
|
+
this.currentPhase = phase;
|
|
239
|
+
if (this.failure !== null)
|
|
240
|
+
throw this.failure;
|
|
241
|
+
const deferred = this.waitForFailure();
|
|
242
|
+
let timer;
|
|
243
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
244
|
+
timer = setTimeout(() => {
|
|
245
|
+
reject(new ProbeFailure(phase, "PHASE_TIMEOUT", "El servidor MCP no respondió a tiempo."));
|
|
246
|
+
}, timeoutMs);
|
|
247
|
+
});
|
|
248
|
+
try {
|
|
249
|
+
return await Promise.race([operation, deferred.promise, timeout]);
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
if (timer !== undefined)
|
|
253
|
+
clearTimeout(timer);
|
|
254
|
+
deferred.dispose();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
waitForFailure() {
|
|
258
|
+
let rejectWaiter = null;
|
|
259
|
+
const promise = new Promise((_resolve, reject) => {
|
|
260
|
+
rejectWaiter = reject;
|
|
261
|
+
if (this.failure !== null) {
|
|
262
|
+
reject(this.failure);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
this.failureWaiters.add(reject);
|
|
266
|
+
});
|
|
267
|
+
return {
|
|
268
|
+
promise,
|
|
269
|
+
dispose: () => {
|
|
270
|
+
if (rejectWaiter !== null)
|
|
271
|
+
this.failureWaiters.delete(rejectWaiter);
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
onStdout(chunk) {
|
|
276
|
+
if (this.finished || this.failure !== null)
|
|
277
|
+
return;
|
|
278
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
279
|
+
let offset = 0;
|
|
280
|
+
while (offset < bytes.length) {
|
|
281
|
+
const newline = bytes.indexOf(0x0a, offset);
|
|
282
|
+
const end = newline < 0 ? bytes.length : newline + 1;
|
|
283
|
+
const segment = bytes.subarray(offset, end);
|
|
284
|
+
// Split raw bytes before decoding: a single giant completed line must
|
|
285
|
+
// fail without allocating a decoded string just to discover its size.
|
|
286
|
+
if (this.stdoutBufferedBytes + segment.length > this.input.maxFrameBytes) {
|
|
287
|
+
this.fail(new ProbeFailure(this.currentPhase, "STDOUT_FRAME_TOO_LARGE", "El servidor MCP excedió el límite de salida del probe."));
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
this.stdoutBufferedBytes += segment.length;
|
|
291
|
+
this.lineBuffer += this.decoder.write(segment);
|
|
292
|
+
if (newline >= 0) {
|
|
293
|
+
const line = this.lineBuffer.slice(0, -1).replace(/\r$/, "");
|
|
294
|
+
this.lineBuffer = "";
|
|
295
|
+
this.stdoutBufferedBytes = 0;
|
|
296
|
+
this.acceptLine(line);
|
|
297
|
+
if (this.failure !== null)
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
offset = end;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
onStdoutEnd() {
|
|
304
|
+
if (this.finished || this.failure !== null)
|
|
305
|
+
return;
|
|
306
|
+
const tail = this.decoder.end();
|
|
307
|
+
if (tail.length > 0)
|
|
308
|
+
this.lineBuffer += tail;
|
|
309
|
+
if (this.lineBuffer.length > 0) {
|
|
310
|
+
this.fail(new ProbeFailure(this.currentPhase, "STDOUT_PROTOCOL_VIOLATION", "El stdout del servidor MCP no contiene JSON-RPC lineal válido."));
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
this.fail(new ProbeFailure(this.currentPhase, "PROCESS_EXITED", "El servidor MCP cerró su salida."));
|
|
314
|
+
}
|
|
315
|
+
acceptLine(line) {
|
|
316
|
+
let message;
|
|
317
|
+
try {
|
|
318
|
+
message = JSON.parse(line);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
this.fail(new ProbeFailure(this.currentPhase, "STDOUT_PROTOCOL_VIOLATION", "El stdout del servidor MCP no contiene JSON-RPC lineal válido."));
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (!isRecord(message) || message.jsonrpc !== "2.0") {
|
|
325
|
+
this.fail(new ProbeFailure(this.currentPhase, "STDOUT_PROTOCOL_VIOLATION", "El stdout del servidor MCP no contiene JSON-RPC lineal válido."));
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const pending = this.pending;
|
|
329
|
+
if (pending === null || message.id !== pending.id)
|
|
330
|
+
return;
|
|
331
|
+
if (Object.hasOwn(message, "error")) {
|
|
332
|
+
pending.reject(new ProbeFailure(this.currentPhase, "SERVER_ERROR", "El servidor MCP rechazó una fase del probe."));
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
if (!Object.hasOwn(message, "result")) {
|
|
336
|
+
pending.reject(new ProbeFailure(this.currentPhase, "STDOUT_PROTOCOL_VIOLATION", "El servidor MCP devolvió una respuesta JSON-RPC inválida."));
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
pending.resolve({ id: pending.id, result: message.result });
|
|
340
|
+
}
|
|
341
|
+
fail(failure) {
|
|
342
|
+
if (this.finished || this.failure !== null)
|
|
343
|
+
return;
|
|
344
|
+
this.failure = failure;
|
|
345
|
+
if (this.pending !== null)
|
|
346
|
+
this.pending.reject(failure);
|
|
347
|
+
for (const reject of this.failureWaiters)
|
|
348
|
+
reject(failure);
|
|
349
|
+
this.failureWaiters.clear();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function defaultSpawner(command, args, options) {
|
|
353
|
+
return nodeSpawn(command, args, options);
|
|
354
|
+
}
|
|
355
|
+
function normalizeInput(input, mode) {
|
|
356
|
+
const descriptor = input.descriptor;
|
|
357
|
+
if (!isRecord(descriptor) ||
|
|
358
|
+
typeof descriptor.command !== "string" ||
|
|
359
|
+
descriptor.command.trim().length === 0 ||
|
|
360
|
+
!isAbsolute(descriptor.command) ||
|
|
361
|
+
!Array.isArray(descriptor.args) ||
|
|
362
|
+
!isAbsolute(descriptor.args[0] ?? "") ||
|
|
363
|
+
descriptor.args.some((arg) => typeof arg !== "string") ||
|
|
364
|
+
(descriptor.env !== undefined && !allStrings(descriptor.env))) {
|
|
365
|
+
return new ProbeFailure("spawn", "INVALID_DESCRIPTOR", "El descriptor MCP persistido es inválido.");
|
|
366
|
+
}
|
|
367
|
+
const protocolVersion = input.protocolVersion ?? MCP_STDIO_PROBE_PROTOCOL_VERSION;
|
|
368
|
+
if (protocolVersion.trim().length === 0) {
|
|
369
|
+
return new ProbeFailure("initialize", "INVALID_DESCRIPTOR", "El protocolo MCP solicitado es inválido.");
|
|
370
|
+
}
|
|
371
|
+
const maxFrameBytes = input.maxFrameBytes ?? DEFAULT_MCP_STDIO_PROBE_MAX_FRAME_BYTES;
|
|
372
|
+
if (!Number.isSafeInteger(maxFrameBytes) || maxFrameBytes < 1) {
|
|
373
|
+
return new ProbeFailure("spawn", "INVALID_DESCRIPTOR", "El límite de salida del probe es inválido.");
|
|
374
|
+
}
|
|
375
|
+
const timeouts = resolveTimeouts(input.timeouts);
|
|
376
|
+
if (timeouts === null) {
|
|
377
|
+
return new ProbeFailure("spawn", "INVALID_DESCRIPTOR", "Los timeouts del probe son inválidos.");
|
|
378
|
+
}
|
|
379
|
+
const expectedTools = input.expectedTools ?? [];
|
|
380
|
+
if (expectedTools.some((tool) => !isExpectedTool(tool)) ||
|
|
381
|
+
new Set(expectedTools.map((tool) => tool.name)).size !== expectedTools.length) {
|
|
382
|
+
return new ProbeFailure("tools/list", "INVALID_DESCRIPTOR", "El catálogo esperado para el probe es inválido.");
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
descriptor: {
|
|
386
|
+
command: descriptor.command,
|
|
387
|
+
args: [...descriptor.args],
|
|
388
|
+
env: { ...(descriptor.env ?? {}) },
|
|
389
|
+
},
|
|
390
|
+
mode,
|
|
391
|
+
expectedTools,
|
|
392
|
+
protocolVersion,
|
|
393
|
+
timeouts,
|
|
394
|
+
maxFrameBytes,
|
|
395
|
+
...(input.cwd === undefined ? {} : { cwd: input.cwd }),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function resolveTimeouts(values) {
|
|
399
|
+
const candidate = {
|
|
400
|
+
spawn: values?.spawn ?? DEFAULT_MCP_STDIO_PROBE_TIMEOUTS.spawn,
|
|
401
|
+
initialize: values?.initialize ?? DEFAULT_MCP_STDIO_PROBE_TIMEOUTS.initialize,
|
|
402
|
+
initialized: values?.initialized ?? DEFAULT_MCP_STDIO_PROBE_TIMEOUTS.initialized,
|
|
403
|
+
toolsList: values?.toolsList ?? DEFAULT_MCP_STDIO_PROBE_TIMEOUTS.toolsList,
|
|
404
|
+
toolsCall: values?.toolsCall ?? DEFAULT_MCP_STDIO_PROBE_TIMEOUTS.toolsCall,
|
|
405
|
+
};
|
|
406
|
+
return Object.values(candidate).every((timeout) => Number.isSafeInteger(timeout) && timeout > 0)
|
|
407
|
+
? candidate
|
|
408
|
+
: null;
|
|
409
|
+
}
|
|
410
|
+
function timeoutFor(timeouts, phase) {
|
|
411
|
+
switch (phase) {
|
|
412
|
+
case "initialize":
|
|
413
|
+
return timeouts.initialize;
|
|
414
|
+
case "tools/list":
|
|
415
|
+
return timeouts.toolsList;
|
|
416
|
+
case "tools/call":
|
|
417
|
+
return timeouts.toolsCall;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function readProtocolVersion(value) {
|
|
421
|
+
if (!isRecord(value) ||
|
|
422
|
+
typeof value.protocolVersion !== "string" ||
|
|
423
|
+
value.protocolVersion.length === 0) {
|
|
424
|
+
return null;
|
|
425
|
+
}
|
|
426
|
+
return value.protocolVersion;
|
|
427
|
+
}
|
|
428
|
+
function readPublishedTools(value) {
|
|
429
|
+
if (!isRecord(value) || !Array.isArray(value.tools))
|
|
430
|
+
return null;
|
|
431
|
+
const tools = [];
|
|
432
|
+
const names = new Set();
|
|
433
|
+
for (const item of value.tools) {
|
|
434
|
+
if (!isRecord(item) ||
|
|
435
|
+
typeof item.name !== "string" ||
|
|
436
|
+
item.name.length === 0 ||
|
|
437
|
+
!Object.hasOwn(item, "inputSchema")) {
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
if (names.has(item.name))
|
|
441
|
+
return null;
|
|
442
|
+
names.add(item.name);
|
|
443
|
+
tools.push({ name: item.name, inputSchema: item.inputSchema });
|
|
444
|
+
}
|
|
445
|
+
return tools;
|
|
446
|
+
}
|
|
447
|
+
function sameToolSchemas(published, expected) {
|
|
448
|
+
if (expected.length === 0)
|
|
449
|
+
return true;
|
|
450
|
+
if (published.length !== expected.length)
|
|
451
|
+
return false;
|
|
452
|
+
return expected.every((required) => {
|
|
453
|
+
const actual = published.find((tool) => tool.name === required.name);
|
|
454
|
+
return actual !== undefined && isDeepStrictEqual(actual.inputSchema, required.inputSchema);
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
function readDataProbeResult(value) {
|
|
458
|
+
if (!isRecord(value) || !Array.isArray(value.content))
|
|
459
|
+
return "invalid";
|
|
460
|
+
const content = value.content[0];
|
|
461
|
+
if (!isRecord(content) ||
|
|
462
|
+
content.type !== "text" ||
|
|
463
|
+
content.mimeType !== "application/json" ||
|
|
464
|
+
typeof content.text !== "string") {
|
|
465
|
+
return "invalid";
|
|
466
|
+
}
|
|
467
|
+
try {
|
|
468
|
+
const body = JSON.parse(content.text);
|
|
469
|
+
if (!isRecord(body) || typeof body.success !== "boolean")
|
|
470
|
+
return "invalid";
|
|
471
|
+
if (!body.success || value.isError === true)
|
|
472
|
+
return "failure";
|
|
473
|
+
return isSelectOneProbePayload(body.data) ? "success" : "invalid";
|
|
474
|
+
}
|
|
475
|
+
catch {
|
|
476
|
+
return "invalid";
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
/** The data probe is proof of the canonical SELECT 1 response, not just a claim of success. */
|
|
480
|
+
function isSelectOneProbePayload(data) {
|
|
481
|
+
if (!isRecord(data) || !Array.isArray(data.statements) || data.statements.length !== 1)
|
|
482
|
+
return false;
|
|
483
|
+
const statement = data.statements[0];
|
|
484
|
+
if (!isRecord(statement) || statement.sql !== "SELECT 1 AS ok" || statement.count !== 1)
|
|
485
|
+
return false;
|
|
486
|
+
if (!Array.isArray(statement.rows) || statement.rows.length !== 1)
|
|
487
|
+
return false;
|
|
488
|
+
const row = statement.rows[0];
|
|
489
|
+
return isRecord(row) && row.ok === 1;
|
|
490
|
+
}
|
|
491
|
+
function isExpectedTool(value) {
|
|
492
|
+
return (isRecord(value) &&
|
|
493
|
+
typeof value.name === "string" &&
|
|
494
|
+
value.name.length > 0 &&
|
|
495
|
+
Object.hasOwn(value, "inputSchema"));
|
|
496
|
+
}
|
|
497
|
+
function allStrings(value) {
|
|
498
|
+
return isRecord(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
499
|
+
}
|
|
500
|
+
function isRecord(value) {
|
|
501
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
502
|
+
}
|
|
503
|
+
function toFailure(mode, failure) {
|
|
504
|
+
return {
|
|
505
|
+
ok: false,
|
|
506
|
+
mode,
|
|
507
|
+
phase: failure.phase,
|
|
508
|
+
code: failure.code,
|
|
509
|
+
error: failure.message,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function terminateChild(child) {
|
|
513
|
+
try {
|
|
514
|
+
child.stdin?.end();
|
|
515
|
+
}
|
|
516
|
+
catch {
|
|
517
|
+
// The process may have exited between the probe and cleanup.
|
|
518
|
+
}
|
|
519
|
+
try {
|
|
520
|
+
child.kill("SIGTERM");
|
|
521
|
+
}
|
|
522
|
+
catch {
|
|
523
|
+
// Best effort only. The caller already has the probe result.
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
//# sourceMappingURL=mcp-stdio-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-stdio-probe.js","sourceRoot":"","sources":["../../src/application/mcp-stdio-probe.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// fatal errors (it sits waiting for MCP input on stdio), the connection is
|
|
4
|
-
// considered valid. If dbhub fails quickly with stderr, the test fails with the detail.
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
1
|
+
import { PostgresReadonlyTools } from "../adapters/postgres-readonly-tools.js";
|
|
2
|
+
import { PostgresToolError } from "../ports/postgres-tools.js";
|
|
6
3
|
import { resolveExactDsn } from "./dsn-reader-service.js";
|
|
4
|
+
/**
|
|
5
|
+
* A real read-only `SELECT 1`, replacing the old five-second DBHub liveness
|
|
6
|
+
* heuristic. MCP lifecycle probing lives in `mcp doctor --probe`; this check is
|
|
7
|
+
* intentionally a direct database health signal for the TUI connection wizard.
|
|
8
|
+
*/
|
|
7
9
|
export async function testMcpConnection(input) {
|
|
10
|
+
void input.platform;
|
|
11
|
+
void input.timeoutMs;
|
|
8
12
|
const resolved = resolveDsnString(input);
|
|
9
13
|
if (!resolved) {
|
|
10
14
|
return {
|
|
@@ -13,53 +17,22 @@ export async function testMcpConnection(input) {
|
|
|
13
17
|
error: `${input.dsnVar} no está exportada en el shell ni en ${input.paths.userDsnFile()}`,
|
|
14
18
|
};
|
|
15
19
|
}
|
|
16
|
-
|
|
20
|
+
try {
|
|
21
|
+
await new PostgresReadonlyTools().execute("SELECT 1 AS ok", resolved.dsn);
|
|
22
|
+
return { ok: true, source: resolved.source };
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error instanceof PostgresToolError) {
|
|
26
|
+
return { ok: false, source: resolved.source, error: error.message };
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
ok: false,
|
|
30
|
+
source: resolved.source,
|
|
31
|
+
error: "No se pudo verificar la conexión PostgreSQL.",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
17
34
|
}
|
|
18
35
|
function resolveDsnString(input) {
|
|
19
|
-
// The caller supplies the exact variable declared by the registry.
|
|
20
36
|
return resolveExactDsn(input.dsnVar, input.env, input.paths);
|
|
21
37
|
}
|
|
22
|
-
function spawnDbhub(dsn, source, input) {
|
|
23
|
-
const timeoutMs = input.timeoutMs ?? 5000;
|
|
24
|
-
const isWin = input.platform === "win32";
|
|
25
|
-
const cmd = isWin ? "npx.cmd" : "npx";
|
|
26
|
-
return new Promise((resolve) => {
|
|
27
|
-
const child = spawn(cmd, ["-y", "@bytebase/dbhub"], {
|
|
28
|
-
env: { ...input.env, DSN: dsn },
|
|
29
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
30
|
-
shell: isWin,
|
|
31
|
-
});
|
|
32
|
-
// Chunks stay as bytes: decoding each one splits multibyte characters at the
|
|
33
|
-
// pipe boundary and garbles the very message the caller is about to show.
|
|
34
|
-
const stderr = [];
|
|
35
|
-
let settled = false;
|
|
36
|
-
const settle = (result) => {
|
|
37
|
-
if (settled)
|
|
38
|
-
return;
|
|
39
|
-
settled = true;
|
|
40
|
-
if (!child.killed)
|
|
41
|
-
child.kill("SIGTERM");
|
|
42
|
-
resolve(result);
|
|
43
|
-
};
|
|
44
|
-
child.stderr.on("data", (chunk) => {
|
|
45
|
-
stderr.push(chunk);
|
|
46
|
-
});
|
|
47
|
-
child.on("error", (err) => settle({ ok: false, source, error: err.message }));
|
|
48
|
-
child.on("exit", (code) => {
|
|
49
|
-
if (code === 0 || code === null) {
|
|
50
|
-
settle({ ok: true, source });
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
settle({
|
|
54
|
-
ok: false,
|
|
55
|
-
source,
|
|
56
|
-
error: Buffer.concat(stderr).toString("utf8").trim() || `dbhub salió con código ${code}`,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
// If dbhub is still running after the timeout, assume it started OK
|
|
61
|
-
// (it connected and is waiting for MCP input on stdio). Kill it and report OK.
|
|
62
|
-
setTimeout(() => settle({ ok: true, source }), timeoutMs);
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
38
|
//# sourceMappingURL=mcp-test-connection-service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-test-connection-service.js","sourceRoot":"","sources":["../../src/application/mcp-test-connection-service.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"mcp-test-connection-service.js","sourceRoot":"","sources":["../../src/application/mcp-test-connection-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAsB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAsB9E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAA6B;IAE7B,KAAK,KAAK,CAAC,QAAQ,CAAC;IACpB,KAAK,KAAK,CAAC,SAAS,CAAC;IACrB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,wCAAwC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE;SAC1F,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,qBAAqB,EAAE,CAAC,OAAO,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,iBAAiB,EAAE,CAAC;YACvC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QACtE,CAAC;QACD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,KAAK,EAAE,8CAA8C;SACtD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,KAA6B;IACrD,OAAO,eAAe,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC"}
|