Compare commits
2 Commits
ede15c6080
...
88c92e316a
| Author | SHA1 | Date |
|---|---|---|
|
|
88c92e316a | |
|
|
987419fade |
|
|
@ -3159,7 +3159,7 @@ function composeFactualReplyBody(intent, rows, options = {}) {
|
||||||
: `Коротко: подтвержденный НДС к уплате за налоговый период${organizationScopeLabel} — ${formatConfirmedMoney(vatToPay)}.`;
|
: `Коротко: подтвержденный НДС к уплате за налоговый период${organizationScopeLabel} — ${formatConfirmedMoney(vatToPay)}.`;
|
||||||
const lines = [
|
const lines = [
|
||||||
directVatLine,
|
directVatLine,
|
||||||
"Расчет сделан по книгам продаж и покупок.",
|
"Расчет сделан по подтвержденным строкам книг продаж и покупок.",
|
||||||
"",
|
"",
|
||||||
"Что вошло в расчет:",
|
"Что вошло в расчет:",
|
||||||
...(organizationLabel ? [`- Организация: ${organizationLabel}.`] : []),
|
...(organizationLabel ? [`- Организация: ${organizationLabel}.`] : []),
|
||||||
|
|
@ -3169,6 +3169,7 @@ function composeFactualReplyBody(intent, rows, options = {}) {
|
||||||
`- НДС по книге покупок (вычеты): ${formatConfirmedMoney(purchaseVat)}.`,
|
`- НДС по книге покупок (вычеты): ${formatConfirmedMoney(purchaseVat)}.`,
|
||||||
`- Нетто НДС (книга продаж - книга покупок): ${formatConfirmedMoney(netVat)}.`
|
`- Нетто НДС (книга продаж - книга покупок): ${formatConfirmedMoney(netVat)}.`
|
||||||
];
|
];
|
||||||
|
lines.push("", "Граница вывода: это подтвержденный баланс по найденным строкам книг продаж/покупок, но не полный налоговый вердикт и не сверка декларации; для финального вывода нужно отдельно проверить корректировки, применимость вычетов, закрытие периода и первичные документы.");
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
lines.push("", "За выбранный налоговый период не найдены строки книг продаж/покупок, поэтому подтвержденная сумма к уплате равна 0.");
|
lines.push("", "За выбранный налоговый период не найдены строки книг продаж/покупок, поэтому подтвержденная сумма к уплате равна 0.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -327,9 +327,6 @@ function parseBusinessOverviewProofBundlesFromTextV2(value, counterpartyHint, to
|
||||||
return valueBundle || documentBundle ? { valueBundle, documentBundle } : null;
|
return valueBundle || documentBundle ? { valueBundle, documentBundle } : null;
|
||||||
}
|
}
|
||||||
function findRecentBusinessOverviewProofBundles(input) {
|
function findRecentBusinessOverviewProofBundles(input) {
|
||||||
if (!input.counterpartyHint) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (let index = input.sessionItems.length - 1; index >= 0; index -= 1) {
|
for (let index = input.sessionItems.length - 1; index >= 0; index -= 1) {
|
||||||
const item = toRecordObject(input.sessionItems[index]);
|
const item = toRecordObject(input.sessionItems[index]);
|
||||||
if (input.toNonEmptyString(item?.role) !== "assistant") {
|
if (input.toNonEmptyString(item?.role) !== "assistant") {
|
||||||
|
|
@ -344,7 +341,7 @@ function findRecentBusinessOverviewProofBundles(input) {
|
||||||
const documentBundle = toRecordObject(turnMeaningRef.previous_counterparty_document_bundle);
|
const documentBundle = toRecordObject(turnMeaningRef.previous_counterparty_document_bundle);
|
||||||
if (valueBundle || documentBundle) {
|
if (valueBundle || documentBundle) {
|
||||||
const bundleCounterparty = turnMeaningCounterpartyName(turnMeaningRef, valueBundle, documentBundle, input.toNonEmptyString);
|
const bundleCounterparty = turnMeaningCounterpartyName(turnMeaningRef, valueBundle, documentBundle, input.toNonEmptyString);
|
||||||
if (sameEntityHint(input.counterpartyHint, bundleCounterparty)) {
|
if (!input.counterpartyHint || sameEntityHint(input.counterpartyHint, bundleCounterparty)) {
|
||||||
return { valueBundle, documentBundle };
|
return { valueBundle, documentBundle };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +353,7 @@ function findRecentBusinessOverviewProofBundles(input) {
|
||||||
}
|
}
|
||||||
const parsedCounterparty = input.toNonEmptyString(parsedBundles.valueBundle?.counterparty) ??
|
const parsedCounterparty = input.toNonEmptyString(parsedBundles.valueBundle?.counterparty) ??
|
||||||
input.toNonEmptyString(parsedBundles.documentBundle?.counterparty);
|
input.toNonEmptyString(parsedBundles.documentBundle?.counterparty);
|
||||||
if (!sameEntityHint(input.counterpartyHint, parsedCounterparty)) {
|
if (input.counterpartyHint && !sameEntityHint(input.counterpartyHint, parsedCounterparty)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return parsedBundles;
|
return parsedBundles;
|
||||||
|
|
@ -381,7 +378,7 @@ function mergeBusinessOverviewProofBundlesFromNavigationState(input) {
|
||||||
const entities = toRecordObject(input.predecomposeContract?.entities);
|
const entities = toRecordObject(input.predecomposeContract?.entities);
|
||||||
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
||||||
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
||||||
if (!hasComparisonScopeProofCue(input.userMessage)) {
|
if (!hasComparisonScopeProofCue(input.userMessage) && !hasCurrentOrganizationSelection) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||||
|
|
@ -416,10 +413,13 @@ function mergeBusinessOverviewProofBundlesFromNavigationState(input) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function mergeBusinessOverviewProofBundlesFromSessionItems(input) {
|
function mergeBusinessOverviewProofBundlesFromSessionItems(input) {
|
||||||
if (!hasComparisonScopeProofCue(input.userMessage)) {
|
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
||||||
|
const entities = toRecordObject(input.predecomposeContract?.entities);
|
||||||
|
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
||||||
|
if (!hasComparisonScopeProofCue(input.userMessage) && !businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
if (!isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString)) {
|
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
const currentValueBundle = toRecordObject(input.followupContext?.previous_discovery_bidirectional_value_flow);
|
const currentValueBundle = toRecordObject(input.followupContext?.previous_discovery_bidirectional_value_flow);
|
||||||
|
|
@ -438,8 +438,21 @@ function mergeBusinessOverviewProofBundlesFromSessionItems(input) {
|
||||||
if (!proofBundles) {
|
if (!proofBundles) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
|
const recoveredCounterparty = counterpartyHint ??
|
||||||
|
input.toNonEmptyString(proofBundles.valueBundle?.counterparty) ??
|
||||||
|
input.toNonEmptyString(proofBundles.documentBundle?.counterparty);
|
||||||
return {
|
return {
|
||||||
...(input.followupContext ?? {}),
|
...(input.followupContext ?? {}),
|
||||||
|
previous_intent: input.toNonEmptyString(input.followupContext?.previous_intent) ?? "business_overview",
|
||||||
|
target_intent: input.toNonEmptyString(input.followupContext?.target_intent) ?? "business_overview",
|
||||||
|
previous_discovery_pilot_scope: input.toNonEmptyString(input.followupContext?.previous_discovery_pilot_scope) ??
|
||||||
|
"business_overview_route_template_v1",
|
||||||
|
previous_discovery_loop_selected_chain_id: input.toNonEmptyString(input.followupContext?.previous_discovery_loop_selected_chain_id) ?? "business_overview",
|
||||||
|
previous_discovery_loop_asked_domain_family: input.toNonEmptyString(input.followupContext?.previous_discovery_loop_asked_domain_family) ?? "business_overview",
|
||||||
|
previous_discovery_loop_asked_action_family: input.toNonEmptyString(input.followupContext?.previous_discovery_loop_asked_action_family) ?? "broad_evaluation",
|
||||||
|
previous_discovery_loop_metadata_scope_hint: input.toNonEmptyString(input.followupContext?.previous_discovery_loop_metadata_scope_hint) ?? recoveredCounterparty ?? undefined,
|
||||||
|
previous_anchor_type: input.toNonEmptyString(input.followupContext?.previous_anchor_type) ?? (recoveredCounterparty ? "counterparty" : undefined),
|
||||||
|
previous_anchor_value: input.toNonEmptyString(input.followupContext?.previous_anchor_value) ?? recoveredCounterparty ?? undefined,
|
||||||
previous_discovery_bidirectional_value_flow: currentValueBundle ?? proofBundles.valueBundle ?? undefined,
|
previous_discovery_bidirectional_value_flow: currentValueBundle ?? proofBundles.valueBundle ?? undefined,
|
||||||
previous_discovery_document_summary: currentDocumentBundle ?? proofBundles.documentBundle ?? undefined
|
previous_discovery_document_summary: currentDocumentBundle ?? proofBundles.documentBundle ?? undefined
|
||||||
};
|
};
|
||||||
|
|
@ -620,6 +633,7 @@ async function buildAssistantAddressOrchestrationRuntime(input) {
|
||||||
const discoveryFollowupContextWithProofBundles = mergeBusinessOverviewProofBundlesFromSessionItems({
|
const discoveryFollowupContextWithProofBundles = mergeBusinessOverviewProofBundlesFromSessionItems({
|
||||||
followupContext: discoveryFollowupContext,
|
followupContext: discoveryFollowupContext,
|
||||||
userMessage: input.userMessage,
|
userMessage: input.userMessage,
|
||||||
|
predecomposeContract,
|
||||||
sessionItems: input.sessionItems,
|
sessionItems: input.sessionItems,
|
||||||
toNonEmptyString: input.toNonEmptyString
|
toNonEmptyString: input.toNonEmptyString
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -933,7 +933,7 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
||||||
return joinBusinessReplyLines(lines);
|
return joinBusinessReplyLines(lines);
|
||||||
}
|
}
|
||||||
if (plainOrganizationClarificationSelection && (incomingAmount || outgoingAmount || netAmount)) {
|
if (plainOrganizationClarificationSelection && (incomingAmount || outgoingAmount || netAmount)) {
|
||||||
lines.push(`Коротко: по компании ${organizationScope} ${period} подтвержден company-level денежный срез: входящие ${incomingAmount ?? "0 руб."}, исходящие ${outgoingAmount ?? "0 руб."}, операционное нетто ${sentenceAmount(netAmount) ?? netAmount ?? "0 руб."}.`);
|
lines.push(`по компании ${organizationScope} ${period} подтвержден company-level денежный срез: входящие ${incomingAmount ?? "0 руб."}, исходящие ${outgoingAmount ?? "0 руб."}, операционное нетто ${sentenceAmount(netAmount) ?? netAmount ?? "0 руб."}.`);
|
||||||
if (previousCounterpartySummary) {
|
if (previousCounterpartySummary) {
|
||||||
lines.push(previousCounterpartySummary.line);
|
lines.push(previousCounterpartySummary.line);
|
||||||
}
|
}
|
||||||
|
|
@ -1137,7 +1137,13 @@ function buildCompactBusinessOverviewReply(entryPoint, draft) {
|
||||||
(actionFamily === "broad_evaluation" || unsupportedFamily === "broad_business_evaluation")) {
|
(actionFamily === "broad_evaluation" || unsupportedFamily === "broad_business_evaluation")) {
|
||||||
const subject = organizationScope ?? "компания";
|
const subject = organizationScope ?? "компания";
|
||||||
const periodWithoutPrefix = period.replace(/^за\s+/iu, "");
|
const periodWithoutPrefix = period.replace(/^за\s+/iu, "");
|
||||||
lines.push(`Коротко: по ограниченному проверенному 1С-срезу ${subject} выглядит как бизнес с крупными контрактными денежными потоками и заметной зависимостью от нескольких крупных контрагентов, а не как равномерный поток мелких продаж; это не аудиторское заключение и не подтвержденная чистая прибыль.`);
|
const executiveFacts = [
|
||||||
|
incomingAmount ? `входящие ${incomingAmount}` : null,
|
||||||
|
outgoingAmount ? `исходящие ${outgoingAmount}` : null,
|
||||||
|
netAmount ? `${netDirection} ${sentenceAmount(netAmount) ?? netAmount}` : null
|
||||||
|
].filter((value) => Boolean(value));
|
||||||
|
lines.push(`По подтвержденным строкам 1С ${subject} за ${periodWithoutPrefix}: ${executiveFacts.length > 0 ? executiveFacts.join(", ") : "денежные метрики не подтверждены"}; это ограниченный проверенный срез, не аудиторское заключение и не подтвержденная чистая прибыль.`);
|
||||||
|
lines.push("Интерпретация: по этому срезу видны крупные контрактные денежные потоки и заметная зависимость от нескольких крупных контрагентов, а не равномерный поток мелких продаж.");
|
||||||
lines.push("Что видно в ограниченном денежном срезе:");
|
lines.push("Что видно в ограниченном денежном срезе:");
|
||||||
if (incomingAmount) {
|
if (incomingAmount) {
|
||||||
lines.push(`- входящие деньги за ${periodWithoutPrefix}: ${incomingAmount};`);
|
lines.push(`- входящие деньги за ${periodWithoutPrefix}: ${incomingAmount};`);
|
||||||
|
|
|
||||||
|
|
@ -2088,10 +2088,13 @@ function buildAssistantMcpDiscoveryTurnInput(input) {
|
||||||
: undefined,
|
: undefined,
|
||||||
explicit_entity_candidates: businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty ? [] : entityCandidates,
|
explicit_entity_candidates: businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty ? [] : entityCandidates,
|
||||||
business_overview_separate_entity_candidates: businessOverviewSeparateEntityCandidates,
|
business_overview_separate_entity_candidates: businessOverviewSeparateEntityCandidates,
|
||||||
previous_counterparty_value_flow_bundle: businessOverviewSignal && followupSeed.previousBidirectionalValueFlow
|
previous_counterparty_value_flow_bundle: (businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty) &&
|
||||||
|
followupSeed.previousBidirectionalValueFlow
|
||||||
? followupSeed.previousBidirectionalValueFlow
|
? followupSeed.previousBidirectionalValueFlow
|
||||||
: undefined,
|
: undefined,
|
||||||
previous_counterparty_document_bundle: businessOverviewSignal && followupSeed.previousDocumentSummary ? followupSeed.previousDocumentSummary : undefined,
|
previous_counterparty_document_bundle: (businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty) && followupSeed.previousDocumentSummary
|
||||||
|
? followupSeed.previousDocumentSummary
|
||||||
|
: undefined,
|
||||||
metadata_ambiguity_entity_sets: metadataAmbiguityLaneClarificationApplicable && followupSeed.metadataAmbiguityEntitySets.length > 0
|
metadata_ambiguity_entity_sets: metadataAmbiguityLaneClarificationApplicable && followupSeed.metadataAmbiguityEntitySets.length > 0
|
||||||
? followupSeed.metadataAmbiguityEntitySets
|
? followupSeed.metadataAmbiguityEntitySets
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,9 @@ function createAssistantTransitionPolicy(deps) {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const match = text.match(/Отдельно\s+по\s+контрагенту\s+([^:\n]+):\s*подтверждено\s+получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^,\n]+?руб\.?),\s*расчетное\s+нетто\s+в\s+нашу\s+сторону\s+([^.\n]+?руб\.?)/iu);
|
const boundaryMatch = text.match(/Отдельно\s+по\s+контрагенту\s+([^:\n]+):\s*подтверждено\s+получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^,\n]+?руб\.?),\s*расчетное\s+нетто\s+в\s+нашу\s+сторону\s+([^.\n]+?руб\.?)/iu);
|
||||||
|
const directMatch = text.match(/по\s+контрагенту\s+([^.\n]+?)\s+в\s+проверенном\s+окне[\s\S]{0,160}?получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^;\n]+?руб\.?);\s*расчетное\s+нетто\s+в\s+нашу\s+сторону:?\s*([^.\n]+?руб\.?)/iu);
|
||||||
|
const match = boundaryMatch ?? directMatch;
|
||||||
if (!match?.[1] || !match?.[2] || !match?.[3] || !match?.[4]) {
|
if (!match?.[1] || !match?.[2] || !match?.[3] || !match?.[4]) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4053,7 +4053,7 @@ function composeFactualReplyBody(
|
||||||
|
|
||||||
const lines = [
|
const lines = [
|
||||||
directVatLine,
|
directVatLine,
|
||||||
"Расчет сделан по книгам продаж и покупок.",
|
"Расчет сделан по подтвержденным строкам книг продаж и покупок.",
|
||||||
"",
|
"",
|
||||||
"Что вошло в расчет:",
|
"Что вошло в расчет:",
|
||||||
...(organizationLabel ? [`- Организация: ${organizationLabel}.`] : []),
|
...(organizationLabel ? [`- Организация: ${organizationLabel}.`] : []),
|
||||||
|
|
@ -4063,6 +4063,10 @@ function composeFactualReplyBody(
|
||||||
`- НДС по книге покупок (вычеты): ${formatConfirmedMoney(purchaseVat)}.`,
|
`- НДС по книге покупок (вычеты): ${formatConfirmedMoney(purchaseVat)}.`,
|
||||||
`- Нетто НДС (книга продаж - книга покупок): ${formatConfirmedMoney(netVat)}.`
|
`- Нетто НДС (книга продаж - книга покупок): ${formatConfirmedMoney(netVat)}.`
|
||||||
];
|
];
|
||||||
|
lines.push(
|
||||||
|
"",
|
||||||
|
"Граница вывода: это подтвержденный баланс по найденным строкам книг продаж/покупок, но не полный налоговый вердикт и не сверка декларации; для финального вывода нужно отдельно проверить корректировки, применимость вычетов, закрытие периода и первичные документы."
|
||||||
|
);
|
||||||
|
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
lines.push(
|
lines.push(
|
||||||
|
|
|
||||||
|
|
@ -483,9 +483,6 @@ function findRecentBusinessOverviewProofBundles(input: {
|
||||||
counterpartyHint: string | null;
|
counterpartyHint: string | null;
|
||||||
toNonEmptyString: BuildAssistantAddressOrchestrationRuntimeInput["toNonEmptyString"];
|
toNonEmptyString: BuildAssistantAddressOrchestrationRuntimeInput["toNonEmptyString"];
|
||||||
}): { valueBundle: Record<string, unknown> | null; documentBundle: Record<string, unknown> | null } | null {
|
}): { valueBundle: Record<string, unknown> | null; documentBundle: Record<string, unknown> | null } | null {
|
||||||
if (!input.counterpartyHint) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (let index = input.sessionItems.length - 1; index >= 0; index -= 1) {
|
for (let index = input.sessionItems.length - 1; index >= 0; index -= 1) {
|
||||||
const item = toRecordObject(input.sessionItems[index]);
|
const item = toRecordObject(input.sessionItems[index]);
|
||||||
if (input.toNonEmptyString(item?.role) !== "assistant") {
|
if (input.toNonEmptyString(item?.role) !== "assistant") {
|
||||||
|
|
@ -505,7 +502,7 @@ function findRecentBusinessOverviewProofBundles(input: {
|
||||||
documentBundle,
|
documentBundle,
|
||||||
input.toNonEmptyString
|
input.toNonEmptyString
|
||||||
);
|
);
|
||||||
if (sameEntityHint(input.counterpartyHint, bundleCounterparty)) {
|
if (!input.counterpartyHint || sameEntityHint(input.counterpartyHint, bundleCounterparty)) {
|
||||||
return { valueBundle, documentBundle };
|
return { valueBundle, documentBundle };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -519,7 +516,7 @@ function findRecentBusinessOverviewProofBundles(input: {
|
||||||
const parsedCounterparty =
|
const parsedCounterparty =
|
||||||
input.toNonEmptyString(parsedBundles.valueBundle?.counterparty) ??
|
input.toNonEmptyString(parsedBundles.valueBundle?.counterparty) ??
|
||||||
input.toNonEmptyString(parsedBundles.documentBundle?.counterparty);
|
input.toNonEmptyString(parsedBundles.documentBundle?.counterparty);
|
||||||
if (!sameEntityHint(input.counterpartyHint, parsedCounterparty)) {
|
if (input.counterpartyHint && !sameEntityHint(input.counterpartyHint, parsedCounterparty)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return parsedBundles;
|
return parsedBundles;
|
||||||
|
|
@ -551,7 +548,7 @@ function mergeBusinessOverviewProofBundlesFromNavigationState(input: {
|
||||||
const entities = toRecordObject(input.predecomposeContract?.entities);
|
const entities = toRecordObject(input.predecomposeContract?.entities);
|
||||||
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
||||||
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
||||||
if (!hasComparisonScopeProofCue(input.userMessage)) {
|
if (!hasComparisonScopeProofCue(input.userMessage) && !hasCurrentOrganizationSelection) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||||
|
|
@ -597,13 +594,17 @@ function mergeBusinessOverviewProofBundlesFromNavigationState(input: {
|
||||||
function mergeBusinessOverviewProofBundlesFromSessionItems(input: {
|
function mergeBusinessOverviewProofBundlesFromSessionItems(input: {
|
||||||
followupContext: Record<string, unknown> | null;
|
followupContext: Record<string, unknown> | null;
|
||||||
userMessage: string;
|
userMessage: string;
|
||||||
|
predecomposeContract: Record<string, unknown> | null;
|
||||||
sessionItems: unknown[];
|
sessionItems: unknown[];
|
||||||
toNonEmptyString: BuildAssistantAddressOrchestrationRuntimeInput["toNonEmptyString"];
|
toNonEmptyString: BuildAssistantAddressOrchestrationRuntimeInput["toNonEmptyString"];
|
||||||
}): Record<string, unknown> | null {
|
}): Record<string, unknown> | null {
|
||||||
if (!hasComparisonScopeProofCue(input.userMessage)) {
|
const businessOverviewFollowup = isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString);
|
||||||
|
const entities = toRecordObject(input.predecomposeContract?.entities);
|
||||||
|
const hasCurrentOrganizationSelection = Boolean(input.toNonEmptyString(entities?.organization));
|
||||||
|
if (!hasComparisonScopeProofCue(input.userMessage) && !businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
if (!isBusinessOverviewDiscoveryFollowup(input.followupContext, input.toNonEmptyString)) {
|
if (!businessOverviewFollowup && !hasCurrentOrganizationSelection) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
const currentValueBundle = toRecordObject(input.followupContext?.previous_discovery_bidirectional_value_flow);
|
const currentValueBundle = toRecordObject(input.followupContext?.previous_discovery_bidirectional_value_flow);
|
||||||
|
|
@ -622,8 +623,27 @@ function mergeBusinessOverviewProofBundlesFromSessionItems(input: {
|
||||||
if (!proofBundles) {
|
if (!proofBundles) {
|
||||||
return input.followupContext;
|
return input.followupContext;
|
||||||
}
|
}
|
||||||
|
const recoveredCounterparty =
|
||||||
|
counterpartyHint ??
|
||||||
|
input.toNonEmptyString(proofBundles.valueBundle?.counterparty) ??
|
||||||
|
input.toNonEmptyString(proofBundles.documentBundle?.counterparty);
|
||||||
return {
|
return {
|
||||||
...(input.followupContext ?? {}),
|
...(input.followupContext ?? {}),
|
||||||
|
previous_intent: input.toNonEmptyString(input.followupContext?.previous_intent) ?? "business_overview",
|
||||||
|
target_intent: input.toNonEmptyString(input.followupContext?.target_intent) ?? "business_overview",
|
||||||
|
previous_discovery_pilot_scope:
|
||||||
|
input.toNonEmptyString(input.followupContext?.previous_discovery_pilot_scope) ??
|
||||||
|
"business_overview_route_template_v1",
|
||||||
|
previous_discovery_loop_selected_chain_id:
|
||||||
|
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_selected_chain_id) ?? "business_overview",
|
||||||
|
previous_discovery_loop_asked_domain_family:
|
||||||
|
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_asked_domain_family) ?? "business_overview",
|
||||||
|
previous_discovery_loop_asked_action_family:
|
||||||
|
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_asked_action_family) ?? "broad_evaluation",
|
||||||
|
previous_discovery_loop_metadata_scope_hint:
|
||||||
|
input.toNonEmptyString(input.followupContext?.previous_discovery_loop_metadata_scope_hint) ?? recoveredCounterparty ?? undefined,
|
||||||
|
previous_anchor_type: input.toNonEmptyString(input.followupContext?.previous_anchor_type) ?? (recoveredCounterparty ? "counterparty" : undefined),
|
||||||
|
previous_anchor_value: input.toNonEmptyString(input.followupContext?.previous_anchor_value) ?? recoveredCounterparty ?? undefined,
|
||||||
previous_discovery_bidirectional_value_flow:
|
previous_discovery_bidirectional_value_flow:
|
||||||
currentValueBundle ?? proofBundles.valueBundle ?? undefined,
|
currentValueBundle ?? proofBundles.valueBundle ?? undefined,
|
||||||
previous_discovery_document_summary: currentDocumentBundle ?? proofBundles.documentBundle ?? undefined
|
previous_discovery_document_summary: currentDocumentBundle ?? proofBundles.documentBundle ?? undefined
|
||||||
|
|
@ -904,6 +924,7 @@ export async function buildAssistantAddressOrchestrationRuntime(
|
||||||
const discoveryFollowupContextWithProofBundles = mergeBusinessOverviewProofBundlesFromSessionItems({
|
const discoveryFollowupContextWithProofBundles = mergeBusinessOverviewProofBundlesFromSessionItems({
|
||||||
followupContext: discoveryFollowupContext,
|
followupContext: discoveryFollowupContext,
|
||||||
userMessage: input.userMessage,
|
userMessage: input.userMessage,
|
||||||
|
predecomposeContract,
|
||||||
sessionItems: input.sessionItems,
|
sessionItems: input.sessionItems,
|
||||||
toNonEmptyString: input.toNonEmptyString
|
toNonEmptyString: input.toNonEmptyString
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1137,7 +1137,7 @@ function buildCompactBusinessOverviewReply(
|
||||||
|
|
||||||
if (plainOrganizationClarificationSelection && (incomingAmount || outgoingAmount || netAmount)) {
|
if (plainOrganizationClarificationSelection && (incomingAmount || outgoingAmount || netAmount)) {
|
||||||
lines.push(
|
lines.push(
|
||||||
`Коротко: по компании ${organizationScope} ${period} подтвержден company-level денежный срез: входящие ${incomingAmount ?? "0 руб."}, исходящие ${outgoingAmount ?? "0 руб."}, операционное нетто ${sentenceAmount(netAmount) ?? netAmount ?? "0 руб."}.`
|
`по компании ${organizationScope} ${period} подтвержден company-level денежный срез: входящие ${incomingAmount ?? "0 руб."}, исходящие ${outgoingAmount ?? "0 руб."}, операционное нетто ${sentenceAmount(netAmount) ?? netAmount ?? "0 руб."}.`
|
||||||
);
|
);
|
||||||
if (previousCounterpartySummary) {
|
if (previousCounterpartySummary) {
|
||||||
lines.push(previousCounterpartySummary.line);
|
lines.push(previousCounterpartySummary.line);
|
||||||
|
|
@ -1403,8 +1403,16 @@ function buildCompactBusinessOverviewReply(
|
||||||
) {
|
) {
|
||||||
const subject = organizationScope ?? "компания";
|
const subject = organizationScope ?? "компания";
|
||||||
const periodWithoutPrefix = period.replace(/^за\s+/iu, "");
|
const periodWithoutPrefix = period.replace(/^за\s+/iu, "");
|
||||||
|
const executiveFacts = [
|
||||||
|
incomingAmount ? `входящие ${incomingAmount}` : null,
|
||||||
|
outgoingAmount ? `исходящие ${outgoingAmount}` : null,
|
||||||
|
netAmount ? `${netDirection} ${sentenceAmount(netAmount) ?? netAmount}` : null
|
||||||
|
].filter((value): value is string => Boolean(value));
|
||||||
lines.push(
|
lines.push(
|
||||||
`Коротко: по ограниченному проверенному 1С-срезу ${subject} выглядит как бизнес с крупными контрактными денежными потоками и заметной зависимостью от нескольких крупных контрагентов, а не как равномерный поток мелких продаж; это не аудиторское заключение и не подтвержденная чистая прибыль.`
|
`По подтвержденным строкам 1С ${subject} за ${periodWithoutPrefix}: ${executiveFacts.length > 0 ? executiveFacts.join(", ") : "денежные метрики не подтверждены"}; это ограниченный проверенный срез, не аудиторское заключение и не подтвержденная чистая прибыль.`
|
||||||
|
);
|
||||||
|
lines.push(
|
||||||
|
"Интерпретация: по этому срезу видны крупные контрактные денежные потоки и заметная зависимость от нескольких крупных контрагентов, а не равномерный поток мелких продаж."
|
||||||
);
|
);
|
||||||
lines.push("Что видно в ограниченном денежном срезе:");
|
lines.push("Что видно в ограниченном денежном срезе:");
|
||||||
if (incomingAmount) {
|
if (incomingAmount) {
|
||||||
|
|
|
||||||
|
|
@ -2779,11 +2779,14 @@ export function buildAssistantMcpDiscoveryTurnInput(
|
||||||
businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty ? [] : entityCandidates,
|
businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty ? [] : entityCandidates,
|
||||||
business_overview_separate_entity_candidates: businessOverviewSeparateEntityCandidates,
|
business_overview_separate_entity_candidates: businessOverviewSeparateEntityCandidates,
|
||||||
previous_counterparty_value_flow_bundle:
|
previous_counterparty_value_flow_bundle:
|
||||||
businessOverviewSignal && followupSeed.previousBidirectionalValueFlow
|
(businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty) &&
|
||||||
|
followupSeed.previousBidirectionalValueFlow
|
||||||
? followupSeed.previousBidirectionalValueFlow
|
? followupSeed.previousBidirectionalValueFlow
|
||||||
: undefined,
|
: undefined,
|
||||||
previous_counterparty_document_bundle:
|
previous_counterparty_document_bundle:
|
||||||
businessOverviewSignal && followupSeed.previousDocumentSummary ? followupSeed.previousDocumentSummary : undefined,
|
(businessOverviewSignal || shouldPreserveBusinessOverviewSeparateCounterparty) && followupSeed.previousDocumentSummary
|
||||||
|
? followupSeed.previousDocumentSummary
|
||||||
|
: undefined,
|
||||||
metadata_ambiguity_entity_sets:
|
metadata_ambiguity_entity_sets:
|
||||||
metadataAmbiguityLaneClarificationApplicable && followupSeed.metadataAmbiguityEntitySets.length > 0
|
metadataAmbiguityLaneClarificationApplicable && followupSeed.metadataAmbiguityEntitySets.length > 0
|
||||||
? followupSeed.metadataAmbiguityEntitySets
|
? followupSeed.metadataAmbiguityEntitySets
|
||||||
|
|
|
||||||
|
|
@ -555,9 +555,13 @@ export function createAssistantTransitionPolicy(deps) {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const match = text.match(
|
const boundaryMatch = text.match(
|
||||||
/Отдельно\s+по\s+контрагенту\s+([^:\n]+):\s*подтверждено\s+получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^,\n]+?руб\.?),\s*расчетное\s+нетто\s+в\s+нашу\s+сторону\s+([^.\n]+?руб\.?)/iu
|
/Отдельно\s+по\s+контрагенту\s+([^:\n]+):\s*подтверждено\s+получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^,\n]+?руб\.?),\s*расчетное\s+нетто\s+в\s+нашу\s+сторону\s+([^.\n]+?руб\.?)/iu
|
||||||
);
|
);
|
||||||
|
const directMatch = text.match(
|
||||||
|
/по\s+контрагенту\s+([^.\n]+?)\s+в\s+проверенном\s+окне[\s\S]{0,160}?получили\s+([^,\n]+?руб\.?),\s*заплатили\s+([^;\n]+?руб\.?);\s*расчетное\s+нетто\s+в\s+нашу\s+сторону:?\s*([^.\n]+?руб\.?)/iu
|
||||||
|
);
|
||||||
|
const match = boundaryMatch ?? directMatch;
|
||||||
if (!match?.[1] || !match?.[2] || !match?.[3] || !match?.[4]) {
|
if (!match?.[1] || !match?.[2] || !match?.[3] || !match?.[4]) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2139,8 +2139,11 @@ describe("address compose stage utf8 headers", () => {
|
||||||
|
|
||||||
expect(reply.responseType).toBe("FACTUAL_SUMMARY");
|
expect(reply.responseType).toBe("FACTUAL_SUMMARY");
|
||||||
expect(reply.text).toContain("Коротко: подтвержденный НДС к уплате за налоговый период по организации ООО Альтернатива Плюс");
|
expect(reply.text).toContain("Коротко: подтвержденный НДС к уплате за налоговый период по организации ООО Альтернатива Плюс");
|
||||||
|
expect(reply.text).toContain("Расчет сделан по подтвержденным строкам книг продаж и покупок.");
|
||||||
expect(reply.text).toContain("- Организация: ООО Альтернатива Плюс.");
|
expect(reply.text).toContain("- Организация: ООО Альтернатива Плюс.");
|
||||||
expect(reply.text).toContain("50.000,00 ₽");
|
expect(reply.text).toContain("50.000,00 ₽");
|
||||||
|
expect(reply.text).toContain("не полный налоговый вердикт");
|
||||||
|
expect(reply.text).toContain("корректировки");
|
||||||
expect(reply.semantics?.result_mode).toBe("confirmed_balance");
|
expect(reply.semantics?.result_mode).toBe("confirmed_balance");
|
||||||
expect(reply.semantics?.balance_confirmed).toBe(true);
|
expect(reply.semantics?.balance_confirmed).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -484,6 +484,77 @@ describe("assistant address orchestration runtime adapter", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("recovers business overview proof bundles for a plain organization clarification", async () => {
|
||||||
|
const runMcpDiscoveryRuntimeEntryPoint = vi.fn(async () => ({
|
||||||
|
schema_version: "assistant_mcp_discovery_runtime_entry_point_v1",
|
||||||
|
policy_owner: "assistantMcpDiscoveryRuntimeEntryPoint",
|
||||||
|
entry_status: "bridge_executed",
|
||||||
|
hot_runtime_wired: false,
|
||||||
|
discovery_attempted: true
|
||||||
|
}));
|
||||||
|
const input = buildInput({
|
||||||
|
userMessage: "Alt Plus",
|
||||||
|
sessionItems: [
|
||||||
|
{
|
||||||
|
role: "assistant",
|
||||||
|
text:
|
||||||
|
"Отдельно по контрагенту Group SVK: " +
|
||||||
|
"подтверждено получили 20 653 490 руб., " +
|
||||||
|
"заплатили 2 129 651 руб., " +
|
||||||
|
"расчетное нетто в нашу сторону 18 523 839 руб. " +
|
||||||
|
"Основа: проверенные входящие платежи и исходящие платежи и документы по цепочке: найдено 19."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
runAddressLlmPreDecompose: vi.fn(async () => ({
|
||||||
|
attempted: true,
|
||||||
|
applied: false,
|
||||||
|
effectiveMessage: "Alt Plus",
|
||||||
|
reason: "raw_kept",
|
||||||
|
predecomposeContract: {
|
||||||
|
mode: "unsupported",
|
||||||
|
intent: "unknown",
|
||||||
|
entities: { organization: "Alt Plus" }
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
resolveAddressFollowupCarryoverContext: vi.fn(() => ({ followupContext: null })),
|
||||||
|
resolveAssistantOrchestrationDecision: vi.fn(() => ({
|
||||||
|
runAddressLane: true,
|
||||||
|
livingMode: "address_data",
|
||||||
|
livingReason: "address_lane_triggered",
|
||||||
|
toolGateDecision: "run_address_lane",
|
||||||
|
toolGateReason: "followup_context_detected",
|
||||||
|
orchestrationContract: {
|
||||||
|
schema_version: "assistant_orchestration_contract_v1",
|
||||||
|
assistant_turn_meaning: {
|
||||||
|
schema_version: "assistant_turn_meaning_v1",
|
||||||
|
asked_domain_family: "business_overview",
|
||||||
|
asked_action_family: "broad_evaluation"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
runMcpDiscoveryRuntimeEntryPoint
|
||||||
|
});
|
||||||
|
|
||||||
|
await buildAssistantAddressOrchestrationRuntime(input);
|
||||||
|
|
||||||
|
expect(runMcpDiscoveryRuntimeEntryPoint).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
followupContext: expect.objectContaining({
|
||||||
|
previous_discovery_loop_selected_chain_id: "business_overview",
|
||||||
|
previous_discovery_loop_metadata_scope_hint: "Group SVK",
|
||||||
|
previous_discovery_bidirectional_value_flow: expect.objectContaining({
|
||||||
|
counterparty: "Group SVK",
|
||||||
|
net_amount_human_ru: "18 523 839 руб."
|
||||||
|
}),
|
||||||
|
previous_discovery_document_summary: expect.objectContaining({
|
||||||
|
counterparty: "Group SVK",
|
||||||
|
document_count: 19
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("recovers business overview proof bundles from navigation comparison state", async () => {
|
it("recovers business overview proof bundles from navigation comparison state", async () => {
|
||||||
const valueFlowBundle = {
|
const valueFlowBundle = {
|
||||||
counterparty: "Group SVK",
|
counterparty: "Group SVK",
|
||||||
|
|
|
||||||
|
|
@ -1546,9 +1546,12 @@ describe("assistant MCP discovery response candidate", () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const firstLine = candidate.reply_text?.split("\n")[0] ?? "";
|
const firstLine = candidate.reply_text?.split("\n")[0] ?? "";
|
||||||
expect(firstLine).toContain("по ограниченному проверенному 1С-срезу");
|
expect(firstLine).toContain("По подтвержденным строкам 1С");
|
||||||
|
expect(firstLine).toContain("входящие 157 192 981,43 руб.");
|
||||||
|
expect(firstLine).toContain("исходящие 35 439 044,74 руб.");
|
||||||
expect(firstLine).toContain("не аудиторское заключение");
|
expect(firstLine).toContain("не аудиторское заключение");
|
||||||
expect(firstLine).toContain("не подтвержденная чистая прибыль");
|
expect(firstLine).toContain("не подтвержденная чистая прибыль");
|
||||||
|
expect(candidate.reply_text).toContain("Интерпретация:");
|
||||||
expect(candidate.reply_text).toContain("Что видно в ограниченном денежном срезе");
|
expect(candidate.reply_text).toContain("Что видно в ограниченном денежном срезе");
|
||||||
expect(candidate.reply_text).toContain("Что не подтверждено в этом срезе");
|
expect(candidate.reply_text).toContain("Что не подтверждено в этом срезе");
|
||||||
expect(candidate.reply_text).toContain("НДС");
|
expect(candidate.reply_text).toContain("НДС");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,63 @@
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
"generation_id": "gen-ag06011942-2ed936",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"mode": "saved_user_sessions",
|
||||||
|
"title": "AGENT | Business overview + SVK boundary reliability",
|
||||||
|
"count": 13,
|
||||||
|
"domain": "agent_business_overview_counterparty_reliability",
|
||||||
|
"questions": [
|
||||||
|
"Дай взрослый бизнес-обзор ООО Альтернатива Плюс за 2020 год по данным 1С: обороты, входящие и исходящие деньги, нетто, НДС, долги, склад, клиенты, поставщики и что пока нельзя утверждать.",
|
||||||
|
"Раскрой деньги подробнее: сколько получили, сколько заплатили, какой чистый денежный поток, кто главный клиент и главный поставщик в 2020.",
|
||||||
|
"Что с НДС за 2020 год по ООО Альтернатива Плюс: какая позиция видна, на чем она основана и чего не хватает для налогового вывода?",
|
||||||
|
"Теперь за все доступное время дай обзор компании в целом, но не тащи НДС за 2020 как подтвержденную общую налоговую позицию.",
|
||||||
|
"Отдельно по контрагенту Группа СВК, без опоры на прошлый диалог: сколько денег прошло, что входящее, что исходящее и есть ли документы или движения, на которых это основано?",
|
||||||
|
"Покажи документы по этой цепочке и не смешивай Группа СВК с организацией ООО Альтернатива Плюс.",
|
||||||
|
"Собери короткий итог: что мы подтвердили по компании, что отдельно по Группа СВК, какие выводы можно делать и какие нельзя.",
|
||||||
|
"По-человечески посмотри ООО Альтернатива Плюс за 2020: что по бизнесу видно в 1С по деньгам, НДС, долгам, складу, клиентам/поставщикам и где пока нельзя делать вывод?",
|
||||||
|
"А по деньгам в этом же году кто больше всего занес и кому больше всего ушло? Банк не называй обычным клиентом без оговорки.",
|
||||||
|
"Возьми как выбранного контрагента Группа СВК: сколько по нему входящих денег, исходящих денег и расчетное нетто, на чем это основано?",
|
||||||
|
"Теперь по нему покажи документы и не переключайся на организацию.",
|
||||||
|
"И коротко сравни: что у нас подтверждено по компании, что отдельно по выбранному контрагенту, и какие выводы нельзя делать?",
|
||||||
|
"ООО Альтернатива Плюс"
|
||||||
|
],
|
||||||
|
"generated_by": "Codex",
|
||||||
|
"saved_case_set_file": "assistant_autogen_saved_user_sessions_20260601194213_gen-ag06011942-2ed936.json",
|
||||||
|
"context": {
|
||||||
|
"llm_provider": null,
|
||||||
|
"model": null,
|
||||||
|
"assistant_prompt_version": null,
|
||||||
|
"decomposition_prompt_version": null,
|
||||||
|
"prompt_fingerprint": null,
|
||||||
|
"autogen_personality_id": null,
|
||||||
|
"autogen_personality_prompt": null,
|
||||||
|
"source_session_id": null,
|
||||||
|
"saved_session_file": "assistant_saved_session_20260601194213_gen-ag06011942-2ed936.json",
|
||||||
|
"saved_case_set_kind": "agent_semantic_scenario",
|
||||||
|
"agent_run": true,
|
||||||
|
"agent_focus": "business overview counterparty boundary continuity",
|
||||||
|
"architecture_phase": "assistant stage1 business overview",
|
||||||
|
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\agent_business_overview_counterparty_reliability_20260524.json",
|
||||||
|
"scenario_id": null,
|
||||||
|
"semantic_tags": [
|
||||||
|
"business_overview",
|
||||||
|
"colloquial",
|
||||||
|
"counterparty",
|
||||||
|
"debt",
|
||||||
|
"documents",
|
||||||
|
"inventory",
|
||||||
|
"money",
|
||||||
|
"organization_clarification",
|
||||||
|
"pronoun_followup",
|
||||||
|
"scope_guard",
|
||||||
|
"selected_object",
|
||||||
|
"vat"
|
||||||
|
],
|
||||||
|
"validation_status": "accepted_domain_pack_loop",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\agent_business_overview_counterparty_reliability_20260601_p5",
|
||||||
|
"saved_after_validated_replay": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"generation_id": "gen-ag06011827-b80e22",
|
"generation_id": "gen-ag06011827-b80e22",
|
||||||
"created_at": "2026-06-01T18:27:36+00:00",
|
"created_at": "2026-06-01T18:27:36+00:00",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,265 @@
|
||||||
|
{
|
||||||
|
"saved_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"generation_id": "gen-ag06011942-2ed936",
|
||||||
|
"mode": "saved_user_sessions",
|
||||||
|
"title": "AGENT | Business overview + SVK boundary reliability",
|
||||||
|
"agent_run": true,
|
||||||
|
"questions": [
|
||||||
|
"Дай взрослый бизнес-обзор ООО Альтернатива Плюс за 2020 год по данным 1С: обороты, входящие и исходящие деньги, нетто, НДС, долги, склад, клиенты, поставщики и что пока нельзя утверждать.",
|
||||||
|
"Раскрой деньги подробнее: сколько получили, сколько заплатили, какой чистый денежный поток, кто главный клиент и главный поставщик в 2020.",
|
||||||
|
"Что с НДС за 2020 год по ООО Альтернатива Плюс: какая позиция видна, на чем она основана и чего не хватает для налогового вывода?",
|
||||||
|
"Теперь за все доступное время дай обзор компании в целом, но не тащи НДС за 2020 как подтвержденную общую налоговую позицию.",
|
||||||
|
"Отдельно по контрагенту Группа СВК, без опоры на прошлый диалог: сколько денег прошло, что входящее, что исходящее и есть ли документы или движения, на которых это основано?",
|
||||||
|
"Покажи документы по этой цепочке и не смешивай Группа СВК с организацией ООО Альтернатива Плюс.",
|
||||||
|
"Собери короткий итог: что мы подтвердили по компании, что отдельно по Группа СВК, какие выводы можно делать и какие нельзя.",
|
||||||
|
"По-человечески посмотри ООО Альтернатива Плюс за 2020: что по бизнесу видно в 1С по деньгам, НДС, долгам, складу, клиентам/поставщикам и где пока нельзя делать вывод?",
|
||||||
|
"А по деньгам в этом же году кто больше всего занес и кому больше всего ушло? Банк не называй обычным клиентом без оговорки.",
|
||||||
|
"Возьми как выбранного контрагента Группа СВК: сколько по нему входящих денег, исходящих денег и расчетное нетто, на чем это основано?",
|
||||||
|
"Теперь по нему покажи документы и не переключайся на организацию.",
|
||||||
|
"И коротко сравни: что у нас подтверждено по компании, что отдельно по выбранному контрагенту, и какие выводы нельзя делать?",
|
||||||
|
"ООО Альтернатива Плюс"
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"assistant_prompt_version": null,
|
||||||
|
"decomposition_prompt_version": null,
|
||||||
|
"prompt_fingerprint": null,
|
||||||
|
"agent_focus": "business overview counterparty boundary continuity",
|
||||||
|
"architecture_phase": "assistant stage1 business overview",
|
||||||
|
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\agent_business_overview_counterparty_reliability_20260524.json",
|
||||||
|
"scenario_id": null,
|
||||||
|
"semantic_tags": [
|
||||||
|
"business_overview",
|
||||||
|
"colloquial",
|
||||||
|
"counterparty",
|
||||||
|
"debt",
|
||||||
|
"documents",
|
||||||
|
"inventory",
|
||||||
|
"money",
|
||||||
|
"organization_clarification",
|
||||||
|
"pronoun_followup",
|
||||||
|
"scope_guard",
|
||||||
|
"selected_object",
|
||||||
|
"vat"
|
||||||
|
],
|
||||||
|
"validation_status": "accepted_domain_pack_loop",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\agent_business_overview_counterparty_reliability_20260601_p5",
|
||||||
|
"saved_after_validated_replay": true,
|
||||||
|
"save_gate": {
|
||||||
|
"schema_version": "agent_semantic_save_gate_v1",
|
||||||
|
"validation_status": "accepted_domain_pack_loop",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\agent_business_overview_counterparty_reliability_20260601_p5",
|
||||||
|
"final_status": "accepted",
|
||||||
|
"loop_id": "agent_business_overview_counterparty_reliability_20260601_p5",
|
||||||
|
"target_score": 90,
|
||||||
|
"iterations_ran": 1,
|
||||||
|
"quality_score": 91,
|
||||||
|
"repair_target_count": 0,
|
||||||
|
"repair_target_severity_counts": {
|
||||||
|
"P0": 0,
|
||||||
|
"P1": 0,
|
||||||
|
"P2": 0
|
||||||
|
},
|
||||||
|
"accepted_gate": true,
|
||||||
|
"effective_runtime": {
|
||||||
|
"manifest_path": "artifacts\\domain_runs\\agent_business_overview_counterparty_reliability_20260601_p5\\effective_runtime.json",
|
||||||
|
"runner": "domain_case_loop.run-pack-loop",
|
||||||
|
"git_sha": "ede15c6080426934c01d5b68b00b7b8b521558fc",
|
||||||
|
"backend_url": "http://127.0.0.1:8787",
|
||||||
|
"mcp_proxy_url": "http://127.0.0.1:6003",
|
||||||
|
"llm_provider": "local",
|
||||||
|
"llm_model": "unsloth/qwen3-30b-a3b-instruct-2507",
|
||||||
|
"temperature": 0.8,
|
||||||
|
"max_output_tokens": 900,
|
||||||
|
"prompt_version": "normalizer_v2_0_2",
|
||||||
|
"prompt_source": "file",
|
||||||
|
"prompt_hash": "f36e36a5e491cd24511b380e0c0059cb01aea5e2af738fb9f01671cd291735c1",
|
||||||
|
"prompt_registry_status": "pass"
|
||||||
|
},
|
||||||
|
"saved_after_validated_replay": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source_session_id": null,
|
||||||
|
"session": {
|
||||||
|
"session_id": null,
|
||||||
|
"mode": "agent_semantic_run",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-001",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Дай взрослый бизнес-обзор ООО Альтернатива Плюс за 2020 год по данным 1С: обороты, входящие и исходящие деньги, нетто, НДС, долги, склад, клиенты, поставщики и что пока нельзя утверждать.",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-002",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Раскрой деньги подробнее: сколько получили, сколько заплатили, какой чистый денежный поток, кто главный клиент и главный поставщик в 2020.",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-003",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Что с НДС за 2020 год по ООО Альтернатива Плюс: какая позиция видна, на чем она основана и чего не хватает для налогового вывода?",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-004",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Теперь за все доступное время дай обзор компании в целом, но не тащи НДС за 2020 как подтвержденную общую налоговую позицию.",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-005",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Отдельно по контрагенту Группа СВК, без опоры на прошлый диалог: сколько денег прошло, что входящее, что исходящее и есть ли документы или движения, на которых это основано?",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-006",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Покажи документы по этой цепочке и не смешивай Группа СВК с организацией ООО Альтернатива Плюс.",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-007",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Собери короткий итог: что мы подтвердили по компании, что отдельно по Группа СВК, какие выводы можно делать и какие нельзя.",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-008",
|
||||||
|
"role": "user",
|
||||||
|
"text": "По-человечески посмотри ООО Альтернатива Плюс за 2020: что по бизнесу видно в 1С по деньгам, НДС, долгам, складу, клиентам/поставщикам и где пока нельзя делать вывод?",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-009",
|
||||||
|
"role": "user",
|
||||||
|
"text": "А по деньгам в этом же году кто больше всего занес и кому больше всего ушло? Банк не называй обычным клиентом без оговорки.",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-010",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Возьми как выбранного контрагента Группа СВК: сколько по нему входящих денег, исходящих денег и расчетное нетто, на чем это основано?",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-011",
|
||||||
|
"role": "user",
|
||||||
|
"text": "Теперь по нему покажи документы и не переключайся на организацию.",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-012",
|
||||||
|
"role": "user",
|
||||||
|
"text": "И коротко сравни: что у нас подтверждено по компании, что отдельно по выбранному контрагенту, и какие выводы нельзя делать?",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"message_id": "agent-user-013",
|
||||||
|
"role": "user",
|
||||||
|
"text": "ООО Альтернатива Плюс",
|
||||||
|
"created_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"reply_type": null,
|
||||||
|
"trace_id": null,
|
||||||
|
"debug": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"agent_run": true,
|
||||||
|
"metadata": {
|
||||||
|
"assistant_prompt_version": null,
|
||||||
|
"decomposition_prompt_version": null,
|
||||||
|
"prompt_fingerprint": null,
|
||||||
|
"agent_focus": "business overview counterparty boundary continuity",
|
||||||
|
"architecture_phase": "assistant stage1 business overview",
|
||||||
|
"source_spec_file": "X:\\1C\\NDC_1C\\docs\\orchestration\\agent_business_overview_counterparty_reliability_20260524.json",
|
||||||
|
"scenario_id": null,
|
||||||
|
"semantic_tags": [
|
||||||
|
"business_overview",
|
||||||
|
"colloquial",
|
||||||
|
"counterparty",
|
||||||
|
"debt",
|
||||||
|
"documents",
|
||||||
|
"inventory",
|
||||||
|
"money",
|
||||||
|
"organization_clarification",
|
||||||
|
"pronoun_followup",
|
||||||
|
"scope_guard",
|
||||||
|
"selected_object",
|
||||||
|
"vat"
|
||||||
|
],
|
||||||
|
"validation_status": "accepted_domain_pack_loop",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\agent_business_overview_counterparty_reliability_20260601_p5",
|
||||||
|
"saved_after_validated_replay": true,
|
||||||
|
"save_gate": {
|
||||||
|
"schema_version": "agent_semantic_save_gate_v1",
|
||||||
|
"validation_status": "accepted_domain_pack_loop",
|
||||||
|
"validated_run_dir": "artifacts\\domain_runs\\agent_business_overview_counterparty_reliability_20260601_p5",
|
||||||
|
"final_status": "accepted",
|
||||||
|
"loop_id": "agent_business_overview_counterparty_reliability_20260601_p5",
|
||||||
|
"target_score": 90,
|
||||||
|
"iterations_ran": 1,
|
||||||
|
"quality_score": 91,
|
||||||
|
"repair_target_count": 0,
|
||||||
|
"repair_target_severity_counts": {
|
||||||
|
"P0": 0,
|
||||||
|
"P1": 0,
|
||||||
|
"P2": 0
|
||||||
|
},
|
||||||
|
"accepted_gate": true,
|
||||||
|
"effective_runtime": {
|
||||||
|
"manifest_path": "artifacts\\domain_runs\\agent_business_overview_counterparty_reliability_20260601_p5\\effective_runtime.json",
|
||||||
|
"runner": "domain_case_loop.run-pack-loop",
|
||||||
|
"git_sha": "ede15c6080426934c01d5b68b00b7b8b521558fc",
|
||||||
|
"backend_url": "http://127.0.0.1:8787",
|
||||||
|
"mcp_proxy_url": "http://127.0.0.1:6003",
|
||||||
|
"llm_provider": "local",
|
||||||
|
"llm_model": "unsloth/qwen3-30b-a3b-instruct-2507",
|
||||||
|
"temperature": 0.8,
|
||||||
|
"max_output_tokens": 900,
|
||||||
|
"prompt_version": "normalizer_v2_0_2",
|
||||||
|
"prompt_source": "file",
|
||||||
|
"prompt_hash": "f36e36a5e491cd24511b380e0c0059cb01aea5e2af738fb9f01671cd291735c1",
|
||||||
|
"prompt_registry_status": "pass"
|
||||||
|
},
|
||||||
|
"saved_after_validated_replay": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
{
|
||||||
|
"suite_id": "assistant_saved_session_gen-ag06011942-2ed936",
|
||||||
|
"suite_version": "0.1.0",
|
||||||
|
"schema_version": "assistant_saved_session_suite_v0_1",
|
||||||
|
"generated_at": "2026-06-01T19:42:13+00:00",
|
||||||
|
"generation_id": "gen-ag06011942-2ed936",
|
||||||
|
"mode": "saved_user_sessions",
|
||||||
|
"title": "AGENT | Business overview + SVK boundary reliability",
|
||||||
|
"domain": "agent_business_overview_counterparty_reliability",
|
||||||
|
"scenario_count": 1,
|
||||||
|
"case_ids": [
|
||||||
|
"SAVED-001"
|
||||||
|
],
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"case_id": "SAVED-001",
|
||||||
|
"scenario_tag": "agent_saved_user_sessions",
|
||||||
|
"title": "AGENT | Business overview + SVK boundary reliability",
|
||||||
|
"question_type": "followup",
|
||||||
|
"broadness_level": "medium",
|
||||||
|
"turns": [
|
||||||
|
{
|
||||||
|
"user_message": "Дай взрослый бизнес-обзор ООО Альтернатива Плюс за 2020 год по данным 1С: обороты, входящие и исходящие деньги, нетто, НДС, долги, склад, клиенты, поставщики и что пока нельзя утверждать."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Раскрой деньги подробнее: сколько получили, сколько заплатили, какой чистый денежный поток, кто главный клиент и главный поставщик в 2020."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Что с НДС за 2020 год по ООО Альтернатива Плюс: какая позиция видна, на чем она основана и чего не хватает для налогового вывода?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Теперь за все доступное время дай обзор компании в целом, но не тащи НДС за 2020 как подтвержденную общую налоговую позицию."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Отдельно по контрагенту Группа СВК, без опоры на прошлый диалог: сколько денег прошло, что входящее, что исходящее и есть ли документы или движения, на которых это основано?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Покажи документы по этой цепочке и не смешивай Группа СВК с организацией ООО Альтернатива Плюс."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Собери короткий итог: что мы подтвердили по компании, что отдельно по Группа СВК, какие выводы можно делать и какие нельзя."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "По-человечески посмотри ООО Альтернатива Плюс за 2020: что по бизнесу видно в 1С по деньгам, НДС, долгам, складу, клиентам/поставщикам и где пока нельзя делать вывод?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "А по деньгам в этом же году кто больше всего занес и кому больше всего ушло? Банк не называй обычным клиентом без оговорки."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Возьми как выбранного контрагента Группа СВК: сколько по нему входящих денег, исходящих денег и расчетное нетто, на чем это основано?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "Теперь по нему покажи документы и не переключайся на организацию."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "И коротко сравни: что у нас подтверждено по компании, что отдельно по выбранному контрагенту, и какие выводы нельзя делать?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"user_message": "ООО Альтернатива Плюс"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue