ARCH: добавить вывод длительности активности MCP discovery
This commit is contained in:
+16
-1
@@ -97,6 +97,17 @@ function buildMustNotClaim(pilot) {
|
||||
}
|
||||
return claims;
|
||||
}
|
||||
function derivedActivityInferenceLine(pilot) {
|
||||
const period = pilot.derived_activity_period;
|
||||
if (!period) {
|
||||
return null;
|
||||
}
|
||||
return [
|
||||
`По подтвержденным строкам активности в 1С период взаимодействия можно оценить примерно как ${period.duration_human_ru}.`,
|
||||
`Первая найденная активность: ${period.first_activity_date}; последняя найденная активность: ${period.latest_activity_date}.`,
|
||||
"Это вывод по данным 1С, а не юридически подтвержденный возраст регистрации."
|
||||
].join(" ");
|
||||
}
|
||||
function buildAssistantMcpDiscoveryAnswerDraft(pilot) {
|
||||
const mode = modeFor(pilot);
|
||||
const reasonCodes = [...pilot.reason_codes, ...pilot.evidence.reason_codes];
|
||||
@@ -107,13 +118,17 @@ function buildAssistantMcpDiscoveryAnswerDraft(pilot) {
|
||||
if (pilot.evidence.inferred_facts.length > 0) {
|
||||
pushReason(reasonCodes, "answer_contains_bounded_inference");
|
||||
}
|
||||
const derivedInferenceLine = derivedActivityInferenceLine(pilot);
|
||||
const inferenceLines = derivedInferenceLine
|
||||
? [derivedInferenceLine]
|
||||
: pilot.evidence.inferred_facts;
|
||||
return {
|
||||
schema_version: exports.ASSISTANT_MCP_DISCOVERY_ANSWER_DRAFT_SCHEMA_VERSION,
|
||||
policy_owner: "assistantMcpDiscoveryAnswerAdapter",
|
||||
answer_mode: mode,
|
||||
headline: headlineFor(mode),
|
||||
confirmed_lines: uniqueStrings(pilot.evidence.confirmed_facts),
|
||||
inference_lines: uniqueStrings(pilot.evidence.inferred_facts),
|
||||
inference_lines: uniqueStrings(inferenceLines),
|
||||
unknown_lines: uniqueStrings(pilot.evidence.unknown_facts),
|
||||
limitation_lines: userFacingLimitations([...pilot.query_limitations, ...pilot.evidence.query_limitations]),
|
||||
next_step_line: nextStepFor(mode, pilot),
|
||||
|
||||
@@ -116,6 +116,74 @@ function summarizeRows(result) {
|
||||
}
|
||||
return `${result.fetched_rows} MCP document rows fetched, ${result.matched_rows} matched lifecycle scope`;
|
||||
}
|
||||
function rowDateValue(row) {
|
||||
const candidates = [
|
||||
row["Период"],
|
||||
row["Period"],
|
||||
row["period"],
|
||||
row["Дата"],
|
||||
row["Date"],
|
||||
row["date"]
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
const text = toNonEmptyString(candidate);
|
||||
const match = text?.match(/(\d{4})-(\d{2})-(\d{2})/);
|
||||
if (match) {
|
||||
return `${match[1]}-${match[2]}-${match[3]}`;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function monthDiff(firstIsoDate, latestIsoDate) {
|
||||
const first = new Date(`${firstIsoDate}T00:00:00.000Z`);
|
||||
const latest = new Date(`${latestIsoDate}T00:00:00.000Z`);
|
||||
if (Number.isNaN(first.getTime()) || Number.isNaN(latest.getTime()) || latest < first) {
|
||||
return 0;
|
||||
}
|
||||
let months = (latest.getUTCFullYear() - first.getUTCFullYear()) * 12;
|
||||
months += latest.getUTCMonth() - first.getUTCMonth();
|
||||
if (latest.getUTCDate() < first.getUTCDate()) {
|
||||
months -= 1;
|
||||
}
|
||||
return Math.max(0, months);
|
||||
}
|
||||
function formatDurationHumanRu(totalMonths) {
|
||||
const years = Math.floor(totalMonths / 12);
|
||||
const months = totalMonths % 12;
|
||||
const parts = [];
|
||||
if (years > 0) {
|
||||
parts.push(`${years} ${years === 1 ? "год" : years >= 2 && years <= 4 ? "года" : "лет"}`);
|
||||
}
|
||||
if (months > 0) {
|
||||
parts.push(`${months} ${months === 1 ? "месяц" : months >= 2 && months <= 4 ? "месяца" : "месяцев"}`);
|
||||
}
|
||||
return parts.length > 0 ? parts.join(" ") : "меньше месяца";
|
||||
}
|
||||
function deriveActivityPeriod(result) {
|
||||
if (!result || result.error || result.matched_rows <= 0) {
|
||||
return null;
|
||||
}
|
||||
const dates = result.rows
|
||||
.map((row) => rowDateValue(row))
|
||||
.filter((value) => Boolean(value))
|
||||
.sort();
|
||||
if (dates.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const first = dates[0];
|
||||
const latest = dates[dates.length - 1];
|
||||
const totalMonths = monthDiff(first, latest);
|
||||
return {
|
||||
first_activity_date: first,
|
||||
latest_activity_date: latest,
|
||||
matched_rows: result.matched_rows,
|
||||
duration_total_months: totalMonths,
|
||||
duration_years: Math.floor(totalMonths / 12),
|
||||
duration_months_remainder: totalMonths % 12,
|
||||
duration_human_ru: formatDurationHumanRu(totalMonths),
|
||||
inference_basis: "first_and_latest_confirmed_1c_activity_rows"
|
||||
};
|
||||
}
|
||||
function buildConfirmedFacts(result, counterparty) {
|
||||
if (result.error || result.matched_rows <= 0) {
|
||||
return [];
|
||||
@@ -166,6 +234,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||
probe_results: probeResults,
|
||||
evidence,
|
||||
source_rows_summary: null,
|
||||
derived_activity_period: null,
|
||||
query_limitations: ["MCP discovery pilot was blocked before execution"],
|
||||
reason_codes: reasonCodes
|
||||
};
|
||||
@@ -185,6 +254,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||
probe_results: probeResults,
|
||||
evidence,
|
||||
source_rows_summary: null,
|
||||
derived_activity_period: null,
|
||||
query_limitations: ["MCP discovery pilot needs more scope before execution"],
|
||||
reason_codes: reasonCodes
|
||||
};
|
||||
@@ -208,6 +278,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||
probe_results: probeResults,
|
||||
evidence,
|
||||
source_rows_summary: null,
|
||||
derived_activity_period: null,
|
||||
query_limitations: ["MCP discovery pilot scope is not implemented yet"],
|
||||
reason_codes: reasonCodes
|
||||
};
|
||||
@@ -231,6 +302,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||
probe_results: probeResults,
|
||||
evidence,
|
||||
source_rows_summary: null,
|
||||
derived_activity_period: null,
|
||||
query_limitations: ["Lifecycle recipe is not available"],
|
||||
reason_codes: reasonCodes
|
||||
};
|
||||
@@ -258,6 +330,10 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||
}
|
||||
}
|
||||
const sourceRowsSummary = queryResult ? summarizeRows(queryResult) : null;
|
||||
const derivedActivityPeriod = deriveActivityPeriod(queryResult);
|
||||
if (derivedActivityPeriod) {
|
||||
pushReason(reasonCodes, "pilot_derived_activity_period_from_confirmed_rows");
|
||||
}
|
||||
const evidence = (0, assistantMcpDiscoveryPolicy_1.resolveAssistantMcpDiscoveryEvidence)({
|
||||
plan: planner.discovery_plan,
|
||||
probeResults,
|
||||
@@ -280,6 +356,7 @@ async function executeAssistantMcpDiscoveryPilot(planner, deps = DEFAULT_DEPS) {
|
||||
probe_results: probeResults,
|
||||
evidence,
|
||||
source_rows_summary: sourceRowsSummary,
|
||||
derived_activity_period: derivedActivityPeriod,
|
||||
query_limitations: queryLimitations,
|
||||
reason_codes: reasonCodes
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user