NODEDC_1C/llm_normalizer/backend/tests/assistantMcpRuntimeBridge.t...

128 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from "fs";
import os from "os";
import path from "path";
import { afterEach, describe, expect, it, vi } from "vitest";
const MCP_FLAG = "FEATURE_ASSISTANT_MCP_RUNTIME_V1";
const MCP_PROXY = "ASSISTANT_MCP_PROXY_URL";
const MCP_CHANNEL = "ASSISTANT_MCP_CHANNEL";
const ORIGINAL_ENV = {
[MCP_FLAG]: process.env[MCP_FLAG],
[MCP_PROXY]: process.env[MCP_PROXY],
[MCP_CHANNEL]: process.env[MCP_CHANNEL]
};
const TEMP_DIRS: string[] = [];
function restoreEnv(): void {
for (const key of [MCP_FLAG, MCP_PROXY, MCP_CHANNEL] as const) {
const original = ORIGINAL_ENV[key];
if (original === undefined) {
delete process.env[key];
} else {
process.env[key] = original;
}
}
}
function cleanupTempDirs(): void {
for (const dir of TEMP_DIRS.splice(0)) {
fs.rmSync(dir, { recursive: true, force: true });
}
}
function createSnapshotRoot(): string {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "assistant-mcp-bridge-"));
TEMP_DIRS.push(root);
return root;
}
describe.sequential("assistant MCP runtime bridge", () => {
afterEach(() => {
vi.unstubAllGlobals();
restoreEnv();
cleanupTempDirs();
vi.resetModules();
});
it("does not call MCP when runtime flag is disabled", async () => {
process.env[MCP_FLAG] = "0";
const fetchMock = vi.fn();
vi.stubGlobal("fetch", fetchMock);
const { AssistantDataLayer } = await import("../src/services/assistantDataLayer");
const dataLayer = new AssistantDataLayer(createSnapshotRoot());
const result = await dataLayer.executeRouteRuntime("hybrid_store_plus_live", "Почему по счету 60.01 долг остался?");
expect(fetchMock).not.toHaveBeenCalled();
expect(result.summary.live_mcp).toBeUndefined();
});
it("uses MCP live probe for hybrid route when runtime flag is enabled", async () => {
process.env[MCP_FLAG] = "1";
process.env[MCP_PROXY] = "http://127.0.0.1:6003";
process.env[MCP_CHANNEL] = "default";
const payload = JSON.stringify({
success: true,
data: [
{
Период: "2026-03-01T00:00:00",
Регистратор: "Списание с расчетного счета 0001",
СчетДт: "60.01",
СчетКт: "51",
Сумма: 15000
},
{
Период: "2026-03-02T00:00:00",
Регистратор: "Операция бухгалтерская 0002",
СчетДт: "91.02",
СчетКт: "51",
Сумма: 900
}
]
});
const fetchMock = vi.fn(async () => new Response(payload, { status: 200 }));
vi.stubGlobal("fetch", fetchMock);
const { AssistantDataLayer } = await import("../src/services/assistantDataLayer");
const dataLayer = new AssistantDataLayer(createSnapshotRoot());
const result = await dataLayer.executeRouteRuntime("hybrid_store_plus_live", "Проверь 60.01 и 60.02: оплата есть, долг остался");
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(result.status).toBe("ok");
expect(result.items.length).toBeGreaterThan(0);
const summary = result.summary as Record<string, unknown>;
const liveSummary = summary.live_mcp as Record<string, unknown>;
expect(liveSummary.status).toBe("ok");
expect(liveSummary.channel).toBe("default");
const firstItem = result.items[0] as Record<string, unknown>;
expect(firstItem.source_layer).toBe("mcp_live_probe");
});
it("keeps snapshot fallback when MCP responds with error", async () => {
process.env[MCP_FLAG] = "1";
process.env[MCP_PROXY] = "http://127.0.0.1:6003";
process.env[MCP_CHANNEL] = "default";
const payload = JSON.stringify({
success: false,
data: null,
error: "channel_not_connected"
});
const fetchMock = vi.fn(async () => new Response(payload, { status: 200 }));
vi.stubGlobal("fetch", fetchMock);
const { AssistantDataLayer } = await import("../src/services/assistantDataLayer");
const dataLayer = new AssistantDataLayer(createSnapshotRoot());
const result = await dataLayer.executeRouteRuntime("hybrid_store_plus_live", "Проверь 60.01 остаток");
expect(fetchMock).toHaveBeenCalledTimes(1);
const summary = result.summary as Record<string, unknown>;
const liveSummary = summary.live_mcp as Record<string, unknown>;
expect(liveSummary.status).toBe("error");
expect(result.limitations.some((item) => item.includes("Live MCP"))).toBe(true);
});
});