noteconnection 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +257 -1803
  2. package/dist/src/agent_workspace.contract.parity.test.js +105 -421
  3. package/dist/src/agent_workspace.frontend.test.js +410 -11
  4. package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
  5. package/dist/src/appimage.patchelf.test.js +113 -0
  6. package/dist/src/appimage.portability.test.js +156 -0
  7. package/dist/src/backend/FileLoader.js +18 -4
  8. package/dist/src/backend/FileLoader.test.js +125 -0
  9. package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
  10. package/dist/src/backend/GraphBuilder.js +66 -18
  11. package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
  12. package/dist/src/backend/GraphMetrics.js +0 -3
  13. package/dist/src/backend/ResourceIdentity.js +155 -0
  14. package/dist/src/backend/ResourceIdentity.test.js +113 -0
  15. package/dist/src/backend/algorithms/CycleDetection.js +0 -1
  16. package/dist/src/backend/algorithms/HybridEngine.js +0 -3
  17. package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
  18. package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
  19. package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
  20. package/dist/src/backend/build_dag.js +0 -1
  21. package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
  22. package/dist/src/capacitor.runtime.contract.test.js +11 -2
  23. package/dist/src/core/Graph.js +138 -42
  24. package/dist/src/core/Graph.test.js +74 -0
  25. package/dist/src/core/NoteConnection.js +2 -2
  26. package/dist/src/core/PathBridge.js +265 -2
  27. package/dist/src/core/ResourceReference.js +17 -0
  28. package/dist/src/desktop.godot.pack.test.js +142 -0
  29. package/dist/src/desktop.runtime.graph.test.js +66 -0
  30. package/dist/src/export/WorkspaceExportBundle.js +44 -0
  31. package/dist/src/export/WorkspaceExportBundle.test.js +61 -0
  32. package/dist/src/foundation.release.evidence.contract.test.js +127 -9
  33. package/dist/src/foundation.sqlite.runtime.contract.test.js +6 -0
  34. package/dist/src/frontend/README.md +257 -1803
  35. package/dist/src/frontend/agent_workspace.js +665 -7
  36. package/dist/src/frontend/index.html +31 -2
  37. package/dist/src/frontend/knowledge_projection_contract.js +230 -0
  38. package/dist/src/frontend/knowledge_projection_store.js +214 -0
  39. package/dist/src/frontend/libs/path_core.js +158 -42
  40. package/dist/src/frontend/locales/en.json +32 -0
  41. package/dist/src/frontend/locales/zh.json +32 -0
  42. package/dist/src/frontend/mobile_budget_runtime.js +33 -0
  43. package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
  44. package/dist/src/frontend/mobile_identity_contract.js +221 -0
  45. package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
  46. package/dist/src/frontend/path.html +6 -2
  47. package/dist/src/frontend/simulationWorker.js +1 -1
  48. package/dist/src/frontend/source_manager.js +110 -4
  49. package/dist/src/frontend/storage_provider.js +661 -71
  50. package/dist/src/frontend/styles.css +107 -13
  51. package/dist/src/frontend/workspace_panes.js +111 -7
  52. package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
  53. package/dist/src/graph.answer.operator.contract.test.js +72 -0
  54. package/dist/src/index.js +6 -2
  55. package/dist/src/index.knowledge-root.test.js +118 -0
  56. package/dist/src/indexing/IndexLifecycle.js +22 -0
  57. package/dist/src/indexing/IndexLifecycle.test.js +24 -0
  58. package/dist/src/knowledge.api.contract.test.js +4 -2
  59. package/dist/src/knowledge_projection.contract.test.js +134 -0
  60. package/dist/src/knowledge_projection_store.test.js +200 -0
  61. package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
  62. package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
  63. package/dist/src/learning/KnowledgeLearningPlatform.js +4687 -3892
  64. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +418 -0
  65. package/dist/src/learning/KnowledgeLearningPlatform.test.js +243 -6
  66. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +25 -1
  67. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +13 -5
  68. package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
  69. package/dist/src/learning/PublicAnswerContract.test.js +85 -0
  70. package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
  71. package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
  72. package/dist/src/learning/agentConversationExecution.js +211 -0
  73. package/dist/src/learning/agentConversationExecution.test.js +209 -0
  74. package/dist/src/learning/agentConversationSerialization.js +266 -0
  75. package/dist/src/learning/agentConversationSerialization.test.js +165 -0
  76. package/dist/src/learning/agentResponseBudget.js +179 -0
  77. package/dist/src/learning/agentResponseBudget.test.js +97 -0
  78. package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
  79. package/dist/src/learning/answerReleaseReview.js +1191 -250
  80. package/dist/src/learning/answerReleaseReview.test.js +1293 -7
  81. package/dist/src/learning/answerTaskPlan.js +473 -0
  82. package/dist/src/learning/conversationComposer.js +627 -386
  83. package/dist/src/learning/conversationComposer.test.js +1403 -0
  84. package/dist/src/learning/evidenceContextAssembler.js +312 -120
  85. package/dist/src/learning/graphAnswerCoverage.js +37 -0
  86. package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
  87. package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
  88. package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
  89. package/dist/src/learning/graphAnswerFacts.js +94 -0
  90. package/dist/src/learning/graphAnswerFacts.test.js +39 -0
  91. package/dist/src/learning/graphAnswerPlan.js +908 -0
  92. package/dist/src/learning/graphAnswerPlan.test.js +907 -0
  93. package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
  94. package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
  95. package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
  96. package/dist/src/learning/graphClaimMatcher.js +104 -0
  97. package/dist/src/learning/graphConditionedContext.js +109 -0
  98. package/dist/src/learning/graphConditionedContext.test.js +99 -0
  99. package/dist/src/learning/graphContextAssembler.js +3 -13
  100. package/dist/src/learning/graphContextAssembler.test.js +2 -2
  101. package/dist/src/learning/graphExpansionPolicy.js +22 -0
  102. package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
  103. package/dist/src/learning/identityMetadata.test.js +26 -0
  104. package/dist/src/learning/index.js +1 -0
  105. package/dist/src/learning/mobileAnswerProjection.js +104 -0
  106. package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
  107. package/dist/src/learning/queryBackend.js +34 -10
  108. package/dist/src/learning/queryBackend.test.js +21 -0
  109. package/dist/src/learning/ragContextPack.js +115 -16
  110. package/dist/src/learning/ragContextPack.test.js +151 -0
  111. package/dist/src/learning/ragEvidenceQuality.js +96 -0
  112. package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
  113. package/dist/src/learning/ragPublicText.js +67 -4
  114. package/dist/src/learning/ragPublicText.test.js +57 -0
  115. package/dist/src/learning/ragSufficiencyJudge.js +11 -1
  116. package/dist/src/learning/ragSufficiencyProviderJudge.js +16 -26
  117. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +51 -0
  118. package/dist/src/learning/requestNormalization.js +106 -0
  119. package/dist/src/learning/requestNormalization.test.js +101 -0
  120. package/dist/src/learning/store.js +116 -12
  121. package/dist/src/learning/store.test.js +299 -0
  122. package/dist/src/learning/vectorAccelerationAdapter.js +22 -6
  123. package/dist/src/learning/vectorAccelerationAdapter.test.js +30 -0
  124. package/dist/src/learning/workspaceHydration.js +168 -0
  125. package/dist/src/learning/workspaceHydration.test.js +30 -0
  126. package/dist/src/license.policy.contract.test.js +9 -4
  127. package/dist/src/markdown/MarkdownGateway.js +4 -0
  128. package/dist/src/markdown/MarkdownGateway.test.js +59 -0
  129. package/dist/src/middleware/SseResponseWriter.js +122 -0
  130. package/dist/src/middleware/SseResponseWriter.test.js +54 -0
  131. package/dist/src/middleware/auth.js +28 -7
  132. package/dist/src/middleware/auth.test.js +33 -0
  133. package/dist/src/middleware/index.js +2 -1
  134. package/dist/src/mobile.android.evidence.contract.test.js +146 -0
  135. package/dist/src/mobile.android.signing.contract.test.js +66 -0
  136. package/dist/src/mobile.artifact.contract.test.js +144 -0
  137. package/dist/src/mobile.budget.contract.test.js +90 -0
  138. package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
  139. package/dist/src/mobile.graph.parity.contract.test.js +207 -0
  140. package/dist/src/mobile.identity.contract.test.js +66 -0
  141. package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
  142. package/dist/src/mobile.identity.corpus.test.js +40 -0
  143. package/dist/src/mobile.native.recovery.contract.test.js +64 -0
  144. package/dist/src/mobile.pipeline.test.js +11 -1
  145. package/dist/src/mobile.profile.contract.test.js +225 -0
  146. package/dist/src/mobile.semantic.parity.test.js +92 -0
  147. package/dist/src/mobile_exact_analyzer.test.js +113 -0
  148. package/dist/src/notemd/ContentGenerator.js +4 -9
  149. package/dist/src/notemd/FileProcessor.js +4 -9
  150. package/dist/src/notemd/NotemdService.js +12 -17
  151. package/dist/src/notemd/Translator.js +4 -9
  152. package/dist/src/notemd/progressReporter.js +9 -0
  153. package/dist/src/notemd.server.integration.test.js +119 -4
  154. package/dist/src/notemd.workflow.pipeline.test.js +1 -1
  155. package/dist/src/pathbridge.handshake.contract.test.js +29 -0
  156. package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
  157. package/dist/src/pathcore.bundle.contract.test.js +8 -0
  158. package/dist/src/platform/ExportProfile.js +28 -0
  159. package/dist/src/platform/MobileBudget.js +11 -0
  160. package/dist/src/platform/PlatformCapabilities.js +14 -0
  161. package/dist/src/platform/PlatformCapabilities.test.js +6 -0
  162. package/dist/src/query_backend.external_http.integration.test.js +2 -2
  163. package/dist/src/release.godot.mirror.contract.test.js +28 -4
  164. package/dist/src/resources/ResourceRegistry.js +40 -0
  165. package/dist/src/resources/ResourceRegistry.test.js +36 -0
  166. package/dist/src/routes/index.js +0 -4
  167. package/dist/src/routes/knowledge.js +46 -33
  168. package/dist/src/routes/knowledgePayload.js +185 -0
  169. package/dist/src/routes/knowledgePayload.test.js +53 -0
  170. package/dist/src/routes/markdown.js +8 -0
  171. package/dist/src/routes/notemd.js +990 -234
  172. package/dist/src/routes/registry.contract.test.js +5 -2
  173. package/dist/src/routes/registry.shadow.contract.test.js +22 -0
  174. package/dist/src/routes/render.js +14 -51
  175. package/dist/src/runtime.capabilities.test.js +18 -2
  176. package/dist/src/server.js +566 -1090
  177. package/dist/src/server.migration.test.js +417 -15
  178. package/dist/src/sidecar.build.lock.contract.test.js +201 -0
  179. package/dist/src/sidecar.freshness.contract.test.js +184 -0
  180. package/dist/src/sidecar.replacement.boundary.contract.test.js +6 -3
  181. package/dist/src/sidecar.supply.readiness.contract.test.js +11 -0
  182. package/dist/src/simulation.worker.offline.test.js +104 -0
  183. package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
  184. package/dist/src/storage.provider.contract.test.js +152 -1
  185. package/dist/src/tauri.frontend.build.contract.test.js +8 -0
  186. package/dist/src/tauri.window.evidence.execution.test.js +68 -0
  187. package/dist/src/utils/RuntimePaths.js +6 -0
  188. package/dist/src/utils/RuntimePaths.test.js +27 -0
  189. package/dist/src/windows.installer.build.test.js +109 -0
  190. package/dist/src/windows.installer.payload.test.js +76 -0
  191. package/dist/src/windows.installer.runtime.test.js +69 -0
  192. package/dist/src/workspace/WorkspaceRegistry.js +13 -0
  193. package/package.json +32 -10
  194. package/dist/src/routes/data.js +0 -267
  195. package/dist/src/routes/diagnostics.js +0 -51
@@ -0,0 +1,225 @@
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 crypto = __importStar(require("crypto"));
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const PlatformCapabilities_1 = require("./platform/PlatformCapabilities");
40
+ const RenderMaterializer_1 = require("./platform/RenderMaterializer");
41
+ describe('mobile-slim profile contract', () => {
42
+ const repoRoot = path.resolve(__dirname, '..');
43
+ const analyzerPath = path.join(repoRoot, 'src', 'frontend', 'mobile_exact_analyzer.js');
44
+ const projectionContractPath = path.join(repoRoot, 'src', 'frontend', 'knowledge_projection_contract.js');
45
+ const verifierPath = path.join(repoRoot, 'scripts', 'verify-mobile-slim-budget.js');
46
+ const preparePath = path.join(repoRoot, 'scripts', 'prepare-mobile-slim.js');
47
+ test('declares sidecar-free local analysis with optional remote inference and hard budgets', () => {
48
+ const capabilities = (0, PlatformCapabilities_1.resolvePlatformCapabilities)({ exportProfileId: 'mobile-slim' });
49
+ expect(capabilities.retrieval.supportsSidecar).toBe(false);
50
+ expect(capabilities.retrieval.supportsLocalIngest).toBe(true);
51
+ expect(capabilities.retrieval.supportsLocalExactQuery).toBe(true);
52
+ expect(capabilities.retrieval.supportsRemoteInference).toBe(true);
53
+ expect(capabilities.retrieval.requiresRemoteInference).toBe(false);
54
+ expect(capabilities.export.assetBudgetBytes).toBe(25 * 1024 * 1024);
55
+ expect(capabilities.export.maxResidentBytes).toBe(256 * 1024 * 1024);
56
+ });
57
+ test('rejects SVG materialization for mobile even when explicitly requested', () => {
58
+ const decision = (0, RenderMaterializer_1.resolveRenderMaterializationDecision)({
59
+ exportProfileId: 'mobile-slim',
60
+ includeSvg: true,
61
+ includeStages: true,
62
+ rendererPreference: 'frontend',
63
+ });
64
+ expect(decision.includeSvg).toBe(false);
65
+ expect(decision.vectorSuppressed).toBe(true);
66
+ expect(decision.responseArtifact).toBe('png');
67
+ expect(decision.rendererPreference).toBe('local');
68
+ });
69
+ test('ships a callable bounded exact graph analyzer without retaining document bodies', () => {
70
+ expect(fs.existsSync(analyzerPath)).toBe(true);
71
+ const analyzer = require(analyzerPath);
72
+ const index = analyzer.createMobileExactIndex({
73
+ nodes: [
74
+ { id: 'fundamentals/alpha', label: 'Alpha', content: 'must not be retained' },
75
+ { id: 'fundamentals/beta', label: 'Beta', metadata: { tags: ['core'] } },
76
+ { id: 'advanced/gamma', label: 'Gamma' },
77
+ ],
78
+ edges: [
79
+ { source: 'fundamentals/alpha', target: 'fundamentals/beta', type: 'prerequisite' },
80
+ { source: 'fundamentals/beta', target: 'advanced/gamma', type: 'next' },
81
+ ],
82
+ });
83
+ expect(index.searchExact('beta')).toEqual([
84
+ expect.objectContaining({ id: 'fundamentals/beta' }),
85
+ ]);
86
+ expect(index.searchExact('core')).toEqual([
87
+ expect.objectContaining({ id: 'fundamentals/beta' }),
88
+ ]);
89
+ expect(index.neighbors('fundamentals/beta')).toEqual([
90
+ expect.objectContaining({ id: 'advanced/gamma' }),
91
+ expect.objectContaining({ id: 'fundamentals/alpha' }),
92
+ ]);
93
+ expect(index.shortestPath('fundamentals/alpha', 'advanced/gamma')).toEqual([
94
+ 'fundamentals/alpha',
95
+ 'fundamentals/beta',
96
+ 'advanced/gamma',
97
+ ]);
98
+ expect(index.statistics()).toEqual({ nodeCount: 3, edgeCount: 2 });
99
+ expect(JSON.stringify(index.searchExact('alpha'))).not.toContain('must not be retained');
100
+ });
101
+ test('normalizes exact lookup keys independently of the device locale', () => {
102
+ const analyzerSource = fs.readFileSync(analyzerPath, 'utf8');
103
+ const analyzer = require(analyzerPath);
104
+ const index = analyzer.createMobileExactIndex({
105
+ nodes: [{ id: 'unicode-i', label: '\u0130' }],
106
+ edges: [],
107
+ });
108
+ expect(analyzerSource).not.toContain('.toLocaleLowerCase(');
109
+ expect(index.searchExact('i\u0307')).toEqual([
110
+ expect.objectContaining({ id: 'unicode-i' }),
111
+ ]);
112
+ });
113
+ test('does not cross the requested visited-node ceiling during path traversal', () => {
114
+ const analyzer = require(analyzerPath);
115
+ const index = analyzer.createMobileExactIndex({
116
+ nodes: [
117
+ { id: 'source' },
118
+ { id: 'first-branch' },
119
+ { id: 'target' },
120
+ ],
121
+ edges: [
122
+ { source: 'source', target: 'first-branch' },
123
+ { source: 'source', target: 'target' },
124
+ ],
125
+ });
126
+ expect(index.shortestPath('source', 'target', 2, 2)).toBeNull();
127
+ });
128
+ test('exposes exact query and path operations through the runtime storage boundary', () => {
129
+ const storageProvider = fs.readFileSync(path.join(repoRoot, 'src', 'frontend', 'storage_provider.js'), 'utf8');
130
+ const indexHtml = fs.readFileSync(path.join(repoRoot, 'src', 'frontend', 'index.html'), 'utf8');
131
+ const analyzerScriptOffset = indexHtml.indexOf('<script src="mobile_exact_analyzer.js"></script>');
132
+ const identityScriptOffset = indexHtml.indexOf('<script src="mobile_identity_contract.js"></script>');
133
+ const storageScriptOffset = indexHtml.indexOf('<script src="storage_provider.js"></script>');
134
+ expect(storageProvider).toContain('async queryKnowledgeBaseExact(request)');
135
+ expect(storageProvider).toContain('async findKnowledgePath(request)');
136
+ expect(storageProvider).toContain("this.readGeneratedAsset('graph_data.json')");
137
+ expect(analyzerScriptOffset).toBeGreaterThan(-1);
138
+ expect(identityScriptOffset).toBeGreaterThan(analyzerScriptOffset);
139
+ expect(identityScriptOffset).toBeLessThan(storageScriptOffset);
140
+ expect(analyzerScriptOffset).toBeLessThan(storageScriptOffset);
141
+ });
142
+ test('loads one versioned projection contract before both mobile consumers', () => {
143
+ const projectionContract = fs.readFileSync(projectionContractPath, 'utf8');
144
+ const storageProvider = fs.readFileSync(path.join(repoRoot, 'src', 'frontend', 'storage_provider.js'), 'utf8');
145
+ const indexHtml = fs.readFileSync(path.join(repoRoot, 'src', 'frontend', 'index.html'), 'utf8');
146
+ const projectionScriptOffset = indexHtml.indexOf('<script src="knowledge_projection_contract.js"></script>');
147
+ expect(projectionContract).toContain('schemaVersion: SCHEMA_VERSION');
148
+ expect(projectionContract).toContain('MAX_NEIGHBORS');
149
+ expect(storageProvider).toContain('window.NoteConnectionKnowledgeProjection');
150
+ expect(storageProvider).toContain('createKnowledgeProjection');
151
+ expect(storageProvider).toContain('createFileProjectionStore');
152
+ expect(storageProvider).toContain("fileName: 'graph_data.json'");
153
+ expect(projectionScriptOffset).toBeGreaterThan(-1);
154
+ expect(projectionScriptOffset).toBeLessThan(indexHtml.indexOf('<script src="mobile_exact_analyzer.js"></script>'));
155
+ expect(projectionScriptOffset).toBeLessThan(indexHtml.indexOf('<script src="storage_provider.js"></script>'));
156
+ });
157
+ test('fails closed for oversized, forbidden, and over-RSS mobile staging evidence', () => {
158
+ expect(fs.existsSync(verifierPath)).toBe(true);
159
+ const verifier = require(verifierPath);
160
+ const fixtureRoot = fs.mkdtempSync(path.join(repoRoot, '.mobile-slim-contract-'));
161
+ try {
162
+ fs.writeFileSync(path.join(fixtureRoot, 'index.html'), crypto.randomBytes(2048));
163
+ expect(() => verifier.assertMobileSlimBudget({
164
+ stagingDir: fixtureRoot,
165
+ assetBudgetBytes: 128,
166
+ maxResidentBytes: 1024,
167
+ })).toThrow(/compressed payload/i);
168
+ fs.rmSync(path.join(fixtureRoot, 'index.html'));
169
+ fs.writeFileSync(path.join(fixtureRoot, 'server-aarch64-linux'), 'forbidden');
170
+ expect(() => verifier.assertMobileSlimBudget({
171
+ stagingDir: fixtureRoot,
172
+ assetBudgetBytes: 4096,
173
+ maxResidentBytes: 1024,
174
+ })).toThrow(/forbidden mobile artifact/i);
175
+ fs.rmSync(path.join(fixtureRoot, 'server-aarch64-linux'));
176
+ fs.writeFileSync(path.join(fixtureRoot, 'index.html'), 'ok');
177
+ const rssEvidencePath = path.join(fixtureRoot, 'rss-evidence.json');
178
+ fs.writeFileSync(rssEvidencePath, JSON.stringify({ peakResidentBytes: 2048 }));
179
+ expect(() => verifier.assertMobileSlimBudget({
180
+ stagingDir: fixtureRoot,
181
+ assetBudgetBytes: 4096,
182
+ maxResidentBytes: 1024,
183
+ rssEvidencePath,
184
+ })).toThrow(/peak RSS/i);
185
+ }
186
+ finally {
187
+ fs.rmSync(fixtureRoot, { recursive: true, force: true });
188
+ }
189
+ });
190
+ test('routes both Android packagers through the deterministic mobile staging directory', () => {
191
+ expect(fs.existsSync(preparePath)).toBe(true);
192
+ const pkg = JSON.parse(fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
193
+ const capacitorConfig = fs.readFileSync(path.join(repoRoot, 'capacitor.config.ts'), 'utf8');
194
+ const capacitorBuild = fs.readFileSync(path.join(repoRoot, 'build_apk.bat'), 'utf8');
195
+ const tauriAndroidConfig = JSON.parse(fs.readFileSync(path.join(repoRoot, 'src-tauri', 'tauri.android.conf.json'), 'utf8'));
196
+ expect(pkg.scripts['mobile:prepare:slim']).toContain('prepare-mobile-slim.js');
197
+ expect(pkg.scripts['mobile:prepare:slim']).toContain('verify-mobile-slim-budget.js');
198
+ expect(pkg.scripts['tauri:android:init']).toContain('mobile:prepare:slim');
199
+ expect(pkg.scripts['verify:mobile:slim:budget']).toContain('verify-mobile-slim-budget.js');
200
+ expect(pkg.scripts['tauri:android:build']).toContain('mobile:prepare:slim');
201
+ expect(pkg.scripts['tauri:android:build']).not.toContain('build:sidecar');
202
+ expect(capacitorConfig).toContain('NOTE_CONNECTION_MOBILE_WEB_DIR');
203
+ expect(capacitorBuild).toContain('npm run mobile:prepare:slim');
204
+ expect(capacitorBuild).toContain('NOTE_CONNECTION_MOBILE_WEB_DIR');
205
+ expect(tauriAndroidConfig.build?.frontendDist).toBe('../dist/mobile-slim/frontend');
206
+ expect(tauriAndroidConfig.bundle?.externalBin).toEqual([]);
207
+ });
208
+ test('keeps Godot Android integration explicit instead of enabling it in mobile-slim', () => {
209
+ const runner = fs.readFileSync(path.join(repoRoot, 'scripts', 'run-tauri-android.js'), 'utf8');
210
+ const patcher = fs.readFileSync(path.join(repoRoot, 'scripts', 'apply-tauri-android-pathmode.js'), 'utf8');
211
+ expect(runner).toContain('NOTE_CONNECTION_ANDROID_INCLUDE_GODOT_PATHMODE');
212
+ expect(runner).toContain("runPathmodePatch({ mode: 'disable'");
213
+ expect(patcher).toContain("process.argv.includes('--disable')");
214
+ expect(patcher).toContain('removePathmodeAssets');
215
+ });
216
+ test('keeps the semantic comparator out of mobile-slim runtime staging', () => {
217
+ const prepareSource = fs.readFileSync(preparePath, 'utf8');
218
+ expect(prepareSource).toContain('mobile_semantic_comparator\\.js');
219
+ });
220
+ test('does not allocate the full-content graph on Android runtime builds', () => {
221
+ const rustSource = fs.readFileSync(path.join(repoRoot, 'src-tauri', 'src', 'lib.rs'), 'utf8');
222
+ expect(rustSource).toContain('#[cfg(not(target_os = "android"))]\n let full_nodes');
223
+ expect(rustSource).toContain('#[cfg(not(target_os = "android"))]\n let full_graph');
224
+ });
225
+ });
@@ -0,0 +1,92 @@
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 path = __importStar(require("path"));
37
+ const comparator = require(path.resolve(__dirname, 'frontend', 'mobile_semantic_comparator.js'));
38
+ const projectionContract = require(path.resolve(__dirname, 'frontend', 'knowledge_projection_contract.js'));
39
+ describe('cross-host mobile semantic parity', () => {
40
+ test('matches canonical nodes and directed edge provenance across host-specific ids', () => {
41
+ const left = projectionContract.createKnowledgeProjection({
42
+ nodes: [
43
+ { id: 'base', canonicalId: 'financial/base', sourceUri: 'note://workspace/v1/financial/base.md' },
44
+ { id: 'intro', canonicalId: 'financial/intro', sourceUri: 'note://workspace/v1/financial/intro.md' },
45
+ ],
46
+ edges: [{
47
+ source: 'base',
48
+ target: 'intro',
49
+ sourceUri: 'note://workspace/v1/financial/base.md',
50
+ targetUri: 'note://workspace/v1/financial/intro.md',
51
+ type: 'explicit-prerequisite',
52
+ kind: 'explicit',
53
+ provenance: 'explicit-prerequisite',
54
+ }],
55
+ });
56
+ const right = projectionContract.createKnowledgeProjection({
57
+ nodes: [
58
+ { id: 'financial/base', canonicalId: 'financial/base', sourceUri: 'note://workspace/v1/financial/base.md' },
59
+ { id: 'financial/intro', canonicalId: 'financial/intro', sourceUri: 'note://workspace/v1/financial/intro.md' },
60
+ ],
61
+ edges: [{
62
+ source: 'financial/base',
63
+ target: 'financial/intro',
64
+ type: 'explicit-prerequisite',
65
+ kind: 'explicit',
66
+ provenance: 'explicit-prerequisite',
67
+ }],
68
+ });
69
+ expect(comparator.compareSemanticProjections(left, right).equal).toBe(true);
70
+ expect(() => comparator.assertSemanticParity(left, right, 'fixture')).not.toThrow();
71
+ });
72
+ test('reports provenance changes instead of collapsing same-endpoint edges', () => {
73
+ const left = {
74
+ nodes: [
75
+ { id: 'a', canonicalId: 'a', sourceUri: 'note://workspace/v1/a.md' },
76
+ { id: 'b', canonicalId: 'b', sourceUri: 'note://workspace/v1/b.md' },
77
+ ],
78
+ edges: [{ source: 'a', target: 'b', type: 'wiki-link', provenance: 'wiki-link' }],
79
+ };
80
+ const right = {
81
+ nodes: [
82
+ { id: 'a', canonicalId: 'a', sourceUri: 'note://workspace/v1/a.md' },
83
+ { id: 'b', canonicalId: 'b', sourceUri: 'note://workspace/v1/b.md' },
84
+ ],
85
+ edges: [{ source: 'a', target: 'b', type: 'markdown-link', provenance: 'markdown-link' }],
86
+ };
87
+ const comparison = comparator.compareSemanticProjections(left, right);
88
+ expect(comparison.equal).toBe(false);
89
+ expect(comparison.extraEdges.length).toBeGreaterThan(0);
90
+ expect(() => comparator.assertSemanticParity(left, right, 'provenance')).toThrow(/semantic projection parity failed/);
91
+ });
92
+ });
@@ -0,0 +1,113 @@
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 path = __importStar(require("path"));
37
+ // The analyzer is deliberately a browser-compatible CommonJS/IIFE artifact so
38
+ // the same projection can be replayed in Capacitor and the desktop test runner.
39
+ const analyzer = require(path.resolve(__dirname, 'frontend', 'mobile_exact_analyzer.js'));
40
+ describe('mobile exact projection contract', () => {
41
+ test('indexes stable URI aliases and separates explicit from inferred edges', () => {
42
+ const index = analyzer.createMobileExactIndex({
43
+ nodes: [
44
+ {
45
+ id: 'Legacy A',
46
+ label: 'A',
47
+ sourceUri: 'note://workspace/v1/a.md',
48
+ identityAliases: ['a.md'],
49
+ metadata: { tags: ['algebra'] },
50
+ },
51
+ { id: 'B', label: 'B' },
52
+ ],
53
+ edges: [
54
+ { source: 'Legacy A', target: 'B', type: 'explicit-prerequisite' },
55
+ { source: 'B', target: 'Legacy A', type: 'vector-association' },
56
+ ],
57
+ });
58
+ expect(index.searchExact('note://workspace/v1/a.md', 5)[0]).toEqual(expect.objectContaining({
59
+ id: 'Legacy A',
60
+ sourceUri: 'note://workspace/v1/a.md',
61
+ }));
62
+ expect(index.neighbors('note://workspace/v1/a.md', 5, ['explicit'])).toEqual([
63
+ expect.objectContaining({ id: 'B', edgeKind: 'explicit' }),
64
+ ]);
65
+ expect(index.statistics({ includeProvenance: true })).toEqual(expect.objectContaining({
66
+ projectionVersion: 1,
67
+ edgeCount: 2,
68
+ explicitEdgeCount: 1,
69
+ inferredEdgeCount: 1,
70
+ }));
71
+ });
72
+ test('resolves a source URI in bounded path queries', () => {
73
+ const index = analyzer.createMobileExactIndex({
74
+ nodes: [
75
+ { id: 'A', sourceUri: 'note://workspace/v1/a.md' },
76
+ { id: 'B', sourceUri: 'note://workspace/v1/b.md' },
77
+ ],
78
+ edges: [{ source: 'A', target: 'B', type: 'sequence' }],
79
+ });
80
+ expect(index.shortestPath('note://workspace/v1/a.md', 'note://workspace/v1/b.md', 4, 10)).toEqual(['A', 'B']);
81
+ });
82
+ test('resolves a path-derived canonical id without changing the legacy node id', () => {
83
+ const index = analyzer.createMobileExactIndex({
84
+ nodes: [{ id: 'Index', canonicalId: 'algebra/index', label: 'Index' }],
85
+ edges: [],
86
+ });
87
+ expect(index.searchExact('algebra/index', 5)).toEqual([
88
+ expect.objectContaining({ id: 'Index', canonicalId: 'algebra/index' }),
89
+ ]);
90
+ });
91
+ test('builds a bounded prerequisite-aware learning route from explicit graph edges', () => {
92
+ const index = analyzer.createMobileExactIndex({
93
+ nodes: [
94
+ { id: 'water', label: 'Water molecules' },
95
+ { id: 'ice', label: 'Amorphous ice' },
96
+ { id: 'rdf', label: 'Radial distribution function g(r)' },
97
+ { id: 'application', label: 'Applications' },
98
+ ],
99
+ edges: [
100
+ { source: 'water', target: 'ice', type: 'explicit-prerequisite' },
101
+ { source: 'ice', target: 'rdf', type: 'sequence' },
102
+ { source: 'ice', target: 'application', type: 'application' },
103
+ ],
104
+ });
105
+ expect(index.learningRoute('ice', 6)).toEqual([
106
+ expect.objectContaining({ nodeId: 'water', role: 'prerequisite', order: 1, orderingBasis: 'explicit_prerequisite' }),
107
+ expect.objectContaining({ nodeId: 'ice', role: 'core', order: 2 }),
108
+ expect.objectContaining({ nodeId: 'rdf', role: 'mechanism', order: 3 }),
109
+ expect.objectContaining({ nodeId: 'application', role: 'application', order: 4 }),
110
+ ]);
111
+ expect(index.learningRoute('ice', 2)).toHaveLength(2);
112
+ });
113
+ });
@@ -41,12 +41,7 @@ const constants_1 = require("./constants");
41
41
  const LlmProvider_1 = require("./LlmProvider");
42
42
  const PromptManager_1 = require("./PromptManager");
43
43
  const types_1 = require("./types");
44
- function defaultReporter() {
45
- return {
46
- report: () => undefined,
47
- isCancelled: () => false,
48
- };
49
- }
44
+ const progressReporter_1 = require("./progressReporter");
50
45
  function isTextExtension(filePath) {
51
46
  return constants_1.NOTEMD_SUPPORTED_TEXT_EXTENSIONS.has(path.extname(filePath).toLowerCase());
52
47
  }
@@ -56,7 +51,7 @@ class ContentGenerator {
56
51
  this.promptManager = promptManager;
57
52
  this.batchProcessor = batchProcessor;
58
53
  }
59
- async generateFromTitle(request, settings, reporter = defaultReporter(), signal) {
54
+ async generateFromTitle(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
60
55
  const title = String(request.title || '').trim();
61
56
  if (!title) {
62
57
  throw new types_1.ValidationError('Missing title.');
@@ -90,7 +85,7 @@ class ContentGenerator {
90
85
  reporter.report({ type: 'done', message: `Generated content for "${title}"`, percent: 100 });
91
86
  return result.text.trim();
92
87
  }
93
- async generateForFile(filePath, settings, reporter = defaultReporter(), signal) {
88
+ async generateForFile(filePath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
94
89
  const absoluteFilePath = path.resolve(String(filePath || '').trim());
95
90
  if (!absoluteFilePath) {
96
91
  throw new types_1.ValidationError('Missing file path.');
@@ -113,7 +108,7 @@ class ContentGenerator {
113
108
  generated: true,
114
109
  };
115
110
  }
116
- async generateFolderFromTitles(folderPath, settings, reporter = defaultReporter(), signal) {
111
+ async generateFolderFromTitles(folderPath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
117
112
  const absoluteFolder = path.resolve(String(folderPath || '').trim());
118
113
  if (!absoluteFolder) {
119
114
  throw new types_1.ValidationError('Missing folder path.');
@@ -42,6 +42,7 @@ const LlmProvider_1 = require("./LlmProvider");
42
42
  const PromptManager_1 = require("./PromptManager");
43
43
  const types_1 = require("./types");
44
44
  const constants_1 = require("./constants");
45
+ const progressReporter_1 = require("./progressReporter");
45
46
  function countWords(text) {
46
47
  return text
47
48
  .trim()
@@ -71,12 +72,6 @@ function looksLikeConcept(raw) {
71
72
  }
72
73
  return true;
73
74
  }
74
- function defaultReporter() {
75
- return {
76
- report: () => undefined,
77
- isCancelled: () => false,
78
- };
79
- }
80
75
  class FileProcessor {
81
76
  constructor(llmClient = new LlmProvider_1.LlmProviderClient(), promptManager = new PromptManager_1.PromptManager(), duplicateDetector = new DuplicateDetector_1.DuplicateDetector(), batchProcessor = new BatchProcessor_1.BatchProcessor()) {
82
77
  this.llmClient = llmClient;
@@ -105,7 +100,7 @@ class FileProcessor {
105
100
  }
106
101
  return chunks.length > 0 ? chunks : [String(content || '')];
107
102
  }
108
- async extractConceptsFromText(content, settings, reporter = defaultReporter(), signal) {
103
+ async extractConceptsFromText(content, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
109
104
  const concepts = new Set();
110
105
  const chunks = this.splitContent(content, settings.chunkWordCount);
111
106
  const provider = (0, LlmProvider_1.selectProviderForTask)(settings, 'extractConcepts');
@@ -151,7 +146,7 @@ class FileProcessor {
151
146
  }
152
147
  return concepts;
153
148
  }
154
- async processFile(request, settings, reporter = defaultReporter(), signal) {
149
+ async processFile(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
155
150
  const filePath = path.resolve(String(request.filePath || '').trim());
156
151
  if (!filePath) {
157
152
  throw new types_1.ValidationError('Missing filePath.');
@@ -208,7 +203,7 @@ class FileProcessor {
208
203
  changed,
209
204
  };
210
205
  }
211
- async processFolder(request, settings, reporter = defaultReporter(), signal) {
206
+ async processFolder(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
212
207
  const folderPath = path.resolve(String(request.folderPath || '').trim());
213
208
  if (!folderPath) {
214
209
  throw new types_1.ValidationError('Missing folderPath.');
@@ -47,12 +47,7 @@ const SearchManager_1 = require("./search/SearchManager");
47
47
  const diagramGenerationService_1 = require("./diagram/diagramGenerationService");
48
48
  const LlmProvider_1 = require("./LlmProvider");
49
49
  const types_1 = require("./types");
50
- function defaultReporter() {
51
- return {
52
- report: () => undefined,
53
- isCancelled: () => false,
54
- };
55
- }
50
+ const progressReporter_1 = require("./progressReporter");
56
51
  class NotemdService {
57
52
  constructor(fileProcessor = new FileProcessor_1.FileProcessor(), translator = new Translator_1.Translator(), contentGenerator = new ContentGenerator_1.ContentGenerator(), mermaidProcessor = new MermaidProcessor_1.MermaidProcessor(), formulaFixer = new FormulaFixer_1.FormulaFixer(), duplicateDetector = new DuplicateDetector_1.DuplicateDetector(), llmProviderClient = new LlmProvider_1.LlmProviderClient()) {
58
53
  // ── Batch progress tracking ──
@@ -65,22 +60,22 @@ class NotemdService {
65
60
  this.duplicateDetector = duplicateDetector;
66
61
  this.llmProviderClient = llmProviderClient;
67
62
  }
68
- processFile(request, settings, reporter = defaultReporter(), signal) {
63
+ processFile(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
69
64
  return this.fileProcessor.processFile(request, settings, reporter, signal);
70
65
  }
71
- processFolder(request, settings, reporter = defaultReporter(), signal) {
66
+ processFolder(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
72
67
  return this.fileProcessor.processFolder(request, settings, reporter, signal);
73
68
  }
74
- translateFile(request, settings, reporter = defaultReporter(), signal) {
69
+ translateFile(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
75
70
  return this.translator.translateFile(request, settings, reporter, signal);
76
71
  }
77
- translateFolder(folderPath, targetLanguage, settings, reporter = defaultReporter(), signal) {
72
+ translateFolder(folderPath, targetLanguage, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
78
73
  return this.translator.translateFolder(folderPath, targetLanguage, settings, reporter, signal);
79
74
  }
80
- generateContent(title, context, settings, reporter = defaultReporter(), signal) {
75
+ generateContent(title, context, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
81
76
  return this.contentGenerator.generateFromTitle({ title, context }, settings, reporter, signal);
82
77
  }
83
- generateFolderContent(folderPath, settings, reporter = defaultReporter(), signal) {
78
+ generateFolderContent(folderPath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
84
79
  return this.contentGenerator.generateFolderFromTitles(folderPath, settings, reporter, signal);
85
80
  }
86
81
  async batchFixMermaid(folderPath, inPlace = true) {
@@ -192,7 +187,7 @@ class NotemdService {
192
187
  duplicateWikiLinks: this.duplicateDetector.detectDuplicateWikiLinks(source),
193
188
  };
194
189
  }
195
- async extractConcepts(filePath, settings, reporter = defaultReporter(), signal) {
190
+ async extractConcepts(filePath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
196
191
  const resolvedPath = path.resolve(String(filePath || '').trim());
197
192
  if (!resolvedPath) {
198
193
  throw new types_1.ValidationError('Missing filePath.');
@@ -205,7 +200,7 @@ class NotemdService {
205
200
  };
206
201
  }
207
202
  // ── Workflow Pipeline (NoteConnection native) ──
208
- async runWorkflow(request, settings, reporter = defaultReporter(), signal) {
203
+ async runWorkflow(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
209
204
  const resolvedPath = path.resolve(String(request.filePath || '').trim());
210
205
  if (!resolvedPath)
211
206
  throw new types_1.ValidationError('Missing filePath.');
@@ -326,7 +321,7 @@ class NotemdService {
326
321
  errors,
327
322
  };
328
323
  }
329
- async runBatchWorkflow(request, settings, reporter = defaultReporter(), signal) {
324
+ async runBatchWorkflow(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
330
325
  const resolvedFolderPath = path.resolve(String(request.folderPath || '').trim());
331
326
  if (!resolvedFolderPath)
332
327
  throw new types_1.ValidationError('Missing folderPath.');
@@ -407,7 +402,7 @@ class NotemdService {
407
402
  };
408
403
  }
409
404
  // Backward-compatible wrapper — uses knowledge-base-root-relative output path
410
- async oneClickExtract(filePath, settings, reporter = defaultReporter(), signal) {
405
+ async oneClickExtract(filePath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
411
406
  const resolvedPath = path.resolve(String(filePath || '').trim());
412
407
  const kbRoot = this.resolveKnowledgeBaseRootForFile(resolvedPath);
413
408
  const outputFolderPath = path.join(kbRoot, path.basename(resolvedPath, path.extname(resolvedPath)));
@@ -597,7 +592,7 @@ class NotemdService {
597
592
  };
598
593
  }
599
594
  // ── Extract original text (obsidian-notemd v1.8.4) ──
600
- async extractOriginalText(request, _settings, _reporter = defaultReporter(), _signal) {
595
+ async extractOriginalText(request, _settings, _reporter = (0, progressReporter_1.createNoopProgressReporter)(), _signal) {
601
596
  const resolvedPath = path.resolve(String(request.filePath || '').trim());
602
597
  if (!resolvedPath)
603
598
  throw new types_1.ValidationError('Missing filePath.');
@@ -41,12 +41,7 @@ const constants_1 = require("./constants");
41
41
  const LlmProvider_1 = require("./LlmProvider");
42
42
  const PromptManager_1 = require("./PromptManager");
43
43
  const types_1 = require("./types");
44
- function defaultReporter() {
45
- return {
46
- report: () => undefined,
47
- isCancelled: () => false,
48
- };
49
- }
44
+ const progressReporter_1 = require("./progressReporter");
50
45
  function countWords(text) {
51
46
  return text
52
47
  .trim()
@@ -80,7 +75,7 @@ class Translator {
80
75
  this.promptManager = promptManager;
81
76
  this.batchProcessor = batchProcessor;
82
77
  }
83
- async translateText(content, targetLanguage, settings, reporter = defaultReporter(), signal) {
78
+ async translateText(content, targetLanguage, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
84
79
  const provider = (0, LlmProvider_1.selectProviderForTask)(settings, 'translate');
85
80
  const model = (0, LlmProvider_1.selectModelForTask)(settings, 'translate', provider);
86
81
  const chunks = splitByWordCount(content, settings.chunkWordCount);
@@ -117,7 +112,7 @@ class Translator {
117
112
  }
118
113
  return translatedChunks.join('\n\n').trim();
119
114
  }
120
- async translateFile(request, settings, reporter = defaultReporter(), signal) {
115
+ async translateFile(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
121
116
  const filePath = path.resolve(String(request.filePath || '').trim());
122
117
  if (!filePath) {
123
118
  throw new types_1.ValidationError('Missing filePath.');
@@ -144,7 +139,7 @@ class Translator {
144
139
  changed: translated !== source || outputPath !== filePath,
145
140
  };
146
141
  }
147
- async translateFolder(folderPath, targetLanguage, settings, reporter = defaultReporter(), signal) {
142
+ async translateFolder(folderPath, targetLanguage, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
148
143
  const root = path.resolve(String(folderPath || '').trim());
149
144
  const stats = await this.stat(root);
150
145
  if (!stats.isDirectory()) {