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
@@ -1566,17 +1566,9 @@ body.agent-workspace-open .agent-workspace-drawer {
1566
1566
  }
1567
1567
 
1568
1568
  .agent-chat-pane {
1569
- display: grid;
1570
- grid-template-rows:
1571
- auto
1572
- auto
1573
- auto
1574
- minmax(128px, 0.92fr)
1575
- minmax(128px, 0.62fr)
1576
- auto
1577
- auto
1578
- auto;
1579
- max-height: calc(100vh - 142px);
1569
+ display: flex;
1570
+ flex-direction: column;
1571
+ height: calc(100vh - 142px);
1580
1572
  padding: 16px;
1581
1573
  gap: 12px;
1582
1574
  overflow-x: hidden;
@@ -1585,6 +1577,10 @@ body.agent-workspace-open .agent-workspace-drawer {
1585
1577
  scrollbar-gutter: stable;
1586
1578
  }
1587
1579
 
1580
+ .agent-chat-pane > * {
1581
+ flex-shrink: 0;
1582
+ }
1583
+
1588
1584
  .agent-pane-header,
1589
1585
  .agent-workspace-pane-header {
1590
1586
  display: flex;
@@ -1683,6 +1679,101 @@ body.agent-workspace-open .agent-workspace-drawer {
1683
1679
  grid-column: 2;
1684
1680
  }
1685
1681
 
1682
+ .agent-answer-language-control {
1683
+ display: flex;
1684
+ align-items: center;
1685
+ gap: 8px;
1686
+ margin: 8px 0 12px;
1687
+ color: var(--text-secondary, #9aa4b2);
1688
+ font-size: 0.78rem;
1689
+ }
1690
+
1691
+ .agent-answer-language-control select {
1692
+ min-width: 108px;
1693
+ padding: 4px 8px;
1694
+ border: 1px solid var(--border-subtle, #3d4652);
1695
+ border-radius: 4px;
1696
+ background: var(--surface-input, #1c232d);
1697
+ color: var(--text-primary, #e8edf3);
1698
+ }
1699
+
1700
+ .agent-answer-language-summary {
1701
+ color: var(--text-muted, #758195);
1702
+ }
1703
+
1704
+ .agent-response-mode-control {
1705
+ display: flex;
1706
+ align-items: center;
1707
+ gap: 8px;
1708
+ margin: 8px 0 12px;
1709
+ color: var(--text-secondary, #9aa4b2);
1710
+ font-size: 0.78rem;
1711
+ }
1712
+
1713
+ .agent-response-mode-control select {
1714
+ min-width: 112px;
1715
+ padding: 4px 8px;
1716
+ border: 1px solid var(--border-subtle, #3d4652);
1717
+ border-radius: 4px;
1718
+ background: var(--surface-input, #1c232d);
1719
+ color: var(--text-primary, #e8edf3);
1720
+ }
1721
+
1722
+ .agent-response-mode-summary {
1723
+ color: var(--text-muted, #758195);
1724
+ overflow-wrap: anywhere;
1725
+ }
1726
+
1727
+ .agent-response-budget-control {
1728
+ display: flex;
1729
+ align-items: center;
1730
+ gap: 8px;
1731
+ margin: 8px 0 12px;
1732
+ color: var(--text-secondary, #9aa4b2);
1733
+ font-size: 0.78rem;
1734
+ }
1735
+
1736
+ .agent-response-budget-control select {
1737
+ min-width: 132px;
1738
+ padding: 4px 8px;
1739
+ border: 1px solid var(--border-subtle, #3d4652);
1740
+ border-radius: 4px;
1741
+ background: var(--surface-input, #1c232d);
1742
+ color: var(--text-primary, #e8edf3);
1743
+ }
1744
+
1745
+ .agent-response-budget-summary {
1746
+ color: var(--text-muted, #758195);
1747
+ overflow-wrap: anywhere;
1748
+ }
1749
+
1750
+ .agent-chat-structured-answer-next-actions-toggle {
1751
+ width: 26px;
1752
+ height: 26px;
1753
+ min-width: 26px;
1754
+ margin: 8px 0 0 auto;
1755
+ padding: 0;
1756
+ border: 1px solid var(--border-subtle, #3d4652);
1757
+ border-radius: 50%;
1758
+ background: var(--surface-raised, #252e3a);
1759
+ color: var(--text-primary, #e8edf3);
1760
+ cursor: pointer;
1761
+ line-height: 24px;
1762
+ text-align: center;
1763
+ }
1764
+
1765
+ .agent-chat-structured-answer-next-actions-toggle:hover,
1766
+ .agent-chat-structured-answer-next-actions-toggle:focus-visible {
1767
+ border-color: var(--accent, #6ea8fe);
1768
+ outline: none;
1769
+ }
1770
+
1771
+ .agent-chat-structured-answer-next-actions {
1772
+ margin-top: 8px;
1773
+ padding-top: 8px;
1774
+ border-top: 1px solid var(--border-subtle, #3d4652);
1775
+ }
1776
+
1686
1777
  .agent-pane-field label {
1687
1778
  color: #cbd5e1;
1688
1779
  font-size: 0.84rem;
@@ -1808,7 +1899,9 @@ body.agent-workspace-open .agent-workspace-drawer {
1808
1899
  }
1809
1900
 
1810
1901
  .agent-chat-messages {
1811
- min-height: 0;
1902
+ /* The transcript owns spare height even when optional controls are inserted. */
1903
+ flex: 1 0 240px;
1904
+ min-height: 128px;
1812
1905
  display: flex;
1813
1906
  flex-direction: column;
1814
1907
  gap: 10px;
@@ -2124,6 +2217,7 @@ body.agent-workspace-open .agent-workspace-drawer {
2124
2217
 
2125
2218
  .agent-knowledge-points {
2126
2219
  min-height: 0;
2220
+ max-height: min(200px, 24vh);
2127
2221
  display: flex;
2128
2222
  flex-direction: column;
2129
2223
  gap: 10px;
@@ -3603,7 +3697,7 @@ body[data-agent-workspace-promotion="learning-path"] #agent-learning-path-pane {
3603
3697
  }
3604
3698
 
3605
3699
  .agent-chat-pane {
3606
- max-height: none;
3700
+ height: auto;
3607
3701
  }
3608
3702
 
3609
3703
  .agent-side-work-area {
@@ -5673,6 +5673,50 @@
5673
5673
  `;
5674
5674
  }
5675
5675
 
5676
+ function buildEvidenceGraphAnswerPlanHtml(payload) {
5677
+ const plan = payload && payload.graphAnswerPlan && typeof payload.graphAnswerPlan === 'object'
5678
+ ? payload.graphAnswerPlan
5679
+ : null;
5680
+ const coverage = payload && payload.graphAnswerCoverage && typeof payload.graphAnswerCoverage === 'object'
5681
+ ? payload.graphAnswerCoverage
5682
+ : null;
5683
+ const expansion = payload && payload.graphExpansion && typeof payload.graphExpansion === 'object'
5684
+ ? payload.graphExpansion
5685
+ : null;
5686
+ if (!plan && !coverage && !expansion) return '';
5687
+ const requiredClaimIds = Array.isArray(coverage && coverage.requiredClaimIds) ? coverage.requiredClaimIds : [];
5688
+ const coveredClaimIds = Array.isArray(coverage && coverage.coveredClaimIds) ? coverage.coveredClaimIds : [];
5689
+ const missingRequiredClaimIds = Array.isArray(coverage && coverage.missingRequiredClaimIds)
5690
+ ? coverage.missingRequiredClaimIds
5691
+ : [];
5692
+ const omissions = Array.isArray(plan && plan.omittedCandidates) ? plan.omittedCandidates : [];
5693
+ const metrics = [
5694
+ {
5695
+ title: translate('agentWorkspace.evidence.graphAnswerIntentLabel', 'Intent / depth'),
5696
+ value: [String(plan && plan.intent || '').trim(), String(plan && plan.depth || '').trim()].filter(Boolean).join(' / ') || 'none',
5697
+ },
5698
+ {
5699
+ title: translate('agentWorkspace.evidence.graphAnswerCoverageLabel', 'Required claim coverage'),
5700
+ value: `${coveredClaimIds.length}/${requiredClaimIds.length} (${Number((Number(coverage && coverage.coverageScore || 0) * 100).toFixed(2))}%)`,
5701
+ },
5702
+ {
5703
+ title: translate('agentWorkspace.evidence.graphAnswerMissingLabel', 'Missing required claims'),
5704
+ value: missingRequiredClaimIds.join(', ') || 'none',
5705
+ },
5706
+ {
5707
+ title: translate('agentWorkspace.evidence.graphAnswerOmissionsLabel', 'Omitted graph candidates'),
5708
+ value: String(omissions.length),
5709
+ },
5710
+ {
5711
+ title: translate('agentWorkspace.evidence.graphExpansionLabel', 'Bounded expansion'),
5712
+ value: expansion
5713
+ ? `${String(expansion.executedSteps || 0)}/${String(expansion.maxSteps || 0)} steps; ${String(expansion.selectedNeighborCount || 0)}/${String(expansion.maxNeighbors || 0)} neighbors`
5714
+ : 'none',
5715
+ },
5716
+ ];
5717
+ return `<div class="agent-pane-section-title">${escapeHtml(translate('agentWorkspace.evidence.graphAnswerPlanLabel', 'Graph answer plan'))}</div><ul class="agent-pane-list">${buildEvidenceMetricListHtml(metrics)}</ul>`;
5718
+ }
5719
+
5676
5720
  function renderEvidenceGroundingBody(body, payload) {
5677
5721
  const title = String(
5678
5722
  payload.title
@@ -5703,6 +5747,7 @@
5703
5747
  const metricsHtml = buildEvidenceMetricListHtml(metrics);
5704
5748
  const ragContextHtml = buildEvidenceRagContextHtml(payload);
5705
5749
  const graphContextHtml = buildEvidenceGraphContextHtml(payload);
5750
+ const graphAnswerPlanHtml = buildEvidenceGraphAnswerPlanHtml(payload);
5706
5751
  body.innerHTML = `
5707
5752
  <div class="agent-pane-block">
5708
5753
  <div class="agent-pane-title">${escapeHtml(title)}</div>
@@ -5711,6 +5756,7 @@
5711
5756
  ${missMessage ? `<div class="agent-pane-section-title">${escapeHtml(translate('agentWorkspace.evidence.missLabel', 'Scope recovery'))}</div><div class="agent-pane-summary">${escapeHtml(missMessage)}</div>` : ''}
5712
5757
  ${ragContextHtml}
5713
5758
  ${graphContextHtml}
5759
+ ${graphAnswerPlanHtml}
5714
5760
  </div>
5715
5761
  `;
5716
5762
  }
@@ -9182,13 +9228,71 @@
9182
9228
  ).trim();
9183
9229
  wrapper.appendChild(title);
9184
9230
 
9185
- const directAnswer = String(block && block.directAnswer || '').trim();
9186
- if (directAnswer) {
9187
- const summary = document.createElement('div');
9188
- summary.className = 'agent-chat-inline-card-summary agent-chat-structured-answer-direct';
9189
- summary.textContent = directAnswer;
9190
- summary.setAttribute('data-structured-answer-section', 'directAnswer');
9191
- wrapper.appendChild(summary);
9231
+ const appendMarkdownSection = async function (sectionName, rawMarkdown, className) {
9232
+ const markdown = String(rawMarkdown || '').trim();
9233
+ if (!markdown) {
9234
+ return;
9235
+ }
9236
+ const section = document.createElement('div');
9237
+ section.className = className;
9238
+ section.setAttribute('data-structured-answer-section', sectionName);
9239
+ if (markdownRuntime && typeof markdownRuntime.renderMarkdownInto === 'function') {
9240
+ await markdownRuntime.renderMarkdownInto(section, markdown);
9241
+ } else {
9242
+ section.style.whiteSpace = 'pre-wrap';
9243
+ section.textContent = markdown;
9244
+ }
9245
+ wrapper.appendChild(section);
9246
+ };
9247
+
9248
+ await appendMarkdownSection(
9249
+ 'directAnswer',
9250
+ block && block.directAnswer,
9251
+ 'agent-chat-inline-card-summary agent-chat-structured-answer-direct agent-chat-structured-answer-markdown'
9252
+ );
9253
+ const nextActionsMarkdown = String(block && block.nextActionsMarkdown || '').trim();
9254
+ if (nextActionsMarkdown) {
9255
+ const nextActionsToggle = document.createElement('button');
9256
+ nextActionsToggle.type = 'button';
9257
+ nextActionsToggle.className = 'agent-chat-structured-answer-next-actions-toggle';
9258
+ nextActionsToggle.setAttribute('data-structured-answer-next-actions-toggle', 'true');
9259
+ const setNextActionsExpanded = function (expanded) {
9260
+ const label = expanded
9261
+ ? translate('agentWorkspace.reply.hideNextActions', 'Hide next actions')
9262
+ : translate('agentWorkspace.reply.showNextActions', 'Show next actions');
9263
+ nextActionsToggle.setAttribute('aria-expanded', expanded ? 'true' : 'false');
9264
+ nextActionsToggle.setAttribute('aria-label', label);
9265
+ nextActionsToggle.title = label;
9266
+ nextActionsToggle.textContent = expanded ? '-' : '+';
9267
+ };
9268
+ setNextActionsExpanded(false);
9269
+ nextActionsToggle.addEventListener('click', function () {
9270
+ const expanded = nextActionsToggle.getAttribute('aria-expanded') === 'true';
9271
+ if (expanded) {
9272
+ const existingPanel = wrapper.querySelector('[data-structured-answer-next-actions-panel]');
9273
+ existingPanel?.remove();
9274
+ setNextActionsExpanded(false);
9275
+ return;
9276
+ }
9277
+ const panel = document.createElement('div');
9278
+ panel.className = 'agent-chat-structured-answer-section agent-chat-structured-answer-next-actions';
9279
+ panel.setAttribute('data-structured-answer-next-actions-panel', 'true');
9280
+ panel.setAttribute('data-structured-answer-section', 'nextActionsMarkdown');
9281
+ wrapper.insertBefore(panel, nextActionsToggle);
9282
+ setNextActionsExpanded(true);
9283
+ if (markdownRuntime && typeof markdownRuntime.renderMarkdownInto === 'function') {
9284
+ Promise.resolve(markdownRuntime.renderMarkdownInto(panel, nextActionsMarkdown)).catch(function () {
9285
+ if (panel.parentNode === wrapper) {
9286
+ panel.remove();
9287
+ setNextActionsExpanded(false);
9288
+ }
9289
+ });
9290
+ } else {
9291
+ panel.style.whiteSpace = 'pre-wrap';
9292
+ panel.textContent = nextActionsMarkdown;
9293
+ }
9294
+ });
9295
+ wrapper.appendChild(nextActionsToggle);
9192
9296
  }
9193
9297
 
9194
9298
  return wrapper;
@@ -0,0 +1,81 @@
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 os = __importStar(require("os"));
38
+ const path = __importStar(require("path"));
39
+ describe('frontend runtime asset verifier', () => {
40
+ const repoRoot = path.resolve(__dirname, '..');
41
+ const verifierPath = path.join(repoRoot, 'scripts', 'verify-frontend-runtime-assets.js');
42
+ let tempDir;
43
+ beforeEach(() => {
44
+ tempDir = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'noteconnection-frontend-assets-'));
45
+ });
46
+ afterEach(() => {
47
+ fs.rmSync(tempDir, { recursive: true, force: true });
48
+ });
49
+ test('rejects an index that references a missing legacy runtime script', () => {
50
+ fs.writeFileSync(path.join(tempDir, 'index.html'), '<script src="markdown_runtime.js"></script><script src="workspace_panes.js"></script>', 'utf8');
51
+ fs.writeFileSync(path.join(tempDir, 'markdown_runtime.js'), 'window.runtime = true;', 'utf8');
52
+ const { verifyFrontendRuntimeAssets } = require(verifierPath);
53
+ expect(() => verifyFrontendRuntimeAssets(tempDir)).toThrow(/workspace_panes\.js/);
54
+ });
55
+ test('accepts an index when every local runtime script is present', () => {
56
+ fs.writeFileSync(path.join(tempDir, 'index.html'), '<script src="markdown_runtime.js"></script><script src="workspace_panes.js"></script><script src="https://example.invalid/remote.js"></script>', 'utf8');
57
+ fs.writeFileSync(path.join(tempDir, 'markdown_runtime.js'), 'window.runtime = true;', 'utf8');
58
+ fs.writeFileSync(path.join(tempDir, 'workspace_panes.js'), 'window.panes = true;', 'utf8');
59
+ const { verifyFrontendRuntimeAssets } = require(verifierPath);
60
+ expect(() => verifyFrontendRuntimeAssets(tempDir)).not.toThrow();
61
+ });
62
+ test('rejects an index that references a missing local stylesheet or module preload', () => {
63
+ fs.writeFileSync(path.join(tempDir, 'index.html'), '<link rel="stylesheet" href="styles.css"><link rel="modulepreload" href="assets/main.js"><script src="workspace_panes.js"></script>', 'utf8');
64
+ fs.writeFileSync(path.join(tempDir, 'workspace_panes.js'), 'window.panes = true;', 'utf8');
65
+ const { verifyFrontendRuntimeAssets } = require(verifierPath);
66
+ expect(() => verifyFrontendRuntimeAssets(tempDir)).toThrow(/styles\.css.*assets\/main\.js|assets\/main\.js.*styles\.css/);
67
+ });
68
+ test('cleans only stale Vite-owned bundle directories from the runtime destination', () => {
69
+ const copierPath = path.join(repoRoot, 'scripts', 'copy-assets.js');
70
+ fs.mkdirSync(path.join(tempDir, 'assets'), { recursive: true });
71
+ fs.mkdirSync(path.join(tempDir, 'vite-assets'), { recursive: true });
72
+ fs.writeFileSync(path.join(tempDir, 'assets', 'stale.js'), 'stale', 'utf8');
73
+ fs.writeFileSync(path.join(tempDir, 'vite-assets', 'stale.js'), 'stale', 'utf8');
74
+ fs.writeFileSync(path.join(tempDir, 'workspace_panes.js'), 'runtime', 'utf8');
75
+ const { cleanGeneratedFrontendBundleDirectories } = require(copierPath);
76
+ cleanGeneratedFrontendBundleDirectories(tempDir);
77
+ expect(fs.existsSync(path.join(tempDir, 'assets'))).toBe(false);
78
+ expect(fs.existsSync(path.join(tempDir, 'vite-assets'))).toBe(false);
79
+ expect(fs.readFileSync(path.join(tempDir, 'workspace_panes.js'), 'utf8')).toBe('runtime');
80
+ });
81
+ });
@@ -0,0 +1,72 @@
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
+ function extractFunctionBody(source, functionName) {
39
+ const functionStart = source.indexOf(`function ${functionName}(`);
40
+ if (functionStart < 0)
41
+ throw new Error(`Function not found: ${functionName}`);
42
+ const openBrace = source.indexOf('{', functionStart);
43
+ let depth = 0;
44
+ for (let index = openBrace; index < source.length; index += 1) {
45
+ if (source[index] === '{')
46
+ depth += 1;
47
+ if (source[index] === '}')
48
+ depth -= 1;
49
+ if (depth === 0)
50
+ return source.slice(openBrace, index + 1);
51
+ }
52
+ throw new Error(`Function body is incomplete: ${functionName}`);
53
+ }
54
+ describe('graph answer operator inspector contract', () => {
55
+ const frontendRoot = path.join(__dirname, 'frontend');
56
+ const workspaceSource = fs.readFileSync(path.join(frontendRoot, 'agent_workspace.js'), 'utf8');
57
+ const panesSource = fs.readFileSync(path.join(frontendRoot, 'workspace_panes.js'), 'utf8');
58
+ test('projects plan, coverage, and bounded expansion only through grounding diagnostics', () => {
59
+ expect(workspaceSource).toContain('graphAnswerPlan');
60
+ expect(workspaceSource).toContain('graphAnswerCoverage');
61
+ expect(workspaceSource).toContain('graphExpansion');
62
+ expect(panesSource).toContain('buildEvidenceGraphAnswerPlanHtml');
63
+ expect(panesSource).toContain("agentWorkspace.evidence.graphAnswerPlanLabel");
64
+ expect(panesSource).toContain('missingRequiredClaimIds');
65
+ expect(panesSource).toContain('executedSteps');
66
+ });
67
+ test('does not render plan scaffolding in the public assistant answer block', () => {
68
+ const answerRenderer = extractFunctionBody(workspaceSource, 'appendAssistantConversationResult');
69
+ expect(answerRenderer).not.toContain('graphAnswerPlan');
70
+ expect(answerRenderer).not.toContain('graphAnswerCoverage');
71
+ });
72
+ });
package/dist/src/index.js CHANGED
@@ -42,7 +42,7 @@ async function buildGraph(options, maxWorkers, enableGPU, enableGPULayout, memor
42
42
  const runtimePaths = (0, RuntimePaths_1.resolveRuntimePaths)(__dirname);
43
43
  const projectRoot = runtimePaths.projectRoot;
44
44
  const runtimeDataDir = runtimePaths.runtimeDataDir;
45
- let buildOptions = { projectRoot };
45
+ let buildOptions = { projectRoot, knowledgeBaseRoot: runtimePaths.kbRoot };
46
46
  if (typeof options === 'string') {
47
47
  // Legacy signature support
48
48
  buildOptions.targetPath = options;
@@ -54,7 +54,11 @@ async function buildGraph(options, maxWorkers, enableGPU, enableGPULayout, memor
54
54
  }
55
55
  else {
56
56
  // New object signature
57
- buildOptions = { ...options, projectRoot };
57
+ buildOptions = {
58
+ ...options,
59
+ projectRoot,
60
+ knowledgeBaseRoot: options.knowledgeBaseRoot ?? runtimePaths.kbRoot,
61
+ };
58
62
  // Map frontend 'target' to backend 'targetPath'
59
63
  // Frontend uses 'target', BuildOptions interface expects 'targetPath'
60
64
  if (options.target && !buildOptions.targetPath) {
@@ -0,0 +1,118 @@
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 os = __importStar(require("os"));
38
+ const path = __importStar(require("path"));
39
+ const index_1 = require("./index");
40
+ const config_1 = require("./backend/config");
41
+ const NoteConnection_1 = require("./core/NoteConnection");
42
+ describe('Graph builds in the selected knowledge workspace', () => {
43
+ const environmentKeys = [
44
+ 'NOTE_CONNECTION_PROJECT_ROOT',
45
+ 'NOTE_CONNECTION_KB_ROOT',
46
+ 'NOTE_CONNECTION_FRONTEND_DIR',
47
+ 'NOTE_CONNECTION_RUNTIME_DATA_DIR',
48
+ ];
49
+ const originalConfig = { ...config_1.config, exclusionList: [...config_1.config.exclusionList] };
50
+ let previousEnvironment;
51
+ let fixtureRoot;
52
+ let projectRoot;
53
+ let selectedRoot;
54
+ beforeEach(() => {
55
+ previousEnvironment = environmentKeys.map(key => process.env[key]);
56
+ fixtureRoot = fs.realpathSync.native(fs.mkdtempSync(path.join(os.tmpdir(), 'noteconnection-selected-kb-')));
57
+ projectRoot = path.join(fixtureRoot, 'application');
58
+ selectedRoot = path.join(fixtureRoot, 'selected-vault');
59
+ const frontendRoot = path.join(projectRoot, 'dist', 'src', 'frontend');
60
+ const runtimeRoot = path.join(fixtureRoot, 'runtime-data');
61
+ for (const directory of [path.join(projectRoot, 'Knowledge_Base'), path.join(selectedRoot, 'notes'), frontendRoot, runtimeRoot]) {
62
+ fs.mkdirSync(directory, { recursive: true });
63
+ }
64
+ fs.writeFileSync(path.join(projectRoot, 'Knowledge_Base', 'Default.md'), '# Default\nThis is a different workspace.');
65
+ fs.writeFileSync(path.join(selectedRoot, 'notes', 'Alpha.md'), '# Alpha\nAlpha requires [[Beta]].');
66
+ fs.writeFileSync(path.join(selectedRoot, 'notes', 'Beta.md'), '# Beta\nBeta is the prerequisite foundation.');
67
+ [projectRoot, selectedRoot, frontendRoot, runtimeRoot].forEach((directory, index) => {
68
+ process.env[environmentKeys[index]] = directory;
69
+ });
70
+ Object.assign(config_1.config, {
71
+ enableTags: false,
72
+ enableStatisticalInference: false,
73
+ enableVectorSimilarity: false,
74
+ enableHybridInference: false,
75
+ enableGPU: false,
76
+ enableGPULayout: false,
77
+ clusteringStrategy: 'folder',
78
+ maxWorkers: 1,
79
+ exclusionList: [],
80
+ });
81
+ });
82
+ afterEach(() => {
83
+ environmentKeys.forEach((key, index) => {
84
+ const previous = previousEnvironment[index];
85
+ if (previous === undefined)
86
+ delete process.env[key];
87
+ else
88
+ process.env[key] = previous;
89
+ });
90
+ Object.assign(config_1.config, originalConfig);
91
+ fs.rmSync(fixtureRoot, { recursive: true, force: true });
92
+ });
93
+ test('builds an absolute native target with identities relative to the selected workspace', async () => {
94
+ const graph = await (0, index_1.buildGraph)({ targetPath: path.join(selectedRoot, 'notes') });
95
+ expect(graph.nodes.map((node) => node.id).sort()).toEqual(['Alpha', 'Beta']);
96
+ expect(graph.nodes.find((node) => node.id === 'Alpha')).toEqual(expect.objectContaining({
97
+ canonicalId: 'notes/alpha',
98
+ sourceUri: 'note://workspace/v1/notes/alpha.md',
99
+ }));
100
+ });
101
+ test('resolves a relative CLI target against the selected workspace', async () => {
102
+ const graph = await (0, index_1.buildGraph)('notes');
103
+ expect(graph.nodes.map((node) => node.canonicalId).sort()).toEqual(['notes/alpha', 'notes/beta']);
104
+ });
105
+ test('builds the entire selected workspace without reading the application default', async () => {
106
+ const graph = await (0, index_1.buildGraph)({});
107
+ expect(graph.nodes.map((node) => node.id).sort()).toEqual(['Alpha', 'Beta']);
108
+ });
109
+ test('preserves the direct library default independently of runtime environment overrides', async () => {
110
+ const result = await NoteConnection_1.NoteConnection.build({ projectRoot });
111
+ expect(result.data.nodes.map((node) => node.id)).toEqual(['Default']);
112
+ });
113
+ test('accepts an explicit library knowledge root without moving the application root', async () => {
114
+ const result = await NoteConnection_1.NoteConnection.build({ projectRoot, knowledgeBaseRoot: selectedRoot, targetPath: 'notes' });
115
+ expect(result.stats.fileCount).toBe(2);
116
+ expect(result.data.nodes.map((node) => node.canonicalId).sort()).toEqual(['notes/alpha', 'notes/beta']);
117
+ });
118
+ });
@@ -109,6 +109,28 @@ class IndexLifecycle {
109
109
  });
110
110
  this.unitIdsByDocumentId.delete(String(documentId || '').trim());
111
111
  }
112
+ /**
113
+ * Moves the indexed path in place. Rebuilding units would allocate new
114
+ * segments and make a path-only identity transition look like content
115
+ * churn, so the existing index identity is deliberately preserved.
116
+ */
117
+ updateDocumentSourcePath(documentId, sourcePath, updatedAt) {
118
+ const unitIds = this.unitIdsByDocumentId.get(String(documentId || '').trim()) || [];
119
+ let updatedCount = 0;
120
+ unitIds.forEach((unitId) => {
121
+ const unit = this.units.get(unitId);
122
+ if (!unit) {
123
+ return;
124
+ }
125
+ this.units.set(unitId, {
126
+ ...unit,
127
+ sourcePath,
128
+ updatedAt,
129
+ });
130
+ updatedCount += 1;
131
+ });
132
+ return updatedCount;
133
+ }
112
134
  listSegmentsForAtom(atomId) {
113
135
  const segmentIds = this.segmentIdsByAtomId.get(String(atomId || '').trim()) || [];
114
136
  return segmentIds
@@ -46,4 +46,28 @@ describe('IndexLifecycle', () => {
46
46
  expect(lifecycle.hasIndexedSegmentsForAtom('atom_1')).toBe(false);
47
47
  expect(lifecycle.buildSummary().totalUnits).toBe(0);
48
48
  });
49
+ test('updates indexed source paths in place during a document move', () => {
50
+ let idCounter = 0;
51
+ const lifecycle = new IndexLifecycle_1.IndexLifecycle((prefix = 'index') => `${prefix}_${++idCounter}`, (value) => `hash_${value.length}`);
52
+ const indexed = lifecycle.syncDocumentIndex({
53
+ resourceId: 'resource_move',
54
+ projectionId: 'projection_move',
55
+ documentId: 'doc_move',
56
+ sourcePath: 'Knowledge_Base/old.md',
57
+ language: 'en',
58
+ workspaceId: 'workspace',
59
+ corpusId: 'corpus',
60
+ title: 'old',
61
+ content: '# Move\nContent',
62
+ atoms: [],
63
+ indexedAt: '2026-05-26T06:00:00.000Z',
64
+ });
65
+ expect(lifecycle.updateDocumentSourcePath('doc_move', 'Knowledge_Base/new.md', '2026-05-26T07:00:00.000Z')).toBe(indexed.units.length);
66
+ expect(lifecycle.listUnitsByProjectionIds(['projection_move'])).toEqual(expect.arrayContaining([
67
+ expect.objectContaining({
68
+ sourcePath: 'Knowledge_Base/new.md',
69
+ updatedAt: '2026-05-26T07:00:00.000Z',
70
+ }),
71
+ ]));
72
+ });
49
73
  });