noteconnection 1.8.0 → 1.9.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 +257 -1803
- package/dist/src/agent_workspace.contract.parity.test.js +105 -421
- package/dist/src/agent_workspace.frontend.test.js +410 -11
- package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
- package/dist/src/appimage.patchelf.test.js +113 -0
- package/dist/src/appimage.portability.test.js +156 -0
- package/dist/src/backend/FileLoader.js +18 -4
- package/dist/src/backend/FileLoader.test.js +125 -0
- package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
- package/dist/src/backend/GraphBuilder.js +66 -18
- package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
- package/dist/src/backend/GraphMetrics.js +0 -3
- package/dist/src/backend/ResourceIdentity.js +155 -0
- package/dist/src/backend/ResourceIdentity.test.js +113 -0
- package/dist/src/backend/algorithms/CycleDetection.js +0 -1
- package/dist/src/backend/algorithms/HybridEngine.js +0 -3
- package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
- package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
- package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
- package/dist/src/backend/build_dag.js +0 -1
- package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
- package/dist/src/capacitor.runtime.contract.test.js +11 -2
- package/dist/src/core/Graph.js +138 -42
- package/dist/src/core/Graph.test.js +74 -0
- package/dist/src/core/NoteConnection.js +2 -2
- package/dist/src/core/PathBridge.js +265 -2
- package/dist/src/core/ResourceReference.js +17 -0
- package/dist/src/desktop.godot.pack.test.js +142 -0
- package/dist/src/desktop.runtime.graph.test.js +66 -0
- package/dist/src/export/WorkspaceExportBundle.js +44 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +61 -0
- package/dist/src/foundation.release.evidence.contract.test.js +127 -9
- package/dist/src/foundation.sqlite.runtime.contract.test.js +6 -0
- package/dist/src/frontend/README.md +257 -1803
- package/dist/src/frontend/agent_workspace.js +665 -7
- package/dist/src/frontend/index.html +31 -2
- package/dist/src/frontend/knowledge_projection_contract.js +230 -0
- package/dist/src/frontend/knowledge_projection_store.js +214 -0
- package/dist/src/frontend/libs/path_core.js +158 -42
- package/dist/src/frontend/locales/en.json +32 -0
- package/dist/src/frontend/locales/zh.json +32 -0
- package/dist/src/frontend/mobile_budget_runtime.js +33 -0
- package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
- package/dist/src/frontend/mobile_identity_contract.js +221 -0
- package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
- package/dist/src/frontend/path.html +6 -2
- package/dist/src/frontend/simulationWorker.js +1 -1
- package/dist/src/frontend/source_manager.js +110 -4
- package/dist/src/frontend/storage_provider.js +661 -71
- package/dist/src/frontend/styles.css +107 -13
- package/dist/src/frontend/workspace_panes.js +111 -7
- package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
- package/dist/src/graph.answer.operator.contract.test.js +72 -0
- package/dist/src/index.js +6 -2
- package/dist/src/index.knowledge-root.test.js +118 -0
- package/dist/src/indexing/IndexLifecycle.js +22 -0
- package/dist/src/indexing/IndexLifecycle.test.js +24 -0
- package/dist/src/knowledge.api.contract.test.js +4 -2
- package/dist/src/knowledge_projection.contract.test.js +134 -0
- package/dist/src/knowledge_projection_store.test.js +200 -0
- package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
- package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +4687 -3892
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +418 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +243 -6
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +25 -1
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +13 -5
- package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
- package/dist/src/learning/PublicAnswerContract.test.js +85 -0
- package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
- package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
- package/dist/src/learning/agentConversationExecution.js +211 -0
- package/dist/src/learning/agentConversationExecution.test.js +209 -0
- package/dist/src/learning/agentConversationSerialization.js +266 -0
- package/dist/src/learning/agentConversationSerialization.test.js +165 -0
- package/dist/src/learning/agentResponseBudget.js +179 -0
- package/dist/src/learning/agentResponseBudget.test.js +97 -0
- package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
- package/dist/src/learning/answerReleaseReview.js +1191 -250
- package/dist/src/learning/answerReleaseReview.test.js +1293 -7
- package/dist/src/learning/answerTaskPlan.js +473 -0
- package/dist/src/learning/conversationComposer.js +627 -386
- package/dist/src/learning/conversationComposer.test.js +1403 -0
- package/dist/src/learning/evidenceContextAssembler.js +312 -120
- package/dist/src/learning/graphAnswerCoverage.js +37 -0
- package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
- package/dist/src/learning/graphAnswerFacts.js +94 -0
- package/dist/src/learning/graphAnswerFacts.test.js +39 -0
- package/dist/src/learning/graphAnswerPlan.js +908 -0
- package/dist/src/learning/graphAnswerPlan.test.js +907 -0
- package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
- package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
- package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
- package/dist/src/learning/graphClaimMatcher.js +104 -0
- package/dist/src/learning/graphConditionedContext.js +109 -0
- package/dist/src/learning/graphConditionedContext.test.js +99 -0
- package/dist/src/learning/graphContextAssembler.js +3 -13
- package/dist/src/learning/graphContextAssembler.test.js +2 -2
- package/dist/src/learning/graphExpansionPolicy.js +22 -0
- package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
- package/dist/src/learning/identityMetadata.test.js +26 -0
- package/dist/src/learning/index.js +1 -0
- package/dist/src/learning/mobileAnswerProjection.js +104 -0
- package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
- package/dist/src/learning/queryBackend.js +34 -10
- package/dist/src/learning/queryBackend.test.js +21 -0
- package/dist/src/learning/ragContextPack.js +115 -16
- package/dist/src/learning/ragContextPack.test.js +151 -0
- package/dist/src/learning/ragEvidenceQuality.js +96 -0
- package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
- package/dist/src/learning/ragPublicText.js +67 -4
- package/dist/src/learning/ragPublicText.test.js +57 -0
- package/dist/src/learning/ragSufficiencyJudge.js +11 -1
- package/dist/src/learning/ragSufficiencyProviderJudge.js +16 -26
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +51 -0
- package/dist/src/learning/requestNormalization.js +106 -0
- package/dist/src/learning/requestNormalization.test.js +101 -0
- package/dist/src/learning/store.js +116 -12
- package/dist/src/learning/store.test.js +299 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +22 -6
- package/dist/src/learning/vectorAccelerationAdapter.test.js +30 -0
- package/dist/src/learning/workspaceHydration.js +168 -0
- package/dist/src/learning/workspaceHydration.test.js +30 -0
- package/dist/src/license.policy.contract.test.js +9 -4
- package/dist/src/markdown/MarkdownGateway.js +4 -0
- package/dist/src/markdown/MarkdownGateway.test.js +59 -0
- package/dist/src/middleware/SseResponseWriter.js +122 -0
- package/dist/src/middleware/SseResponseWriter.test.js +54 -0
- package/dist/src/middleware/auth.js +28 -7
- package/dist/src/middleware/auth.test.js +33 -0
- package/dist/src/middleware/index.js +2 -1
- package/dist/src/mobile.android.evidence.contract.test.js +146 -0
- package/dist/src/mobile.android.signing.contract.test.js +66 -0
- package/dist/src/mobile.artifact.contract.test.js +144 -0
- package/dist/src/mobile.budget.contract.test.js +90 -0
- package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
- package/dist/src/mobile.graph.parity.contract.test.js +207 -0
- package/dist/src/mobile.identity.contract.test.js +66 -0
- package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
- package/dist/src/mobile.identity.corpus.test.js +40 -0
- package/dist/src/mobile.native.recovery.contract.test.js +64 -0
- package/dist/src/mobile.pipeline.test.js +11 -1
- package/dist/src/mobile.profile.contract.test.js +225 -0
- package/dist/src/mobile.semantic.parity.test.js +92 -0
- package/dist/src/mobile_exact_analyzer.test.js +113 -0
- package/dist/src/notemd/ContentGenerator.js +4 -9
- package/dist/src/notemd/FileProcessor.js +4 -9
- package/dist/src/notemd/NotemdService.js +12 -17
- package/dist/src/notemd/Translator.js +4 -9
- package/dist/src/notemd/progressReporter.js +9 -0
- package/dist/src/notemd.server.integration.test.js +119 -4
- package/dist/src/notemd.workflow.pipeline.test.js +1 -1
- package/dist/src/pathbridge.handshake.contract.test.js +29 -0
- package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
- package/dist/src/pathcore.bundle.contract.test.js +8 -0
- package/dist/src/platform/ExportProfile.js +28 -0
- package/dist/src/platform/MobileBudget.js +11 -0
- package/dist/src/platform/PlatformCapabilities.js +14 -0
- package/dist/src/platform/PlatformCapabilities.test.js +6 -0
- package/dist/src/query_backend.external_http.integration.test.js +2 -2
- package/dist/src/release.godot.mirror.contract.test.js +28 -4
- package/dist/src/resources/ResourceRegistry.js +40 -0
- package/dist/src/resources/ResourceRegistry.test.js +36 -0
- package/dist/src/routes/index.js +0 -4
- package/dist/src/routes/knowledge.js +46 -33
- package/dist/src/routes/knowledgePayload.js +185 -0
- package/dist/src/routes/knowledgePayload.test.js +53 -0
- package/dist/src/routes/markdown.js +8 -0
- package/dist/src/routes/notemd.js +990 -234
- package/dist/src/routes/registry.contract.test.js +5 -2
- package/dist/src/routes/registry.shadow.contract.test.js +22 -0
- package/dist/src/routes/render.js +14 -51
- package/dist/src/runtime.capabilities.test.js +18 -2
- package/dist/src/server.js +566 -1090
- package/dist/src/server.migration.test.js +417 -15
- package/dist/src/sidecar.build.lock.contract.test.js +201 -0
- package/dist/src/sidecar.freshness.contract.test.js +184 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +6 -3
- package/dist/src/sidecar.supply.readiness.contract.test.js +11 -0
- package/dist/src/simulation.worker.offline.test.js +104 -0
- package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
- package/dist/src/storage.provider.contract.test.js +152 -1
- package/dist/src/tauri.frontend.build.contract.test.js +8 -0
- package/dist/src/tauri.window.evidence.execution.test.js +68 -0
- package/dist/src/utils/RuntimePaths.js +6 -0
- package/dist/src/utils/RuntimePaths.test.js +27 -0
- package/dist/src/windows.installer.build.test.js +109 -0
- package/dist/src/windows.installer.payload.test.js +76 -0
- package/dist/src/windows.installer.runtime.test.js +69 -0
- package/dist/src/workspace/WorkspaceRegistry.js +13 -0
- package/package.json +32 -10
- package/dist/src/routes/data.js +0 -267
- package/dist/src/routes/diagnostics.js +0 -51
|
@@ -5,7 +5,376 @@ exports.collectAgentConversationAtomIds = collectAgentConversationAtomIds;
|
|
|
5
5
|
exports.buildScopedConversationReply = buildScopedConversationReply;
|
|
6
6
|
const answerReleaseReview_1 = require("./answerReleaseReview");
|
|
7
7
|
const graphContextAssembler_1 = require("./graphContextAssembler");
|
|
8
|
+
const graphAnswerPlan_1 = require("./graphAnswerPlan");
|
|
9
|
+
const graphAnswerCoverage_1 = require("./graphAnswerCoverage");
|
|
10
|
+
const graphAnswerFacts_1 = require("./graphAnswerFacts");
|
|
8
11
|
const ragPublicText_1 = require("./ragPublicText");
|
|
12
|
+
const graphAnswerQualityPolicy_1 = require("./graphAnswerQualityPolicy");
|
|
13
|
+
const answerTaskPlan_1 = require("./answerTaskPlan");
|
|
14
|
+
const LEGACY_FULL_RESPONSE_MAX_CHARS = 24000;
|
|
15
|
+
const LEGACY_FULL_RESPONSE_MAX_FRAGMENTS = 24;
|
|
16
|
+
const FULL_REPORT_FRAGMENT_ROLES = new Set([
|
|
17
|
+
'direct_support',
|
|
18
|
+
'parent_context',
|
|
19
|
+
'adjacent_context',
|
|
20
|
+
'graph_neighbor_support',
|
|
21
|
+
'conflict',
|
|
22
|
+
]);
|
|
23
|
+
function isFullResponseMode(params) {
|
|
24
|
+
return params.responseMode === 'full';
|
|
25
|
+
}
|
|
26
|
+
function normalizeSourcePathForComparison(value) {
|
|
27
|
+
return String(value || '')
|
|
28
|
+
.trim()
|
|
29
|
+
.replace(/\\/gu, '/')
|
|
30
|
+
.replace(/\/{2,}/gu, '/')
|
|
31
|
+
.replace(/\/+$/gu, '')
|
|
32
|
+
.toLowerCase();
|
|
33
|
+
}
|
|
34
|
+
function resolveFullReportAnchorSource(params) {
|
|
35
|
+
const anchorAtomId = normalizeWhitespace(String(params.graphContext?.anchorAtomId || ''));
|
|
36
|
+
const anchorDocumentId = normalizeWhitespace(String(params.graphContext?.anchorDocumentId || ''));
|
|
37
|
+
const knowledgePoints = Array.isArray(params.knowledgePoints) ? params.knowledgePoints : [];
|
|
38
|
+
const anchorPoint = knowledgePoints.find((point) => {
|
|
39
|
+
const pointAtomId = normalizeWhitespace(String(point.atomId || ''));
|
|
40
|
+
const pointAtomIds = Array.isArray(point.atomIds) ? point.atomIds.map((atomId) => normalizeWhitespace(String(atomId || ''))) : [];
|
|
41
|
+
return Boolean(anchorAtomId && (pointAtomId === anchorAtomId || pointAtomIds.includes(anchorAtomId)));
|
|
42
|
+
})
|
|
43
|
+
|| knowledgePoints.find((point) => anchorDocumentId && normalizeWhitespace(String(point.documentId || '')) === anchorDocumentId)
|
|
44
|
+
|| knowledgePoints[0];
|
|
45
|
+
const documentId = anchorDocumentId || normalizeWhitespace(String(anchorPoint?.documentId || ''));
|
|
46
|
+
let sourcePath = normalizeSourcePathForComparison(String(anchorPoint?.sourcePath || ''));
|
|
47
|
+
if (!sourcePath && documentId) {
|
|
48
|
+
const sourceFragment = (params.ragContextPack?.fragments || []).find((fragment) => (fragment.role !== 'graph_neighbor_support'
|
|
49
|
+
&& normalizeWhitespace(String(fragment.documentId || '')) === documentId
|
|
50
|
+
&& normalizeSourcePathForComparison(String(fragment.sourcePath || ''))));
|
|
51
|
+
sourcePath = normalizeSourcePathForComparison(String(sourceFragment?.sourcePath || ''));
|
|
52
|
+
}
|
|
53
|
+
return { documentId, sourcePath };
|
|
54
|
+
}
|
|
55
|
+
function isFullReportGraphNeighborFromAnchorSource(fragment, anchorSource) {
|
|
56
|
+
if (fragment.role !== 'graph_neighbor_support') {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
const fragmentDocumentId = normalizeWhitespace(String(fragment.documentId || ''));
|
|
60
|
+
const fragmentSourcePath = normalizeSourcePathForComparison(String(fragment.sourcePath || ''));
|
|
61
|
+
if (!anchorSource.documentId && !anchorSource.sourcePath) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
if (anchorSource.documentId && fragmentDocumentId !== anchorSource.documentId) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
if (anchorSource.sourcePath && fragmentSourcePath !== anchorSource.sourcePath) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return Boolean(fragmentDocumentId || fragmentSourcePath);
|
|
71
|
+
}
|
|
72
|
+
function hasFullReportBodyOutsideMermaid(fragment) {
|
|
73
|
+
const source = stripFullReportMermaid(String(fragment.text || ''))
|
|
74
|
+
.replace(/^#{1,6}\s+[^\n]*$/gmu, '')
|
|
75
|
+
.trim();
|
|
76
|
+
return Boolean(source) && !isFullReportInternalBlock(source);
|
|
77
|
+
}
|
|
78
|
+
function fullReportProductCaps(params) {
|
|
79
|
+
const budget = params.responseBudget;
|
|
80
|
+
const productCapDisabled = budget?.productCapDisabled === true;
|
|
81
|
+
if (!budget) {
|
|
82
|
+
return {
|
|
83
|
+
maxFragments: LEGACY_FULL_RESPONSE_MAX_FRAGMENTS,
|
|
84
|
+
maxChars: LEGACY_FULL_RESPONSE_MAX_CHARS,
|
|
85
|
+
productCapDisabled: false,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
maxFragments: productCapDisabled
|
|
90
|
+
? budget.runtimeGovernor.maxFragmentsProcessed
|
|
91
|
+
: (budget.rag?.maxFragments || LEGACY_FULL_RESPONSE_MAX_FRAGMENTS),
|
|
92
|
+
maxChars: productCapDisabled
|
|
93
|
+
? budget.runtimeGovernor.maxReportChars
|
|
94
|
+
: (budget.reportMaxChars || LEGACY_FULL_RESPONSE_MAX_CHARS),
|
|
95
|
+
productCapDisabled,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function selectFullReportFragments(params) {
|
|
99
|
+
const fragments = params.ragContextPack?.fragments || [];
|
|
100
|
+
const anchorSource = resolveFullReportAnchorSource(params);
|
|
101
|
+
const caps = fullReportProductCaps(params);
|
|
102
|
+
let truncated = false;
|
|
103
|
+
let truncationReason;
|
|
104
|
+
const candidates = fragments
|
|
105
|
+
.filter((fragment) => {
|
|
106
|
+
const title = normalizeWhitespace(String(fragment.title || '')).toLowerCase();
|
|
107
|
+
const headingPath = (Array.isArray(fragment.headingPath) ? fragment.headingPath : [])
|
|
108
|
+
.map((heading) => normalizeWhitespace(String(heading || '')).toLowerCase())
|
|
109
|
+
.join(' ');
|
|
110
|
+
const mermaidMarked = title.includes('mermaid') || headingPath.includes('mermaid');
|
|
111
|
+
return !title.includes('preamble')
|
|
112
|
+
&& (!mermaidMarked || hasFullReportBodyOutsideMermaid(fragment))
|
|
113
|
+
&& !headingPath.includes('preamble')
|
|
114
|
+
&& (!headingPath.includes('mermaid') || hasFullReportBodyOutsideMermaid(fragment));
|
|
115
|
+
})
|
|
116
|
+
.filter((fragment) => (FULL_REPORT_FRAGMENT_ROLES.has(fragment.role)
|
|
117
|
+
&& isFullReportGraphNeighborFromAnchorSource(fragment, anchorSource)));
|
|
118
|
+
const selected = [];
|
|
119
|
+
const selectedSections = new Set();
|
|
120
|
+
let usedChars = 0;
|
|
121
|
+
const sectionKey = (fragment) => {
|
|
122
|
+
const path = Array.isArray(fragment.headingPath) ? fragment.headingPath : [];
|
|
123
|
+
const leaf = normalizeWhitespace(String(path[path.length - 1] || fragment.title || ''))
|
|
124
|
+
.replace(/^#+\s*/u, '')
|
|
125
|
+
.replace(/\s*\((?:mermaid|code|diagram)\s+block\)\s*$/iu, '')
|
|
126
|
+
.toLowerCase();
|
|
127
|
+
return `${fragment.documentId}:${leaf}`;
|
|
128
|
+
};
|
|
129
|
+
const appendCandidate = (fragment) => {
|
|
130
|
+
if (selected.length >= caps.maxFragments || usedChars >= caps.maxChars) {
|
|
131
|
+
truncated = true;
|
|
132
|
+
truncationReason = caps.productCapDisabled
|
|
133
|
+
? (selected.length >= caps.maxFragments ? 'runtime_fragment_limit' : 'runtime_report_chars_limit')
|
|
134
|
+
: (selected.length >= caps.maxFragments ? 'product_fragment_limit' : 'product_report_chars_limit');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const text = String(fragment.text || '').trim();
|
|
138
|
+
if (!text
|
|
139
|
+
|| !FULL_REPORT_FRAGMENT_ROLES.has(fragment.role)
|
|
140
|
+
|| !isFullReportGraphNeighborFromAnchorSource(fragment, anchorSource)
|
|
141
|
+
|| (fragment.truncated && !hasBalancedMathDelimiters(text))) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const remaining = caps.maxChars - usedChars;
|
|
145
|
+
if (text.length > remaining) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const key = sectionKey(fragment);
|
|
149
|
+
if (selectedSections.has(key)) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
selected.push({
|
|
153
|
+
...fragment,
|
|
154
|
+
text,
|
|
155
|
+
charCount: text.length,
|
|
156
|
+
});
|
|
157
|
+
usedChars += text.length;
|
|
158
|
+
selectedSections.add(key);
|
|
159
|
+
};
|
|
160
|
+
const rolePriority = {
|
|
161
|
+
parent_context: 0,
|
|
162
|
+
adjacent_context: 1,
|
|
163
|
+
graph_neighbor_support: 2,
|
|
164
|
+
direct_support: 3,
|
|
165
|
+
conflict: 4,
|
|
166
|
+
};
|
|
167
|
+
const grouped = new Map();
|
|
168
|
+
candidates.forEach((fragment) => {
|
|
169
|
+
const key = sectionKey(fragment);
|
|
170
|
+
const group = grouped.get(key) || [];
|
|
171
|
+
group.push(fragment);
|
|
172
|
+
grouped.set(key, group);
|
|
173
|
+
});
|
|
174
|
+
const sectionCandidates = Array.from(grouped.values())
|
|
175
|
+
.map((group) => group.sort((left, right) => {
|
|
176
|
+
const roleDelta = (rolePriority[left.role] ?? 9) - (rolePriority[right.role] ?? 9);
|
|
177
|
+
if (roleDelta !== 0) {
|
|
178
|
+
return roleDelta;
|
|
179
|
+
}
|
|
180
|
+
const boundaryDelta = Number(right.sourceBoundary === 'full_document') - Number(left.sourceBoundary === 'full_document');
|
|
181
|
+
if (boundaryDelta !== 0) {
|
|
182
|
+
return boundaryDelta;
|
|
183
|
+
}
|
|
184
|
+
const lengthDelta = String(right.text || '').length - String(left.text || '').length;
|
|
185
|
+
if (lengthDelta !== 0) {
|
|
186
|
+
return lengthDelta;
|
|
187
|
+
}
|
|
188
|
+
const leftLine = Number.isFinite(Number(left.startLine)) ? Number(left.startLine) : Number.MAX_SAFE_INTEGER;
|
|
189
|
+
const rightLine = Number.isFinite(Number(right.startLine)) ? Number(right.startLine) : Number.MAX_SAFE_INTEGER;
|
|
190
|
+
return leftLine - rightLine;
|
|
191
|
+
}))
|
|
192
|
+
.sort((left, right) => {
|
|
193
|
+
const leftFragment = left[0];
|
|
194
|
+
const rightFragment = right[0];
|
|
195
|
+
const leftLine = Number.isFinite(Number(leftFragment?.startLine)) ? Number(leftFragment?.startLine) : Number.MAX_SAFE_INTEGER;
|
|
196
|
+
const rightLine = Number.isFinite(Number(rightFragment?.startLine)) ? Number(rightFragment?.startLine) : Number.MAX_SAFE_INTEGER;
|
|
197
|
+
if (leftFragment?.documentId !== rightFragment?.documentId) {
|
|
198
|
+
return String(leftFragment?.documentId || '').localeCompare(String(rightFragment?.documentId || ''));
|
|
199
|
+
}
|
|
200
|
+
return leftLine - rightLine;
|
|
201
|
+
});
|
|
202
|
+
sectionCandidates.forEach((group) => appendCandidate(group[0]));
|
|
203
|
+
if (selected.length < sectionCandidates.length && !truncated) {
|
|
204
|
+
truncated = true;
|
|
205
|
+
truncationReason = caps.productCapDisabled ? 'runtime_report_chars_limit' : 'product_report_chars_limit';
|
|
206
|
+
}
|
|
207
|
+
return { fragments: selected, truncated, truncationReason };
|
|
208
|
+
}
|
|
209
|
+
function hasBalancedMathDelimiters(value) {
|
|
210
|
+
const source = String(value || '');
|
|
211
|
+
const displayCount = (source.match(/(?<!\\)\$\$/gu) || []).length;
|
|
212
|
+
if (displayCount % 2 !== 0) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
const inlineSource = source.replace(/(?<!\\)\$\$/gu, '');
|
|
216
|
+
return ((inlineSource.match(/(?<!\\)\$/gu) || []).length % 2) === 0;
|
|
217
|
+
}
|
|
218
|
+
function isFullReportInternalBlock(value) {
|
|
219
|
+
const normalized = normalizeWhitespace(value);
|
|
220
|
+
return !normalized
|
|
221
|
+
|| /(?:遵从.{0,20}(?:指示|要求)|仅基于标题|所有推理过程|推理过程以英文|最终输出|输出为简体中文|本技术文档旨在|本文档旨在|we will|based only on the title|final output|all reasoning)/iu.test(normalized)
|
|
222
|
+
|| /(?:grounded by|key evidence|missDiagnostics|workspaceReadiness|matchedAtomCount|titleLikeQueries|retrieval_candidates_below_threshold|rag context pack|planner)/iu.test(normalized);
|
|
223
|
+
}
|
|
224
|
+
function stripFullReportMermaid(value) {
|
|
225
|
+
return String(value || '')
|
|
226
|
+
.replace(/```mermaid[\s\S]*?(?:```|$)/giu, '')
|
|
227
|
+
.replace(/```(?:graphviz|dot)[\s\S]*?(?:```|$)/giu, '')
|
|
228
|
+
.trim();
|
|
229
|
+
}
|
|
230
|
+
function sanitizeFullReportBlock(value) {
|
|
231
|
+
const source = String(value || '').replace(/\r\n?/gu, '\n').trim();
|
|
232
|
+
if (!source) {
|
|
233
|
+
return '';
|
|
234
|
+
}
|
|
235
|
+
const lines = source.split('\n');
|
|
236
|
+
const sanitizedLines = [];
|
|
237
|
+
lines.forEach((line) => {
|
|
238
|
+
const normalizedLine = line.trim();
|
|
239
|
+
if (!normalizedLine) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (/^#{1,6}\s+/u.test(normalizedLine) || /^\s*\|/u.test(normalizedLine)) {
|
|
243
|
+
if (!isFullReportInternalBlock(normalizedLine)) {
|
|
244
|
+
sanitizedLines.push(normalizedLine);
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const clauses = normalizedLine
|
|
249
|
+
.split(/(?<=[.!?。!?;;])(?:\s+|(?=[\p{L}]))/u)
|
|
250
|
+
.map((clause) => clause.trim())
|
|
251
|
+
.filter((clause) => clause && !isFullReportInternalBlock(clause));
|
|
252
|
+
if (clauses.length > 0) {
|
|
253
|
+
sanitizedLines.push(clauses.join(' '));
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
return sanitizedLines.join('\n').trim();
|
|
257
|
+
}
|
|
258
|
+
function isStandaloneFullReportHeading(value) {
|
|
259
|
+
return /^#{1,6}\s+\S[^\n]*$/u.test(String(value || '').trim());
|
|
260
|
+
}
|
|
261
|
+
function splitFullReportHeadingBody(value, headingPath) {
|
|
262
|
+
const normalized = String(value || '').trim();
|
|
263
|
+
const headingName = normalizeWhitespace(String(headingPath[headingPath.length - 1] || ''))
|
|
264
|
+
.replace(/^#+\s*/u, '')
|
|
265
|
+
.trim();
|
|
266
|
+
if (!normalized || !headingName || !/^#{1,6}\s+/u.test(normalized)) {
|
|
267
|
+
return { heading: '', body: normalized };
|
|
268
|
+
}
|
|
269
|
+
const escapedHeadingName = headingName.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
270
|
+
const headingMatch = normalized.match(new RegExp(`^(#{1,6})\\s+${escapedHeadingName}(?:\\s+|$)([\\s\\S]*)$`, 'iu'));
|
|
271
|
+
if (!headingMatch) {
|
|
272
|
+
return { heading: '', body: normalized };
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
heading: `${headingMatch[1]} ${headingName}`,
|
|
276
|
+
body: String(headingMatch[2] || '').trim(),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function appendFullReportBlock(lines, block, currentLength, dedupeValue = block, maxChars = LEGACY_FULL_RESPONSE_MAX_CHARS, onLimit) {
|
|
280
|
+
const normalized = sanitizeFullReportBlock(block);
|
|
281
|
+
if (!normalized || isFullReportInternalBlock(normalized) || !hasBalancedMathDelimiters(normalized)) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
const separatorLength = lines.length > 0 ? 2 : 0;
|
|
285
|
+
if (currentLength.value + separatorLength + normalized.length > maxChars) {
|
|
286
|
+
onLimit?.('report_chars_limit');
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
const key = normalizeWhitespace(dedupeValue).toLowerCase();
|
|
290
|
+
if (!key || currentLength.keys.has(key)) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
lines.push(normalized);
|
|
294
|
+
currentLength.value += separatorLength + normalized.length;
|
|
295
|
+
currentLength.keys.add(key);
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
function buildFullTechnicalReportResult(params, graphContext, graphAnswerPlan) {
|
|
299
|
+
const useChinese = useChineseAnswerLanguage(params);
|
|
300
|
+
const selection = selectFullReportFragments(params);
|
|
301
|
+
const caps = fullReportProductCaps(params);
|
|
302
|
+
if (selection.fragments.length <= 0) {
|
|
303
|
+
return {
|
|
304
|
+
answer: buildScopedConversationAnswer({ ...params, responseMode: 'slim' }, graphContext, graphAnswerPlan),
|
|
305
|
+
state: {
|
|
306
|
+
truncated: selection.truncated,
|
|
307
|
+
truncationReason: selection.truncationReason,
|
|
308
|
+
selectedFragmentCount: 0,
|
|
309
|
+
acceptedBlockCount: 0,
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
const reportBlocks = [];
|
|
314
|
+
const reportLength = { value: 0, keys: new Set() };
|
|
315
|
+
let truncated = selection.truncated;
|
|
316
|
+
let truncationReason = selection.truncationReason;
|
|
317
|
+
const markLimit = (reason) => {
|
|
318
|
+
truncated = true;
|
|
319
|
+
if (!truncationReason) {
|
|
320
|
+
truncationReason = caps.productCapDisabled ? `runtime_${reason}` : `product_${reason}`;
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
selection.fragments.forEach((fragment) => {
|
|
324
|
+
const source = stripFullReportMermaid(fragment.text);
|
|
325
|
+
let pendingHeading = '';
|
|
326
|
+
source
|
|
327
|
+
.split(/\n{2,}/u)
|
|
328
|
+
.map((block) => block.trim())
|
|
329
|
+
.filter(Boolean)
|
|
330
|
+
.forEach((block) => {
|
|
331
|
+
const normalizedBlock = block
|
|
332
|
+
.replace(/^#{1,6}\s+Water Glass\s*$/imu, '')
|
|
333
|
+
.trim();
|
|
334
|
+
if (!normalizedBlock) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const headingBody = splitFullReportHeadingBody(normalizedBlock, Array.isArray(fragment.headingPath) ? fragment.headingPath : []);
|
|
338
|
+
if (headingBody.heading && headingBody.body) {
|
|
339
|
+
appendFullReportBlock(reportBlocks, `${headingBody.heading}\n\n${headingBody.body}`, reportLength, headingBody.body, caps.maxChars, markLimit);
|
|
340
|
+
pendingHeading = '';
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (isStandaloneFullReportHeading(normalizedBlock)) {
|
|
344
|
+
pendingHeading = normalizedBlock;
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
const sectionBlock = pendingHeading
|
|
348
|
+
? `${pendingHeading}\n\n${normalizedBlock}`
|
|
349
|
+
: normalizedBlock;
|
|
350
|
+
appendFullReportBlock(reportBlocks, sectionBlock, reportLength, pendingHeading ? normalizedBlock : sectionBlock, caps.maxChars, markLimit);
|
|
351
|
+
pendingHeading = '';
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
const directClaims = graphAnswerPlan.claims
|
|
355
|
+
.filter((claim) => claim.required || claim.role === 'definition')
|
|
356
|
+
.map((claim) => normalizeWhitespace((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)(claim.statement)))
|
|
357
|
+
.filter(Boolean);
|
|
358
|
+
if (directClaims.length > 0 && !directClaims.some((claim) => reportBlocks.some((block) => normalizeWhitespace(block).toLowerCase().includes(claim.toLowerCase())))) {
|
|
359
|
+
const heading = useChinese ? '## 核心定义' : '## Definition';
|
|
360
|
+
appendFullReportBlock(reportBlocks, heading, reportLength, heading, caps.maxChars, markLimit);
|
|
361
|
+
directClaims.forEach((claim) => appendFullReportBlock(reportBlocks, claim, reportLength, claim, caps.maxChars, markLimit));
|
|
362
|
+
}
|
|
363
|
+
const answer = reportBlocks.join('\n\n').trim()
|
|
364
|
+
|| buildScopedConversationAnswer({ ...params, responseMode: 'slim' }, graphContext, graphAnswerPlan);
|
|
365
|
+
return {
|
|
366
|
+
answer,
|
|
367
|
+
state: {
|
|
368
|
+
truncated,
|
|
369
|
+
truncationReason,
|
|
370
|
+
selectedFragmentCount: selection.fragments.length,
|
|
371
|
+
acceptedBlockCount: reportBlocks.length,
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function buildFullTechnicalReport(params, graphContext, graphAnswerPlan) {
|
|
376
|
+
return buildFullTechnicalReportResult(params, graphContext, graphAnswerPlan).answer;
|
|
377
|
+
}
|
|
9
378
|
function normalizeWhitespace(value) {
|
|
10
379
|
return String(value || '').replace(/\s+/g, ' ').trim();
|
|
11
380
|
}
|
|
@@ -427,50 +796,23 @@ function classifyScopedConversationIntent(message) {
|
|
|
427
796
|
}
|
|
428
797
|
return 'generic';
|
|
429
798
|
}
|
|
430
|
-
function resolveRagAnswerProfile(message) {
|
|
431
|
-
const intent = classifyScopedConversationIntent(message);
|
|
432
|
-
if (intent === 'compare') {
|
|
433
|
-
return {
|
|
434
|
-
directSupportSentenceCount: 4,
|
|
435
|
-
documentContextSentenceCount: 1,
|
|
436
|
-
graphNeighborSentenceCount: 2,
|
|
437
|
-
publicSentenceCount: 6,
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
if (intent === 'how_to') {
|
|
441
|
-
return {
|
|
442
|
-
directSupportSentenceCount: 3,
|
|
443
|
-
documentContextSentenceCount: 1,
|
|
444
|
-
graphNeighborSentenceCount: 2,
|
|
445
|
-
publicSentenceCount: 6,
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
if (intent === 'causal_explain') {
|
|
449
|
-
return {
|
|
450
|
-
directSupportSentenceCount: 2,
|
|
451
|
-
documentContextSentenceCount: 2,
|
|
452
|
-
graphNeighborSentenceCount: 2,
|
|
453
|
-
publicSentenceCount: 6,
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
|
-
if (intent === 'generic') {
|
|
457
|
-
return {
|
|
458
|
-
directSupportSentenceCount: 2,
|
|
459
|
-
documentContextSentenceCount: 2,
|
|
460
|
-
graphNeighborSentenceCount: 1,
|
|
461
|
-
publicSentenceCount: 6,
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
return {
|
|
465
|
-
directSupportSentenceCount: 1,
|
|
466
|
-
documentContextSentenceCount: 2,
|
|
467
|
-
graphNeighborSentenceCount: 1,
|
|
468
|
-
publicSentenceCount: 6,
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
799
|
function containsCjk(value) {
|
|
472
800
|
return /[\u3040-\u30ff\u3400-\u9fff\uf900-\ufaff]/u.test(String(value || ''));
|
|
473
801
|
}
|
|
802
|
+
function useChineseAnswerLanguage(params) {
|
|
803
|
+
if (params.answerLanguage === 'zh') {
|
|
804
|
+
return true;
|
|
805
|
+
}
|
|
806
|
+
if (params.answerLanguage === 'en') {
|
|
807
|
+
return false;
|
|
808
|
+
}
|
|
809
|
+
return containsCjk([
|
|
810
|
+
params.message,
|
|
811
|
+
params.knowledgePoints[0]?.title,
|
|
812
|
+
params.knowledgePoints[0]?.summary,
|
|
813
|
+
params.graphContext?.anchorTitle,
|
|
814
|
+
].filter(Boolean).join(' '));
|
|
815
|
+
}
|
|
474
816
|
function stripConversationAnswerTerminalPunctuation(value) {
|
|
475
817
|
return normalizeWhitespace(String(value || '').replace(/[.!?\u3002\uFF01\uFF1F]+$/u, ''));
|
|
476
818
|
}
|
|
@@ -517,170 +859,24 @@ function normalizeGraphAnswerDisplayTitle(value) {
|
|
|
517
859
|
.replace(/\s*\((?:mermaid|code|diagram)\s+block\)\s*$/iu, '')
|
|
518
860
|
.trim());
|
|
519
861
|
}
|
|
520
|
-
function normalizeGraphAnswerComparableTitle(value) {
|
|
521
|
-
return normalizeGraphAnswerDisplayTitle(value).toLowerCase();
|
|
522
|
-
}
|
|
523
|
-
function collectGraphWindowTitles(graphContext, windowKey, limit) {
|
|
524
|
-
if (!graphContext || !Array.isArray(graphContext[windowKey])) {
|
|
525
|
-
return [];
|
|
526
|
-
}
|
|
527
|
-
const anchorAtomId = normalizeWhitespace(String(graphContext.anchorAtomId || '').trim());
|
|
528
|
-
const anchorTitle = normalizeGraphAnswerComparableTitle(graphContext.anchorTitle);
|
|
529
|
-
const seen = new Set();
|
|
530
|
-
const titles = [];
|
|
531
|
-
for (const node of graphContext[windowKey] || []) {
|
|
532
|
-
const atomId = normalizeWhitespace(String(node && node.atomId || '').trim());
|
|
533
|
-
const title = normalizeGraphAnswerDisplayTitle(String(node && node.title || ''));
|
|
534
|
-
const comparableTitle = normalizeGraphAnswerComparableTitle(title);
|
|
535
|
-
if (!title || (atomId && atomId === anchorAtomId) || (comparableTitle && comparableTitle === anchorTitle)) {
|
|
536
|
-
continue;
|
|
537
|
-
}
|
|
538
|
-
const key = comparableTitle || atomId;
|
|
539
|
-
if (seen.has(key)) {
|
|
540
|
-
continue;
|
|
541
|
-
}
|
|
542
|
-
seen.add(key);
|
|
543
|
-
titles.push(title);
|
|
544
|
-
if (titles.length >= limit) {
|
|
545
|
-
break;
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
return titles;
|
|
549
|
-
}
|
|
550
862
|
function buildGraphProfileAnswerSentence(graphContext, useChinese) {
|
|
551
863
|
if (!graphContext) {
|
|
552
864
|
return '';
|
|
553
865
|
}
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
:
|
|
557
|
-
|
|
558
|
-
const predecessorTitles = collectGraphWindowTitles(graphContext, 'predecessorWindow', 2);
|
|
559
|
-
const successorTitles = collectGraphWindowTitles(graphContext, 'successorWindow', 2);
|
|
560
|
-
const degreeParts = [];
|
|
561
|
-
const inDegree = anchorProfile ? Number(anchorProfile.inDegree) : NaN;
|
|
562
|
-
const outDegree = anchorProfile ? Number(anchorProfile.outDegree) : NaN;
|
|
563
|
-
if (Number.isFinite(inDegree)) {
|
|
564
|
-
degreeParts.push(useChinese ? `入度为 ${inDegree}` : `${inDegree} incoming`);
|
|
565
|
-
}
|
|
566
|
-
if (Number.isFinite(outDegree)) {
|
|
567
|
-
degreeParts.push(useChinese ? `出度为 ${outDegree}` : `${outDegree} outgoing`);
|
|
568
|
-
}
|
|
569
|
-
if (degreeParts.length <= 0 && predecessorTitles.length <= 0 && successorTitles.length <= 0) {
|
|
570
|
-
return '';
|
|
571
|
-
}
|
|
572
|
-
if (useChinese) {
|
|
573
|
-
const fragments = [];
|
|
574
|
-
if (degreeParts.length > 0) {
|
|
575
|
-
fragments.push(`${anchorTitle || '当前锚点'}在当前图中的${degreeParts.join(',')}`);
|
|
576
|
-
}
|
|
577
|
-
if (predecessorTitles.length > 0) {
|
|
578
|
-
fragments.push(`紧邻前置节点包括 ${predecessorTitles.join('、')}`);
|
|
579
|
-
}
|
|
580
|
-
if (successorTitles.length > 0) {
|
|
581
|
-
fragments.push(`后续分支包括 ${successorTitles.join('、')}`);
|
|
582
|
-
}
|
|
583
|
-
return fragments.join(',');
|
|
584
|
-
}
|
|
585
|
-
const fragments = [];
|
|
586
|
-
if (degreeParts.length > 0) {
|
|
587
|
-
fragments.push(`${anchorTitle || 'The current anchor'} has ${degreeParts.join(' and ')} links in the current graph`);
|
|
588
|
-
}
|
|
589
|
-
if (predecessorTitles.length > 0 && successorTitles.length > 0) {
|
|
590
|
-
fragments.push(`its immediate predecessors include ${predecessorTitles.join(', ')}, and likely next nodes include ${successorTitles.join(', ')}`);
|
|
591
|
-
}
|
|
592
|
-
else if (predecessorTitles.length > 0) {
|
|
593
|
-
fragments.push(`its immediate predecessors include ${predecessorTitles.join(', ')}`);
|
|
594
|
-
}
|
|
595
|
-
else if (successorTitles.length > 0) {
|
|
596
|
-
fragments.push(`its likely next nodes include ${successorTitles.join(', ')}`);
|
|
597
|
-
}
|
|
598
|
-
return fragments.join('; ');
|
|
599
|
-
}
|
|
600
|
-
const RAG_ANSWER_QUERY_STOPWORDS = new Set([
|
|
601
|
-
'a', 'about', 'an', 'and', 'are', 'as', 'at', 'be', 'between', 'by', 'compare',
|
|
602
|
-
'contrast', 'difference', 'differences', 'do', 'does', 'from', 'how',
|
|
603
|
-
'in', 'is', 'it', 'me', 'of', 'on', 'or', 'plan', 'step', 'steps', 'tell', 'the', 'to', 'versus', 'vs', 'what',
|
|
604
|
-
'which', 'with',
|
|
605
|
-
]);
|
|
606
|
-
function extractRagAnswerQueryTerms(message) {
|
|
607
|
-
const terms = (String(message || '').toLowerCase().match(/[\p{L}\p{N}]+/gu) || [])
|
|
608
|
-
.map((term) => term.trim())
|
|
609
|
-
.filter((term) => term.length >= 2 && !RAG_ANSWER_QUERY_STOPWORDS.has(term));
|
|
610
|
-
return Array.from(new Set(terms));
|
|
611
|
-
}
|
|
612
|
-
function normalizeMermaidEvidenceLabel(value) {
|
|
613
|
-
return normalizeWhitespace(String(value || '')
|
|
614
|
-
.replace(/<br\s*\/?>/giu, ' ')
|
|
615
|
-
.replace(/\\n/gu, ' ')
|
|
616
|
-
.replace(/[`*_~#|{}]/gu, ' ')
|
|
617
|
-
.replace(/\s{2,}/gu, ' ')
|
|
618
|
-
.trim());
|
|
619
|
-
}
|
|
620
|
-
function extractMermaidEvidenceLabels(fenceText) {
|
|
621
|
-
const normalizedFence = String(fenceText || '').trim();
|
|
622
|
-
if (!/^mermaid\b/iu.test(normalizedFence)) {
|
|
623
|
-
return '';
|
|
624
|
-
}
|
|
625
|
-
const mermaidBody = normalizedFence.replace(/^mermaid\b/iu, '').trim();
|
|
626
|
-
const labels = [];
|
|
627
|
-
const appendLabel = (value) => {
|
|
628
|
-
const label = normalizeMermaidEvidenceLabel(value);
|
|
629
|
-
if (label && !labels.includes(label)) {
|
|
630
|
-
labels.push(label);
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
mermaidBody.replace(/\[([^\]]+)\]/gu, (_match, label) => {
|
|
634
|
-
appendLabel(label);
|
|
635
|
-
return '';
|
|
866
|
+
const facts = (0, graphAnswerFacts_1.collectGraphAnswerFacts)(graphContext, {
|
|
867
|
+
anchorAtomId: graphContext.anchorAtomId,
|
|
868
|
+
anchorTitle: graphContext.anchorTitle,
|
|
869
|
+
normalizeTitle: (value) => normalizeGraphAnswerDisplayTitle(String(value || '')),
|
|
636
870
|
});
|
|
637
|
-
|
|
638
|
-
appendLabel(label);
|
|
871
|
+
if (!facts) {
|
|
639
872
|
return '';
|
|
640
|
-
});
|
|
641
|
-
return labels.join('. ');
|
|
642
|
-
}
|
|
643
|
-
function cleanRagEvidenceText(value) {
|
|
644
|
-
return normalizeWhitespace(String(value || '')
|
|
645
|
-
.replace(/```([\s\S]*?)(?:```|$)/gu, (_match, fenceText) => (` ${extractMermaidEvidenceLabels(fenceText)} `))
|
|
646
|
-
.split(/\r?\n/u)
|
|
647
|
-
.filter((line) => !/^#{1,6}\s+/u.test(line.trim()))
|
|
648
|
-
.join(' ')
|
|
649
|
-
.replace(/\[[^\]]+\]\([^)]*\)/gu, ' ')
|
|
650
|
-
.replace(/!\[[^\]]*\]\([^)]*\)/gu, ' ')
|
|
651
|
-
.replace(/[*_~`>#|]/gu, ' ')
|
|
652
|
-
.replace(/\s{2,}/gu, ' '));
|
|
653
|
-
}
|
|
654
|
-
function splitRagEvidenceSentences(fragment) {
|
|
655
|
-
const cleaned = cleanRagEvidenceText(fragment.text);
|
|
656
|
-
if (!cleaned) {
|
|
657
|
-
return [];
|
|
658
|
-
}
|
|
659
|
-
const sentences = [];
|
|
660
|
-
let start = 0;
|
|
661
|
-
for (let index = 0; index < cleaned.length; index += 1) {
|
|
662
|
-
const char = cleaned[index];
|
|
663
|
-
const isDecimalPoint = char === '.'
|
|
664
|
-
&& /\d/u.test(cleaned[index - 1] || '')
|
|
665
|
-
&& /\d/u.test(cleaned[index + 1] || '');
|
|
666
|
-
const isBoundary = !isDecimalPoint && /[.!?\u3002\uFF01\uFF1F]/u.test(char);
|
|
667
|
-
if (!isBoundary) {
|
|
668
|
-
continue;
|
|
669
|
-
}
|
|
670
|
-
sentences.push(cleaned.slice(start, index + 1));
|
|
671
|
-
start = index + 1;
|
|
672
873
|
}
|
|
673
|
-
|
|
674
|
-
sentences.push(cleaned.slice(start));
|
|
675
|
-
}
|
|
676
|
-
return (sentences.length > 0 ? sentences : [cleaned])
|
|
677
|
-
.map((sentence) => normalizeWhitespace(sentence))
|
|
678
|
-
.filter((sentence) => sentence.length >= 16);
|
|
874
|
+
return (0, graphAnswerFacts_1.formatGraphAnswerProfileSentence)(facts, useChinese);
|
|
679
875
|
}
|
|
680
876
|
function sentenceComparableKey(value) {
|
|
681
877
|
return stripConversationAnswerTerminalPunctuation(value).toLowerCase();
|
|
682
878
|
}
|
|
683
|
-
function
|
|
879
|
+
function appendPlannedEvidenceSentence(sentences, candidate, useChinese) {
|
|
684
880
|
const normalized = normalizeConversationAnswerSentence((0, ragPublicText_1.naturalizeRagPublicEvidenceClause)(candidate), useChinese);
|
|
685
881
|
if (!normalized) {
|
|
686
882
|
return;
|
|
@@ -690,101 +886,14 @@ function appendRagEvidenceSentence(sentences, candidate, useChinese) {
|
|
|
690
886
|
const existingKey = sentenceComparableKey(sentence);
|
|
691
887
|
return existingKey === candidateKey
|
|
692
888
|
|| (candidateKey.length >= 32 && existingKey.includes(candidateKey))
|
|
693
|
-
|| (existingKey.length >= 32 && candidateKey.includes(existingKey))
|
|
889
|
+
|| (existingKey.length >= 32 && candidateKey.includes(existingKey))
|
|
890
|
+
|| (0, graphAnswerQualityPolicy_1.isPolaritySafeSemanticDuplicate)(existingKey, candidateKey);
|
|
694
891
|
});
|
|
695
892
|
if (!alreadyCovered) {
|
|
696
893
|
sentences.push(normalized);
|
|
697
894
|
}
|
|
698
895
|
}
|
|
699
|
-
function
|
|
700
|
-
const lower = sentence.toLowerCase();
|
|
701
|
-
return new Set(queryTerms.filter((term) => lower.includes(term)));
|
|
702
|
-
}
|
|
703
|
-
function collectFragmentLeafHeadingQueryTerms(fragment, queryTerms) {
|
|
704
|
-
const headingPath = Array.isArray(fragment.headingPath) ? fragment.headingPath : [];
|
|
705
|
-
const leafHeading = normalizeWhitespace(String(headingPath[headingPath.length - 1] || ''));
|
|
706
|
-
if (!leafHeading) {
|
|
707
|
-
return new Set();
|
|
708
|
-
}
|
|
709
|
-
return collectSentenceQueryTerms(leafHeading, queryTerms);
|
|
710
|
-
}
|
|
711
|
-
function rankRagEvidenceSentenceCandidates(candidates, limit, options = {}) {
|
|
712
|
-
const remaining = candidates.slice();
|
|
713
|
-
const ranked = [];
|
|
714
|
-
const coveredTerms = new Set();
|
|
715
|
-
while (remaining.length > 0 && ranked.length < limit) {
|
|
716
|
-
let bestIndex = 0;
|
|
717
|
-
let bestScore = Number.NEGATIVE_INFINITY;
|
|
718
|
-
remaining.forEach((candidate, index) => {
|
|
719
|
-
const totalTermCount = candidate.queryTerms.size;
|
|
720
|
-
const headingTermCount = options.useLeafHeadingScore ? candidate.headingQueryTerms.size : 0;
|
|
721
|
-
const uncoveredTermCount = Array.from(candidate.queryTerms)
|
|
722
|
-
.filter((term) => !coveredTerms.has(term))
|
|
723
|
-
.length;
|
|
724
|
-
const score = uncoveredTermCount * 4
|
|
725
|
-
+ (uncoveredTermCount > 0 ? totalTermCount : 0)
|
|
726
|
-
+ (totalTermCount > 0 ? candidate.fragmentQueryTermCount / 2 : 0)
|
|
727
|
-
+ headingTermCount * 6
|
|
728
|
-
- candidate.order / 10000;
|
|
729
|
-
if (score > bestScore) {
|
|
730
|
-
bestScore = score;
|
|
731
|
-
bestIndex = index;
|
|
732
|
-
}
|
|
733
|
-
});
|
|
734
|
-
const [selected] = remaining.splice(bestIndex, 1);
|
|
735
|
-
ranked.push(selected);
|
|
736
|
-
selected.queryTerms.forEach((term) => coveredTerms.add(term));
|
|
737
|
-
}
|
|
738
|
-
return ranked;
|
|
739
|
-
}
|
|
740
|
-
function selectRagEvidenceSentences(fragments, roles, limit, queryTerms = [], options = {}) {
|
|
741
|
-
const selected = [];
|
|
742
|
-
const candidates = [];
|
|
743
|
-
let sentenceOrder = 0;
|
|
744
|
-
fragments
|
|
745
|
-
.filter((fragment) => roles.has(fragment.role))
|
|
746
|
-
.forEach((fragment) => {
|
|
747
|
-
const sentences = splitRagEvidenceSentences(fragment);
|
|
748
|
-
const headingQueryTerms = collectFragmentLeafHeadingQueryTerms(fragment, queryTerms);
|
|
749
|
-
const fragmentQueryTerms = new Set(sentences.flatMap((sentence) => Array.from(collectSentenceQueryTerms(sentence, queryTerms))));
|
|
750
|
-
sentences.forEach((sentence) => {
|
|
751
|
-
if (options.rejectSentence?.(sentence)) {
|
|
752
|
-
sentenceOrder += 1;
|
|
753
|
-
return;
|
|
754
|
-
}
|
|
755
|
-
const comparable = sentenceComparableKey(sentence);
|
|
756
|
-
if (!candidates.some((existing) => sentenceComparableKey(existing.sentence) === comparable)) {
|
|
757
|
-
candidates.push({
|
|
758
|
-
sentence,
|
|
759
|
-
queryTerms: collectSentenceQueryTerms(sentence, queryTerms),
|
|
760
|
-
headingQueryTerms,
|
|
761
|
-
fragmentQueryTermCount: fragmentQueryTerms.size,
|
|
762
|
-
order: sentenceOrder,
|
|
763
|
-
});
|
|
764
|
-
}
|
|
765
|
-
sentenceOrder += 1;
|
|
766
|
-
});
|
|
767
|
-
});
|
|
768
|
-
const maxHeadingTermCount = candidates.reduce((max, candidate) => Math.max(max, candidate.headingQueryTerms.size), 0);
|
|
769
|
-
const selectionCandidates = options.preferBestLeafHeadingMatch && maxHeadingTermCount > 0
|
|
770
|
-
? candidates.filter((candidate) => candidate.headingQueryTerms.size === maxHeadingTermCount)
|
|
771
|
-
: candidates;
|
|
772
|
-
const hasQuerySignal = queryTerms.length > 0 && selectionCandidates.some((candidate) => (candidate.queryTerms.size > 0 || candidate.headingQueryTerms.size > 0));
|
|
773
|
-
const orderedCandidates = hasQuerySignal
|
|
774
|
-
? rankRagEvidenceSentenceCandidates(selectionCandidates, limit, options)
|
|
775
|
-
: selectionCandidates;
|
|
776
|
-
orderedCandidates.forEach((candidate) => {
|
|
777
|
-
if (selected.length >= limit) {
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
const comparable = sentenceComparableKey(candidate.sentence);
|
|
781
|
-
if (!selected.some((existing) => sentenceComparableKey(existing) === comparable)) {
|
|
782
|
-
selected.push(candidate.sentence);
|
|
783
|
-
}
|
|
784
|
-
});
|
|
785
|
-
return selected;
|
|
786
|
-
}
|
|
787
|
-
function buildRagAugmentedConversationAnswer(params, graphContext, useChinese) {
|
|
896
|
+
function buildCoverageDrivenRagAnswer(params, graphContext, graphAnswerPlan, useChinese) {
|
|
788
897
|
const pack = params.ragContextPack;
|
|
789
898
|
if (!pack || !Array.isArray(pack.fragments) || pack.fragments.length <= 0) {
|
|
790
899
|
return '';
|
|
@@ -792,63 +901,62 @@ function buildRagAugmentedConversationAnswer(params, graphContext, useChinese) {
|
|
|
792
901
|
if (params.ragSufficiencyReview?.status === 'insufficient') {
|
|
793
902
|
return '';
|
|
794
903
|
}
|
|
795
|
-
const profile = resolveRagAnswerProfile(params.message);
|
|
796
|
-
const intent = classifyScopedConversationIntent(params.message);
|
|
797
|
-
const answerQueryTerms = extractRagAnswerQueryTerms(params.message);
|
|
798
|
-
const rejectCompareProcedureSentence = intent === 'compare'
|
|
799
|
-
? (sentence) => (0, ragPublicText_1.shouldRejectCompareProcedureEvidenceClause)(sentence, params.message)
|
|
800
|
-
: undefined;
|
|
801
904
|
const answerSentences = [];
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
if (hasConflictEvidence) {
|
|
809
|
-
selectRagEvidenceSentences(pack.fragments, new Set(['conflict']), 3, answerQueryTerms)
|
|
810
|
-
.forEach((sentence) => appendRagEvidenceSentence(answerSentences, sentence, useChinese));
|
|
811
|
-
}
|
|
812
|
-
selectRagEvidenceSentences(pack.fragments, new Set(['parent_context', 'adjacent_context']), profile.documentContextSentenceCount, answerQueryTerms, {
|
|
813
|
-
useLeafHeadingScore: intent !== 'compare',
|
|
814
|
-
preferBestLeafHeadingMatch: intent !== 'compare',
|
|
815
|
-
rejectSentence: rejectCompareProcedureSentence,
|
|
816
|
-
})
|
|
817
|
-
.forEach((sentence) => appendRagEvidenceSentence(answerSentences, sentence, useChinese));
|
|
818
|
-
selectRagEvidenceSentences(pack.fragments, new Set(['graph_neighbor_support']), profile.graphNeighborSentenceCount, answerQueryTerms, {
|
|
819
|
-
rejectSentence: rejectCompareProcedureSentence,
|
|
820
|
-
})
|
|
821
|
-
.forEach((sentence) => appendRagEvidenceSentence(answerSentences, sentence, useChinese));
|
|
905
|
+
const hasLearningRouteTask = Boolean(graphAnswerPlan.answerTaskPlan?.subtasks.some((subtask) => subtask.kind === 'learning_route'));
|
|
906
|
+
graphAnswerPlan.claims
|
|
907
|
+
.forEach((claim) => appendPlannedEvidenceSentence(answerSentences, claim.statement, useChinese));
|
|
908
|
+
if (answerSentences.length <= 0) {
|
|
909
|
+
return '';
|
|
910
|
+
}
|
|
822
911
|
if (params.ragSufficiencyReview?.status === 'borderline') {
|
|
823
|
-
|
|
912
|
+
appendPlannedEvidenceSentence(answerSentences, useChinese
|
|
824
913
|
? '当前证据覆盖仍然有限,因此这只能作为基于已命中材料的部分回答'
|
|
825
914
|
: 'The available evidence is still partial, so this answer stays within the matched material', useChinese);
|
|
826
915
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
916
|
+
if (!hasLearningRouteTask) {
|
|
917
|
+
appendConversationAnswerSentence(answerSentences, buildGraphConnectionPathAnswerSentence(graphContext, useChinese), useChinese);
|
|
918
|
+
appendConversationAnswerSentence(answerSentences, buildGraphProfileAnswerSentence(graphContext, useChinese), useChinese);
|
|
919
|
+
}
|
|
920
|
+
return (0, answerTaskPlan_1.formatTaskAwareAnswer)(answerSentences, graphAnswerPlan.answerTaskPlan, useChinese);
|
|
830
921
|
}
|
|
831
|
-
function buildScopedConversationAnswer(params, graphContext) {
|
|
922
|
+
function buildScopedConversationAnswer(params, graphContext, graphAnswerPlan) {
|
|
923
|
+
if (isFullResponseMode(params)) {
|
|
924
|
+
return buildFullTechnicalReport(params, graphContext, graphAnswerPlan);
|
|
925
|
+
}
|
|
926
|
+
const useChinese = useChineseAnswerLanguage(params);
|
|
832
927
|
if (params.knowledgePoints.length <= 0) {
|
|
833
|
-
const
|
|
834
|
-
const missMessage = String(params.usedScope.missDiagnostics?.message || '').trim();
|
|
928
|
+
const query = normalizeWhitespace(String(params.message || '')) || (useChinese ? '当前问题' : 'your query');
|
|
835
929
|
if (params.recalledMemories.length > 0) {
|
|
836
|
-
return
|
|
930
|
+
return useChinese
|
|
931
|
+
? `当前范围没有匹配“${query}”的知识点,但已找回 ${params.recalledMemories.length} 条相关会话记忆。请调整知识范围,或将这条记忆作为后续检索锚点。`
|
|
932
|
+
: `No scoped knowledge points matched "${query}", but I recovered ${params.recalledMemories.length} relevant conversation memory note(s). Refine the corpus scope or use the recalled memory as a follow-up anchor.`;
|
|
837
933
|
}
|
|
838
|
-
return
|
|
934
|
+
return useChinese
|
|
935
|
+
? `当前范围没有匹配“${query}”的知识点。请调整范围、补充笔记,或使用更具体的检索词。`
|
|
936
|
+
: `No scoped knowledge points matched "${query}". Refine the scope, add more notes to the corpus, or broaden the query terms.`;
|
|
839
937
|
}
|
|
840
938
|
const leadingPoint = params.knowledgePoints[0];
|
|
841
|
-
const useChinese = containsCjk([
|
|
842
|
-
params.message,
|
|
843
|
-
leadingPoint.title,
|
|
844
|
-
leadingPoint.summary,
|
|
845
|
-
graphContext && graphContext.anchorTitle,
|
|
846
|
-
].filter(Boolean).join(' '));
|
|
847
939
|
const answerSentences = [];
|
|
848
|
-
const ragAnswer =
|
|
940
|
+
const ragAnswer = buildCoverageDrivenRagAnswer(params, graphContext, graphAnswerPlan, useChinese);
|
|
849
941
|
if (ragAnswer) {
|
|
850
942
|
return ragAnswer;
|
|
851
943
|
}
|
|
944
|
+
if (graphAnswerPlan.claims.length > 0) {
|
|
945
|
+
const hasLearningRouteTask = Boolean(graphAnswerPlan.answerTaskPlan?.subtasks.some((subtask) => subtask.kind === 'learning_route'));
|
|
946
|
+
graphAnswerPlan.claims.forEach((claim) => {
|
|
947
|
+
appendConversationAnswerSentence(answerSentences, claim.statement, useChinese);
|
|
948
|
+
});
|
|
949
|
+
if (params.ragSufficiencyReview?.status === 'borderline') {
|
|
950
|
+
appendConversationAnswerSentence(answerSentences, useChinese
|
|
951
|
+
? '当前证据覆盖仍然有限,因此回答只陈述已有材料能够支持的内容'
|
|
952
|
+
: 'The evidence coverage is still partial, so the answer stays within the retrieved material', useChinese);
|
|
953
|
+
}
|
|
954
|
+
if (!hasLearningRouteTask) {
|
|
955
|
+
appendConversationAnswerSentence(answerSentences, buildGraphConnectionPathAnswerSentence(graphContext, useChinese), useChinese);
|
|
956
|
+
appendConversationAnswerSentence(answerSentences, buildGraphProfileAnswerSentence(graphContext, useChinese), useChinese);
|
|
957
|
+
}
|
|
958
|
+
return (0, answerTaskPlan_1.formatTaskAwareAnswer)(answerSentences, graphAnswerPlan.answerTaskPlan, useChinese);
|
|
959
|
+
}
|
|
852
960
|
const directSentence = selectScopedConversationDirectSentence(params.message, leadingPoint);
|
|
853
961
|
if (directSentence) {
|
|
854
962
|
appendConversationAnswerSentence(answerSentences, directSentence, useChinese);
|
|
@@ -868,94 +976,150 @@ function buildScopedConversationAnswer(params, graphContext) {
|
|
|
868
976
|
if (answerSentences.length < 2 && params.knowledgePoints.length > 1) {
|
|
869
977
|
appendConversationAnswerSentence(answerSentences, selectScopedConversationDirectSentence(params.message, params.knowledgePoints[1]), useChinese);
|
|
870
978
|
}
|
|
871
|
-
return answerSentences.
|
|
979
|
+
return answerSentences.join(useChinese ? '' : ' ');
|
|
872
980
|
}
|
|
873
981
|
function buildScopedConversationOverviewMarkdown(params, graphContext) {
|
|
982
|
+
const useChinese = useChineseAnswerLanguage(params);
|
|
874
983
|
const strongestPoint = params.knowledgePoints[0];
|
|
875
984
|
const lines = [
|
|
876
|
-
'## Answer Context',
|
|
985
|
+
useChinese ? '## 回答上下文' : '## Answer Context',
|
|
877
986
|
'',
|
|
878
987
|
];
|
|
879
988
|
if (strongestPoint) {
|
|
880
|
-
lines.push(
|
|
989
|
+
lines.push(useChinese
|
|
990
|
+
? `当前最佳范围锚点:**${strongestPoint.title}**。`
|
|
991
|
+
: `Best scoped anchor: **${strongestPoint.title}**.`, '');
|
|
881
992
|
}
|
|
882
993
|
else {
|
|
883
|
-
lines.push(
|
|
884
|
-
|
|
885
|
-
|
|
994
|
+
lines.push(useChinese
|
|
995
|
+
? '当前请求没有得到足够强的范围内知识点匹配。'
|
|
996
|
+
: 'No scoped knowledge point produced a strong match for the current request.', '');
|
|
997
|
+
}
|
|
998
|
+
lines.push(...(useChinese
|
|
999
|
+
? [
|
|
1000
|
+
`- 相关知识点:**${params.knowledgePoints.length}**`,
|
|
1001
|
+
`- 返回引用:**${params.citations.length}**`,
|
|
1002
|
+
`- 已召回范围内记忆:**${params.recalledMemories.length}**`,
|
|
1003
|
+
]
|
|
1004
|
+
: [
|
|
1005
|
+
`- Relevant knowledge points: **${params.knowledgePoints.length}**`,
|
|
1006
|
+
`- Citations returned: **${params.citations.length}**`,
|
|
1007
|
+
`- Scoped memories recalled: **${params.recalledMemories.length}**`,
|
|
1008
|
+
]));
|
|
886
1009
|
if (graphContext && graphContext.relationKinds.length > 0) {
|
|
887
|
-
lines.push(
|
|
1010
|
+
lines.push(useChinese
|
|
1011
|
+
? `- 图谱支持关系:**${graphContext.relationKinds.join(', ')}**`
|
|
1012
|
+
: `- Graph-supported relations: **${graphContext.relationKinds.join(', ')}**`);
|
|
888
1013
|
}
|
|
889
1014
|
if (graphContext) {
|
|
890
|
-
lines.push(
|
|
1015
|
+
lines.push(useChinese
|
|
1016
|
+
? `- 时序有效性:**${graphContext.temporalValidity.allPointsValid ? '有效' : '警告'}**`
|
|
1017
|
+
: `- Temporal validity: **${graphContext.temporalValidity.allPointsValid ? 'valid' : 'warning'}**`);
|
|
891
1018
|
}
|
|
892
1019
|
if (graphContext && Array.isArray(graphContext.connectionPaths) && graphContext.connectionPaths.length > 0) {
|
|
893
|
-
lines.push(
|
|
1020
|
+
lines.push(useChinese
|
|
1021
|
+
? `- 显式连接路径:**${graphContext.connectionPaths.length}**`
|
|
1022
|
+
: `- Explicit connection paths: **${graphContext.connectionPaths.length}**`);
|
|
894
1023
|
}
|
|
895
1024
|
if (graphContext && Array.isArray(graphContext.predecessorWindow) && graphContext.predecessorWindow.length > 0) {
|
|
896
|
-
lines.push(
|
|
1025
|
+
lines.push(useChinese
|
|
1026
|
+
? `- 直接前置节点:**${graphContext.predecessorWindow.length}**`
|
|
1027
|
+
: `- Immediate predecessors: **${graphContext.predecessorWindow.length}**`);
|
|
897
1028
|
}
|
|
898
1029
|
if (graphContext && Array.isArray(graphContext.successorWindow) && graphContext.successorWindow.length > 0) {
|
|
899
|
-
lines.push(
|
|
1030
|
+
lines.push(useChinese
|
|
1031
|
+
? `- 直接后继节点:**${graphContext.successorWindow.length}**`
|
|
1032
|
+
: `- Immediate successors: **${graphContext.successorWindow.length}**`);
|
|
900
1033
|
}
|
|
901
1034
|
return lines.join('\n');
|
|
902
1035
|
}
|
|
903
1036
|
function buildScopedConversationExplanationMarkdown(params, graphContext) {
|
|
1037
|
+
const useChinese = useChineseAnswerLanguage(params);
|
|
904
1038
|
if (params.knowledgePoints.length <= 0) {
|
|
905
|
-
return
|
|
1039
|
+
return useChinese
|
|
1040
|
+
? '## 说明\n\n当前范围没有返回足够强的知识点来直接解释该请求。'
|
|
1041
|
+
: '## Explanation\n\nThe current scope did not return a strong enough knowledge point to explain the request directly.';
|
|
906
1042
|
}
|
|
907
1043
|
const intent = classifyScopedConversationIntent(params.message);
|
|
908
1044
|
const strongestPoint = params.knowledgePoints[0];
|
|
909
1045
|
const explanationLines = [
|
|
910
|
-
'## Explanation',
|
|
1046
|
+
useChinese ? '## 说明' : '## Explanation',
|
|
911
1047
|
'',
|
|
912
1048
|
];
|
|
913
1049
|
if (intent === 'compare') {
|
|
914
|
-
explanationLines.push(
|
|
1050
|
+
explanationLines.push(useChinese
|
|
1051
|
+
? `将 **${strongestPoint.title}** 作为当前范围内的比较基准。`
|
|
1052
|
+
: `Use **${strongestPoint.title}** as the comparison baseline inside the current scope.`);
|
|
915
1053
|
}
|
|
916
1054
|
else if (intent === 'how_to') {
|
|
917
|
-
explanationLines.push(
|
|
1055
|
+
explanationLines.push(useChinese
|
|
1056
|
+
? `将 **${strongestPoint.title}** 作为后续具体步骤的起始锚点。`
|
|
1057
|
+
: `Use **${strongestPoint.title}** as the starting anchor for the next concrete steps.`);
|
|
918
1058
|
}
|
|
919
1059
|
else if (intent === 'explain') {
|
|
920
|
-
explanationLines.push(
|
|
1060
|
+
explanationLines.push(useChinese
|
|
1061
|
+
? `**${strongestPoint.title}** 是当前用于说明的最佳范围锚点。`
|
|
1062
|
+
: `**${strongestPoint.title}** is the current best scoped anchor for the explanation.`);
|
|
921
1063
|
}
|
|
922
1064
|
else {
|
|
923
|
-
explanationLines.push(
|
|
1065
|
+
explanationLines.push(useChinese
|
|
1066
|
+
? `**${strongestPoint.title}** 是当前最佳范围锚点。`
|
|
1067
|
+
: `**${strongestPoint.title}** is the current best scoped anchor.`);
|
|
924
1068
|
}
|
|
925
1069
|
const summary = normalizeWhitespace(String(strongestPoint.summary || strongestPoint.evidenceSnippet || '').trim());
|
|
926
1070
|
if (summary) {
|
|
927
1071
|
explanationLines.push('', summary);
|
|
928
1072
|
}
|
|
929
1073
|
if (graphContext && graphContext.relationKinds.length > 0) {
|
|
930
|
-
explanationLines.push('',
|
|
1074
|
+
explanationLines.push('', useChinese
|
|
1075
|
+
? `**${graphContext.anchorTitle}** 周边的图谱支持关系包括:${graphContext.relationKinds.join(', ')}。`
|
|
1076
|
+
: `Graph support around **${graphContext.anchorTitle}** includes: ${graphContext.relationKinds.join(', ')}.`);
|
|
931
1077
|
}
|
|
932
1078
|
if (graphContext && Array.isArray(graphContext.knowledgePointRelations) && graphContext.knowledgePointRelations.length > 0) {
|
|
933
1079
|
const relationPreview = graphContext.knowledgePointRelations
|
|
934
1080
|
.slice(0, 2)
|
|
935
1081
|
.map((relation) => `${relation.sourceTitle} -> ${relation.relationKind} -> ${relation.targetTitle}`)
|
|
936
1082
|
.join('; ');
|
|
937
|
-
explanationLines.push('',
|
|
1083
|
+
explanationLines.push('', useChinese
|
|
1084
|
+
? `当前结果集内的直接图链接:${relationPreview}。`
|
|
1085
|
+
: `Direct graph links inside the current result set: ${relationPreview}.`);
|
|
938
1086
|
}
|
|
939
1087
|
if (graphContext && Array.isArray(graphContext.connectionPaths) && graphContext.connectionPaths.length > 0) {
|
|
940
|
-
explanationLines.push('',
|
|
1088
|
+
explanationLines.push('', useChinese
|
|
1089
|
+
? `显式图路径:${formatGraphConnectionPath(graphContext.connectionPaths[0])}。`
|
|
1090
|
+
: `Explicit graph path: ${formatGraphConnectionPath(graphContext.connectionPaths[0])}.`);
|
|
941
1091
|
}
|
|
942
1092
|
if (graphContext) {
|
|
943
|
-
const predecessorTitles =
|
|
1093
|
+
const predecessorTitles = (0, graphAnswerFacts_1.collectGraphAnswerWindowTitles)(graphContext, 'predecessorWindow', {
|
|
1094
|
+
anchorAtomId: graphContext.anchorAtomId,
|
|
1095
|
+
anchorTitle: graphContext.anchorTitle,
|
|
1096
|
+
normalizeTitle: (value) => normalizeGraphAnswerDisplayTitle(String(value || '')),
|
|
1097
|
+
}, 3);
|
|
944
1098
|
if (predecessorTitles.length > 0) {
|
|
945
|
-
explanationLines.push('',
|
|
1099
|
+
explanationLines.push('', useChinese
|
|
1100
|
+
? '直接前置窗口:' + predecessorTitles.join('、') + '。'
|
|
1101
|
+
: 'Immediate predecessor window: ' + predecessorTitles.join(', ') + '.');
|
|
946
1102
|
}
|
|
947
1103
|
}
|
|
948
1104
|
if (graphContext) {
|
|
949
|
-
const successorTitles =
|
|
1105
|
+
const successorTitles = (0, graphAnswerFacts_1.collectGraphAnswerWindowTitles)(graphContext, 'successorWindow', {
|
|
1106
|
+
anchorAtomId: graphContext.anchorAtomId,
|
|
1107
|
+
anchorTitle: graphContext.anchorTitle,
|
|
1108
|
+
normalizeTitle: (value) => normalizeGraphAnswerDisplayTitle(String(value || '')),
|
|
1109
|
+
}, 3);
|
|
950
1110
|
if (successorTitles.length > 0) {
|
|
951
|
-
explanationLines.push('',
|
|
1111
|
+
explanationLines.push('', useChinese
|
|
1112
|
+
? '直接后继窗口:' + successorTitles.join('、') + '。'
|
|
1113
|
+
: 'Immediate successor window: ' + successorTitles.join(', ') + '.');
|
|
952
1114
|
}
|
|
953
1115
|
}
|
|
954
1116
|
if (graphContext && graphContext.temporalValidity.allPointsValid === false) {
|
|
955
1117
|
const reasonSummary = graphContext.temporalValidity.warningReasons.length > 0
|
|
956
1118
|
? graphContext.temporalValidity.warningReasons.join(', ')
|
|
957
1119
|
: 'temporal validity checks reported a warning';
|
|
958
|
-
explanationLines.push('',
|
|
1120
|
+
explanationLines.push('', useChinese
|
|
1121
|
+
? `时序有效性警告:${reasonSummary}。`
|
|
1122
|
+
: `Temporal validity warning: ${reasonSummary}.`);
|
|
959
1123
|
}
|
|
960
1124
|
const supersedesCount = graphContext
|
|
961
1125
|
? (Array.isArray(graphContext.temporalValidity.details)
|
|
@@ -963,48 +1127,70 @@ function buildScopedConversationExplanationMarkdown(params, graphContext) {
|
|
|
963
1127
|
: 0)
|
|
964
1128
|
: 0;
|
|
965
1129
|
if (supersedesCount > 0) {
|
|
966
|
-
explanationLines.push('',
|
|
1130
|
+
explanationLines.push('', useChinese
|
|
1131
|
+
? `时序谱系表明该锚点替代了 ${supersedesCount} 个更早版本。`
|
|
1132
|
+
: `Temporal lineage indicates this anchor supersedes ${supersedesCount} earlier revision${supersedesCount === 1 ? '' : 's'}.`);
|
|
967
1133
|
}
|
|
968
1134
|
const supportingTitles = params.knowledgePoints
|
|
969
1135
|
.slice(1, 3)
|
|
970
1136
|
.map((point) => normalizeWhitespace(String(point.title || '').trim()))
|
|
971
1137
|
.filter(Boolean);
|
|
972
1138
|
if (supportingTitles.length > 0) {
|
|
973
|
-
explanationLines.push('',
|
|
974
|
-
?
|
|
975
|
-
|
|
1139
|
+
explanationLines.push('', useChinese
|
|
1140
|
+
? (intent === 'compare'
|
|
1141
|
+
? `支持比较节点:${supportingTitles.join('、')}。`
|
|
1142
|
+
: `支持范围节点:${supportingTitles.join('、')}。`)
|
|
1143
|
+
: (intent === 'compare'
|
|
1144
|
+
? `Supporting comparison nodes: ${supportingTitles.join(', ')}.`
|
|
1145
|
+
: `Supporting scoped nodes: ${supportingTitles.join(', ')}.`));
|
|
976
1146
|
}
|
|
977
1147
|
if (params.recalledMemories.length > 0) {
|
|
978
|
-
explanationLines.push('',
|
|
1148
|
+
explanationLines.push('', useChinese
|
|
1149
|
+
? `范围内记忆召回为该说明提供了 ${params.recalledMemories.length} 条先前笔记。`
|
|
1150
|
+
: `Scoped memory recall contributed ${params.recalledMemories.length} prior note(s) to this explanation.`);
|
|
979
1151
|
}
|
|
980
1152
|
if (params.citations.length > 0) {
|
|
981
|
-
explanationLines.push('',
|
|
1153
|
+
explanationLines.push('', useChinese
|
|
1154
|
+
? `该说明由当前范围内的 ${params.citations.length} 条引用支撑。`
|
|
1155
|
+
: `The explanation is grounded by ${params.citations.length} citation(s) from the current scope.`);
|
|
982
1156
|
}
|
|
983
1157
|
return explanationLines.join('\n');
|
|
984
1158
|
}
|
|
985
1159
|
function buildScopedConversationEvidenceMarkdown(params) {
|
|
986
1160
|
const evidenceLines = params.citations.slice(0, 3).map((citation, index) => (`${index + 1}. **${citation.title}** (${citation.sourcePath}${citation.startLine ? `:${citation.startLine}` : ''})\n - ${citation.snippet}`));
|
|
987
1161
|
if (evidenceLines.length <= 0) {
|
|
988
|
-
return
|
|
1162
|
+
return useChineseAnswerLanguage(params)
|
|
1163
|
+
? '## 证据摘要\n\n当前范围没有返回引用。'
|
|
1164
|
+
: '## Evidence Summary\n\nNo scoped citations were returned.';
|
|
989
1165
|
}
|
|
990
1166
|
return [
|
|
991
|
-
'## Evidence Summary',
|
|
1167
|
+
useChineseAnswerLanguage(params) ? '## 证据摘要' : '## Evidence Summary',
|
|
992
1168
|
'',
|
|
993
1169
|
...evidenceLines,
|
|
994
1170
|
].join('\n');
|
|
995
1171
|
}
|
|
996
1172
|
function buildScopedConversationMemoryNotice(params) {
|
|
1173
|
+
const useChinese = useChineseAnswerLanguage(params);
|
|
997
1174
|
if (params.recalledMemories.length <= 0) {
|
|
998
|
-
return
|
|
1175
|
+
return useChinese
|
|
1176
|
+
? '本回合未召回范围内记忆。'
|
|
1177
|
+
: 'No scoped memory note was recalled for this turn.';
|
|
999
1178
|
}
|
|
1000
1179
|
if (params.recalledMemories.length === 1) {
|
|
1001
|
-
return
|
|
1180
|
+
return useChinese
|
|
1181
|
+
? '已召回 1 条范围内记忆并合并到回答上下文。'
|
|
1182
|
+
: '1 scoped memory note was recalled and merged into the answer context.';
|
|
1002
1183
|
}
|
|
1003
|
-
return
|
|
1184
|
+
return useChinese
|
|
1185
|
+
? `已召回 ${params.recalledMemories.length} 条范围内记忆并合并到回答上下文。`
|
|
1186
|
+
: `${params.recalledMemories.length} scoped memory notes were recalled and merged into the answer context.`;
|
|
1004
1187
|
}
|
|
1005
|
-
function buildScopedConversationActionGuideMarkdown(params, graphContext) {
|
|
1188
|
+
function buildScopedConversationActionGuideMarkdown(params, graphContext, answerTaskPlan) {
|
|
1189
|
+
const useChinese = useChineseAnswerLanguage(params);
|
|
1006
1190
|
if (params.knowledgePoints.length <= 0) {
|
|
1007
|
-
return
|
|
1191
|
+
return useChinese
|
|
1192
|
+
? '## 下一步行动\n\n当前回合没有可执行的限定知识卡片。'
|
|
1193
|
+
: '## Next Actions\n\nNo actionable scoped knowledge card is available for this turn.';
|
|
1008
1194
|
}
|
|
1009
1195
|
const intent = classifyScopedConversationIntent(params.message);
|
|
1010
1196
|
const topTitles = params.knowledgePoints
|
|
@@ -1012,15 +1198,23 @@ function buildScopedConversationActionGuideMarkdown(params, graphContext) {
|
|
|
1012
1198
|
.map((point) => `- ${point.title}`);
|
|
1013
1199
|
const actionHints = params.memoryActions
|
|
1014
1200
|
.slice(0, 2)
|
|
1015
|
-
.map((action) =>
|
|
1201
|
+
.map((action) => useChinese
|
|
1202
|
+
? (action.kind === 'persist_session_memory' ? '- 记录本回合的用户关注点。' : '- 根据当前证据评估是否需要保存学习记忆。')
|
|
1203
|
+
: normalizeWhitespace(String(action.reason || '').trim()))
|
|
1016
1204
|
.filter(Boolean)
|
|
1017
1205
|
.map((reason) => `- ${reason}`);
|
|
1018
1206
|
const graphActionHints = [];
|
|
1207
|
+
const learningRoute = answerTaskPlan?.learningRoute || [];
|
|
1208
|
+
if (answerTaskPlan?.subtasks.some((subtask) => subtask.kind === 'learning_route') && learningRoute.length > 0) {
|
|
1209
|
+
graphActionHints.push(useChinese
|
|
1210
|
+
? `- 建议按以下顺序学习:${learningRoute.map((node) => `${node.order}. ${node.title}`).join(' -> ')}。`
|
|
1211
|
+
: `- Follow the evidence-backed learning order: ${learningRoute.map((node) => `${node.order}. ${node.title}`).join(' -> ')}.`);
|
|
1212
|
+
}
|
|
1019
1213
|
if (graphContext && graphContext.relationKinds.includes('prerequisite')) {
|
|
1020
|
-
graphActionHints.push('- Inspect prerequisite-linked concepts in focus mode before guided learning.');
|
|
1214
|
+
graphActionHints.push(useChinese ? '- 在进入引导学习前,先在聚焦模式查看前置概念。' : '- Inspect prerequisite-linked concepts in focus mode before guided learning.');
|
|
1021
1215
|
}
|
|
1022
1216
|
if (graphContext && graphContext.temporalValidity.allPointsValid === false) {
|
|
1023
|
-
graphActionHints.push('- Validate whether a fresher or superseding note should replace this anchor before promotion.');
|
|
1217
|
+
graphActionHints.push(useChinese ? '- 提升答案前,确认是否存在更新或替代当前锚点的笔记。' : '- Validate whether a fresher or superseding note should replace this anchor before promotion.');
|
|
1024
1218
|
}
|
|
1025
1219
|
const supersedesCount = graphContext
|
|
1026
1220
|
? (Array.isArray(graphContext.temporalValidity.details)
|
|
@@ -1028,11 +1222,13 @@ function buildScopedConversationActionGuideMarkdown(params, graphContext) {
|
|
|
1028
1222
|
: 0)
|
|
1029
1223
|
: 0;
|
|
1030
1224
|
if (supersedesCount > 0) {
|
|
1031
|
-
graphActionHints.push('- Trace the superseded lineage before promoting this answer.');
|
|
1225
|
+
graphActionHints.push(useChinese ? '- 提升答案前,追踪已被替代的知识谱系。' : '- Trace the superseded lineage before promoting this answer.');
|
|
1032
1226
|
}
|
|
1033
1227
|
if (graphContext && Array.isArray(graphContext.knowledgePointRelations) && graphContext.knowledgePointRelations.length > 0) {
|
|
1034
1228
|
const firstRelation = graphContext.knowledgePointRelations[0];
|
|
1035
|
-
graphActionHints.push(
|
|
1229
|
+
graphActionHints.push(useChinese
|
|
1230
|
+
? `- 在扩展到外部支持节点前,沿 ${firstRelation.sourceTitle} 与 ${firstRelation.targetTitle} 之间的直接图路径查看。`
|
|
1231
|
+
: `- Follow the direct graph path between ${firstRelation.sourceTitle} and ${firstRelation.targetTitle} before branching to external support nodes.`);
|
|
1036
1232
|
}
|
|
1037
1233
|
if (graphContext && Array.isArray(graphContext.connectionPaths) && graphContext.connectionPaths.length > 0) {
|
|
1038
1234
|
const firstConnectionPath = graphContext.connectionPaths[0];
|
|
@@ -1040,33 +1236,45 @@ function buildScopedConversationActionGuideMarkdown(params, graphContext) {
|
|
|
1040
1236
|
? firstConnectionPath.pathTitles.map((title) => normalizeWhitespace(String(title || '').trim())).filter(Boolean)
|
|
1041
1237
|
: [];
|
|
1042
1238
|
if (titles.length > 1) {
|
|
1043
|
-
graphActionHints.push(`- Review the path order: ${titles.join(' -> ')}.`);
|
|
1239
|
+
graphActionHints.push(useChinese ? `- 检查路径顺序:${titles.join(' -> ')}。` : `- Review the path order: ${titles.join(' -> ')}.`);
|
|
1044
1240
|
}
|
|
1045
1241
|
}
|
|
1046
1242
|
if (graphContext) {
|
|
1047
|
-
const predecessorTitles =
|
|
1243
|
+
const predecessorTitles = (0, graphAnswerFacts_1.collectGraphAnswerWindowTitles)(graphContext, 'predecessorWindow', {
|
|
1244
|
+
anchorAtomId: graphContext.anchorAtomId,
|
|
1245
|
+
anchorTitle: graphContext.anchorTitle,
|
|
1246
|
+
normalizeTitle: (value) => normalizeGraphAnswerDisplayTitle(String(value || '')),
|
|
1247
|
+
}, 2);
|
|
1048
1248
|
if (predecessorTitles.length > 0) {
|
|
1049
|
-
graphActionHints.push(
|
|
1249
|
+
graphActionHints.push(useChinese
|
|
1250
|
+
? '- 扩展答案前,先查看前置上下文:' + predecessorTitles.join('、') + '。'
|
|
1251
|
+
: '- Inspect prerequisite context from ' + predecessorTitles.join(', ') + ' before expanding the answer.');
|
|
1050
1252
|
}
|
|
1051
1253
|
}
|
|
1052
1254
|
if (graphContext) {
|
|
1053
|
-
const successorTitles =
|
|
1255
|
+
const successorTitles = (0, graphAnswerFacts_1.collectGraphAnswerWindowTitles)(graphContext, 'successorWindow', {
|
|
1256
|
+
anchorAtomId: graphContext.anchorAtomId,
|
|
1257
|
+
anchorTitle: graphContext.anchorTitle,
|
|
1258
|
+
normalizeTitle: (value) => normalizeGraphAnswerDisplayTitle(String(value || '')),
|
|
1259
|
+
}, 2);
|
|
1054
1260
|
if (successorTitles.length > 0) {
|
|
1055
|
-
graphActionHints.push(
|
|
1261
|
+
graphActionHints.push(useChinese
|
|
1262
|
+
? '- 可沿后续节点继续:' + successorTitles.join('、') + '。'
|
|
1263
|
+
: '- Use likely next-step nodes such as ' + successorTitles.join(', ') + ' to continue follow-through after this answer.');
|
|
1056
1264
|
}
|
|
1057
1265
|
}
|
|
1058
1266
|
return [
|
|
1059
|
-
'## Next Actions',
|
|
1267
|
+
useChinese ? '## 下一步行动' : '## Next Actions',
|
|
1060
1268
|
'',
|
|
1061
1269
|
intent === 'compare'
|
|
1062
|
-
? 'Use the scoped knowledge cards below to inspect the strongest nodes side by side before deciding which distinctions matter most:'
|
|
1270
|
+
? (useChinese ? '先查看下方限定知识卡片中的高相关节点,再判断关键差异:' : 'Use the scoped knowledge cards below to inspect the strongest nodes side by side before deciding which distinctions matter most:')
|
|
1063
1271
|
: intent === 'how_to'
|
|
1064
|
-
? 'Use the scoped knowledge cards below to move from explanation into concrete guided-learning or focus-mode steps:'
|
|
1065
|
-
: 'Use the scoped knowledge cards below to continue with focus mode or guided learning for the highest-signal nodes:',
|
|
1272
|
+
? (useChinese ? '使用下方限定知识卡片,将解释推进为具体的引导学习或聚焦步骤:' : 'Use the scoped knowledge cards below to move from explanation into concrete guided-learning or focus-mode steps:')
|
|
1273
|
+
: (useChinese ? '使用下方限定知识卡片,继续聚焦或引导学习高相关节点:' : 'Use the scoped knowledge cards below to continue with focus mode or guided learning for the highest-signal nodes:'),
|
|
1066
1274
|
...topTitles,
|
|
1067
|
-
...(graphActionHints.length > 0 ? ['', 'Graph-aware follow-through:', ...graphActionHints] : []),
|
|
1275
|
+
...(graphActionHints.length > 0 ? ['', useChinese ? '图谱辅助行动:' : 'Graph-aware follow-through:', ...graphActionHints] : []),
|
|
1068
1276
|
...(actionHints.length > 0
|
|
1069
|
-
? ['', 'Suggested follow-through from the current turn:', ...actionHints]
|
|
1277
|
+
? ['', useChinese ? '本回合建议行动:' : 'Suggested follow-through from the current turn:', ...actionHints]
|
|
1070
1278
|
: []),
|
|
1071
1279
|
].join('\n');
|
|
1072
1280
|
}
|
|
@@ -1408,10 +1616,22 @@ function buildKnowledgeRun(params, graphContext) {
|
|
|
1408
1616
|
function buildScopedConversationReply(params) {
|
|
1409
1617
|
const blocks = [];
|
|
1410
1618
|
const graphContext = params.graphContext || (0, graphContextAssembler_1.buildAgentConversationGraphContextFromKnowledgePoints)(params.knowledgePoints);
|
|
1411
|
-
const
|
|
1619
|
+
const auditGraphAnswerPlan = (0, graphAnswerPlan_1.buildGraphAnswerPlan)({
|
|
1620
|
+
message: params.message,
|
|
1621
|
+
knowledgePoints: params.knowledgePoints,
|
|
1622
|
+
graphContext,
|
|
1623
|
+
ragContextPack: params.ragContextPack,
|
|
1624
|
+
});
|
|
1625
|
+
const fullReportAssembly = params.responseMode === 'full'
|
|
1626
|
+
? buildFullTechnicalReportResult(params, graphContext, auditGraphAnswerPlan)
|
|
1627
|
+
: undefined;
|
|
1628
|
+
const draftAnswer = fullReportAssembly?.answer
|
|
1629
|
+
|| buildScopedConversationAnswer(params, graphContext, auditGraphAnswerPlan);
|
|
1412
1630
|
const knowledgeRun = buildKnowledgeRun(params, graphContext);
|
|
1413
1631
|
const answerReleaseReview = (0, answerReleaseReview_1.reviewAnswerRelease)({
|
|
1414
1632
|
message: params.message,
|
|
1633
|
+
answerLanguage: params.answerLanguage,
|
|
1634
|
+
responseMode: params.responseMode === 'full' ? 'full' : 'slim',
|
|
1415
1635
|
draftAnswer,
|
|
1416
1636
|
knowledgePoints: params.knowledgePoints,
|
|
1417
1637
|
citations: params.citations,
|
|
@@ -1419,20 +1639,38 @@ function buildScopedConversationReply(params) {
|
|
|
1419
1639
|
graphContext,
|
|
1420
1640
|
ragContextPack: params.ragContextPack,
|
|
1421
1641
|
ragSufficiencyReview: params.ragSufficiencyReview,
|
|
1642
|
+
graphAnswerPlan: auditGraphAnswerPlan,
|
|
1422
1643
|
reviewedAt: params.generatedAt,
|
|
1423
1644
|
});
|
|
1424
1645
|
knowledgeRun.answerReleaseReview = answerReleaseReview;
|
|
1425
1646
|
const answer = answerReleaseReview.publicAnswer;
|
|
1647
|
+
const publicGraphAnswerPlan = answerReleaseReview.publicGraphAnswerPlan;
|
|
1648
|
+
const releasedGraphAnswerPlan = publicGraphAnswerPlan || {
|
|
1649
|
+
...auditGraphAnswerPlan,
|
|
1650
|
+
leadClaimId: '',
|
|
1651
|
+
claims: [],
|
|
1652
|
+
requiredRoles: [],
|
|
1653
|
+
depth: 'compact',
|
|
1654
|
+
};
|
|
1655
|
+
const graphAnswerCoverage = answerReleaseReview.graphAnswerCoverage
|
|
1656
|
+
|| (0, graphAnswerCoverage_1.reviewGraphAnswerCoverage)(answer, publicGraphAnswerPlan || null);
|
|
1657
|
+
knowledgeRun.graphAnswerPlan = releasedGraphAnswerPlan;
|
|
1658
|
+
knowledgeRun.graphAnswerCoverage = graphAnswerCoverage;
|
|
1659
|
+
knowledgeRun.answerTaskPlan = releasedGraphAnswerPlan.answerTaskPlan;
|
|
1660
|
+
knowledgeRun.answerTaskCoverage = answerReleaseReview.answerTaskCoverage;
|
|
1661
|
+
const useChinese = useChineseAnswerLanguage(params);
|
|
1426
1662
|
const overviewMarkdown = buildScopedConversationOverviewMarkdown(params, graphContext);
|
|
1427
1663
|
const explanationMarkdown = buildScopedConversationExplanationMarkdown(params, graphContext);
|
|
1428
1664
|
const evidenceMarkdown = buildScopedConversationEvidenceMarkdown(params);
|
|
1429
1665
|
const memoryNotice = buildScopedConversationMemoryNotice(params);
|
|
1430
|
-
const actionGuideMarkdown = buildScopedConversationActionGuideMarkdown(params, graphContext);
|
|
1666
|
+
const actionGuideMarkdown = buildScopedConversationActionGuideMarkdown(params, graphContext, releasedGraphAnswerPlan.answerTaskPlan);
|
|
1431
1667
|
blocks.push({
|
|
1432
1668
|
blockId: params.nextBlockId(),
|
|
1433
1669
|
type: 'structured_answer',
|
|
1434
|
-
title: 'Grounded Answer',
|
|
1670
|
+
title: useChinese ? '可信回答' : 'Grounded Answer',
|
|
1435
1671
|
directAnswer: answer,
|
|
1672
|
+
answerTaskPlan: releasedGraphAnswerPlan.answerTaskPlan,
|
|
1673
|
+
answerTaskCoverage: answerReleaseReview.answerTaskCoverage,
|
|
1436
1674
|
overviewMarkdown,
|
|
1437
1675
|
explanationMarkdown,
|
|
1438
1676
|
evidenceMarkdown,
|
|
@@ -1444,7 +1682,7 @@ function buildScopedConversationReply(params) {
|
|
|
1444
1682
|
blocks.push({
|
|
1445
1683
|
blockId: params.nextBlockId(),
|
|
1446
1684
|
type: 'knowledge_run_summary',
|
|
1447
|
-
title: 'Knowledge Run',
|
|
1685
|
+
title: useChinese ? '知识运行' : 'Knowledge Run',
|
|
1448
1686
|
knowledgeRun,
|
|
1449
1687
|
});
|
|
1450
1688
|
if (memoryNotice) {
|
|
@@ -1458,7 +1696,7 @@ function buildScopedConversationReply(params) {
|
|
|
1458
1696
|
blocks.push({
|
|
1459
1697
|
blockId: params.nextBlockId(),
|
|
1460
1698
|
type: 'citations',
|
|
1461
|
-
title: 'Citations',
|
|
1699
|
+
title: useChinese ? '引用' : 'Citations',
|
|
1462
1700
|
citations: params.citations.map((citation) => ({ ...citation })),
|
|
1463
1701
|
});
|
|
1464
1702
|
}
|
|
@@ -1466,7 +1704,7 @@ function buildScopedConversationReply(params) {
|
|
|
1466
1704
|
blocks.push({
|
|
1467
1705
|
blockId: params.nextBlockId(),
|
|
1468
1706
|
type: 'knowledge_actions',
|
|
1469
|
-
title: 'Knowledge Actions',
|
|
1707
|
+
title: useChinese ? '知识操作' : 'Knowledge Actions',
|
|
1470
1708
|
atomIds: collectAgentConversationAtomIds(params.knowledgePoints),
|
|
1471
1709
|
});
|
|
1472
1710
|
}
|
|
@@ -1476,5 +1714,8 @@ function buildScopedConversationReply(params) {
|
|
|
1476
1714
|
knowledgeRun,
|
|
1477
1715
|
graphContext,
|
|
1478
1716
|
answerReleaseReview,
|
|
1717
|
+
graphAnswerPlan: releasedGraphAnswerPlan,
|
|
1718
|
+
graphAnswerCoverage,
|
|
1719
|
+
...(fullReportAssembly ? { fullReportAssembly: fullReportAssembly.state } : {}),
|
|
1479
1720
|
};
|
|
1480
1721
|
}
|