noteconnection 1.7.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/LICENSE +674 -21
- package/README.md +260 -1626
- package/dist/src/agent_workspace.contract.parity.test.js +159 -0
- package/dist/src/agent_workspace.frontend.test.js +10388 -0
- package/dist/src/agent_workspace.locale.contract.test.js +95 -0
- package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
- 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/copy.assets.contract.test.js +130 -0
- 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 +293 -5
- 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 +1174 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +1541 -0
- package/dist/src/export/index.js +18 -0
- package/dist/src/export/types.js +2 -0
- package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
- package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
- package/dist/src/foundation.release.evidence.contract.test.js +524 -0
- package/dist/src/foundation.sqlite.runtime.contract.test.js +88 -0
- package/dist/src/frontend/README.md +260 -1626
- package/dist/src/frontend/agent_workspace.js +6011 -0
- package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
- package/dist/src/frontend/analysis.js +31 -4
- package/dist/src/frontend/app.js +2178 -62
- package/dist/src/frontend/focus_mode_interactions.js +33 -0
- package/dist/src/frontend/godot_future_path_renderer.js +540 -0
- package/dist/src/frontend/godot_tree_interactions.js +178 -0
- package/dist/src/frontend/graph_state.mjs +105 -0
- package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
- package/dist/src/frontend/i18n.mjs +186 -0
- package/dist/src/frontend/index.html +672 -268
- package/dist/src/frontend/knowledge_projection_contract.js +230 -0
- package/dist/src/frontend/knowledge_projection_store.js +214 -0
- package/dist/src/frontend/layout_gpu.js +12 -4
- package/dist/src/frontend/libs/path_core.js +158 -42
- package/dist/src/frontend/locales/en.json +753 -5
- package/dist/src/frontend/locales/zh.json +753 -5
- package/dist/src/frontend/main.mjs +60 -0
- package/dist/src/frontend/markdown_runtime.js +827 -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/notemd.css +49 -0
- package/dist/src/frontend/notemd.html +7 -1
- package/dist/src/frontend/notemd.js +64 -0
- package/dist/src/frontend/path.html +113 -2
- package/dist/src/frontend/path_app.js +2108 -130
- package/dist/src/frontend/path_layout.mjs +143 -0
- package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
- package/dist/src/frontend/path_modules_bridge.js +486 -0
- package/dist/src/frontend/path_state.mjs +118 -0
- package/dist/src/frontend/path_styles.css +146 -0
- package/dist/src/frontend/path_worker_bridge.mjs +85 -0
- package/dist/src/frontend/reader.js +393 -33
- package/dist/src/frontend/runtime_bridge.js +67 -54
- package/dist/src/frontend/runtime_bridge.mjs +279 -0
- package/dist/src/frontend/settings.js +130 -12
- package/dist/src/frontend/simulationWorker.js +1 -1
- package/dist/src/frontend/source_manager.js +297 -22
- package/dist/src/frontend/storage_provider.js +661 -71
- package/dist/src/frontend/styles.css +2814 -72
- package/dist/src/frontend/workbench_state.mjs +101 -0
- package/dist/src/frontend/workspace_panes.js +10272 -0
- package/dist/src/frontend.locale.contract.test.js +62 -0
- package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
- package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -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 +217 -0
- package/dist/src/indexing/IndexLifecycle.test.js +73 -0
- package/dist/src/indexing/SegmentBuilder.js +64 -0
- package/dist/src/indexing/UnitBuilder.js +48 -0
- package/dist/src/indexing/types.js +2 -0
- package/dist/src/knowledge.api.contract.test.js +172 -0
- 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 +11181 -0
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +745 -0
- package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +3208 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2998 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3936 -0
- 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 +5260 -0
- package/dist/src/learning/answerReleaseReview.test.js +4174 -0
- package/dist/src/learning/answerTaskPlan.js +473 -0
- package/dist/src/learning/api.js +2 -0
- package/dist/src/learning/conversationComposer.js +1721 -0
- package/dist/src/learning/conversationComposer.test.js +3220 -0
- package/dist/src/learning/domains/ConversationManager.js +53 -0
- package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
- package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
- package/dist/src/learning/domains/MasteryEngine.js +387 -0
- package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
- package/dist/src/learning/domains/QualityEvaluator.js +307 -0
- package/dist/src/learning/domains/TutorRouter.js +313 -0
- package/dist/src/learning/domains/index.js +33 -0
- package/dist/src/learning/domains/types.js +7 -0
- package/dist/src/learning/errors.js +29 -0
- package/dist/src/learning/evidenceContextAssembler.js +1368 -0
- package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
- 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 +860 -0
- package/dist/src/learning/graphContextAssembler.test.js +1033 -0
- 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 +29 -0
- package/dist/src/learning/mobileAnswerProjection.js +104 -0
- package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
- package/dist/src/learning/queryBackend.js +1922 -0
- package/dist/src/learning/queryBackend.test.js +976 -0
- package/dist/src/learning/ragContextPack.js +356 -0
- package/dist/src/learning/ragContextPack.test.js +311 -0
- package/dist/src/learning/ragEvidenceQuality.js +96 -0
- package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
- package/dist/src/learning/ragPublicText.js +101 -0
- package/dist/src/learning/ragPublicText.test.js +57 -0
- package/dist/src/learning/ragSufficiencyJudge.js +171 -0
- package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.js +217 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +207 -0
- package/dist/src/learning/requestNormalization.js +304 -0
- package/dist/src/learning/requestNormalization.test.js +101 -0
- package/dist/src/learning/runtimeCapability.js +4677 -0
- package/dist/src/learning/runtimeCapability.test.js +3635 -0
- package/dist/src/learning/store.js +1344 -0
- package/dist/src/learning/store.test.js +1425 -0
- package/dist/src/learning/tutorAdapter.js +2 -0
- package/dist/src/learning/types.js +2 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +958 -0
- package/dist/src/learning/vectorAccelerationAdapter.test.js +412 -0
- package/dist/src/learning/workspaceHydration.js +168 -0
- package/dist/src/learning/workspaceHydration.test.js +30 -0
- package/dist/src/lfs.asset.policy.contract.test.js +153 -0
- package/dist/src/license.policy.contract.test.js +71 -0
- package/dist/src/markdown/MarkdownGateway.js +4 -0
- package/dist/src/markdown/MarkdownGateway.test.js +59 -0
- package/dist/src/memory/MemoryGovernance.js +74 -0
- package/dist/src/memory/MemoryGovernance.test.js +46 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
- package/dist/src/middleware/SseResponseWriter.js +122 -0
- package/dist/src/middleware/SseResponseWriter.test.js +54 -0
- package/dist/src/middleware/auth.js +38 -0
- package/dist/src/middleware/auth.test.js +33 -0
- package/dist/src/middleware/body-parser.js +45 -0
- package/dist/src/middleware/cors.js +44 -0
- package/dist/src/middleware/index.js +22 -0
- package/dist/src/middleware/request-trace.js +96 -0
- 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/AppConfigToml.js +6 -4
- package/dist/src/notemd/ContentGenerator.js +4 -9
- package/dist/src/notemd/FileProcessor.js +4 -9
- package/dist/src/notemd/MermaidProcessor.js +400 -50
- package/dist/src/notemd/NotemdService.js +506 -26
- package/dist/src/notemd/PromptManager.js +15 -0
- package/dist/src/notemd/Translator.js +4 -9
- package/dist/src/notemd/cli/commands.js +357 -0
- package/dist/src/notemd/cli/dispatcher.js +225 -0
- package/dist/src/notemd/cli/index.js +169 -0
- package/dist/src/notemd/cli/parser.js +68 -0
- package/dist/src/notemd/cli/types.js +2 -0
- package/dist/src/notemd/constants.js +43 -0
- package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
- package/dist/src/notemd/diagram/diagramSpec.js +79 -0
- package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
- package/dist/src/notemd/diagram/intent.js +95 -0
- package/dist/src/notemd/diagram/planner.js +71 -0
- package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
- package/dist/src/notemd/diagram/types.js +18 -0
- package/dist/src/notemd/index.js +26 -0
- package/dist/src/notemd/operations/capabilityManifest.js +23 -0
- package/dist/src/notemd/operations/cliContracts.js +17 -0
- package/dist/src/notemd/operations/configProfileCommands.js +85 -0
- package/dist/src/notemd/operations/registry.contract.test.js +95 -0
- package/dist/src/notemd/operations/registry.js +991 -0
- package/dist/src/notemd/operations/types.js +2 -0
- package/dist/src/notemd/progressReporter.js +9 -0
- package/dist/src/notemd/providerDiagnostics.js +220 -0
- package/dist/src/notemd/providerProfiles.js +42 -0
- package/dist/src/notemd/providerTemplates.js +231 -0
- package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
- package/dist/src/notemd/search/SearchManager.js +13 -0
- package/dist/src/notemd/search/SearchProvider.js +2 -0
- package/dist/src/notemd/search/TavilyProvider.js +44 -0
- package/dist/src/notemd.agent.manifest.test.js +85 -0
- package/dist/src/notemd.api.contract.test.js +14 -1
- package/dist/src/notemd.app_config_toml.test.js +2 -1
- package/dist/src/notemd.batch.workflow.test.js +117 -0
- package/dist/src/notemd.cli.e2e.test.js +136 -0
- package/dist/src/notemd.core.test.js +51 -0
- package/dist/src/notemd.diagram.pipeline.test.js +233 -0
- package/dist/src/notemd.providerTemplates.test.js +34 -0
- package/dist/src/notemd.server.integration.test.js +262 -39
- package/dist/src/notemd.workflow.pipeline.test.js +162 -0
- package/dist/src/pathbridge.handshake.contract.test.js +45 -2
- package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
- package/dist/src/pathcore.bundle.contract.test.js +8 -0
- package/dist/src/pathmode.background.contract.test.js +69 -0
- package/dist/src/pathmode.settings.api.contract.test.js +9 -0
- package/dist/src/pkg.sidecar.contract.test.js +9 -3
- package/dist/src/platform/ExportProfile.js +86 -0
- package/dist/src/platform/MobileBudget.js +11 -0
- package/dist/src/platform/PlatformCapabilities.js +59 -0
- package/dist/src/platform/PlatformCapabilities.test.js +36 -0
- package/dist/src/platform/RenderMaterializer.js +33 -0
- package/dist/src/platform/RenderMaterializer.test.js +32 -0
- package/dist/src/query_backend.external_http.integration.test.js +410 -0
- package/dist/src/reader_renderer.js +404 -3
- package/dist/src/reader_renderer.test.js +87 -0
- package/dist/src/release.godot.mirror.contract.test.js +97 -0
- package/dist/src/resources/ResourceRegistry.js +263 -0
- package/dist/src/resources/ResourceRegistry.test.js +97 -0
- package/dist/src/resources/types.js +2 -0
- package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
- package/dist/src/routes/index.js +19 -0
- package/dist/src/routes/knowledge.js +981 -0
- package/dist/src/routes/knowledgePayload.js +185 -0
- package/dist/src/routes/knowledgePayload.test.js +53 -0
- package/dist/src/routes/markdown.js +295 -0
- package/dist/src/routes/notemd.js +1321 -0
- package/dist/src/routes/registry.contract.test.js +133 -0
- package/dist/src/routes/registry.shadow.contract.test.js +22 -0
- package/dist/src/routes/render.js +248 -0
- package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
- package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
- package/dist/src/routes/settings.js +6 -0
- package/dist/src/routes/staticFiles.js +94 -0
- package/dist/src/routes/types.js +2 -0
- package/dist/src/runtime.capabilities.test.js +18 -2
- package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
- package/dist/src/server.js +10342 -1325
- package/dist/src/server.migration.test.js +584 -10
- package/dist/src/server.port.fallback.contract.test.js +63 -0
- package/dist/src/session/SessionStateStore.js +81 -0
- package/dist/src/session/SessionStateStore.test.js +58 -0
- package/dist/src/session/types.js +2 -0
- package/dist/src/settings.runtime.contract.test.js +50 -0
- package/dist/src/shared/types.contract.test.js +107 -0
- package/dist/src/shared/types.js +22 -0
- 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 +131 -0
- package/dist/src/sidecar.supply.readiness.contract.test.js +155 -0
- package/dist/src/simulation.worker.offline.test.js +104 -0
- package/dist/src/source_manager.loadflow.test.js +46 -0
- package/dist/src/startup.layout.snapshot.contract.test.js +57 -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 +68 -0
- package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
- package/dist/src/tauri.window.evidence.execution.test.js +68 -0
- package/dist/src/utils/RuntimePaths.js +10 -13
- package/dist/src/utils/RuntimePaths.test.js +27 -0
- package/dist/src/utils/platform.js +153 -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/workflows/WorkflowArtifactStore.js +96 -0
- package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
- package/dist/src/workflows/types.js +2 -0
- package/dist/src/workspace/WorkspaceRegistry.js +135 -0
- package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
- package/dist/src/workspace/types.js +2 -0
- package/package.json +80 -15
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const KnowledgeLearningPlatform_1 = require("./KnowledgeLearningPlatform");
|
|
4
|
+
async function measurementEvidence(first, second) {
|
|
5
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
6
|
+
await platform.ingestKnowledge({ relationRecomputeMode: 'none', documents: [
|
|
7
|
+
{ documentId: 'measurement-left', sourcePath: 'quality/measurement-left.md', content: `# Calibration Measurements\n${first}` },
|
|
8
|
+
{ documentId: 'measurement-right', sourcePath: 'quality/measurement-right.md', content: `# Calibration Measurements\n${second}` },
|
|
9
|
+
] });
|
|
10
|
+
return platform.agentConversation({ message: 'Summarize calibration measurements.', responseMode: 'full', persistMemory: false });
|
|
11
|
+
}
|
|
12
|
+
const measurements = [
|
|
13
|
+
['different frequencies', 'The calibration rate is 12 Hz.', 'The calibration rate is 18 Hz.', true],
|
|
14
|
+
['storage capacity', 'The calibration capacity is 64 MB.', 'The calibration capacity is 128 MB.', true],
|
|
15
|
+
['Chinese storage capacity', '定标缓冲区容量是64MB。', '定标缓冲区容量是128MB。', true],
|
|
16
|
+
['decimal storage units', 'The calibration capacity is 1 MB.', 'The calibration capacity is 1000000 B.', false],
|
|
17
|
+
['binary storage units', 'The calibration capacity is 1 MiB.', 'The calibration capacity is 1048576 B.', false],
|
|
18
|
+
['decimal and binary storage units differ', 'The calibration capacity is 1 MB.', 'The calibration capacity is 1 MiB.', true],
|
|
19
|
+
['bits and bytes', 'The calibration capacity is 1 B.', 'The calibration capacity is 8 b.', false],
|
|
20
|
+
['megabits and megabytes', 'The calibration capacity is 1 MB.', 'The calibration capacity is 8 Mb.', false],
|
|
21
|
+
['case-distinct storage units', 'The calibration capacity is 1 MB.', 'The calibration capacity is 1 Mb.', true],
|
|
22
|
+
['opposed storage constraint', 'The calibration capacity is 1 MB.', 'The calibration capacity is not 1000000 B.', true],
|
|
23
|
+
['Chinese frequencies', '定标频率是12赫兹。', '定标频率是18赫兹。', true],
|
|
24
|
+
['day durations', 'The calibration retention period is 7 days.', 'The calibration retention period is 30 days.', true],
|
|
25
|
+
['Chinese day durations', '定标记录保留周期是7天。', '定标记录保留周期是30天。', true],
|
|
26
|
+
['opposed exact constraints', 'The calibration rate is 12 Hz.', 'The calibration rate is not 12 Hz.', true],
|
|
27
|
+
['Chinese opposed constraints', '定标频率是12赫兹。', '定标频率不是12赫兹。', true],
|
|
28
|
+
['compatible negative constraint', 'The calibration rate is not 12 Hz.', 'The calibration rate is 18 Hz.', false],
|
|
29
|
+
['two exclusions', 'The calibration rate is not 12 Hz.', 'The calibration rate is not 18 Hz.', false],
|
|
30
|
+
['Chinese compatible constraint', '定标频率不是12赫兹。', '定标频率是18赫兹。', false],
|
|
31
|
+
['equivalent frequency units', 'The calibration rate is 1 kHz.', 'The calibration rate is 1000 Hz.', false],
|
|
32
|
+
['equivalent duration units', 'The calibration duration is 1000 ms.', 'The calibration duration is 1 s.', false],
|
|
33
|
+
['equivalent length units', 'The calibration length is 12 mm.', 'The calibration length is 1.2 cm.', false],
|
|
34
|
+
['equivalent mass units', 'The calibration mass is 1000 mg.', 'The calibration mass is 1 g.', false],
|
|
35
|
+
['equivalent temperature units', 'The calibration temperature is 0 °C.', 'The calibration temperature is 273.15 K.', false],
|
|
36
|
+
['incompatible dimensions', 'The calibration reading is 5 s.', 'The calibration reading is 5 m.', false],
|
|
37
|
+
['Chinese incompatible dimensions', '定标读数是5赫兹。', '定标读数是5毫秒。', false],
|
|
38
|
+
['historical headings', '## Current\nThe calibration duration is 12 ms.', '## Historical\nThe calibration duration is 18 ms.', false],
|
|
39
|
+
['environment headings', '## Production\nThe calibration duration is 12 ms.', '## Staging\nThe calibration duration is 18 ms.', false],
|
|
40
|
+
['Chinese environment headings', '## 生产环境\n定标时长是12毫秒。', '## 测试环境\n定标时长是18毫秒。', false],
|
|
41
|
+
['distinct minor versions', 'The calibration duration is 12 ms for version 1.2.', 'The calibration duration is 18 ms for version 1.3.', false],
|
|
42
|
+
['same minor version', 'The calibration duration is 12 ms for version 1.2.', 'The calibration duration is 18 ms for version 1.2.', true],
|
|
43
|
+
['different subjects', 'The alpha calibration duration is 12 ms.', 'The beta calibration duration is 18 ms.', false],
|
|
44
|
+
['scientific notation', 'The calibration rate is 1e3 Hz.', 'The calibration rate is 2e3 Hz.', true],
|
|
45
|
+
['scientific equivalence', 'The calibration rate is 1e3 Hz.', 'The calibration rate is 1000 Hz.', false],
|
|
46
|
+
['leading decimal magnitudes', 'The calibration duration is .5 s.', 'The calibration duration is .8 s.', true],
|
|
47
|
+
['uncertain magnitude', 'The calibration offset is ±12 ms.', 'The calibration offset is 4 ms.', false],
|
|
48
|
+
['range constraint', 'The calibration duration is at least 12 ms.', 'The calibration duration is 18 ms.', false],
|
|
49
|
+
['tolerance half-width constraints', 'The calibration tolerance is +/-0.10 mm.', 'The calibration tolerance is +/-0.50 mm.', true],
|
|
50
|
+
['equivalent tolerance half-widths', 'The calibration tolerance is ±0.10 mm.', 'The calibration tolerance is 0.01 cm.', false],
|
|
51
|
+
['Chinese tolerance half-widths', '定标公差为±0.10毫米。', '定标公差为±0.50毫米。', true],
|
|
52
|
+
['postfix uncertainty', 'The calibration duration is 12 ms ± 2 ms.', 'The calibration duration is 18 ms.', false],
|
|
53
|
+
['postfix range', 'The calibration duration is 12 ms to 20 ms.', 'The calibration duration is 18 ms.', false],
|
|
54
|
+
['unrecognized compound dimension', 'The calibration reading is 5 m/s.', 'The calibration reading is 8 m.', false],
|
|
55
|
+
['SI symbol case', 'The calibration reading is 5 µM.', 'The calibration reading is 8 µm.', false],
|
|
56
|
+
['tiny distinct magnitudes', 'The calibration length is 1e-10 nm.', 'The calibration length is 2e-10 nm.', true],
|
|
57
|
+
['equivalent measured capacity', 'The calibration size is 10 mm.', 'The calibration size is 1 cm.', false],
|
|
58
|
+
['explicit distinct years', 'The calibration duration is 12 ms in 2023.', 'The calibration duration is 18 ms in 2024.', false],
|
|
59
|
+
['explicit same year', 'The calibration duration is 12 ms in 2024.', 'The calibration duration is 18 ms in 2024.', true],
|
|
60
|
+
['Chinese distinct years', '定标时长在2023年是12毫秒。', '定标时长在2024年是18毫秒。', false],
|
|
61
|
+
['distinct platforms', 'The calibration duration is 12 ms on Linux.', 'The calibration duration is 18 ms on Windows.', false],
|
|
62
|
+
['same platform', 'The calibration duration is 12 ms on Linux.', 'The calibration duration is 18 ms on Linux.', true],
|
|
63
|
+
['standalone paragraph qualifiers', 'In production. The calibration duration is 12 ms.', 'In staging. The calibration duration is 18 ms.', false],
|
|
64
|
+
['matching paragraph qualifiers', 'In production. The calibration duration is 12 ms.', 'In production. The calibration duration is 18 ms.', true],
|
|
65
|
+
['ambiguous environment', 'The calibration duration is 12 ms in production or staging.', 'The calibration duration is 18 ms in production.', false],
|
|
66
|
+
['ambiguous heading', '## Production and Staging\nThe calibration duration is 12 ms.', '## Production\nThe calibration duration is 18 ms.', false],
|
|
67
|
+
];
|
|
68
|
+
describe('measurement evidence comparability', () => {
|
|
69
|
+
test.each(measurements)('%s', async (_name, first, second, conflictExpected) => {
|
|
70
|
+
const response = await measurementEvidence(first, second);
|
|
71
|
+
const conflicts = response.trace.ragContextPack?.fragments.filter(fragment => fragment.role === 'conflict') || [];
|
|
72
|
+
expect(conflicts.length > 0).toBe(conflictExpected);
|
|
73
|
+
for (const fragment of conflicts) {
|
|
74
|
+
expect(fragment.citationIds).toHaveLength(2);
|
|
75
|
+
expect(fragment.sourceBoundary).toBe('full_document');
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const KnowledgeLearningPlatform_1 = require("./KnowledgeLearningPlatform");
|
|
9
|
+
const AnswerQualityEvaluation_1 = require("./AnswerQualityEvaluation");
|
|
10
|
+
// V3's first confirmation is archived. These observed cases are now regression evidence.
|
|
11
|
+
const corpus = (0, AnswerQualityEvaluation_1.parseAnswerQualityCorpus)(JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../fixtures/answer-quality/v3.json'), 'utf8')));
|
|
12
|
+
const cases = corpus.cases.filter(entry => [
|
|
13
|
+
'cal-dag-en', 'cal-dag-zh', 'cal-retention-en', 'v3-retry-budget-en', 'v3-idempotency-zh',
|
|
14
|
+
'v3-sets-en', 'v3-index-swap-en', 'v3-memory-fences-en', 'v3-transaction-isolation-zh',
|
|
15
|
+
'v3-channels-zh', 'v3-checksum-en', 'v3-stable-reference-zh',
|
|
16
|
+
].includes(entry.id));
|
|
17
|
+
const observedV4 = (0, AnswerQualityEvaluation_1.parseAnswerQualityCorpus)(JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../fixtures/answer-quality/v4.json'), 'utf8')));
|
|
18
|
+
cases.push(...observedV4.cases.filter(entry => ['v4-receives-en', 'v4-content-addressing-en'].includes(entry.id)));
|
|
19
|
+
const observedV5 = (0, AnswerQualityEvaluation_1.parseAnswerQualityCorpus)(JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../fixtures/answer-quality/v5.json'), 'utf8')));
|
|
20
|
+
cases.push(...observedV5.cases.filter(entry => ['v5-iterator-en', 'v5-reentrant-lock-zh', 'v5-replication-zh'].includes(entry.id)));
|
|
21
|
+
const observedV6 = (0, AnswerQualityEvaluation_1.parseAnswerQualityCorpus)(JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../fixtures/answer-quality/v6.json'), 'utf8')));
|
|
22
|
+
cases.push(...observedV6.cases.filter(entry => ['v6-locking-en', 'v6-queue-en', 'v6-repeatable-command-en', 'v6-read-isolation-zh'].includes(entry.id)));
|
|
23
|
+
const observedV1 = (0, AnswerQualityEvaluation_1.parseAnswerQualityCorpus)(JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../fixtures/answer-quality/v1.json'), 'utf8')));
|
|
24
|
+
const observedV2 = (0, AnswerQualityEvaluation_1.parseAnswerQualityCorpus)(JSON.parse(fs_1.default.readFileSync(path_1.default.resolve(__dirname, '../../fixtures/answer-quality/v2.json'), 'utf8')));
|
|
25
|
+
cases.push(...observedV1.cases.filter(entry => ['eval-capacity-en', 'eval-capacity-zh', 'eval-math-zh'].includes(entry.id)));
|
|
26
|
+
cases.push(...observedV2.cases.filter(entry => entry.id === 'confirm-collections-zh'));
|
|
27
|
+
describe.each(['slim', 'full'])('public answer contracts in %s', responseMode => {
|
|
28
|
+
test('keeps an unrelated Chinese sentence out after an explicit comparison subject', async () => {
|
|
29
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
30
|
+
await platform.ingestKnowledge({ relationRecomputeMode: 'none', documents: [
|
|
31
|
+
{ documentId: 'mutable', sourcePath: 'quality/mutable.md', content: '# 可变向量\n可变向量允许原地修改元素。火星有两颗卫星。' },
|
|
32
|
+
{ documentId: 'fixed', sourcePath: 'quality/fixed.md', content: '# 不可变向量\n不可变向量不允许原地修改元素。' },
|
|
33
|
+
] });
|
|
34
|
+
const response = await platform.agentConversation({ message: '比较可变向量和不可变向量。', answerLanguage: 'zh', responseMode, persistMemory: false });
|
|
35
|
+
if (responseMode === 'slim')
|
|
36
|
+
expect(response.answer).not.toContain('火星');
|
|
37
|
+
expect(response.answer).toContain('不允许原地修改元素');
|
|
38
|
+
});
|
|
39
|
+
test('treats a requested table concept as subject matter', async () => {
|
|
40
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
41
|
+
await platform.ingestKnowledge({ relationRecomputeMode: 'none', documents: [
|
|
42
|
+
{ documentId: 'dispatch-table', sourcePath: 'quality/dispatch.md', content: '# Dispatch Table\nA dispatch table maps operation codes to executable targets.' },
|
|
43
|
+
] });
|
|
44
|
+
const response = await platform.agentConversation({ message: 'What is a dispatch table?', answerLanguage: 'en', responseMode, persistMemory: false });
|
|
45
|
+
expect(response.answer).toContain('maps operation codes');
|
|
46
|
+
expect(response.answerReleaseReview?.decision).not.toBe('abstain');
|
|
47
|
+
});
|
|
48
|
+
test('keeps a short Chinese definition and its supported constraint', async () => {
|
|
49
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
50
|
+
await platform.ingestKnowledge({ relationRecomputeMode: 'none', documents: [
|
|
51
|
+
{ documentId: 'mutex', sourcePath: 'quality/mutex.md', content: '# 互斥锁\n互斥锁保护临界区。同一时刻只有一个持有者。' },
|
|
52
|
+
] });
|
|
53
|
+
const response = await platform.agentConversation({ message: '什么是互斥锁?', answerLanguage: 'zh', responseMode, persistMemory: false });
|
|
54
|
+
expect(response.answer).toContain('保护临界区');
|
|
55
|
+
expect(response.answer).toContain('同一时刻只有一个持有者');
|
|
56
|
+
});
|
|
57
|
+
test('rejects an attribute assertion about a different entity', async () => {
|
|
58
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
59
|
+
await platform.ingestKnowledge({ relationRecomputeMode: 'none', documents: [
|
|
60
|
+
{ documentId: 'helium', sourcePath: 'quality/helium.md', content: '# Helium Log\nThe Helium log retention period is 9 days.' },
|
|
61
|
+
] });
|
|
62
|
+
const response = await platform.agentConversation({ message: 'What is the retention period for the Titanium log?', answerLanguage: 'en', responseMode, persistMemory: false });
|
|
63
|
+
expect(response.answerReleaseReview?.decision).toBe('abstain');
|
|
64
|
+
expect(response.answer).not.toMatch(/9 days/iu);
|
|
65
|
+
});
|
|
66
|
+
test.each(cases)('$id preserves the requested evidence and its ordering', async (entry) => {
|
|
67
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
68
|
+
await platform.ingestKnowledge({ documents: entry.documents, relationRecomputeMode: 'none' });
|
|
69
|
+
const response = await platform.agentConversation({ message: entry.query, answerLanguage: entry.language, responseMode,
|
|
70
|
+
persistMemory: false, scope: { documentIds: entry.documents.map(document => document.documentId) } });
|
|
71
|
+
expect(response.answerReleaseReview?.decision).not.toBe('abstain');
|
|
72
|
+
for (const fact of entry.reference.facts) {
|
|
73
|
+
expect({ id: fact.id, covered: fact.patterns.some(pattern => new RegExp(pattern, 'iu').test(response.answer)) })
|
|
74
|
+
.toEqual({ id: fact.id, covered: true });
|
|
75
|
+
}
|
|
76
|
+
for (const claim of entry.reference.unsupportedClaims)
|
|
77
|
+
expect(response.answer).not.toMatch(new RegExp(claim.pattern, 'iu'));
|
|
78
|
+
let previousEnd = 0;
|
|
79
|
+
for (const step of entry.reference.orderedSteps || []) {
|
|
80
|
+
const match = new RegExp(step, 'iu').exec(response.answer.slice(previousEnd));
|
|
81
|
+
expect(match).not.toBeNull();
|
|
82
|
+
previousEnd += match.index + match[0].length;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const fs = __importStar(require("fs"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const KnowledgeLearningPlatform_1 = require("./KnowledgeLearningPlatform");
|
|
39
|
+
const regressionCorpus = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../../fixtures/answer-quality/v2.json'), 'utf8'));
|
|
40
|
+
async function answer(message, documents, language = 'en') {
|
|
41
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
42
|
+
await platform.ingestKnowledge({ documents, relationRecomputeMode: 'none' });
|
|
43
|
+
const request = { message, answerLanguage: language, responseMode: 'full', persistMemory: false,
|
|
44
|
+
scope: { documentIds: documents.map(document => document.documentId) } };
|
|
45
|
+
return { platform, response: await platform.agentConversation(request) };
|
|
46
|
+
}
|
|
47
|
+
describe('public evidence source selection', () => {
|
|
48
|
+
test.each(['en', 'zh'])('keeps scoped topic distractors out of the %s answer, citations and required claims', async (language) => {
|
|
49
|
+
const entry = regressionCorpus.cases.find((candidate) => candidate.id === `confirm-wal-${language}`);
|
|
50
|
+
const { platform, response } = await answer(entry.query, entry.documents, language);
|
|
51
|
+
const excludedDocumentId = entry.documents[1].documentId;
|
|
52
|
+
expect(response.answer).not.toMatch(/cardinals|bird.watching|红雀|观鸟/iu);
|
|
53
|
+
expect(response.answer).toMatch(language === 'en' ? /durable log.*reconstruct/iu : /持久日志重建/u);
|
|
54
|
+
expect(response.citations.every(citation => citation.documentId !== excludedDocumentId)).toBe(true);
|
|
55
|
+
expect(response.answerReleaseReview?.auditGraphAnswerPlan?.claims.every(claim => (claim.evidenceRefs.every(reference => reference.sourcePath !== entry.documents[1].sourcePath)))).toBe(true);
|
|
56
|
+
expect(response.trace.ragContextPack?.sourceDecisions).toContainEqual(expect.objectContaining({
|
|
57
|
+
documentId: excludedDocumentId, status: 'fragment_dropped', reason: 'query_subject_mismatch', charsRead: 0,
|
|
58
|
+
}));
|
|
59
|
+
const retrieval = await platform.queryKnowledge({ query: entry.query, topK: 12,
|
|
60
|
+
scope: { documentIds: entry.documents.map((document) => document.documentId) } });
|
|
61
|
+
expect(retrieval.items.some(item => item.atom.documentId === excludedDocumentId)).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
test('retains a second source whose body establishes the requested subject', async () => {
|
|
64
|
+
const { response } = await answer('Explain recovery point objectives.', [
|
|
65
|
+
{ documentId: 'rpo-definition', sourcePath: 'quality/rpo.md', content: '# Recovery Point Objectives\nA recovery point objective bounds the acceptable age of recovered data.' },
|
|
66
|
+
{ documentId: 'rpo-scheduling', sourcePath: 'quality/schedule.md', content: '# Scheduling Policy\nRecovery point objectives determine how frequently snapshots must be taken.' },
|
|
67
|
+
{ documentId: 'business-objectives', sourcePath: 'quality/business.md', content: '# Business Objectives\nBusiness objectives guide revenue targets and quarterly sales reviews.' },
|
|
68
|
+
]);
|
|
69
|
+
expect(response.answer).toMatch(/acceptable age/iu);
|
|
70
|
+
expect(response.answer).toMatch(/how frequently snapshots/iu);
|
|
71
|
+
expect(response.answer).not.toMatch(/revenue|quarterly sales/iu);
|
|
72
|
+
expect(response.citations.map(citation => citation.documentId)).toEqual(expect.arrayContaining(['rpo-definition', 'rpo-scheduling']));
|
|
73
|
+
});
|
|
74
|
+
test('retains both comparison operands while rejecting a shared-word distractor', async () => {
|
|
75
|
+
const { response } = await answer('Compare an exclusive lock and a shared lock.', [
|
|
76
|
+
{ documentId: 'exclusive', sourcePath: 'quality/exclusive.md', content: '# Exclusive Lock\nAn exclusive lock permits only one owner to access the protected resource.' },
|
|
77
|
+
{ documentId: 'shared', sourcePath: 'quality/shared.md', content: '# Shared Lock\nA shared lock permits several readers to access the protected resource concurrently.' },
|
|
78
|
+
{ documentId: 'door', sourcePath: 'quality/door.md', content: '# Door Lock\nA door lock may be painted bright yellow to match a wooden door.' },
|
|
79
|
+
]);
|
|
80
|
+
expect(response.answer).toMatch(/only one owner/iu);
|
|
81
|
+
expect(response.answer).toMatch(/several readers/iu);
|
|
82
|
+
expect(response.answer).not.toMatch(/bright yellow|wooden door/iu);
|
|
83
|
+
expect(response.citations.map(citation => citation.documentId)).not.toContain('door');
|
|
84
|
+
});
|
|
85
|
+
test('does not choose a winner among competing observations of the same subject', async () => {
|
|
86
|
+
const { response } = await answer('What is the Echo clock rate?', [
|
|
87
|
+
{ documentId: 'echo-a', sourcePath: 'quality/echo-a.md', content: '# Echo Clock Rate\nThe Echo clock rate is 4 Hz.' },
|
|
88
|
+
{ documentId: 'echo-b', sourcePath: 'quality/echo-b.md', content: '# Echo Clock Rate Record\nThe Echo clock rate is 9 Hz.' },
|
|
89
|
+
]);
|
|
90
|
+
expect(response.answer).toMatch(/4\s*Hz/iu);
|
|
91
|
+
expect(response.answer).toMatch(/9\s*Hz/iu);
|
|
92
|
+
expect(response.citations.map(citation => citation.documentId)).toEqual(expect.arrayContaining(['echo-a', 'echo-b']));
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const KnowledgeLearningPlatform_1 = require("./KnowledgeLearningPlatform");
|
|
4
|
+
const agentConversationSerialization_1 = require("./agentConversationSerialization");
|
|
5
|
+
async function answerMeasurements(request, first, second) {
|
|
6
|
+
const platform = new KnowledgeLearningPlatform_1.KnowledgeLearningPlatform({ autoPersist: false });
|
|
7
|
+
await platform.ingestKnowledge({ relationRecomputeMode: 'none', documents: [
|
|
8
|
+
{ documentId: 'clock-primary', sourcePath: 'quality/clock-primary.md', content: first },
|
|
9
|
+
{ documentId: 'clock-secondary', sourcePath: 'quality/clock-secondary.md', content: second },
|
|
10
|
+
] });
|
|
11
|
+
return platform.agentConversation({ ...request, persistMemory: false });
|
|
12
|
+
}
|
|
13
|
+
describe('public measurement conflict disclosure', () => {
|
|
14
|
+
test.each(['slim', 'full'])('keeps conflicting English observations and their citations in %s', async (responseMode) => {
|
|
15
|
+
const response = await answerMeasurements({ message: 'What is the Echo clock rate?', answerLanguage: 'en', responseMode }, '# Echo Clock Rate\nThe Echo clock rate is 4 Hz.', '# Echo Clock Rate Record\nThe Echo clock rate is 9 Hz.');
|
|
16
|
+
expect(response.trace.ragContextPack?.fragments.some(fragment => fragment.role === 'conflict')).toBe(true);
|
|
17
|
+
expect(response.answer).toMatch(/4\s*Hz/iu);
|
|
18
|
+
expect(response.answer).toMatch(/9\s*Hz/iu);
|
|
19
|
+
expect(response.answer).toMatch(/conflict|contradict|disagree/iu);
|
|
20
|
+
expect(response.citations.map(citation => citation.documentId)).toEqual(expect.arrayContaining(['clock-primary', 'clock-secondary']));
|
|
21
|
+
expect(response.answerReleaseReview?.decision).not.toBe('abstain');
|
|
22
|
+
});
|
|
23
|
+
test.each(['slim', 'full'])('keeps conflicting Chinese observations and their citations in %s', async (responseMode) => {
|
|
24
|
+
const response = await answerMeasurements({ message: '回声时钟频率是多少?', answerLanguage: 'zh', responseMode }, '# 回声时钟频率\n回声时钟频率是4赫兹。', '# 回声时钟频率记录\n回声时钟频率是9赫兹。');
|
|
25
|
+
expect(response.trace.ragContextPack?.fragments.some(fragment => fragment.role === 'conflict')).toBe(true);
|
|
26
|
+
expect(response.answer).toContain('4赫兹');
|
|
27
|
+
expect(response.answer).toContain('9赫兹');
|
|
28
|
+
expect(response.answer).toMatch(/冲突|矛盾|不一致/u);
|
|
29
|
+
expect(response.citations.map(citation => citation.documentId)).toEqual(expect.arrayContaining(['clock-primary', 'clock-secondary']));
|
|
30
|
+
expect(response.answerReleaseReview?.decision).not.toBe('abstain');
|
|
31
|
+
});
|
|
32
|
+
test.each(['slim', 'full'])('does not manufacture conflicts between equivalent observations in %s', async (responseMode) => {
|
|
33
|
+
const response = await answerMeasurements({ message: 'What is the Echo clock rate?', answerLanguage: 'en', responseMode }, '# Echo Clock Rate\nThe Echo clock rate is 1 kHz.', '# Echo Clock Rate Record\nThe Echo clock rate is 1000 Hz.');
|
|
34
|
+
expect(response.trace.ragContextPack?.fragments.some(fragment => fragment.role === 'conflict')).toBe(false);
|
|
35
|
+
expect(response.answer).not.toMatch(/conflict|contradict|disagree/iu);
|
|
36
|
+
expect(response.answer).toMatch(/(?:1\s*kHz|1000\s*Hz)/iu);
|
|
37
|
+
expect(response.answerReleaseReview?.decision).not.toBe('abstain');
|
|
38
|
+
});
|
|
39
|
+
test('retains the same conflict and citations through bounded JSON, SSE and replay', async () => {
|
|
40
|
+
const response = await answerMeasurements({ message: 'What is the Echo clock rate?', answerLanguage: 'en', responseMode: 'full' }, '# Echo Clock Rate\nThe Echo clock rate is 4 Hz.', '# Echo Clock Rate Record\nThe Echo clock rate is 9 Hz.');
|
|
41
|
+
response.responseBudget.runtimeGovernor.maxSerializedBytes = 6000;
|
|
42
|
+
const http = (0, agentConversationSerialization_1.serializeAgentConversationHttpResponse)(response);
|
|
43
|
+
const event = { type: 'turn_completed', turnId: 'conflict-disclosure', emittedAt: '2026-09-13T00:00:00.000Z', result: response };
|
|
44
|
+
const live = (0, agentConversationSerialization_1.serializeAgentConversationTurnEvent)('turn_completed', event);
|
|
45
|
+
const replay = (0, agentConversationSerialization_1.serializeAgentConversationTurnEvent)('turn_completed', { ...event, result: http.result });
|
|
46
|
+
expect(http.truncated).toBe(true);
|
|
47
|
+
expect(JSON.parse(live.json).result).toEqual(http.result);
|
|
48
|
+
expect(JSON.parse(replay.json).result).toEqual(http.result);
|
|
49
|
+
expect(http.result.answer).toMatch(/observations conflict/iu);
|
|
50
|
+
expect(http.result.answer).toMatch(/4\s*Hz/iu);
|
|
51
|
+
expect(http.result.answer).toMatch(/9\s*Hz/iu);
|
|
52
|
+
expect(http.result.citations.map(citation => citation.documentId)).toEqual(expect.arrayContaining(['clock-primary', 'clock-secondary']));
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentConversationExecution = exports.AgentConversationExecutionError = exports.DEFAULT_AGENT_CONVERSATION_EXECUTION_POLICY = void 0;
|
|
4
|
+
exports.normalizeAgentConversationExecutionPolicy = normalizeAgentConversationExecutionPolicy;
|
|
5
|
+
const promises_1 = require("fs/promises");
|
|
6
|
+
const async_hooks_1 = require("async_hooks");
|
|
7
|
+
const agentResponseBudget_1 = require("./agentResponseBudget");
|
|
8
|
+
exports.DEFAULT_AGENT_CONVERSATION_EXECUTION_POLICY = Object.freeze({
|
|
9
|
+
timeoutMs: 180000,
|
|
10
|
+
maxSourceBytes: 4 * 1024 * 1024,
|
|
11
|
+
maxTotalSourceBytes: 16 * 1024 * 1024,
|
|
12
|
+
maxPendingTurns: 8,
|
|
13
|
+
maxSourceLines: 16384,
|
|
14
|
+
maxSourceFacts: 4096,
|
|
15
|
+
});
|
|
16
|
+
class AgentConversationExecutionError extends Error {
|
|
17
|
+
constructor(code) {
|
|
18
|
+
super(code);
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.name = 'AgentConversationExecutionError';
|
|
21
|
+
this.statusCode = code === 'runtime_turn_capacity' ? 429
|
|
22
|
+
: code === 'runtime_timeout' ? 504
|
|
23
|
+
: code === 'runtime_cancelled' ? 499 : 413;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.AgentConversationExecutionError = AgentConversationExecutionError;
|
|
27
|
+
function normalizeAgentConversationExecutionPolicy(input = {}) {
|
|
28
|
+
const policy = { ...exports.DEFAULT_AGENT_CONVERSATION_EXECUTION_POLICY };
|
|
29
|
+
for (const key of Object.keys(policy)) {
|
|
30
|
+
const candidate = input[key];
|
|
31
|
+
if (candidate === undefined)
|
|
32
|
+
continue;
|
|
33
|
+
if (!Number.isFinite(candidate) || candidate < 1) {
|
|
34
|
+
throw new TypeError(`Invalid agent conversation execution policy: ${key}`);
|
|
35
|
+
}
|
|
36
|
+
policy[key] = Math.min(policy[key], Math.floor(candidate));
|
|
37
|
+
}
|
|
38
|
+
policy.maxSourceBytes = Math.min(policy.maxSourceBytes, policy.maxTotalSourceBytes);
|
|
39
|
+
return policy;
|
|
40
|
+
}
|
|
41
|
+
/** Owns one turn's cooperative deadline and bounded source I/O, including queued time. */
|
|
42
|
+
class AgentConversationExecution {
|
|
43
|
+
constructor(budget, policy, parentSignal) {
|
|
44
|
+
this.budget = budget;
|
|
45
|
+
this.policy = policy;
|
|
46
|
+
this.parentSignal = parentSignal;
|
|
47
|
+
this.active = true;
|
|
48
|
+
this.controller = new AbortController();
|
|
49
|
+
this.startedAtMs = Date.now();
|
|
50
|
+
this.sourceBytes = 0;
|
|
51
|
+
this.sourceReads = 0;
|
|
52
|
+
this.processedFragments = 0;
|
|
53
|
+
this.sourceFacts = 0;
|
|
54
|
+
this.timeoutMs = Math.min(policy.timeoutMs, budget.runtimeGovernor.timeoutMs);
|
|
55
|
+
this.budget = { ...budget, runtimeGovernor: { ...budget.runtimeGovernor, timeoutMs: this.timeoutMs } };
|
|
56
|
+
this.onParentAbort = () => this.controller.abort(new AgentConversationExecutionError('runtime_cancelled'));
|
|
57
|
+
this.timer = setTimeout(() => {
|
|
58
|
+
this.controller.abort(new AgentConversationExecutionError('runtime_timeout'));
|
|
59
|
+
}, this.timeoutMs);
|
|
60
|
+
this.timer.unref();
|
|
61
|
+
if (parentSignal?.aborted)
|
|
62
|
+
this.onParentAbort();
|
|
63
|
+
else
|
|
64
|
+
parentSignal?.addEventListener('abort', this.onParentAbort, { once: true });
|
|
65
|
+
}
|
|
66
|
+
static async run(options, operation) {
|
|
67
|
+
const existing = this.current();
|
|
68
|
+
if (existing) {
|
|
69
|
+
existing.assertActive();
|
|
70
|
+
return operation(existing);
|
|
71
|
+
}
|
|
72
|
+
const execution = new AgentConversationExecution(options.budget, options.policy, options.signal);
|
|
73
|
+
try {
|
|
74
|
+
execution.assertActive();
|
|
75
|
+
// Keep the state lease until cooperative work has actually stopped.
|
|
76
|
+
// Racing an uncancelled promise would allow it to mutate a later turn.
|
|
77
|
+
return await this.scope.run(execution, () => operation(execution));
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
execution.active = false;
|
|
81
|
+
clearTimeout(execution.timer);
|
|
82
|
+
options.signal?.removeEventListener('abort', execution.onParentAbort);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
get signal() { return this.controller.signal; }
|
|
86
|
+
get maxFragmentChars() { return this.budget.rag.maxCharsPerFragment; }
|
|
87
|
+
get truncationReason() { return this.sourceStop; }
|
|
88
|
+
static current() {
|
|
89
|
+
const execution = this.scope.getStore();
|
|
90
|
+
return execution?.active ? execution : undefined;
|
|
91
|
+
}
|
|
92
|
+
isResourceLimit(error) {
|
|
93
|
+
return error instanceof AgentConversationExecutionError && (error.code === 'runtime_source_bytes_limit'
|
|
94
|
+
|| error.code === 'runtime_total_source_bytes_limit'
|
|
95
|
+
|| error.code === 'runtime_fragment_limit'
|
|
96
|
+
|| error.code === 'runtime_source_lines_limit'
|
|
97
|
+
|| error.code === 'runtime_source_facts_limit');
|
|
98
|
+
}
|
|
99
|
+
assertActive() {
|
|
100
|
+
if (!this.active)
|
|
101
|
+
throw new AgentConversationExecutionError('runtime_cancelled');
|
|
102
|
+
if (this.signal.aborted)
|
|
103
|
+
throw this.signal.reason;
|
|
104
|
+
const decision = (0, agentResponseBudget_1.applyRuntimeGovernor)({
|
|
105
|
+
budget: this.budget,
|
|
106
|
+
startedAtMs: this.startedAtMs, nowMs: Date.now(),
|
|
107
|
+
processedFragments: this.processedFragments, serializedBytes: 0, reportChars: 0,
|
|
108
|
+
});
|
|
109
|
+
if (!decision.allowed) {
|
|
110
|
+
const code = decision.reason === 'runtime_timeout' ? 'runtime_timeout' : 'runtime_fragment_limit';
|
|
111
|
+
throw new AgentConversationExecutionError(code);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async yieldCheckpoint() {
|
|
115
|
+
this.assertActive();
|
|
116
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
117
|
+
this.assertActive();
|
|
118
|
+
}
|
|
119
|
+
recordFragment() {
|
|
120
|
+
if (this.processedFragments >= this.budget.runtimeGovernor.maxFragmentsProcessed) {
|
|
121
|
+
this.sourceStop = 'runtime_fragment_limit';
|
|
122
|
+
throw new AgentConversationExecutionError(this.sourceStop);
|
|
123
|
+
}
|
|
124
|
+
this.processedFragments++;
|
|
125
|
+
this.assertActive();
|
|
126
|
+
}
|
|
127
|
+
checkSourceLineCount(count) {
|
|
128
|
+
this.assertActive();
|
|
129
|
+
if (count > this.policy.maxSourceLines) {
|
|
130
|
+
this.sourceStop = 'runtime_source_lines_limit';
|
|
131
|
+
throw new AgentConversationExecutionError(this.sourceStop);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
recordSourceFact() {
|
|
135
|
+
this.assertActive();
|
|
136
|
+
if (this.sourceFacts >= this.policy.maxSourceFacts) {
|
|
137
|
+
this.sourceStop = 'runtime_source_facts_limit';
|
|
138
|
+
throw new AgentConversationExecutionError(this.sourceStop);
|
|
139
|
+
}
|
|
140
|
+
this.sourceFacts++;
|
|
141
|
+
}
|
|
142
|
+
acceptSourceText(content) {
|
|
143
|
+
this.assertActive();
|
|
144
|
+
const bytes = Buffer.byteLength(content, 'utf8');
|
|
145
|
+
this.assertSourceFits(bytes, bytes);
|
|
146
|
+
this.sourceBytes += bytes;
|
|
147
|
+
this.sourceReads++;
|
|
148
|
+
return content;
|
|
149
|
+
}
|
|
150
|
+
async readSourceFile(filePath) {
|
|
151
|
+
this.assertActive();
|
|
152
|
+
const file = await (0, promises_1.open)(filePath, 'r');
|
|
153
|
+
try {
|
|
154
|
+
this.assertActive();
|
|
155
|
+
const stat = await file.stat();
|
|
156
|
+
if (!stat.isFile())
|
|
157
|
+
return null;
|
|
158
|
+
this.assertSourceFits(stat.size, stat.size);
|
|
159
|
+
const chunks = [];
|
|
160
|
+
let fileBytes = 0;
|
|
161
|
+
const stream = file.createReadStream({ autoClose: false, highWaterMark: 64 * 1024, signal: this.signal });
|
|
162
|
+
try {
|
|
163
|
+
for await (const chunk of stream) {
|
|
164
|
+
this.assertActive();
|
|
165
|
+
const bytes = chunk;
|
|
166
|
+
fileBytes += bytes.length;
|
|
167
|
+
// Check actual bytes too: the file can grow after stat().
|
|
168
|
+
this.assertSourceFits(fileBytes, bytes.length);
|
|
169
|
+
this.sourceBytes += bytes.length;
|
|
170
|
+
chunks.push(bytes);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
this.assertActive();
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
this.sourceReads++;
|
|
178
|
+
return Buffer.concat(chunks, fileBytes).toString('utf8');
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
await file.close();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
diagnostics() {
|
|
185
|
+
return {
|
|
186
|
+
elapsedMs: Math.max(0, Date.now() - this.startedAtMs),
|
|
187
|
+
timeoutMs: this.timeoutMs,
|
|
188
|
+
maxSourceBytes: this.policy.maxSourceBytes,
|
|
189
|
+
maxTotalSourceBytes: this.policy.maxTotalSourceBytes,
|
|
190
|
+
sourceBytes: this.sourceBytes,
|
|
191
|
+
sourceReads: this.sourceReads,
|
|
192
|
+
processedFragments: this.processedFragments,
|
|
193
|
+
maxSourceLines: this.policy.maxSourceLines,
|
|
194
|
+
maxSourceFacts: this.policy.maxSourceFacts,
|
|
195
|
+
sourceFacts: this.sourceFacts,
|
|
196
|
+
...(this.sourceStop ? { truncationReason: this.sourceStop } : {}),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
assertSourceFits(fileBytes, additionalBytes) {
|
|
200
|
+
if (fileBytes > this.policy.maxSourceBytes) {
|
|
201
|
+
this.sourceStop = 'runtime_source_bytes_limit';
|
|
202
|
+
throw new AgentConversationExecutionError(this.sourceStop);
|
|
203
|
+
}
|
|
204
|
+
if (this.sourceBytes + additionalBytes > this.policy.maxTotalSourceBytes) {
|
|
205
|
+
this.sourceStop = 'runtime_total_source_bytes_limit';
|
|
206
|
+
throw new AgentConversationExecutionError(this.sourceStop);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
exports.AgentConversationExecution = AgentConversationExecution;
|
|
211
|
+
AgentConversationExecution.scope = new async_hooks_1.AsyncLocalStorage();
|