ДОМЕНЫ - ВОПРОСЫ - Усилить НДС forecast: сумма в начале ответа, расширенный MCP probe источников и форматирование чисел
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import {
|
||||
import {
|
||||
ASSISTANT_MCP_CHANNEL,
|
||||
ASSISTANT_MCP_PROXY_URL,
|
||||
ASSISTANT_MCP_TIMEOUT_MS
|
||||
@@ -17,6 +17,13 @@ export interface AddressMcpQueryResult {
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
export interface AddressMcpMetadataRowsResult {
|
||||
fetched_rows: number;
|
||||
raw_rows: Array<Record<string, unknown>>;
|
||||
rows: Array<Record<string, unknown>>;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
function toStringValue(value: unknown): string {
|
||||
if (value === null || value === undefined) {
|
||||
return "";
|
||||
@@ -188,7 +195,12 @@ function parseRowsFromTextTable(source: string): Array<Record<string, unknown>>
|
||||
return normalizeMojibakeRows(rows);
|
||||
}
|
||||
|
||||
function parseExecutePayload(payload: unknown): AddressMcpQueryResult {
|
||||
function parseRowsPayload(
|
||||
payload: unknown,
|
||||
options: {
|
||||
allowSingleObjectRow?: boolean;
|
||||
} = {}
|
||||
): AddressMcpQueryResult {
|
||||
if (!payload || typeof payload !== "object") {
|
||||
return {
|
||||
ok: false,
|
||||
@@ -240,6 +252,14 @@ function parseExecutePayload(payload: unknown): AddressMcpQueryResult {
|
||||
};
|
||||
}
|
||||
|
||||
if (source.data && typeof source.data === "object" && options.allowSingleObjectRow) {
|
||||
return {
|
||||
ok: true,
|
||||
rows: [normalizeMojibakeValue(source.data) as Record<string, unknown>],
|
||||
error: null
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
rows: [],
|
||||
@@ -312,7 +332,7 @@ export async function executeAddressMcpQuery(input: {
|
||||
}
|
||||
|
||||
const payload = responseText.trim() ? (JSON.parse(responseText) as unknown) : {};
|
||||
const parsed = parseExecutePayload(payload);
|
||||
const parsed = parseRowsPayload(payload);
|
||||
if (!parsed.ok) {
|
||||
return {
|
||||
fetched_rows: 0,
|
||||
@@ -344,3 +364,100 @@ export async function executeAddressMcpQuery(input: {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
export async function executeAddressMcpMetadata(input: {
|
||||
filter?: string;
|
||||
meta_type?: string | string[];
|
||||
name_mask?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
sections?: string[];
|
||||
extension_name?: string | null;
|
||||
}): Promise<AddressMcpMetadataRowsResult> {
|
||||
const endpoint = buildMcpUrl("/api/get_metadata");
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), Math.max(300, ASSISTANT_MCP_TIMEOUT_MS));
|
||||
try {
|
||||
const body: Record<string, unknown> = {};
|
||||
if (typeof input.filter === "string" && input.filter.trim().length > 0) {
|
||||
body.filter = input.filter.trim();
|
||||
}
|
||||
if (typeof input.meta_type === "string" && input.meta_type.trim().length > 0) {
|
||||
body.meta_type = input.meta_type.trim();
|
||||
} else if (Array.isArray(input.meta_type) && input.meta_type.length > 0) {
|
||||
const values = input.meta_type
|
||||
.map((item) => String(item ?? "").trim())
|
||||
.filter((item) => item.length > 0);
|
||||
if (values.length > 0) {
|
||||
body.meta_type = values;
|
||||
}
|
||||
}
|
||||
if (typeof input.name_mask === "string" && input.name_mask.trim().length > 0) {
|
||||
body.name_mask = input.name_mask.trim();
|
||||
}
|
||||
if (typeof input.limit === "number" && Number.isFinite(input.limit)) {
|
||||
body.limit = Math.max(1, Math.min(1000, Math.trunc(input.limit)));
|
||||
}
|
||||
if (typeof input.offset === "number" && Number.isFinite(input.offset)) {
|
||||
body.offset = Math.max(0, Math.min(1_000_000, Math.trunc(input.offset)));
|
||||
}
|
||||
if (Array.isArray(input.sections) && input.sections.length > 0) {
|
||||
const sections = input.sections
|
||||
.map((item) => String(item ?? "").trim())
|
||||
.filter((item) => item.length > 0);
|
||||
if (sections.length > 0) {
|
||||
body.sections = sections;
|
||||
}
|
||||
}
|
||||
if (input.extension_name !== undefined) {
|
||||
body.extension_name = input.extension_name;
|
||||
}
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"content-type": "application/json; charset=utf-8"
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
signal: controller.signal
|
||||
});
|
||||
|
||||
const responseText = await response.text();
|
||||
if (!response.ok) {
|
||||
return {
|
||||
fetched_rows: 0,
|
||||
raw_rows: [],
|
||||
rows: [],
|
||||
error: `MCP HTTP ${response.status}: ${responseText.slice(0, 240)}`
|
||||
};
|
||||
}
|
||||
|
||||
const payload = responseText.trim() ? (JSON.parse(responseText) as unknown) : {};
|
||||
const parsed = parseRowsPayload(payload, { allowSingleObjectRow: true });
|
||||
if (!parsed.ok) {
|
||||
return {
|
||||
fetched_rows: 0,
|
||||
raw_rows: [],
|
||||
rows: [],
|
||||
error: parsed.error
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
fetched_rows: parsed.rows.length,
|
||||
raw_rows: parsed.rows,
|
||||
rows: parsed.rows,
|
||||
error: null
|
||||
};
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
fetched_rows: 0,
|
||||
raw_rows: [],
|
||||
rows: [],
|
||||
error: `MCP fetch failed: ${message}`
|
||||
};
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user