noteconnection 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/LICENSE +674 -21
  2. package/README.md +260 -1626
  3. package/dist/src/agent_workspace.contract.parity.test.js +159 -0
  4. package/dist/src/agent_workspace.frontend.test.js +10388 -0
  5. package/dist/src/agent_workspace.locale.contract.test.js +95 -0
  6. package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
  7. package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
  8. package/dist/src/appimage.patchelf.test.js +113 -0
  9. package/dist/src/appimage.portability.test.js +156 -0
  10. package/dist/src/backend/FileLoader.js +18 -4
  11. package/dist/src/backend/FileLoader.test.js +125 -0
  12. package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
  13. package/dist/src/backend/GraphBuilder.js +66 -18
  14. package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
  15. package/dist/src/backend/GraphMetrics.js +0 -3
  16. package/dist/src/backend/ResourceIdentity.js +155 -0
  17. package/dist/src/backend/ResourceIdentity.test.js +113 -0
  18. package/dist/src/backend/algorithms/CycleDetection.js +0 -1
  19. package/dist/src/backend/algorithms/HybridEngine.js +0 -3
  20. package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
  21. package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
  22. package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
  23. package/dist/src/backend/build_dag.js +0 -1
  24. package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
  25. package/dist/src/capacitor.runtime.contract.test.js +11 -2
  26. package/dist/src/copy.assets.contract.test.js +130 -0
  27. package/dist/src/core/Graph.js +138 -42
  28. package/dist/src/core/Graph.test.js +74 -0
  29. package/dist/src/core/NoteConnection.js +2 -2
  30. package/dist/src/core/PathBridge.js +293 -5
  31. package/dist/src/core/ResourceReference.js +17 -0
  32. package/dist/src/desktop.godot.pack.test.js +142 -0
  33. package/dist/src/desktop.runtime.graph.test.js +66 -0
  34. package/dist/src/export/WorkspaceExportBundle.js +1174 -0
  35. package/dist/src/export/WorkspaceExportBundle.test.js +1541 -0
  36. package/dist/src/export/index.js +18 -0
  37. package/dist/src/export/types.js +2 -0
  38. package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
  39. package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
  40. package/dist/src/foundation.release.evidence.contract.test.js +524 -0
  41. package/dist/src/foundation.sqlite.runtime.contract.test.js +88 -0
  42. package/dist/src/frontend/README.md +260 -1626
  43. package/dist/src/frontend/agent_workspace.js +6011 -0
  44. package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
  45. package/dist/src/frontend/analysis.js +31 -4
  46. package/dist/src/frontend/app.js +2178 -62
  47. package/dist/src/frontend/focus_mode_interactions.js +33 -0
  48. package/dist/src/frontend/godot_future_path_renderer.js +540 -0
  49. package/dist/src/frontend/godot_tree_interactions.js +178 -0
  50. package/dist/src/frontend/graph_state.mjs +105 -0
  51. package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
  52. package/dist/src/frontend/i18n.mjs +186 -0
  53. package/dist/src/frontend/index.html +672 -268
  54. package/dist/src/frontend/knowledge_projection_contract.js +230 -0
  55. package/dist/src/frontend/knowledge_projection_store.js +214 -0
  56. package/dist/src/frontend/layout_gpu.js +12 -4
  57. package/dist/src/frontend/libs/path_core.js +158 -42
  58. package/dist/src/frontend/locales/en.json +753 -5
  59. package/dist/src/frontend/locales/zh.json +753 -5
  60. package/dist/src/frontend/main.mjs +60 -0
  61. package/dist/src/frontend/markdown_runtime.js +827 -0
  62. package/dist/src/frontend/mobile_budget_runtime.js +33 -0
  63. package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
  64. package/dist/src/frontend/mobile_identity_contract.js +221 -0
  65. package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
  66. package/dist/src/frontend/notemd.css +49 -0
  67. package/dist/src/frontend/notemd.html +7 -1
  68. package/dist/src/frontend/notemd.js +64 -0
  69. package/dist/src/frontend/path.html +113 -2
  70. package/dist/src/frontend/path_app.js +2108 -130
  71. package/dist/src/frontend/path_layout.mjs +143 -0
  72. package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
  73. package/dist/src/frontend/path_modules_bridge.js +486 -0
  74. package/dist/src/frontend/path_state.mjs +118 -0
  75. package/dist/src/frontend/path_styles.css +146 -0
  76. package/dist/src/frontend/path_worker_bridge.mjs +85 -0
  77. package/dist/src/frontend/reader.js +393 -33
  78. package/dist/src/frontend/runtime_bridge.js +67 -54
  79. package/dist/src/frontend/runtime_bridge.mjs +279 -0
  80. package/dist/src/frontend/settings.js +130 -12
  81. package/dist/src/frontend/simulationWorker.js +1 -1
  82. package/dist/src/frontend/source_manager.js +297 -22
  83. package/dist/src/frontend/storage_provider.js +661 -71
  84. package/dist/src/frontend/styles.css +2814 -72
  85. package/dist/src/frontend/workbench_state.mjs +101 -0
  86. package/dist/src/frontend/workspace_panes.js +10272 -0
  87. package/dist/src/frontend.locale.contract.test.js +62 -0
  88. package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
  89. package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
  90. package/dist/src/graph.answer.operator.contract.test.js +72 -0
  91. package/dist/src/index.js +6 -2
  92. package/dist/src/index.knowledge-root.test.js +118 -0
  93. package/dist/src/indexing/IndexLifecycle.js +217 -0
  94. package/dist/src/indexing/IndexLifecycle.test.js +73 -0
  95. package/dist/src/indexing/SegmentBuilder.js +64 -0
  96. package/dist/src/indexing/UnitBuilder.js +48 -0
  97. package/dist/src/indexing/types.js +2 -0
  98. package/dist/src/knowledge.api.contract.test.js +172 -0
  99. package/dist/src/knowledge_projection.contract.test.js +134 -0
  100. package/dist/src/knowledge_projection_store.test.js +200 -0
  101. package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
  102. package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
  103. package/dist/src/learning/KnowledgeLearningPlatform.js +11181 -0
  104. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +745 -0
  105. package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
  106. package/dist/src/learning/KnowledgeLearningPlatform.test.js +3208 -0
  107. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2998 -0
  108. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3936 -0
  109. package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
  110. package/dist/src/learning/PublicAnswerContract.test.js +85 -0
  111. package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
  112. package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
  113. package/dist/src/learning/agentConversationExecution.js +211 -0
  114. package/dist/src/learning/agentConversationExecution.test.js +209 -0
  115. package/dist/src/learning/agentConversationSerialization.js +266 -0
  116. package/dist/src/learning/agentConversationSerialization.test.js +165 -0
  117. package/dist/src/learning/agentResponseBudget.js +179 -0
  118. package/dist/src/learning/agentResponseBudget.test.js +97 -0
  119. package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
  120. package/dist/src/learning/answerReleaseReview.js +5260 -0
  121. package/dist/src/learning/answerReleaseReview.test.js +4174 -0
  122. package/dist/src/learning/answerTaskPlan.js +473 -0
  123. package/dist/src/learning/api.js +2 -0
  124. package/dist/src/learning/conversationComposer.js +1721 -0
  125. package/dist/src/learning/conversationComposer.test.js +3220 -0
  126. package/dist/src/learning/domains/ConversationManager.js +53 -0
  127. package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
  128. package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
  129. package/dist/src/learning/domains/MasteryEngine.js +387 -0
  130. package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
  131. package/dist/src/learning/domains/QualityEvaluator.js +307 -0
  132. package/dist/src/learning/domains/TutorRouter.js +313 -0
  133. package/dist/src/learning/domains/index.js +33 -0
  134. package/dist/src/learning/domains/types.js +7 -0
  135. package/dist/src/learning/errors.js +29 -0
  136. package/dist/src/learning/evidenceContextAssembler.js +1368 -0
  137. package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
  138. package/dist/src/learning/graphAnswerCoverage.js +37 -0
  139. package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
  140. package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
  141. package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
  142. package/dist/src/learning/graphAnswerFacts.js +94 -0
  143. package/dist/src/learning/graphAnswerFacts.test.js +39 -0
  144. package/dist/src/learning/graphAnswerPlan.js +908 -0
  145. package/dist/src/learning/graphAnswerPlan.test.js +907 -0
  146. package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
  147. package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
  148. package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
  149. package/dist/src/learning/graphClaimMatcher.js +104 -0
  150. package/dist/src/learning/graphConditionedContext.js +109 -0
  151. package/dist/src/learning/graphConditionedContext.test.js +99 -0
  152. package/dist/src/learning/graphContextAssembler.js +860 -0
  153. package/dist/src/learning/graphContextAssembler.test.js +1033 -0
  154. package/dist/src/learning/graphExpansionPolicy.js +22 -0
  155. package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
  156. package/dist/src/learning/identityMetadata.test.js +26 -0
  157. package/dist/src/learning/index.js +29 -0
  158. package/dist/src/learning/mobileAnswerProjection.js +104 -0
  159. package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
  160. package/dist/src/learning/queryBackend.js +1922 -0
  161. package/dist/src/learning/queryBackend.test.js +976 -0
  162. package/dist/src/learning/ragContextPack.js +356 -0
  163. package/dist/src/learning/ragContextPack.test.js +311 -0
  164. package/dist/src/learning/ragEvidenceQuality.js +96 -0
  165. package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
  166. package/dist/src/learning/ragPublicText.js +101 -0
  167. package/dist/src/learning/ragPublicText.test.js +57 -0
  168. package/dist/src/learning/ragSufficiencyJudge.js +171 -0
  169. package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
  170. package/dist/src/learning/ragSufficiencyProviderJudge.js +217 -0
  171. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +207 -0
  172. package/dist/src/learning/requestNormalization.js +304 -0
  173. package/dist/src/learning/requestNormalization.test.js +101 -0
  174. package/dist/src/learning/runtimeCapability.js +4677 -0
  175. package/dist/src/learning/runtimeCapability.test.js +3635 -0
  176. package/dist/src/learning/store.js +1344 -0
  177. package/dist/src/learning/store.test.js +1425 -0
  178. package/dist/src/learning/tutorAdapter.js +2 -0
  179. package/dist/src/learning/types.js +2 -0
  180. package/dist/src/learning/vectorAccelerationAdapter.js +958 -0
  181. package/dist/src/learning/vectorAccelerationAdapter.test.js +412 -0
  182. package/dist/src/learning/workspaceHydration.js +168 -0
  183. package/dist/src/learning/workspaceHydration.test.js +30 -0
  184. package/dist/src/lfs.asset.policy.contract.test.js +153 -0
  185. package/dist/src/license.policy.contract.test.js +71 -0
  186. package/dist/src/markdown/MarkdownGateway.js +4 -0
  187. package/dist/src/markdown/MarkdownGateway.test.js +59 -0
  188. package/dist/src/memory/MemoryGovernance.js +74 -0
  189. package/dist/src/memory/MemoryGovernance.test.js +46 -0
  190. package/dist/src/memory/types.js +2 -0
  191. package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
  192. package/dist/src/middleware/SseResponseWriter.js +122 -0
  193. package/dist/src/middleware/SseResponseWriter.test.js +54 -0
  194. package/dist/src/middleware/auth.js +38 -0
  195. package/dist/src/middleware/auth.test.js +33 -0
  196. package/dist/src/middleware/body-parser.js +45 -0
  197. package/dist/src/middleware/cors.js +44 -0
  198. package/dist/src/middleware/index.js +22 -0
  199. package/dist/src/middleware/request-trace.js +96 -0
  200. package/dist/src/mobile.android.evidence.contract.test.js +146 -0
  201. package/dist/src/mobile.android.signing.contract.test.js +66 -0
  202. package/dist/src/mobile.artifact.contract.test.js +144 -0
  203. package/dist/src/mobile.budget.contract.test.js +90 -0
  204. package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
  205. package/dist/src/mobile.graph.parity.contract.test.js +207 -0
  206. package/dist/src/mobile.identity.contract.test.js +66 -0
  207. package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
  208. package/dist/src/mobile.identity.corpus.test.js +40 -0
  209. package/dist/src/mobile.native.recovery.contract.test.js +64 -0
  210. package/dist/src/mobile.pipeline.test.js +11 -1
  211. package/dist/src/mobile.profile.contract.test.js +225 -0
  212. package/dist/src/mobile.semantic.parity.test.js +92 -0
  213. package/dist/src/mobile_exact_analyzer.test.js +113 -0
  214. package/dist/src/notemd/AppConfigToml.js +6 -4
  215. package/dist/src/notemd/ContentGenerator.js +4 -9
  216. package/dist/src/notemd/FileProcessor.js +4 -9
  217. package/dist/src/notemd/MermaidProcessor.js +400 -50
  218. package/dist/src/notemd/NotemdService.js +506 -26
  219. package/dist/src/notemd/PromptManager.js +15 -0
  220. package/dist/src/notemd/Translator.js +4 -9
  221. package/dist/src/notemd/cli/commands.js +357 -0
  222. package/dist/src/notemd/cli/dispatcher.js +225 -0
  223. package/dist/src/notemd/cli/index.js +169 -0
  224. package/dist/src/notemd/cli/parser.js +68 -0
  225. package/dist/src/notemd/cli/types.js +2 -0
  226. package/dist/src/notemd/constants.js +43 -0
  227. package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
  228. package/dist/src/notemd/diagram/diagramSpec.js +79 -0
  229. package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
  230. package/dist/src/notemd/diagram/intent.js +95 -0
  231. package/dist/src/notemd/diagram/planner.js +71 -0
  232. package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
  233. package/dist/src/notemd/diagram/types.js +18 -0
  234. package/dist/src/notemd/index.js +26 -0
  235. package/dist/src/notemd/operations/capabilityManifest.js +23 -0
  236. package/dist/src/notemd/operations/cliContracts.js +17 -0
  237. package/dist/src/notemd/operations/configProfileCommands.js +85 -0
  238. package/dist/src/notemd/operations/registry.contract.test.js +95 -0
  239. package/dist/src/notemd/operations/registry.js +991 -0
  240. package/dist/src/notemd/operations/types.js +2 -0
  241. package/dist/src/notemd/progressReporter.js +9 -0
  242. package/dist/src/notemd/providerDiagnostics.js +220 -0
  243. package/dist/src/notemd/providerProfiles.js +42 -0
  244. package/dist/src/notemd/providerTemplates.js +231 -0
  245. package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
  246. package/dist/src/notemd/search/SearchManager.js +13 -0
  247. package/dist/src/notemd/search/SearchProvider.js +2 -0
  248. package/dist/src/notemd/search/TavilyProvider.js +44 -0
  249. package/dist/src/notemd.agent.manifest.test.js +85 -0
  250. package/dist/src/notemd.api.contract.test.js +14 -1
  251. package/dist/src/notemd.app_config_toml.test.js +2 -1
  252. package/dist/src/notemd.batch.workflow.test.js +117 -0
  253. package/dist/src/notemd.cli.e2e.test.js +136 -0
  254. package/dist/src/notemd.core.test.js +51 -0
  255. package/dist/src/notemd.diagram.pipeline.test.js +233 -0
  256. package/dist/src/notemd.providerTemplates.test.js +34 -0
  257. package/dist/src/notemd.server.integration.test.js +262 -39
  258. package/dist/src/notemd.workflow.pipeline.test.js +162 -0
  259. package/dist/src/pathbridge.handshake.contract.test.js +45 -2
  260. package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
  261. package/dist/src/pathcore.bundle.contract.test.js +8 -0
  262. package/dist/src/pathmode.background.contract.test.js +69 -0
  263. package/dist/src/pathmode.settings.api.contract.test.js +9 -0
  264. package/dist/src/pkg.sidecar.contract.test.js +9 -3
  265. package/dist/src/platform/ExportProfile.js +86 -0
  266. package/dist/src/platform/MobileBudget.js +11 -0
  267. package/dist/src/platform/PlatformCapabilities.js +59 -0
  268. package/dist/src/platform/PlatformCapabilities.test.js +36 -0
  269. package/dist/src/platform/RenderMaterializer.js +33 -0
  270. package/dist/src/platform/RenderMaterializer.test.js +32 -0
  271. package/dist/src/query_backend.external_http.integration.test.js +410 -0
  272. package/dist/src/reader_renderer.js +404 -3
  273. package/dist/src/reader_renderer.test.js +87 -0
  274. package/dist/src/release.godot.mirror.contract.test.js +97 -0
  275. package/dist/src/resources/ResourceRegistry.js +263 -0
  276. package/dist/src/resources/ResourceRegistry.test.js +97 -0
  277. package/dist/src/resources/types.js +2 -0
  278. package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
  279. package/dist/src/routes/index.js +19 -0
  280. package/dist/src/routes/knowledge.js +981 -0
  281. package/dist/src/routes/knowledgePayload.js +185 -0
  282. package/dist/src/routes/knowledgePayload.test.js +53 -0
  283. package/dist/src/routes/markdown.js +295 -0
  284. package/dist/src/routes/notemd.js +1321 -0
  285. package/dist/src/routes/registry.contract.test.js +133 -0
  286. package/dist/src/routes/registry.shadow.contract.test.js +22 -0
  287. package/dist/src/routes/render.js +248 -0
  288. package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
  289. package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
  290. package/dist/src/routes/settings.js +6 -0
  291. package/dist/src/routes/staticFiles.js +94 -0
  292. package/dist/src/routes/types.js +2 -0
  293. package/dist/src/runtime.capabilities.test.js +18 -2
  294. package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
  295. package/dist/src/server.js +10342 -1325
  296. package/dist/src/server.migration.test.js +584 -10
  297. package/dist/src/server.port.fallback.contract.test.js +63 -0
  298. package/dist/src/session/SessionStateStore.js +81 -0
  299. package/dist/src/session/SessionStateStore.test.js +58 -0
  300. package/dist/src/session/types.js +2 -0
  301. package/dist/src/settings.runtime.contract.test.js +50 -0
  302. package/dist/src/shared/types.contract.test.js +107 -0
  303. package/dist/src/shared/types.js +22 -0
  304. package/dist/src/sidecar.build.lock.contract.test.js +201 -0
  305. package/dist/src/sidecar.freshness.contract.test.js +184 -0
  306. package/dist/src/sidecar.replacement.boundary.contract.test.js +131 -0
  307. package/dist/src/sidecar.supply.readiness.contract.test.js +155 -0
  308. package/dist/src/simulation.worker.offline.test.js +104 -0
  309. package/dist/src/source_manager.loadflow.test.js +46 -0
  310. package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
  311. package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
  312. package/dist/src/storage.provider.contract.test.js +152 -1
  313. package/dist/src/tauri.frontend.build.contract.test.js +68 -0
  314. package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
  315. package/dist/src/tauri.window.evidence.execution.test.js +68 -0
  316. package/dist/src/utils/RuntimePaths.js +10 -13
  317. package/dist/src/utils/RuntimePaths.test.js +27 -0
  318. package/dist/src/utils/platform.js +153 -0
  319. package/dist/src/windows.installer.build.test.js +109 -0
  320. package/dist/src/windows.installer.payload.test.js +76 -0
  321. package/dist/src/windows.installer.runtime.test.js +69 -0
  322. package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
  323. package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
  324. package/dist/src/workflows/types.js +2 -0
  325. package/dist/src/workspace/WorkspaceRegistry.js +135 -0
  326. package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
  327. package/dist/src/workspace/types.js +2 -0
  328. package/package.json +80 -15
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KnowledgePayloadError = void 0;
4
+ exports.parseKnowledgeIngestBody = parseKnowledgeIngestBody;
5
+ const MAX_DOCUMENTS_PER_REQUEST = 5000;
6
+ const MAX_ALIASES_PER_DOCUMENT = 64;
7
+ const MAX_ALIAS_LENGTH = 2048;
8
+ const MAX_CONTENT_BYTES = 64 * 1024 * 1024;
9
+ class KnowledgePayloadError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.statusCode = 400;
13
+ this.code = 'invalid_knowledge_payload';
14
+ this.name = 'KnowledgePayloadError';
15
+ }
16
+ }
17
+ exports.KnowledgePayloadError = KnowledgePayloadError;
18
+ function isRecord(value) {
19
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value));
20
+ }
21
+ function firstString(record, keys) {
22
+ for (const key of keys) {
23
+ const value = record[key];
24
+ if (typeof value === 'string' && value.trim().length > 0) {
25
+ return value.trim();
26
+ }
27
+ }
28
+ return undefined;
29
+ }
30
+ function firstValue(record, keys) {
31
+ for (const key of keys) {
32
+ if (Object.prototype.hasOwnProperty.call(record, key)) {
33
+ return record[key];
34
+ }
35
+ }
36
+ return undefined;
37
+ }
38
+ function normalizeStringArray(value, field) {
39
+ if (value === undefined || value === null) {
40
+ return [];
41
+ }
42
+ if (!Array.isArray(value)) {
43
+ throw new KnowledgePayloadError(`${field} must be an array of strings.`);
44
+ }
45
+ if (value.length > MAX_ALIASES_PER_DOCUMENT) {
46
+ throw new KnowledgePayloadError(`${field} exceeds ${MAX_ALIASES_PER_DOCUMENT} entries.`);
47
+ }
48
+ const values = Array.from(new Set(value.map((item, index) => {
49
+ if (typeof item !== 'string' || item.trim().length === 0) {
50
+ throw new KnowledgePayloadError(`${field}[${index}] must be a non-empty string.`);
51
+ }
52
+ const normalized = item.trim();
53
+ if (normalized.length > MAX_ALIAS_LENGTH) {
54
+ throw new KnowledgePayloadError(`${field}[${index}] exceeds ${MAX_ALIAS_LENGTH} characters.`);
55
+ }
56
+ return normalized;
57
+ })));
58
+ return values;
59
+ }
60
+ function normalizeDocument(raw) {
61
+ if (!isRecord(raw)) {
62
+ throw new KnowledgePayloadError('Each ingest document must be an object.');
63
+ }
64
+ const contentRaw = firstValue(raw, ['content', 'text', 'body', 'markdown']);
65
+ const content = typeof contentRaw === 'string' ? contentRaw : String(contentRaw ?? '');
66
+ if (Buffer.byteLength(content, 'utf8') > MAX_CONTENT_BYTES) {
67
+ throw new KnowledgePayloadError(`Document content exceeds ${MAX_CONTENT_BYTES} bytes.`);
68
+ }
69
+ if (!content.trim() && !firstString(raw, ['documentId', 'docId', 'id', 'sourcePath', 'source_path', 'path'])) {
70
+ throw new KnowledgePayloadError('Document requires content or an identity.');
71
+ }
72
+ const identityAliases = normalizeStringArray(firstValue(raw, ['identityAliases', 'identity_aliases', 'aliases']), 'identityAliases');
73
+ return {
74
+ documentId: firstString(raw, ['documentId', 'docId', 'id']),
75
+ sourcePath: firstString(raw, ['sourcePath', 'source_path', 'path', 'filePath', 'filepath', 'file']) || '',
76
+ sourceUri: firstString(raw, ['sourceUri', 'source_uri', 'uri']),
77
+ revision: firstString(raw, ['revision', 'sourceRevision', 'source_revision']),
78
+ identityAliases: identityAliases.length > 0 ? identityAliases : undefined,
79
+ content,
80
+ language: firstString(raw, ['language', 'lang', 'locale']),
81
+ updatedAt: firstString(raw, ['updatedAt', 'updated_at', 'timestamp', 'now']),
82
+ workspaceId: firstString(raw, ['workspaceId', 'workspace_id']),
83
+ corpusId: firstString(raw, ['corpusId', 'corpus_id']),
84
+ exportProfileId: firstString(raw, ['exportProfileId', 'export_profile_id']),
85
+ metadata: isRecord(raw.metadata) ? { ...raw.metadata } : undefined,
86
+ };
87
+ }
88
+ function normalizeDelete(raw) {
89
+ if (!isRecord(raw)) {
90
+ throw new KnowledgePayloadError('Each deleted document must be an object.');
91
+ }
92
+ const identityAliases = normalizeStringArray(firstValue(raw, ['identityAliases', 'identity_aliases', 'aliases']), 'identityAliases');
93
+ const result = {
94
+ documentId: firstString(raw, ['documentId', 'docId', 'id']),
95
+ sourcePath: firstString(raw, ['sourcePath', 'source_path', 'path', 'filePath', 'filepath', 'file']),
96
+ sourceUri: firstString(raw, ['sourceUri', 'source_uri', 'uri']),
97
+ identityAliases: identityAliases.length > 0 ? identityAliases : undefined,
98
+ };
99
+ if (!result.documentId && !result.sourcePath && !result.sourceUri && identityAliases.length === 0) {
100
+ throw new KnowledgePayloadError('Delete requires documentId, sourcePath, sourceUri, or identityAliases.');
101
+ }
102
+ return result;
103
+ }
104
+ function normalizeMove(raw) {
105
+ if (!isRecord(raw)) {
106
+ throw new KnowledgePayloadError('Each move document must be an object.');
107
+ }
108
+ const toSourcePath = firstString(raw, ['toSourcePath', 'to_source_path', 'destinationPath', 'destination_path']);
109
+ if (!toSourcePath) {
110
+ throw new KnowledgePayloadError('Move requires toSourcePath.');
111
+ }
112
+ const aliases = normalizeStringArray(firstValue(raw, ['toIdentityAliases', 'to_identity_aliases', 'aliases']), 'toIdentityAliases');
113
+ const fromAliases = normalizeStringArray(firstValue(raw, ['fromIdentityAliases', 'from_identity_aliases', 'fromAliases']), 'fromIdentityAliases');
114
+ return {
115
+ documentId: firstString(raw, ['documentId', 'docId', 'id']),
116
+ fromSourcePath: firstString(raw, ['fromSourcePath', 'from_source_path', 'sourcePath', 'source_path']),
117
+ fromSourceUri: firstString(raw, ['fromSourceUri', 'from_source_uri', 'sourceUri', 'source_uri']),
118
+ fromIdentityAliases: fromAliases.length > 0 ? fromAliases : undefined,
119
+ toSourcePath,
120
+ toSourceUri: firstString(raw, ['toSourceUri', 'to_source_uri', 'destinationUri', 'destination_uri']),
121
+ toIdentityAliases: aliases.length > 0 ? aliases : undefined,
122
+ revision: firstString(raw, ['revision', 'sourceRevision', 'source_revision']),
123
+ updatedAt: firstString(raw, ['updatedAt', 'updated_at', 'timestamp', 'now']),
124
+ };
125
+ }
126
+ function normalizeOperation(raw) {
127
+ if (!isRecord(raw)) {
128
+ throw new KnowledgePayloadError('Each ingest operation must be an object.');
129
+ }
130
+ const operation = (firstString(raw, ['op', 'operation', 'action', 'type']) || 'upsert').toLowerCase();
131
+ const nested = firstValue(raw, ['document', 'payload', 'item']) ?? raw;
132
+ if (operation === 'delete' || operation === 'remove' || operation === 'del') {
133
+ return { op: 'delete', document: normalizeDelete(nested) };
134
+ }
135
+ if (operation === 'move' || operation === 'rename') {
136
+ return { op: 'move', document: normalizeMove(nested) };
137
+ }
138
+ if (operation === 'upsert' || operation === 'insert' || operation === 'update' || operation === 'put') {
139
+ return { op: 'upsert', document: normalizeDocument(nested) };
140
+ }
141
+ throw new KnowledgePayloadError(`Unsupported ingest operation: ${operation}.`);
142
+ }
143
+ function asArray(value) {
144
+ if (value === undefined || value === null)
145
+ return [];
146
+ return Array.isArray(value) ? value : [value];
147
+ }
148
+ function parseKnowledgeIngestBody(body) {
149
+ let payload;
150
+ try {
151
+ payload = body.trim() ? JSON.parse(body) : {};
152
+ }
153
+ catch (_error) {
154
+ throw new KnowledgePayloadError('Request body must be valid JSON.');
155
+ }
156
+ if (!isRecord(payload) && !Array.isArray(payload)) {
157
+ throw new KnowledgePayloadError('Request body must be an object or document array.');
158
+ }
159
+ const record = isRecord(payload) ? payload : {};
160
+ const rawDocuments = firstValue(record, ['documents', 'docs', 'items']);
161
+ const rawDeletes = firstValue(record, ['deletedDocuments', 'deleted', 'deletes']);
162
+ const rawOperations = firstValue(record, ['operations', 'ops']);
163
+ const documents = asArray(rawDocuments ?? (Array.isArray(payload) ? payload : undefined)).map(normalizeDocument);
164
+ const deletedDocuments = asArray(rawDeletes).map(normalizeDelete);
165
+ const operations = asArray(rawOperations).map(normalizeOperation);
166
+ const totalItems = documents.length + deletedDocuments.length + operations.length;
167
+ if (totalItems > MAX_DOCUMENTS_PER_REQUEST) {
168
+ throw new KnowledgePayloadError(`Ingest request exceeds ${MAX_DOCUMENTS_PER_REQUEST} documents/operations.`);
169
+ }
170
+ const incremental = typeof record.incremental === 'boolean' ? record.incremental : undefined;
171
+ const recomputeRelations = typeof record.recomputeRelations === 'boolean' ? record.recomputeRelations : undefined;
172
+ const relationRecomputeMode = firstString(record, ['relationRecomputeMode', 'relation_recompute_mode', 'recomputeMode']);
173
+ if (relationRecomputeMode && !['auto', 'none', 'incremental', 'full'].includes(relationRecomputeMode.toLowerCase())) {
174
+ throw new KnowledgePayloadError('relationRecomputeMode must be one of auto, none, incremental, full.');
175
+ }
176
+ return {
177
+ documents: documents.length > 0 ? documents : undefined,
178
+ deletedDocuments: deletedDocuments.length > 0 ? deletedDocuments : undefined,
179
+ operations: operations.length > 0 ? operations : undefined,
180
+ incremental,
181
+ recomputeRelations,
182
+ relationRecomputeMode: relationRecomputeMode?.toLowerCase(),
183
+ ingestedAt: firstString(record, ['ingestedAt', 'timestamp', 'now']),
184
+ };
185
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const knowledgePayload_1 = require("./knowledgePayload");
4
+ describe('knowledge HTTP payload contract', () => {
5
+ test('normalizes legacy aliases while preserving portable identity fields', () => {
6
+ const request = (0, knowledgePayload_1.parseKnowledgeIngestBody)(JSON.stringify({
7
+ docs: [{
8
+ id: 'legacy-doc',
9
+ path: 'Knowledge_Base/one.md',
10
+ text: '# One',
11
+ uri: 'note://workspace/v1/one.md',
12
+ source_revision: 'sha256:one',
13
+ aliases: ['one', 'notes/one.md'],
14
+ }],
15
+ }));
16
+ expect(request.documents?.[0]).toEqual(expect.objectContaining({
17
+ documentId: 'legacy-doc',
18
+ sourcePath: 'Knowledge_Base/one.md',
19
+ sourceUri: 'note://workspace/v1/one.md',
20
+ revision: 'sha256:one',
21
+ identityAliases: ['one', 'notes/one.md'],
22
+ content: '# One',
23
+ }));
24
+ });
25
+ test('accepts explicit move operations for replay', () => {
26
+ const request = (0, knowledgePayload_1.parseKnowledgeIngestBody)(JSON.stringify({
27
+ operations: [{
28
+ op: 'rename',
29
+ document: {
30
+ documentId: 'doc-1',
31
+ fromSourcePath: 'old.md',
32
+ toSourcePath: 'new.md',
33
+ toSourceUri: 'note://workspace/v1/new.md',
34
+ },
35
+ }],
36
+ }));
37
+ expect(request.operations).toEqual([expect.objectContaining({
38
+ op: 'move',
39
+ document: expect.objectContaining({
40
+ documentId: 'doc-1',
41
+ toSourcePath: 'new.md',
42
+ }),
43
+ })]);
44
+ });
45
+ test('rejects malformed identity arrays and oversized documents at the edge', () => {
46
+ expect(() => (0, knowledgePayload_1.parseKnowledgeIngestBody)(JSON.stringify({
47
+ documents: [{ content: '# invalid', aliases: ['ok', 3] }],
48
+ }))).toThrow(knowledgePayload_1.KnowledgePayloadError);
49
+ expect(() => (0, knowledgePayload_1.parseKnowledgeIngestBody)(JSON.stringify({
50
+ documents: [{ content: 'x'.repeat(64 * 1024 * 1024 + 1) }],
51
+ }))).toThrow(/exceeds 67108864 bytes/);
52
+ });
53
+ });
@@ -0,0 +1,295 @@
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
+ exports.registerMarkdownRoutes = registerMarkdownRoutes;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const CrashLogger_1 = require("../backend/utils/CrashLogger");
40
+ const MarkdownGateway_1 = require("../markdown/MarkdownGateway");
41
+ const PROTOCOL_VERSION = '1.0.0';
42
+ const INDEXES = new Map();
43
+ function buildIndexId(filePath) {
44
+ return `md-idx-${Buffer.from(filePath).toString('base64').slice(0, 16)}-${Date.now()}`;
45
+ }
46
+ function indexMarkdownFile(filePath) {
47
+ const resolved = path.resolve(filePath);
48
+ const content = fs.readFileSync(resolved, 'utf8');
49
+ const lines = content.split('\n');
50
+ const blocks = [];
51
+ let currentBlock = [];
52
+ let currentHeading;
53
+ let currentHeadingLevel = 0;
54
+ let blockStartLine = 0;
55
+ let blockId = 0;
56
+ for (let i = 0; i < lines.length; i++) {
57
+ const line = lines[i];
58
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)/);
59
+ if (headingMatch) {
60
+ // Flush current block
61
+ if (currentBlock.length > 0 || currentHeading) {
62
+ blocks.push({
63
+ id: blockId++,
64
+ text: currentBlock.join('\n').trim(),
65
+ heading: currentHeading,
66
+ headingLevel: currentHeadingLevel,
67
+ startLine: blockStartLine,
68
+ endLine: i - 1,
69
+ });
70
+ }
71
+ currentHeading = headingMatch[2].trim();
72
+ currentHeadingLevel = headingMatch[1].length;
73
+ currentBlock = [];
74
+ blockStartLine = i;
75
+ }
76
+ else {
77
+ currentBlock.push(line);
78
+ }
79
+ }
80
+ // Flush final block
81
+ if (currentBlock.length > 0 || currentHeading) {
82
+ blocks.push({
83
+ id: blockId,
84
+ text: currentBlock.join('\n').trim(),
85
+ heading: currentHeading,
86
+ headingLevel: currentHeadingLevel,
87
+ startLine: blockStartLine,
88
+ endLine: lines.length - 1,
89
+ });
90
+ }
91
+ // Ensure at least one block for empty files
92
+ if (blocks.length === 0) {
93
+ blocks.push({
94
+ id: 0,
95
+ text: content.trim() || '(empty)',
96
+ heading: undefined,
97
+ headingLevel: 0,
98
+ startLine: 0,
99
+ endLine: lines.length - 1,
100
+ });
101
+ }
102
+ const indexId = buildIndexId(filePath);
103
+ const index = {
104
+ indexId,
105
+ filePath,
106
+ blocks,
107
+ markdownProtocolVersion: PROTOCOL_VERSION,
108
+ indexedAt: new Date().toISOString(),
109
+ };
110
+ INDEXES.set(indexId, index);
111
+ return index;
112
+ }
113
+ function resolveNodeFromIndex(index, nodeId) {
114
+ const block = index.blocks.find(b => b.heading?.toLowerCase() === nodeId.toLowerCase() ||
115
+ b.text.toLowerCase().includes(nodeId.toLowerCase()));
116
+ return block ? { targetBlockId: block.id, filePath: index.filePath } : null;
117
+ }
118
+ function resolveWikiFromIndex(index, wikiTarget) {
119
+ const clean = wikiTarget.replace(/^\[\[|\]\]$/g, '').trim();
120
+ const exact = index.blocks.find(b => b.heading?.toLowerCase() === clean.toLowerCase());
121
+ if (exact)
122
+ return { matchType: 'exact', filePath: index.filePath, targetBlockId: exact.id };
123
+ const partial = index.blocks.find(b => b.heading?.toLowerCase().includes(clean.toLowerCase()) ||
124
+ b.text.toLowerCase().includes(clean.toLowerCase()));
125
+ if (partial)
126
+ return { matchType: 'alias', filePath: index.filePath, targetBlockId: partial.id };
127
+ return { matchType: 'fallback', filePath: index.filePath };
128
+ }
129
+ function registerMarkdownRoutes(_ctx) {
130
+ const ctx = _ctx;
131
+ const api = (p) => `/api/markdown${p}`;
132
+ const json = (res, code, data) => {
133
+ res.writeHead(code, { 'Content-Type': 'application/json' });
134
+ res.end(JSON.stringify(data));
135
+ };
136
+ const ok = (res, data) => json(res, 200, { success: true, ...data });
137
+ const fail = (res, error, label) => {
138
+ console.error(error);
139
+ CrashLogger_1.CrashLogger.log(error, label);
140
+ json(res, 500, { success: false, error: String(error) });
141
+ };
142
+ const readBody = (req) => new Promise((resolve, reject) => {
143
+ const chunks = [];
144
+ req.on('data', (c) => chunks.push(c));
145
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
146
+ req.on('error', reject);
147
+ });
148
+ const resolveRuntimeConfig = async () => {
149
+ if (ctx.loadFrontendSettings) {
150
+ const frontendSettings = await ctx.loadFrontendSettings();
151
+ return (0, MarkdownGateway_1.normalizeMarkdownRuntimeConfig)(frontendSettings?.reading);
152
+ }
153
+ return (0, MarkdownGateway_1.normalizeMarkdownRuntimeConfig)({});
154
+ };
155
+ return [
156
+ {
157
+ method: 'POST',
158
+ path: api('/index'),
159
+ handler: async (req, res) => {
160
+ try {
161
+ const body = await readBody(req);
162
+ const payload = JSON.parse(body);
163
+ const filePath = payload.filePath || payload.path || '';
164
+ if (!filePath) {
165
+ json(res, 400, {
166
+ success: false,
167
+ error: 'Missing filePath for /api/markdown/index',
168
+ markdownProtocolVersion: PROTOCOL_VERSION,
169
+ });
170
+ return;
171
+ }
172
+ if (ctx.markdownGateway) {
173
+ const runtimeConfig = await resolveRuntimeConfig();
174
+ const result = await ctx.markdownGateway.buildIndex({
175
+ filePath,
176
+ forceRebuild: payload.forceRebuild === true,
177
+ }, runtimeConfig);
178
+ ok(res, result);
179
+ return;
180
+ }
181
+ if (!filePath || !fs.existsSync(filePath)) {
182
+ return fail(res, new Error('File not found: ' + filePath), 'API:POST /api/markdown/index');
183
+ }
184
+ const index = indexMarkdownFile(filePath);
185
+ ok(res, {
186
+ indexId: index.indexId,
187
+ filePath: index.filePath,
188
+ blocksSummary: { totalBlocks: index.blocks.length },
189
+ markdownProtocolVersion: index.markdownProtocolVersion,
190
+ });
191
+ }
192
+ catch (e) {
193
+ fail(res, e, 'API:POST /api/markdown/index');
194
+ }
195
+ },
196
+ },
197
+ {
198
+ method: 'POST',
199
+ path: api('/chunk'),
200
+ handler: async (req, res) => {
201
+ try {
202
+ const body = await readBody(req);
203
+ const payload = JSON.parse(body);
204
+ if (ctx.markdownGateway) {
205
+ const result = await ctx.markdownGateway.getChunk({
206
+ indexId: String(payload.indexId || ''),
207
+ startBlock: Number(payload.startBlock) || 0,
208
+ blockCount: Number(payload.blockCount) || 1,
209
+ });
210
+ ok(res, result);
211
+ return;
212
+ }
213
+ const index = INDEXES.get(payload.indexId || '');
214
+ if (!index)
215
+ return fail(res, new Error('Index not found'), 'API:POST /api/markdown/chunk');
216
+ const start = payload.startBlock || 0;
217
+ const count = payload.blockCount || index.blocks.length;
218
+ const blocks = index.blocks.slice(start, start + count).map(b => ({
219
+ blockId: b.id,
220
+ text: b.text,
221
+ heading: b.heading,
222
+ headingLevel: b.headingLevel,
223
+ }));
224
+ ok(res, { blocks });
225
+ }
226
+ catch (e) {
227
+ fail(res, e, 'API:POST /api/markdown/chunk');
228
+ }
229
+ },
230
+ },
231
+ {
232
+ method: 'POST',
233
+ path: api('/resolve-node'),
234
+ handler: async (req, res) => {
235
+ try {
236
+ const body = await readBody(req);
237
+ const payload = JSON.parse(body);
238
+ if (ctx.markdownGateway) {
239
+ const runtimeConfig = await resolveRuntimeConfig();
240
+ const result = await ctx.markdownGateway.resolveNode({
241
+ nodeId: String(payload.nodeId || ''),
242
+ currentFilePath: String(payload.currentFilePath || '').trim() || undefined,
243
+ }, runtimeConfig);
244
+ ok(res, result);
245
+ return;
246
+ }
247
+ const index = INDEXES.get(payload.indexId || '');
248
+ // Fallback: search all indexes
249
+ const searchIndex = index || [...INDEXES.values()].find(i => i.filePath === payload.currentFilePath);
250
+ if (!searchIndex && INDEXES.size > 0) {
251
+ return ok(res, { filePath: payload.currentFilePath || '', targetBlockId: 0 });
252
+ }
253
+ if (!searchIndex)
254
+ return fail(res, new Error('No index available'), 'API:POST /api/markdown/resolve-node');
255
+ const result = resolveNodeFromIndex(searchIndex, payload.nodeId || '');
256
+ ok(res, result || { filePath: searchIndex.filePath, targetBlockId: 0 });
257
+ }
258
+ catch (e) {
259
+ fail(res, e, 'API:POST /api/markdown/resolve-node');
260
+ }
261
+ },
262
+ },
263
+ {
264
+ method: 'POST',
265
+ path: api('/resolve-wiki'),
266
+ handler: async (req, res) => {
267
+ try {
268
+ const body = await readBody(req);
269
+ const payload = JSON.parse(body);
270
+ if (ctx.markdownGateway) {
271
+ const runtimeConfig = await resolveRuntimeConfig();
272
+ const result = await ctx.markdownGateway.resolveWiki({
273
+ wikiTarget: String(payload.wikiTarget || ''),
274
+ currentFilePath: String(payload.currentFilePath || ''),
275
+ }, runtimeConfig);
276
+ ok(res, result);
277
+ return;
278
+ }
279
+ const index = INDEXES.get(payload.indexId || '');
280
+ const searchIndex = index || [...INDEXES.values()].find(i => i.filePath === payload.currentFilePath);
281
+ if (!searchIndex && INDEXES.size > 0) {
282
+ return ok(res, { filePath: payload.currentFilePath || '', matchType: 'fallback' });
283
+ }
284
+ if (!searchIndex)
285
+ return fail(res, new Error('No index available'), 'API:POST /api/markdown/resolve-wiki');
286
+ const result = resolveWikiFromIndex(searchIndex, payload.wikiTarget || '');
287
+ ok(res, result || { filePath: searchIndex.filePath, matchType: 'fallback' });
288
+ }
289
+ catch (e) {
290
+ fail(res, e, 'API:POST /api/markdown/resolve-wiki');
291
+ }
292
+ },
293
+ },
294
+ ];
295
+ }