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
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
(function attachMobileSemanticComparator(root, factory) {
|
|
2
|
+
const api = factory();
|
|
3
|
+
if (typeof module === 'object' && module.exports) {
|
|
4
|
+
module.exports = api;
|
|
5
|
+
}
|
|
6
|
+
if (root) {
|
|
7
|
+
root.NoteConnectionMobileSemanticComparator = api;
|
|
8
|
+
}
|
|
9
|
+
}(typeof globalThis !== 'undefined' ? globalThis : this, function createMobileSemanticComparator() {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const SOURCE_URI_PREFIX = 'note://workspace/v1/';
|
|
13
|
+
const MAX_DIAGNOSTICS = 64;
|
|
14
|
+
|
|
15
|
+
function normalizeText(value) {
|
|
16
|
+
const text = String(value || '').trim();
|
|
17
|
+
return typeof text.normalize === 'function' ? text.normalize('NFC') : text;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function normalizePath(value) {
|
|
21
|
+
const text = normalizeText(value)
|
|
22
|
+
.replace(/\\/g, '/')
|
|
23
|
+
.replace(/^\/+/, '')
|
|
24
|
+
.replace(/^knowledge_base\//i, '');
|
|
25
|
+
const segments = [];
|
|
26
|
+
for (const segment of text.split('/')) {
|
|
27
|
+
if (!segment || segment === '.') {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (segment === '..') {
|
|
31
|
+
if (segments.length === 0) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
segments.pop();
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
segments.push(segment);
|
|
38
|
+
}
|
|
39
|
+
return segments.join('/').replace(/\.(?:md|markdown)$/i, '').toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function canonicalIdFromSourceUri(sourceUri) {
|
|
43
|
+
const normalized = normalizeText(sourceUri);
|
|
44
|
+
if (!normalized.startsWith(SOURCE_URI_PREFIX)) {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const decoded = normalized.slice(SOURCE_URI_PREFIX.length)
|
|
49
|
+
.split('/')
|
|
50
|
+
.map((segment) => decodeURIComponent(segment))
|
|
51
|
+
.join('/');
|
|
52
|
+
return normalizePath(decoded);
|
|
53
|
+
} catch (_error) {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function normalizeSourceUri(sourceUri) {
|
|
59
|
+
const normalized = normalizeText(sourceUri);
|
|
60
|
+
if (!normalized) {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
const canonicalId = canonicalIdFromSourceUri(normalized);
|
|
64
|
+
return canonicalId ? `${SOURCE_URI_PREFIX}${canonicalId.split('/').map(encodeURIComponent).join('/')}.md` : normalized;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function nodeCanonicalId(node) {
|
|
68
|
+
return normalizePath(node && node.canonicalId)
|
|
69
|
+
|| canonicalIdFromSourceUri(node && node.sourceUri)
|
|
70
|
+
|| normalizePath(node && node.id);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function nodeIdentity(node) {
|
|
74
|
+
const canonicalId = nodeCanonicalId(node);
|
|
75
|
+
if (canonicalId) {
|
|
76
|
+
return `canonical:${canonicalId}`;
|
|
77
|
+
}
|
|
78
|
+
const sourceUri = normalizeSourceUri(node && node.sourceUri);
|
|
79
|
+
if (sourceUri) {
|
|
80
|
+
return `uri:${sourceUri}`;
|
|
81
|
+
}
|
|
82
|
+
const legacyId = normalizeText(node && node.id).toLowerCase();
|
|
83
|
+
if (legacyId) {
|
|
84
|
+
return `legacy:${legacyId}`;
|
|
85
|
+
}
|
|
86
|
+
throw new Error('Semantic parity requires every node to expose an identity.');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function nodeSignature(node) {
|
|
90
|
+
return {
|
|
91
|
+
canonicalId: nodeCanonicalId(node),
|
|
92
|
+
sourceUri: normalizeSourceUri(node && node.sourceUri),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function endpointIdentity(rawEndpoint, rawUri, nodeById) {
|
|
97
|
+
const endpointId = rawEndpoint && typeof rawEndpoint === 'object'
|
|
98
|
+
? normalizeText(rawEndpoint.id)
|
|
99
|
+
: normalizeText(rawEndpoint);
|
|
100
|
+
const node = nodeById.get(endpointId) || nodeById.get(endpointId.toLowerCase());
|
|
101
|
+
const endpointUri = normalizeSourceUri(rawUri) || normalizeSourceUri(node && node.sourceUri);
|
|
102
|
+
const canonicalId = nodeCanonicalId(node) || canonicalIdFromSourceUri(rawUri);
|
|
103
|
+
if (canonicalId) {
|
|
104
|
+
return {
|
|
105
|
+
identity: `canonical:${canonicalId}`,
|
|
106
|
+
sourceUri: endpointUri,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
if (endpointUri) {
|
|
110
|
+
return {
|
|
111
|
+
identity: `uri:${endpointUri}`,
|
|
112
|
+
sourceUri: endpointUri,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (endpointId) {
|
|
116
|
+
return {
|
|
117
|
+
identity: `legacy:${endpointId.toLowerCase()}`,
|
|
118
|
+
sourceUri: '',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
throw new Error('Semantic parity requires every edge endpoint to resolve.');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function semanticEdge(rawEdge, nodeById) {
|
|
125
|
+
if (!rawEdge || typeof rawEdge !== 'object') {
|
|
126
|
+
throw new Error('Semantic parity requires every edge to be an object.');
|
|
127
|
+
}
|
|
128
|
+
const source = endpointIdentity(rawEdge.source || rawEdge.from, rawEdge.sourceUri, nodeById);
|
|
129
|
+
const target = endpointIdentity(rawEdge.target || rawEdge.to, rawEdge.targetUri, nodeById);
|
|
130
|
+
const type = normalizeText(rawEdge.type) || 'association';
|
|
131
|
+
const kind = normalizeText(rawEdge.kind).toLowerCase() || 'explicit';
|
|
132
|
+
const provenance = normalizeText(rawEdge.provenance) || type;
|
|
133
|
+
return {
|
|
134
|
+
source: source.identity,
|
|
135
|
+
target: target.identity,
|
|
136
|
+
sourceUri: source.sourceUri,
|
|
137
|
+
targetUri: target.sourceUri,
|
|
138
|
+
type,
|
|
139
|
+
kind,
|
|
140
|
+
provenance,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function edgeKey(edge) {
|
|
145
|
+
return [
|
|
146
|
+
edge.source,
|
|
147
|
+
edge.target,
|
|
148
|
+
edge.sourceUri,
|
|
149
|
+
edge.targetUri,
|
|
150
|
+
edge.type,
|
|
151
|
+
edge.kind,
|
|
152
|
+
edge.provenance,
|
|
153
|
+
].join('|');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function buildIndex(projection, side) {
|
|
157
|
+
if (!projection || typeof projection !== 'object') {
|
|
158
|
+
throw new Error(`${side} projection must be an object.`);
|
|
159
|
+
}
|
|
160
|
+
const nodes = Array.isArray(projection.nodes) ? projection.nodes : [];
|
|
161
|
+
const edges = Array.isArray(projection.edges) ? projection.edges : [];
|
|
162
|
+
const nodeByIdentity = new Map();
|
|
163
|
+
const nodeById = new Map();
|
|
164
|
+
nodes.forEach((node) => {
|
|
165
|
+
const identity = nodeIdentity(node);
|
|
166
|
+
if (nodeByIdentity.has(identity)) {
|
|
167
|
+
throw new Error(`${side} projection contains duplicate semantic node identity: ${identity}.`);
|
|
168
|
+
}
|
|
169
|
+
const id = normalizeText(node && node.id);
|
|
170
|
+
if (!id) {
|
|
171
|
+
throw new Error(`${side} projection contains a node without an id.`);
|
|
172
|
+
}
|
|
173
|
+
nodeByIdentity.set(identity, {
|
|
174
|
+
identity,
|
|
175
|
+
signature: nodeSignature(node),
|
|
176
|
+
});
|
|
177
|
+
nodeById.set(id, node);
|
|
178
|
+
nodeById.set(id.toLowerCase(), node);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const edgeByKey = new Map();
|
|
182
|
+
edges.forEach((edge) => {
|
|
183
|
+
const semantic = semanticEdge(edge, nodeById);
|
|
184
|
+
const key = edgeKey(semantic);
|
|
185
|
+
if (edgeByKey.has(key)) {
|
|
186
|
+
throw new Error(`${side} projection contains duplicate semantic edge: ${key}.`);
|
|
187
|
+
}
|
|
188
|
+
edgeByKey.set(key, semantic);
|
|
189
|
+
});
|
|
190
|
+
return { nodeByIdentity, edgeByKey };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function boundedDiagnostics(values) {
|
|
194
|
+
return values.sort().slice(0, MAX_DIAGNOSTICS);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function compareSemanticProjections(leftProjection, rightProjection) {
|
|
198
|
+
const left = buildIndex(leftProjection, 'left');
|
|
199
|
+
const right = buildIndex(rightProjection, 'right');
|
|
200
|
+
const missingNodes = [];
|
|
201
|
+
const extraNodes = [];
|
|
202
|
+
const nodeMismatches = [];
|
|
203
|
+
left.nodeByIdentity.forEach((leftNode, identity) => {
|
|
204
|
+
const rightNode = right.nodeByIdentity.get(identity);
|
|
205
|
+
if (!rightNode) {
|
|
206
|
+
missingNodes.push(identity);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (JSON.stringify(leftNode.signature) !== JSON.stringify(rightNode.signature)) {
|
|
210
|
+
nodeMismatches.push({ identity, left: leftNode.signature, right: rightNode.signature });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
right.nodeByIdentity.forEach((_rightNode, identity) => {
|
|
214
|
+
if (!left.nodeByIdentity.has(identity)) {
|
|
215
|
+
extraNodes.push(identity);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const missingEdges = [];
|
|
220
|
+
const extraEdges = [];
|
|
221
|
+
left.edgeByKey.forEach((_edge, key) => {
|
|
222
|
+
if (!right.edgeByKey.has(key)) {
|
|
223
|
+
missingEdges.push(key);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
right.edgeByKey.forEach((_edge, key) => {
|
|
227
|
+
if (!left.edgeByKey.has(key)) {
|
|
228
|
+
extraEdges.push(key);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
equal: missingNodes.length === 0
|
|
234
|
+
&& extraNodes.length === 0
|
|
235
|
+
&& nodeMismatches.length === 0
|
|
236
|
+
&& missingEdges.length === 0
|
|
237
|
+
&& extraEdges.length === 0,
|
|
238
|
+
left: { nodeCount: left.nodeByIdentity.size, edgeCount: left.edgeByKey.size },
|
|
239
|
+
right: { nodeCount: right.nodeByIdentity.size, edgeCount: right.edgeByKey.size },
|
|
240
|
+
missingNodes: boundedDiagnostics(missingNodes),
|
|
241
|
+
extraNodes: boundedDiagnostics(extraNodes),
|
|
242
|
+
nodeMismatches: nodeMismatches.slice(0, MAX_DIAGNOSTICS),
|
|
243
|
+
missingEdges: boundedDiagnostics(missingEdges),
|
|
244
|
+
extraEdges: boundedDiagnostics(extraEdges),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function assertSemanticParity(leftProjection, rightProjection, label) {
|
|
249
|
+
const comparison = compareSemanticProjections(leftProjection, rightProjection);
|
|
250
|
+
if (!comparison.equal) {
|
|
251
|
+
const prefix = label ? `${label}: ` : '';
|
|
252
|
+
const error = new Error(`${prefix}semantic projection parity failed: ${JSON.stringify(comparison)}`);
|
|
253
|
+
error.comparison = comparison;
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
return comparison;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return Object.freeze({
|
|
260
|
+
canonicalIdFromSourceUri,
|
|
261
|
+
compareSemanticProjections,
|
|
262
|
+
assertSemanticParity,
|
|
263
|
+
});
|
|
264
|
+
}));
|
|
@@ -171,8 +171,12 @@
|
|
|
171
171
|
<script src="libs/katex/katex.min.js"></script>
|
|
172
172
|
<script src="libs/katex/contrib/auto-render.min.js"></script>
|
|
173
173
|
<script src="libs/mermaid.min.js"></script>
|
|
174
|
-
|
|
175
|
-
|
|
174
|
+
<script src="runtime_bridge.js"></script>
|
|
175
|
+
<script src="knowledge_projection_contract.js"></script>
|
|
176
|
+
<script src="knowledge_projection_store.js"></script>
|
|
177
|
+
<script src="mobile_exact_analyzer.js"></script>
|
|
178
|
+
<script src="mobile_identity_contract.js"></script>
|
|
179
|
+
<script src="storage_provider.js"></script>
|
|
176
180
|
<script src="reader.js"></script>
|
|
177
181
|
|
|
178
182
|
<!-- Reading Window -->
|
|
@@ -46,12 +46,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
46
46
|
return /^https?:\/\/(?:127\.0\.0\.1|localhost):3000$/.test(origin);
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
const isTauriRuntime = typeof window !== 'undefined' && Boolean(window.__TAURI__);
|
|
50
|
+
const initialBrowserRuntimeBackend = canUseBrowserRuntimeBackend();
|
|
49
51
|
let runtimeCaps = {
|
|
50
52
|
platform: 'web',
|
|
51
|
-
supports_sidecar:
|
|
52
|
-
supports_build:
|
|
53
|
-
supports_content_api:
|
|
53
|
+
supports_sidecar: initialBrowserRuntimeBackend,
|
|
54
|
+
supports_build: initialBrowserRuntimeBackend,
|
|
55
|
+
supports_content_api: initialBrowserRuntimeBackend,
|
|
54
56
|
supports_kb_runtime_change: false,
|
|
57
|
+
supports_kb_import: false,
|
|
58
|
+
kb_import_mode: 'none',
|
|
59
|
+
supports_projection_store: true,
|
|
60
|
+
storage_requested_provider: isTauriRuntime || initialBrowserRuntimeBackend ? 'sqlite' : 'projection',
|
|
61
|
+
storage_resolved_provider: isTauriRuntime || initialBrowserRuntimeBackend ? 'unknown' : 'projection',
|
|
62
|
+
storage_fallback_reason: isTauriRuntime
|
|
63
|
+
? 'runtime_capability_unavailable'
|
|
64
|
+
: initialBrowserRuntimeBackend ? '' : 'runtime_backend_unavailable',
|
|
65
|
+
supports_sqlite: initialBrowserRuntimeBackend,
|
|
55
66
|
supports_native_pathmode: false,
|
|
56
67
|
supports_mobile_wasm_compute: false,
|
|
57
68
|
mobile_wasm_reason: 'non-mobile-runtime'
|
|
@@ -217,6 +228,25 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
217
228
|
return window.NoteConnectionStorage.createProvider({ runtimeCaps });
|
|
218
229
|
};
|
|
219
230
|
|
|
231
|
+
const refreshStorageResolution = async () => {
|
|
232
|
+
const provider = getStorageProvider();
|
|
233
|
+
if (!provider || typeof provider.refreshStorageResolution !== 'function') {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const resolution = await provider.refreshStorageResolution();
|
|
237
|
+
if (!resolution || typeof resolution !== 'object') {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
runtimeCaps = {
|
|
241
|
+
...runtimeCaps,
|
|
242
|
+
storage_requested_provider: resolution.requestedProvider,
|
|
243
|
+
storage_resolved_provider: resolution.resolvedProvider,
|
|
244
|
+
storage_fallback_reason: resolution.fallbackReason || '',
|
|
245
|
+
supports_sqlite: resolution.supportsSqlite === true,
|
|
246
|
+
};
|
|
247
|
+
exposeRuntimeCaps();
|
|
248
|
+
};
|
|
249
|
+
|
|
220
250
|
const resolveRuntimeCapabilities = async () => {
|
|
221
251
|
if (!window.__TAURI__) {
|
|
222
252
|
const capacitorPlatform = resolveCapacitorPlatform();
|
|
@@ -231,6 +261,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
231
261
|
supports_build: canBuildGraph,
|
|
232
262
|
supports_content_api: canReadContent,
|
|
233
263
|
supports_kb_runtime_change: false,
|
|
264
|
+
supports_kb_import: false,
|
|
265
|
+
kb_import_mode: 'app-local-only',
|
|
266
|
+
supports_projection_store: true,
|
|
267
|
+
storage_requested_provider: 'projection',
|
|
268
|
+
storage_resolved_provider: 'projection',
|
|
269
|
+
storage_fallback_reason: 'native_sqlite_runtime_unavailable',
|
|
270
|
+
supports_sqlite: false,
|
|
234
271
|
supports_native_pathmode: false,
|
|
235
272
|
supports_mobile_wasm_compute: mobileWasm.supported,
|
|
236
273
|
mobile_wasm_reason: mobileWasm.reason,
|
|
@@ -251,6 +288,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
251
288
|
supports_build: browserRuntimeBackend,
|
|
252
289
|
supports_content_api: browserRuntimeBackend,
|
|
253
290
|
supports_kb_runtime_change: false,
|
|
291
|
+
supports_kb_import: false,
|
|
292
|
+
kb_import_mode: 'none',
|
|
293
|
+
supports_projection_store: true,
|
|
294
|
+
storage_requested_provider: browserRuntimeBackend ? 'sqlite' : 'projection',
|
|
295
|
+
storage_resolved_provider: browserRuntimeBackend ? 'unknown' : 'projection',
|
|
296
|
+
storage_fallback_reason: browserRuntimeBackend ? '' : 'runtime_backend_unavailable',
|
|
297
|
+
supports_sqlite: browserRuntimeBackend,
|
|
254
298
|
supports_native_pathmode: false
|
|
255
299
|
};
|
|
256
300
|
if (!browserRuntimeBackend) {
|
|
@@ -313,6 +357,26 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
313
357
|
// 动态脚本加载器(缓存破坏与顺序保证)
|
|
314
358
|
const loadGraphDataFromSidecar = async (src) => {
|
|
315
359
|
const parseGraphDataPayload = (text) => {
|
|
360
|
+
const mobileRuntime = window.NoteConnectionMobileBudget && window.NoteConnectionMobileBudget.runtime;
|
|
361
|
+
if (mobileRuntime && Number.isInteger(mobileRuntime.maxProjectionBytes)) {
|
|
362
|
+
const payloadText = String(text || '');
|
|
363
|
+
const byteCounter = window.NoteConnectionStorage
|
|
364
|
+
&& typeof window.NoteConnectionStorage.measureUtf8Bytes === 'function'
|
|
365
|
+
? window.NoteConnectionStorage.measureUtf8Bytes
|
|
366
|
+
: null;
|
|
367
|
+
const payloadBytes = byteCounter
|
|
368
|
+
? byteCounter(payloadText)
|
|
369
|
+
: (typeof TextEncoder === 'function'
|
|
370
|
+
? new TextEncoder().encode(payloadText).length
|
|
371
|
+
: (typeof Buffer !== 'undefined' && typeof Buffer.byteLength === 'function'
|
|
372
|
+
? Buffer.byteLength(payloadText, 'utf8')
|
|
373
|
+
: payloadText.length));
|
|
374
|
+
if (payloadBytes > mobileRuntime.maxProjectionBytes) {
|
|
375
|
+
throw new Error(
|
|
376
|
+
`Mobile graph projection exceeds ${mobileRuntime.maxProjectionBytes} bytes.`
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
316
380
|
const trimmed = text.trim();
|
|
317
381
|
let parsed = null;
|
|
318
382
|
const extractAssignedJson = (sourceText, equalsIndex) => {
|
|
@@ -1081,6 +1145,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
1081
1145
|
if (window.__TAURI__ && runtimeCaps.supports_sidecar) {
|
|
1082
1146
|
await waitForSidecarReady();
|
|
1083
1147
|
}
|
|
1148
|
+
await refreshStorageResolution();
|
|
1084
1149
|
bootstrapScriptLoad();
|
|
1085
1150
|
|
|
1086
1151
|
if (window.i18n && window.i18n.isInitialized) {
|
|
@@ -1125,6 +1190,47 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
1125
1190
|
});
|
|
1126
1191
|
}
|
|
1127
1192
|
|
|
1193
|
+
const requestKnowledgeBasePathChange = async () => {
|
|
1194
|
+
try {
|
|
1195
|
+
const request = await window.__TAURI__.core.invoke('request_kb_path_change');
|
|
1196
|
+
if (typeof request === 'string') {
|
|
1197
|
+
return request;
|
|
1198
|
+
}
|
|
1199
|
+
const status = String(request && request.status || '').trim().toLowerCase();
|
|
1200
|
+
if (status === 'completed') {
|
|
1201
|
+
return String(request.path || '').trim();
|
|
1202
|
+
}
|
|
1203
|
+
if (status !== 'pending') {
|
|
1204
|
+
return '';
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
const deadline = Date.now() + 120000;
|
|
1208
|
+
while (Date.now() < deadline) {
|
|
1209
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1210
|
+
const result = await window.__TAURI__.core.invoke('poll_kb_path_change');
|
|
1211
|
+
const resultStatus = String(result && result.status || '').trim().toLowerCase();
|
|
1212
|
+
if (resultStatus === 'completed') {
|
|
1213
|
+
return String(result.path || '').trim();
|
|
1214
|
+
}
|
|
1215
|
+
if (resultStatus === 'cancelled') {
|
|
1216
|
+
return '';
|
|
1217
|
+
}
|
|
1218
|
+
if (resultStatus === 'failed' || resultStatus === 'unavailable') {
|
|
1219
|
+
const detail = String(result && result.detail || '').trim();
|
|
1220
|
+
throw new Error(detail || `Knowledge base picker ${resultStatus}.`);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
throw new Error('Timed out waiting for Android knowledge base import.');
|
|
1224
|
+
} catch (error) {
|
|
1225
|
+
// Older Tauri builds do not expose the additive request/poll commands.
|
|
1226
|
+
// Preserve their synchronous desktop picker contract as a fallback.
|
|
1227
|
+
if (/unknown command|not found|invalid command/i.test(String(error && error.message || error))) {
|
|
1228
|
+
return await window.__TAURI__.core.invoke('choose_kb_path');
|
|
1229
|
+
}
|
|
1230
|
+
throw error;
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1128
1234
|
if (changeKbPathBtn && window.__TAURI__) {
|
|
1129
1235
|
changeKbPathBtn.addEventListener('click', async () => {
|
|
1130
1236
|
if (!runtimeCaps.supports_kb_runtime_change) {
|
|
@@ -1136,7 +1242,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
1136
1242
|
if (resetKbPathBtn) resetKbPathBtn.disabled = true;
|
|
1137
1243
|
|
|
1138
1244
|
try {
|
|
1139
|
-
const selectedPath = await
|
|
1245
|
+
const selectedPath = await requestKnowledgeBasePathChange();
|
|
1140
1246
|
if (!selectedPath) {
|
|
1141
1247
|
return;
|
|
1142
1248
|
}
|