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.
Files changed (195) hide show
  1. package/README.md +257 -1803
  2. package/dist/src/agent_workspace.contract.parity.test.js +105 -421
  3. package/dist/src/agent_workspace.frontend.test.js +410 -11
  4. package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
  5. package/dist/src/appimage.patchelf.test.js +113 -0
  6. package/dist/src/appimage.portability.test.js +156 -0
  7. package/dist/src/backend/FileLoader.js +18 -4
  8. package/dist/src/backend/FileLoader.test.js +125 -0
  9. package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
  10. package/dist/src/backend/GraphBuilder.js +66 -18
  11. package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
  12. package/dist/src/backend/GraphMetrics.js +0 -3
  13. package/dist/src/backend/ResourceIdentity.js +155 -0
  14. package/dist/src/backend/ResourceIdentity.test.js +113 -0
  15. package/dist/src/backend/algorithms/CycleDetection.js +0 -1
  16. package/dist/src/backend/algorithms/HybridEngine.js +0 -3
  17. package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
  18. package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
  19. package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
  20. package/dist/src/backend/build_dag.js +0 -1
  21. package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
  22. package/dist/src/capacitor.runtime.contract.test.js +11 -2
  23. package/dist/src/core/Graph.js +138 -42
  24. package/dist/src/core/Graph.test.js +74 -0
  25. package/dist/src/core/NoteConnection.js +2 -2
  26. package/dist/src/core/PathBridge.js +265 -2
  27. package/dist/src/core/ResourceReference.js +17 -0
  28. package/dist/src/desktop.godot.pack.test.js +142 -0
  29. package/dist/src/desktop.runtime.graph.test.js +66 -0
  30. package/dist/src/export/WorkspaceExportBundle.js +44 -0
  31. package/dist/src/export/WorkspaceExportBundle.test.js +61 -0
  32. package/dist/src/foundation.release.evidence.contract.test.js +127 -9
  33. package/dist/src/foundation.sqlite.runtime.contract.test.js +6 -0
  34. package/dist/src/frontend/README.md +257 -1803
  35. package/dist/src/frontend/agent_workspace.js +665 -7
  36. package/dist/src/frontend/index.html +31 -2
  37. package/dist/src/frontend/knowledge_projection_contract.js +230 -0
  38. package/dist/src/frontend/knowledge_projection_store.js +214 -0
  39. package/dist/src/frontend/libs/path_core.js +158 -42
  40. package/dist/src/frontend/locales/en.json +32 -0
  41. package/dist/src/frontend/locales/zh.json +32 -0
  42. package/dist/src/frontend/mobile_budget_runtime.js +33 -0
  43. package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
  44. package/dist/src/frontend/mobile_identity_contract.js +221 -0
  45. package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
  46. package/dist/src/frontend/path.html +6 -2
  47. package/dist/src/frontend/simulationWorker.js +1 -1
  48. package/dist/src/frontend/source_manager.js +110 -4
  49. package/dist/src/frontend/storage_provider.js +661 -71
  50. package/dist/src/frontend/styles.css +107 -13
  51. package/dist/src/frontend/workspace_panes.js +111 -7
  52. package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
  53. package/dist/src/graph.answer.operator.contract.test.js +72 -0
  54. package/dist/src/index.js +6 -2
  55. package/dist/src/index.knowledge-root.test.js +118 -0
  56. package/dist/src/indexing/IndexLifecycle.js +22 -0
  57. package/dist/src/indexing/IndexLifecycle.test.js +24 -0
  58. package/dist/src/knowledge.api.contract.test.js +4 -2
  59. package/dist/src/knowledge_projection.contract.test.js +134 -0
  60. package/dist/src/knowledge_projection_store.test.js +200 -0
  61. package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
  62. package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
  63. package/dist/src/learning/KnowledgeLearningPlatform.js +4687 -3892
  64. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +418 -0
  65. package/dist/src/learning/KnowledgeLearningPlatform.test.js +243 -6
  66. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +25 -1
  67. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +13 -5
  68. package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
  69. package/dist/src/learning/PublicAnswerContract.test.js +85 -0
  70. package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
  71. package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
  72. package/dist/src/learning/agentConversationExecution.js +211 -0
  73. package/dist/src/learning/agentConversationExecution.test.js +209 -0
  74. package/dist/src/learning/agentConversationSerialization.js +266 -0
  75. package/dist/src/learning/agentConversationSerialization.test.js +165 -0
  76. package/dist/src/learning/agentResponseBudget.js +179 -0
  77. package/dist/src/learning/agentResponseBudget.test.js +97 -0
  78. package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
  79. package/dist/src/learning/answerReleaseReview.js +1191 -250
  80. package/dist/src/learning/answerReleaseReview.test.js +1293 -7
  81. package/dist/src/learning/answerTaskPlan.js +473 -0
  82. package/dist/src/learning/conversationComposer.js +627 -386
  83. package/dist/src/learning/conversationComposer.test.js +1403 -0
  84. package/dist/src/learning/evidenceContextAssembler.js +312 -120
  85. package/dist/src/learning/graphAnswerCoverage.js +37 -0
  86. package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
  87. package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
  88. package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
  89. package/dist/src/learning/graphAnswerFacts.js +94 -0
  90. package/dist/src/learning/graphAnswerFacts.test.js +39 -0
  91. package/dist/src/learning/graphAnswerPlan.js +908 -0
  92. package/dist/src/learning/graphAnswerPlan.test.js +907 -0
  93. package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
  94. package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
  95. package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
  96. package/dist/src/learning/graphClaimMatcher.js +104 -0
  97. package/dist/src/learning/graphConditionedContext.js +109 -0
  98. package/dist/src/learning/graphConditionedContext.test.js +99 -0
  99. package/dist/src/learning/graphContextAssembler.js +3 -13
  100. package/dist/src/learning/graphContextAssembler.test.js +2 -2
  101. package/dist/src/learning/graphExpansionPolicy.js +22 -0
  102. package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
  103. package/dist/src/learning/identityMetadata.test.js +26 -0
  104. package/dist/src/learning/index.js +1 -0
  105. package/dist/src/learning/mobileAnswerProjection.js +104 -0
  106. package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
  107. package/dist/src/learning/queryBackend.js +34 -10
  108. package/dist/src/learning/queryBackend.test.js +21 -0
  109. package/dist/src/learning/ragContextPack.js +115 -16
  110. package/dist/src/learning/ragContextPack.test.js +151 -0
  111. package/dist/src/learning/ragEvidenceQuality.js +96 -0
  112. package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
  113. package/dist/src/learning/ragPublicText.js +67 -4
  114. package/dist/src/learning/ragPublicText.test.js +57 -0
  115. package/dist/src/learning/ragSufficiencyJudge.js +11 -1
  116. package/dist/src/learning/ragSufficiencyProviderJudge.js +16 -26
  117. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +51 -0
  118. package/dist/src/learning/requestNormalization.js +106 -0
  119. package/dist/src/learning/requestNormalization.test.js +101 -0
  120. package/dist/src/learning/store.js +116 -12
  121. package/dist/src/learning/store.test.js +299 -0
  122. package/dist/src/learning/vectorAccelerationAdapter.js +22 -6
  123. package/dist/src/learning/vectorAccelerationAdapter.test.js +30 -0
  124. package/dist/src/learning/workspaceHydration.js +168 -0
  125. package/dist/src/learning/workspaceHydration.test.js +30 -0
  126. package/dist/src/license.policy.contract.test.js +9 -4
  127. package/dist/src/markdown/MarkdownGateway.js +4 -0
  128. package/dist/src/markdown/MarkdownGateway.test.js +59 -0
  129. package/dist/src/middleware/SseResponseWriter.js +122 -0
  130. package/dist/src/middleware/SseResponseWriter.test.js +54 -0
  131. package/dist/src/middleware/auth.js +28 -7
  132. package/dist/src/middleware/auth.test.js +33 -0
  133. package/dist/src/middleware/index.js +2 -1
  134. package/dist/src/mobile.android.evidence.contract.test.js +146 -0
  135. package/dist/src/mobile.android.signing.contract.test.js +66 -0
  136. package/dist/src/mobile.artifact.contract.test.js +144 -0
  137. package/dist/src/mobile.budget.contract.test.js +90 -0
  138. package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
  139. package/dist/src/mobile.graph.parity.contract.test.js +207 -0
  140. package/dist/src/mobile.identity.contract.test.js +66 -0
  141. package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
  142. package/dist/src/mobile.identity.corpus.test.js +40 -0
  143. package/dist/src/mobile.native.recovery.contract.test.js +64 -0
  144. package/dist/src/mobile.pipeline.test.js +11 -1
  145. package/dist/src/mobile.profile.contract.test.js +225 -0
  146. package/dist/src/mobile.semantic.parity.test.js +92 -0
  147. package/dist/src/mobile_exact_analyzer.test.js +113 -0
  148. package/dist/src/notemd/ContentGenerator.js +4 -9
  149. package/dist/src/notemd/FileProcessor.js +4 -9
  150. package/dist/src/notemd/NotemdService.js +12 -17
  151. package/dist/src/notemd/Translator.js +4 -9
  152. package/dist/src/notemd/progressReporter.js +9 -0
  153. package/dist/src/notemd.server.integration.test.js +119 -4
  154. package/dist/src/notemd.workflow.pipeline.test.js +1 -1
  155. package/dist/src/pathbridge.handshake.contract.test.js +29 -0
  156. package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
  157. package/dist/src/pathcore.bundle.contract.test.js +8 -0
  158. package/dist/src/platform/ExportProfile.js +28 -0
  159. package/dist/src/platform/MobileBudget.js +11 -0
  160. package/dist/src/platform/PlatformCapabilities.js +14 -0
  161. package/dist/src/platform/PlatformCapabilities.test.js +6 -0
  162. package/dist/src/query_backend.external_http.integration.test.js +2 -2
  163. package/dist/src/release.godot.mirror.contract.test.js +28 -4
  164. package/dist/src/resources/ResourceRegistry.js +40 -0
  165. package/dist/src/resources/ResourceRegistry.test.js +36 -0
  166. package/dist/src/routes/index.js +0 -4
  167. package/dist/src/routes/knowledge.js +46 -33
  168. package/dist/src/routes/knowledgePayload.js +185 -0
  169. package/dist/src/routes/knowledgePayload.test.js +53 -0
  170. package/dist/src/routes/markdown.js +8 -0
  171. package/dist/src/routes/notemd.js +990 -234
  172. package/dist/src/routes/registry.contract.test.js +5 -2
  173. package/dist/src/routes/registry.shadow.contract.test.js +22 -0
  174. package/dist/src/routes/render.js +14 -51
  175. package/dist/src/runtime.capabilities.test.js +18 -2
  176. package/dist/src/server.js +566 -1090
  177. package/dist/src/server.migration.test.js +417 -15
  178. package/dist/src/sidecar.build.lock.contract.test.js +201 -0
  179. package/dist/src/sidecar.freshness.contract.test.js +184 -0
  180. package/dist/src/sidecar.replacement.boundary.contract.test.js +6 -3
  181. package/dist/src/sidecar.supply.readiness.contract.test.js +11 -0
  182. package/dist/src/simulation.worker.offline.test.js +104 -0
  183. package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
  184. package/dist/src/storage.provider.contract.test.js +152 -1
  185. package/dist/src/tauri.frontend.build.contract.test.js +8 -0
  186. package/dist/src/tauri.window.evidence.execution.test.js +68 -0
  187. package/dist/src/utils/RuntimePaths.js +6 -0
  188. package/dist/src/utils/RuntimePaths.test.js +27 -0
  189. package/dist/src/windows.installer.build.test.js +109 -0
  190. package/dist/src/windows.installer.payload.test.js +76 -0
  191. package/dist/src/windows.installer.runtime.test.js +69 -0
  192. package/dist/src/workspace/WorkspaceRegistry.js +13 -0
  193. package/package.json +32 -10
  194. package/dist/src/routes/data.js +0 -267
  195. 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
- <script src="runtime_bridge.js"></script>
175
- <script src="storage_provider.js"></script>
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 -->
@@ -1,4 +1,4 @@
1
- importScripts("https://d3js.org/d3.v6.min.js", "libs/gpu-browser.min.js", "layout_gpu.js");
1
+ importScripts("libs/d3.v7.min.js", "libs/gpu-browser.min.js", "layout_gpu.js");
2
2
 
3
3
  let simulation;
4
4
  let nodes = [];
@@ -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: canUseBrowserRuntimeBackend(),
52
- supports_build: canUseBrowserRuntimeBackend(),
53
- supports_content_api: canUseBrowserRuntimeBackend(),
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 window.__TAURI__.core.invoke('choose_kb_path');
1245
+ const selectedPath = await requestKnowledgeBasePathChange();
1140
1246
  if (!selectedPath) {
1141
1247
  return;
1142
1248
  }