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
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PathBridge = exports.BRIDGE_INBOUND_SCHEMA_LIMITS = exports.BRIDGE_INBOUND_LIMITS = exports.BRIDGE_BACKPRESSURE_LIMITS = void 0;
3
+ exports.PathBridge = exports.BRIDGE_INBOUND_SCHEMA_LIMITS = exports.BRIDGE_INBOUND_LIMITS = exports.BRIDGE_BACKPRESSURE_LIMITS = exports.PATH_BRIDGE_CAPABILITIES = exports.PATH_BRIDGE_PROTOCOL_VERSION = void 0;
4
4
  exports.resolveBridgeInboundSchemaPolicy = resolveBridgeInboundSchemaPolicy;
5
5
  exports.resolveBridgeInboundLimitConfig = resolveBridgeInboundLimitConfig;
6
6
  exports.parseBridgeInboundEnvelope = parseBridgeInboundEnvelope;
@@ -8,10 +8,21 @@ exports.computeBridgePathFingerprint = computeBridgePathFingerprint;
8
8
  exports.buildBridgePathTransportSummary = buildBridgePathTransportSummary;
9
9
  exports.validateBridgePathPayload = validateBridgePathPayload;
10
10
  const ws_1 = require("ws");
11
+ /** Versioned, host-neutral contract shared by Web, Tauri, Capacitor, and Godot. */
12
+ exports.PATH_BRIDGE_PROTOCOL_VERSION = '2.0';
13
+ exports.PATH_BRIDGE_CAPABILITIES = Object.freeze([
14
+ 'path.transport',
15
+ 'knowledge.analyze',
16
+ 'knowledge.query',
17
+ 'knowledge.readEvidence',
18
+ 'knowledge.exportBundle',
19
+ 'request.cancel',
20
+ ]);
11
21
  const PATH_REQUEST_TIMEOUT_MS = 3000;
12
22
  const PATH_PRODUCER_GRACE_MS = 30000;
13
23
  const MERMAID_RENDER_TIMEOUT_MS = 12000;
14
24
  const UNAUTHORIZED_CLIENT_TIMEOUT_MS = 5000;
25
+ const DEFAULT_HOST_OPERATION_TIMEOUT_MS = 15000;
15
26
  const BYTES_PER_MIB = 1024 * 1024;
16
27
  const DEFAULT_INBOUND_MESSAGE_LIMIT_MIB = 128;
17
28
  const LARGE_GRAPH_INBOUND_MESSAGE_LIMIT_MIB = 256;
@@ -131,6 +142,12 @@ const PATH_MUTATION_TYPES = new Set([
131
142
  const KNOWN_BRIDGE_MESSAGE_TYPES = new Set([
132
143
  'authenticate',
133
144
  'identify',
145
+ 'capabilities',
146
+ 'analyze',
147
+ 'query',
148
+ 'readEvidence',
149
+ 'exportBundle',
150
+ 'cancel',
134
151
  'requestPath',
135
152
  'pathResult',
136
153
  'pathStatus',
@@ -185,8 +202,8 @@ const ALLOWED_BACKGROUND_FILE_EXTENSIONS = ['.exr', '.hdr'];
185
202
  const CONFIG_TARGET_ID_MAX_LENGTH = 512;
186
203
  const CONFIG_SHORTCUT_MAX_LENGTH = 64;
187
204
  const CONFIG_BACKGROUND_MAX_LENGTH = 128;
188
- const CONFIG_BRIGHTNESS_MIN = 0.01;
189
- const CONFIG_BRIGHTNESS_MAX = 10.0;
205
+ const CONFIG_BRIGHTNESS_MIN = 0.0;
206
+ const CONFIG_BRIGHTNESS_MAX = 0.1;
190
207
  const CONFIG_READER_MEDIA_SCALE_MIN = 0.1;
191
208
  const CONFIG_READER_MEDIA_SCALE_MAX = 3.0;
192
209
  const CONFIG_CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/;
@@ -247,6 +264,74 @@ function validateRequestPathPayload(payload) {
247
264
  }
248
265
  return null;
249
266
  }
267
+ const BRIDGE_CORRELATION_ID_MAX_LENGTH = 128;
268
+ const BRIDGE_CAPABILITY_MAX_COUNT = 32;
269
+ function validateCorrelationId(value, field) {
270
+ if (value === undefined) {
271
+ return null;
272
+ }
273
+ if (!isNonEmptyString(value)) {
274
+ return `${field} must be a non-empty string when provided.`;
275
+ }
276
+ if (value.trim().length > BRIDGE_CORRELATION_ID_MAX_LENGTH) {
277
+ return `${field} must be at most ${BRIDGE_CORRELATION_ID_MAX_LENGTH} characters.`;
278
+ }
279
+ if (/[\u0000-\u001f\u007f]/.test(value)) {
280
+ return `${field} must not contain control characters.`;
281
+ }
282
+ return null;
283
+ }
284
+ function validateCapabilitiesPayload(payload) {
285
+ if (payload.protocolVersion !== undefined && !isNonEmptyString(payload.protocolVersion)) {
286
+ return 'capabilities payload.protocolVersion must be a non-empty string when provided.';
287
+ }
288
+ if (payload.client !== undefined && !isNonEmptyString(payload.client)) {
289
+ return 'capabilities payload.client must be a non-empty string when provided.';
290
+ }
291
+ if (!Array.isArray(payload.capabilities)) {
292
+ return 'capabilities payload.capabilities must be an array.';
293
+ }
294
+ if (payload.capabilities.length > BRIDGE_CAPABILITY_MAX_COUNT) {
295
+ return `capabilities payload.capabilities must contain at most ${BRIDGE_CAPABILITY_MAX_COUNT} entries.`;
296
+ }
297
+ if (payload.capabilities.some((capability) => !isNonEmptyString(capability))) {
298
+ return 'capabilities payload.capabilities must contain only non-empty strings.';
299
+ }
300
+ if (payload.maxPayloadBytes !== undefined && !isFiniteNumberValue(payload.maxPayloadBytes)) {
301
+ return 'capabilities payload.maxPayloadBytes must be a finite number when provided.';
302
+ }
303
+ return null;
304
+ }
305
+ function validateAnalysisRequestPayload(type, payload) {
306
+ if (!isRecord(payload)) {
307
+ return `${type} payload must be an object.`;
308
+ }
309
+ const requestIdError = validateCorrelationId(payload.requestId, `${type} payload.requestId`);
310
+ if (requestIdError) {
311
+ return requestIdError;
312
+ }
313
+ if (type !== 'cancel' && !isNonEmptyString(payload.requestId)) {
314
+ return `${type} payload.requestId must be a non-empty string.`;
315
+ }
316
+ if (payload.workspaceId !== undefined && !isNonEmptyString(payload.workspaceId)) {
317
+ return `${type} payload.workspaceId must be a non-empty string when provided.`;
318
+ }
319
+ if (payload.sourceUri !== undefined && !isNonEmptyString(payload.sourceUri)) {
320
+ return `${type} payload.sourceUri must be a non-empty string when provided.`;
321
+ }
322
+ return null;
323
+ }
324
+ function identifyPayloadCapabilitiesInvalid(payload) {
325
+ if (payload.capabilities === undefined) {
326
+ return null;
327
+ }
328
+ return validateCapabilitiesPayload({
329
+ protocolVersion: payload.protocolVersion,
330
+ client: payload.client ?? payload.tag,
331
+ capabilities: payload.capabilities,
332
+ maxPayloadBytes: payload.maxPayloadBytes,
333
+ });
334
+ }
250
335
  function validatePathStatusPayload(payload) {
251
336
  if (payload.level !== undefined && !isValidBridgeStatusLevel(payload.level)) {
252
337
  return 'pathStatus payload.level must be one of info/success/warning/error when provided.';
@@ -485,8 +570,22 @@ function validateKnownEnvelopePayload(type, payload, policy) {
485
570
  if (client !== undefined && typeof client !== 'string') {
486
571
  return `${type} client/tag must be a string when provided.`;
487
572
  }
573
+ if (identifyPayloadCapabilitiesInvalid(payload)) {
574
+ return identifyPayloadCapabilitiesInvalid(payload);
575
+ }
488
576
  }
489
577
  return null;
578
+ case 'capabilities':
579
+ if (!isRecord(payload)) {
580
+ return 'capabilities payload must be an object.';
581
+ }
582
+ return validateCapabilitiesPayload(payload);
583
+ case 'analyze':
584
+ case 'query':
585
+ case 'readEvidence':
586
+ case 'exportBundle':
587
+ case 'cancel':
588
+ return validateAnalysisRequestPayload(type, payload);
490
589
  case 'requestPath':
491
590
  if (payload !== undefined && !isRecord(payload)) {
492
591
  return 'requestPath payload must be an object when provided.';
@@ -593,6 +692,9 @@ function parseBridgeInboundEnvelope(data, policy = BRIDGE_INBOUND_SCHEMA_POLICY)
593
692
  payload: data.payload,
594
693
  token: data.token,
595
694
  client: data.client,
695
+ version: data.version,
696
+ requestId: data.requestId,
697
+ correlationId: data.correlationId,
596
698
  };
597
699
  if (envelope.token !== undefined && typeof envelope.token !== 'string') {
598
700
  return {
@@ -606,6 +708,18 @@ function parseBridgeInboundEnvelope(data, policy = BRIDGE_INBOUND_SCHEMA_POLICY)
606
708
  reason: 'Bridge message client must be a string when provided.',
607
709
  };
608
710
  }
711
+ const versionError = validateCorrelationId(envelope.version, 'Bridge message version');
712
+ if (versionError) {
713
+ return { ok: false, reason: versionError };
714
+ }
715
+ const requestIdError = validateCorrelationId(envelope.requestId, 'Bridge message requestId');
716
+ if (requestIdError) {
717
+ return { ok: false, reason: requestIdError };
718
+ }
719
+ const correlationIdError = validateCorrelationId(envelope.correlationId, 'Bridge message correlationId');
720
+ if (correlationIdError) {
721
+ return { ok: false, reason: correlationIdError };
722
+ }
609
723
  const isKnownType = KNOWN_BRIDGE_MESSAGE_TYPES.has(type);
610
724
  if (!isKnownType && policy.rejectUnknownTypes) {
611
725
  return {
@@ -828,20 +942,45 @@ class PathBridge {
828
942
  this.currentPath = null;
829
943
  this.pendingPathRequests = new Map();
830
944
  this.pendingMermaidRenderRequests = new Map();
945
+ this.pendingHostOperations = new Map();
831
946
  this.unauthorizedClientTimers = new Map();
832
947
  this.outboundQueueState = new Map();
833
948
  this.nextMermaidRenderRequestId = 1;
949
+ this.readySettled = false;
834
950
  const resolvedOptions = typeof options === 'number'
835
951
  ? { port: options }
836
952
  : (options || {});
837
- this.port = resolvedOptions.port || 9876;
953
+ this.port = Number.isFinite(Number(resolvedOptions.port))
954
+ ? Number(resolvedOptions.port)
955
+ : 9876;
838
956
  this.host = resolvedOptions.host || '127.0.0.1';
839
957
  this.authToken = typeof resolvedOptions.authToken === 'string' ? resolvedOptions.authToken.trim() : '';
958
+ this.hostAdapter = resolvedOptions.hostAdapter || null;
959
+ this.hostOperationTimeoutMs = Number.isFinite(Number(resolvedOptions.hostOperationTimeoutMs)) &&
960
+ Number(resolvedOptions.hostOperationTimeoutMs) > 0
961
+ ? Math.floor(Number(resolvedOptions.hostOperationTimeoutMs))
962
+ : DEFAULT_HOST_OPERATION_TIMEOUT_MS;
840
963
  this.wss = new ws_1.WebSocketServer({
841
964
  port: this.port,
842
965
  host: this.host,
843
966
  maxPayload: MAX_INBOUND_MESSAGE_BYTES,
844
967
  });
968
+ this.readyPromise = new Promise((resolve, reject) => {
969
+ this.wss.once('listening', () => {
970
+ this.readySettled = true;
971
+ const address = this.wss.address();
972
+ if (address && typeof address === 'object') {
973
+ this.port = Number(address.port || this.port);
974
+ }
975
+ resolve();
976
+ });
977
+ this.wss.once('error', (error) => {
978
+ if (!this.readySettled) {
979
+ this.readySettled = true;
980
+ reject(error);
981
+ }
982
+ });
983
+ });
845
984
  console.log(`[PathBridge] WebSocket Server started on ws://${this.host}:${this.port}`);
846
985
  console.log(`[PathBridge] Inbound frame limit ${BRIDGE_INBOUND_LIMIT_CONFIG.selectedMessageMb} MiB ` +
847
986
  `(recommended=${BRIDGE_INBOUND_LIMIT_CONFIG.recommendedMessageMb} MiB, ` +
@@ -899,6 +1038,7 @@ class PathBridge {
899
1038
  const wasProducer = !!meta && this.isPathProducerTag(meta.tag);
900
1039
  this.clearUnauthorizedDisconnect(ws);
901
1040
  this.clearPendingPathRequest(ws);
1041
+ this.cancelHostOperationsForClient(ws, 'client_disconnected');
902
1042
  this.clearOutboundQueueState(ws);
903
1043
  this.clients.delete(ws);
904
1044
  this.clientMeta.delete(ws);
@@ -1168,7 +1308,11 @@ class PathBridge {
1168
1308
  }
1169
1309
  let serialized = '';
1170
1310
  try {
1171
- serialized = JSON.stringify({ type, payload });
1311
+ serialized = JSON.stringify({
1312
+ type,
1313
+ payload,
1314
+ version: exports.PATH_BRIDGE_PROTOCOL_VERSION,
1315
+ });
1172
1316
  }
1173
1317
  catch (error) {
1174
1318
  const meta = this.clientMeta.get(client);
@@ -1202,6 +1346,15 @@ class PathBridge {
1202
1346
  sendStatus(client, payload) {
1203
1347
  this.sendMessage(client, 'pathStatus', payload);
1204
1348
  }
1349
+ sendCapabilities(client) {
1350
+ this.sendMessage(client, 'capabilities', {
1351
+ protocolVersion: exports.PATH_BRIDGE_PROTOCOL_VERSION,
1352
+ capabilities: [...exports.PATH_BRIDGE_CAPABILITIES],
1353
+ maxPayloadBytes: MAX_INBOUND_MESSAGE_BYTES,
1354
+ hostAdapter: Boolean(this.hostAdapter),
1355
+ hostOperationTimeoutMs: this.hostOperationTimeoutMs,
1356
+ });
1357
+ }
1205
1358
  notifyPendingPathRequests(payload) {
1206
1359
  const pendingClients = Array.from(this.pendingPathRequests.keys());
1207
1360
  pendingClients.forEach((client) => this.sendStatus(client, payload));
@@ -1220,6 +1373,17 @@ class PathBridge {
1220
1373
  clearAllPendingPathRequests() {
1221
1374
  Array.from(this.pendingPathRequests.keys()).forEach((client) => this.clearPendingPathRequest(client));
1222
1375
  }
1376
+ cancelHostOperationsForClient(client, reason) {
1377
+ Array.from(this.pendingHostOperations.entries()).forEach(([requestId, pending]) => {
1378
+ if (pending.client !== client) {
1379
+ return;
1380
+ }
1381
+ clearTimeout(pending.timer);
1382
+ pending.controller.abort(reason);
1383
+ this.pendingHostOperations.delete(requestId);
1384
+ this.hostAdapter?.cancel?.(requestId);
1385
+ });
1386
+ }
1223
1387
  invalidateCurrentPath(reason) {
1224
1388
  if (!this.currentPath) {
1225
1389
  return;
@@ -1432,6 +1596,101 @@ class PathBridge {
1432
1596
  }
1433
1597
  this.broadcast('pathStatus', status);
1434
1598
  }
1599
+ sendHostOperationResult(client, operationType, requestId, correlationId, result, error, cancelled = false) {
1600
+ this.sendMessage(client, 'operationResult', {
1601
+ type: operationType,
1602
+ requestId,
1603
+ correlationId,
1604
+ ok: !error && !cancelled,
1605
+ cancelled,
1606
+ result: error || cancelled ? undefined : result,
1607
+ error: error || (cancelled ? 'operation_cancelled' : undefined),
1608
+ });
1609
+ }
1610
+ executeHostOperation(type, payloadLike, envelope, sender) {
1611
+ if (!this.hostAdapter || !isRecord(payloadLike)) {
1612
+ this.broadcast(type, payloadLike || {});
1613
+ return;
1614
+ }
1615
+ const requestId = typeof payloadLike.requestId === 'string' ? payloadLike.requestId.trim() : '';
1616
+ if (!requestId) {
1617
+ this.sendHostOperationResult(sender, type, '', '', undefined, 'request_id_required');
1618
+ return;
1619
+ }
1620
+ if (this.pendingHostOperations.has(requestId)) {
1621
+ this.sendHostOperationResult(sender, type, requestId, requestId, undefined, 'request_in_flight');
1622
+ return;
1623
+ }
1624
+ const controller = new AbortController();
1625
+ const correlationId = typeof envelope.correlationId === 'string' && envelope.correlationId.trim()
1626
+ ? envelope.correlationId.trim()
1627
+ : requestId;
1628
+ const timer = setTimeout(() => {
1629
+ const pending = this.pendingHostOperations.get(requestId);
1630
+ if (!pending) {
1631
+ return;
1632
+ }
1633
+ this.pendingHostOperations.delete(requestId);
1634
+ pending.controller.abort();
1635
+ this.hostAdapter?.cancel?.(requestId);
1636
+ this.sendHostOperationResult(sender, type, requestId, correlationId, undefined, 'operation_timeout');
1637
+ }, this.hostOperationTimeoutMs);
1638
+ const pending = { client: sender, controller, timer };
1639
+ this.pendingHostOperations.set(requestId, pending);
1640
+ const clientTag = this.clientMeta.get(sender)?.tag || 'unknown';
1641
+ Promise.resolve()
1642
+ .then(() => this.hostAdapter.execute({
1643
+ type,
1644
+ requestId,
1645
+ correlationId,
1646
+ payload: payloadLike,
1647
+ clientTag,
1648
+ signal: controller.signal,
1649
+ }))
1650
+ .then((result) => {
1651
+ if (this.pendingHostOperations.get(requestId) !== pending) {
1652
+ return;
1653
+ }
1654
+ this.pendingHostOperations.delete(requestId);
1655
+ clearTimeout(timer);
1656
+ this.sendHostOperationResult(sender, type, requestId, correlationId, result);
1657
+ })
1658
+ .catch((error) => {
1659
+ if (this.pendingHostOperations.get(requestId) !== pending) {
1660
+ return;
1661
+ }
1662
+ this.pendingHostOperations.delete(requestId);
1663
+ clearTimeout(timer);
1664
+ const message = controller.signal.aborted ? 'operation_cancelled' : String(error?.message || error);
1665
+ this.sendHostOperationResult(sender, type, requestId, correlationId, undefined, message, controller.signal.aborted);
1666
+ });
1667
+ }
1668
+ cancelHostOperation(payloadLike, sender) {
1669
+ if (!this.hostAdapter) {
1670
+ // Preserve the pre-adapter relay contract for legacy clients,
1671
+ // including cancellation frames without a request ID.
1672
+ this.broadcast('cancel', payloadLike || {});
1673
+ return;
1674
+ }
1675
+ const payload = isRecord(payloadLike) ? payloadLike : {};
1676
+ const requestId = typeof payload.requestId === 'string' ? payload.requestId.trim() : '';
1677
+ if (!requestId) {
1678
+ this.sendHostOperationResult(sender, 'cancel', '', '', undefined, 'request_id_required');
1679
+ return;
1680
+ }
1681
+ const pending = this.pendingHostOperations.get(requestId);
1682
+ if (pending) {
1683
+ clearTimeout(pending.timer);
1684
+ pending.controller.abort();
1685
+ this.pendingHostOperations.delete(requestId);
1686
+ this.hostAdapter?.cancel?.(requestId);
1687
+ this.sendHostOperationResult(sender, 'cancel', requestId, requestId, undefined, undefined, true);
1688
+ }
1689
+ else {
1690
+ this.sendHostOperationResult(sender, 'cancel', requestId, requestId, undefined, 'operation_not_found');
1691
+ }
1692
+ this.broadcast('cancel', payloadLike || {});
1693
+ }
1435
1694
  handleMessage(envelope, sender) {
1436
1695
  const { type, payload, client } = envelope;
1437
1696
  console.log(`[PathBridge] Received: ${type}`);
@@ -1442,8 +1701,25 @@ class PathBridge {
1442
1701
  const identifyPayload = isRecord(payload) ? payload : {};
1443
1702
  const requestedTag = identifyPayload.client ?? identifyPayload.tag ?? client ?? 'unknown';
1444
1703
  this.setClientTag(sender, String(requestedTag));
1704
+ this.sendCapabilities(sender);
1445
1705
  break;
1446
1706
  }
1707
+ case 'capabilities':
1708
+ // Capability advertisements are relayed so a Web/Tauri client
1709
+ // can negotiate the same contract with Godot or a mobile peer.
1710
+ this.broadcast('capabilities', payload || {});
1711
+ break;
1712
+ case 'analyze':
1713
+ case 'query':
1714
+ case 'readEvidence':
1715
+ case 'exportBundle':
1716
+ // The optional host adapter owns domain execution while the
1717
+ // bridge retains correlation, timeout, and cancellation policy.
1718
+ this.executeHostOperation(type, payload, envelope, sender);
1719
+ break;
1720
+ case 'cancel':
1721
+ this.cancelHostOperation(payload, sender);
1722
+ break;
1447
1723
  case 'requestPath':
1448
1724
  this.handlePathRequest(sender);
1449
1725
  break;
@@ -1580,6 +1856,12 @@ class PathBridge {
1580
1856
  }
1581
1857
  close() {
1582
1858
  this.clearAllPendingPathRequests();
1859
+ Array.from(this.pendingHostOperations.entries()).forEach(([requestId, pending]) => {
1860
+ clearTimeout(pending.timer);
1861
+ pending.controller.abort();
1862
+ this.hostAdapter?.cancel?.(requestId);
1863
+ });
1864
+ this.pendingHostOperations.clear();
1583
1865
  Array.from(this.pendingMermaidRenderRequests.values()).forEach((pendingRequest) => {
1584
1866
  clearTimeout(pendingRequest.timer);
1585
1867
  pendingRequest.reject(new Error('PathBridge is closing before Mermaid render completed.'));
@@ -1591,5 +1873,11 @@ class PathBridge {
1591
1873
  this.clients.clear();
1592
1874
  this.clientMeta.clear();
1593
1875
  }
1876
+ waitUntilReady() {
1877
+ return this.readyPromise;
1878
+ }
1879
+ getPort() {
1880
+ return this.port;
1881
+ }
1594
1882
  }
1595
1883
  exports.PathBridge = PathBridge;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeResourceReference = normalizeResourceReference;
4
+ /**
5
+ * Shared, host-neutral reference normalization used by Graph and backend
6
+ * identity generation. It intentionally has no Node or platform dependency so
7
+ * the path-core bundle can execute in a browser VM and in Godot WebView.
8
+ */
9
+ function normalizeResourceReference(reference) {
10
+ if (typeof reference !== 'string') {
11
+ throw new Error('Resource reference must be a string');
12
+ }
13
+ if (reference.includes('\0')) {
14
+ throw new Error('Resource reference must not contain NUL characters');
15
+ }
16
+ return reference.normalize('NFC').replace(/\\/g, '/').toLowerCase();
17
+ }
@@ -0,0 +1,142 @@
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 child_process_1 = require("child_process");
40
+ jest.mock('child_process', () => ({ ...jest.requireActual('child_process'), spawnSync: jest.fn() }));
41
+ const { prepareDesktopGodotPack } = require('../scripts/prepare-desktop-godot-pack');
42
+ const { resolveHostGodotBinaryName } = require('../scripts/tauri-sidecar-utils');
43
+ const runtime = require('../config/godot-desktop-runtime.json');
44
+ const spawn = child_process_1.spawnSync;
45
+ describe('desktop Godot resource package', () => {
46
+ let directory;
47
+ const write = (relative, content) => {
48
+ const file = path.join(directory, relative);
49
+ fs.mkdirSync(path.dirname(file), { recursive: true });
50
+ fs.writeFileSync(file, content);
51
+ };
52
+ beforeEach(() => {
53
+ directory = fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'desktop-godot-pack-'));
54
+ write('path_mode/project.godot', `config_version=5\nconfig/features=PackedStringArray("${runtime.version}", "Forward+")\n`);
55
+ write('path_mode/export_presets.cfg', '[preset.0]\nname="Windows Desktop"\n');
56
+ write('path_mode/scenes/main.tscn', '[gd_scene format=3]\n');
57
+ write('path_mode/scripts/main.gd', 'extends Node\n');
58
+ write('path_mode/shaders/main.gdshader', 'shader_type spatial;\n');
59
+ write('path_mode/assets/background.exr', 'fixture');
60
+ write(`src-tauri/bin/${resolveHostGodotBinaryName()}`, 'engine fixture');
61
+ spawn.mockImplementation((_executable, args) => {
62
+ if (args.includes('--version'))
63
+ return { status: 0, stdout: `${runtime.version}.stable.official.fixture\n`, stderr: '' };
64
+ if (args.includes('--export-pack'))
65
+ fs.writeFileSync(args[args.length - 1], 'GDPC resource fixture');
66
+ return { status: 0, stdout: 'done\n', stderr: '' };
67
+ });
68
+ });
69
+ afterEach(() => {
70
+ jest.resetAllMocks();
71
+ fs.rmSync(directory, { recursive: true, force: true });
72
+ });
73
+ test('exports only runtime roots and binds the pack to source and engine bytes', () => {
74
+ write('path_mode/.godot/editor/state', 'private editor state');
75
+ write('path_mode/tmp/debug.gd', 'debug fixture');
76
+ const report = prepareDesktopGodotPack(directory);
77
+ expect(report.engineVersion).toBe(`${runtime.version}.stable.official.fixture`);
78
+ expect(report.pack.path).toBe('output/desktop/path_mode.pck');
79
+ expect(report.pack.sha256).toMatch(/^[a-f0-9]{64}$/);
80
+ expect(report.files.map((file) => file.path)).toEqual(expect.arrayContaining(['project.godot', 'scenes/main.tscn', 'assets/background.exr']));
81
+ expect(report.files.some((file) => /editor|tmp/.test(file.path))).toBe(false);
82
+ expect(fs.readdirSync(path.join(directory, 'output/desktop')).some(name => name.startsWith('.pathmode-'))).toBe(false);
83
+ });
84
+ test('rejects an engine version that cannot consume the declared project', () => {
85
+ spawn.mockReturnValue({ status: 0, stdout: '4.3.stable.official.fixture\n', stderr: '' });
86
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/requires Godot/);
87
+ expect(spawn).toHaveBeenCalledTimes(1);
88
+ });
89
+ test('rejects SVG before invoking Godot import', () => {
90
+ write('path_mode/assets/unsupported.svg', '<svg/>');
91
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/cannot import SVG/);
92
+ expect(spawn.mock.calls.every(([, args]) => args.includes('--version'))).toBe(true);
93
+ });
94
+ test('does not accept zero exit after a Godot script error or replace an earlier pack', () => {
95
+ write('output/desktop/path_mode.pck', 'GDPC previous pack');
96
+ spawn.mockImplementation((_executable, args) => args.includes('--version')
97
+ ? { status: 0, stdout: `${runtime.version}.stable.official.fixture`, stderr: '' }
98
+ : { status: 0, stdout: '', stderr: '\u001b[31mSCRIPT ERROR: invalid exported script\u001b[0m\n' });
99
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/invalid exported script/);
100
+ expect(fs.readFileSync(path.join(directory, 'output/desktop/path_mode.pck'), 'utf8')).toBe('GDPC previous pack');
101
+ });
102
+ test('rejects successful export without a resource pack', () => {
103
+ spawn.mockImplementation((_executable, args) => ({ status: 0, stdout: args.includes('--version') ? `${runtime.version}.stable.official.fixture` : '', stderr: '' }));
104
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/ENOENT/);
105
+ });
106
+ test('rejects an invalid pack header', () => {
107
+ spawn.mockImplementation((_executable, args) => {
108
+ if (args.includes('--export-pack'))
109
+ fs.writeFileSync(args[args.length - 1], 'not a pack');
110
+ return { status: 0, stdout: args.includes('--version') ? `${runtime.version}.stable.official.fixture` : '', stderr: '' };
111
+ });
112
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/PCK resource pack/);
113
+ });
114
+ test('rejects source changes between staging and publication', () => {
115
+ spawn.mockImplementation((_executable, args) => {
116
+ if (args.includes('--export-pack')) {
117
+ fs.writeFileSync(args[args.length - 1], 'GDPC resource fixture');
118
+ write('path_mode/scripts/main.gd', 'extends Node\n# changed during export\n');
119
+ }
120
+ return { status: 0, stdout: args.includes('--version') ? `${runtime.version}.stable.official.fixture` : '', stderr: '' };
121
+ });
122
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/inputs changed/);
123
+ expect(fs.existsSync(path.join(directory, 'output/desktop/path_mode.pck'))).toBe(false);
124
+ });
125
+ test('rejects files added between staging and publication', () => {
126
+ spawn.mockImplementation((_executable, args) => {
127
+ if (args.includes('--export-pack')) {
128
+ fs.writeFileSync(args[args.length - 1], 'GDPC resource fixture');
129
+ write('path_mode/scripts/added.gd', 'extends Node\n');
130
+ }
131
+ return { status: 0, stdout: args.includes('--version') ? `${runtime.version}.stable.official.fixture` : '', stderr: '' };
132
+ });
133
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/inputs changed/);
134
+ expect(fs.existsSync(path.join(directory, 'output/desktop/path_mode.pck'))).toBe(false);
135
+ });
136
+ test('rejects a symlinked runtime root before importing external files', () => {
137
+ fs.renameSync(path.join(directory, 'path_mode/assets'), path.join(directory, 'external-assets'));
138
+ fs.symlinkSync(path.join(directory, 'external-assets'), path.join(directory, 'path_mode/assets'), process.platform === 'win32' ? 'junction' : 'dir');
139
+ expect(() => prepareDesktopGodotPack(directory)).toThrow(/must not be a symlink/);
140
+ expect(spawn.mock.calls.every(([, args]) => args.includes('--version'))).toBe(true);
141
+ });
142
+ });
@@ -0,0 +1,66 @@
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 vm = __importStar(require("node:vm"));
37
+ const { waitForAcceptanceGraph } = require('../scripts/verify-desktop-runtime');
38
+ const graph = { nodes: [{ id: 'Alpha' }, { id: 'Beta' }], edges: [{ source: 'Alpha', target: 'Beta' }] };
39
+ test('waits past the build reload and returns one snapshot from the ready document', async () => {
40
+ const pages = [
41
+ vm.createContext({ performance: { timeOrigin: 100 }, graphData: graph }),
42
+ vm.createContext({ performance: { timeOrigin: 200 } }),
43
+ vm.createContext({ performance: { timeOrigin: 200 }, graphData: graph }),
44
+ ];
45
+ const evaluate = jest.fn(async (expression) => {
46
+ const page = pages.shift();
47
+ if (!page)
48
+ throw new Error('Unexpected extra WebView read');
49
+ return vm.runInContext(expression, page);
50
+ });
51
+ await expect(waitForAcceptanceGraph({ evaluate }, 100)).resolves.toEqual({ nodes: ['Alpha', 'Beta'], edges: 1 });
52
+ expect(evaluate).toHaveBeenCalledTimes(3);
53
+ });
54
+ test('captures lexical graphData and its links before another CDP request can replace the document', async () => {
55
+ const page = vm.createContext({ performance: { timeOrigin: 200 } });
56
+ vm.runInContext(`const graphData = ${JSON.stringify({ nodes: graph.nodes, links: graph.edges })}`, page);
57
+ const evaluate = jest.fn(async (expression) => {
58
+ const snapshot = vm.runInContext(expression, page);
59
+ // Navigation destroys the document after this single serialized CDP response.
60
+ if (evaluate.mock.calls.length > 1)
61
+ throw new Error('Execution context was destroyed');
62
+ return snapshot;
63
+ });
64
+ await expect(waitForAcceptanceGraph({ evaluate }, 100)).resolves.toEqual({ nodes: ['Alpha', 'Beta'], edges: 1 });
65
+ expect(evaluate).toHaveBeenCalledTimes(1);
66
+ });