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.
- package/LICENSE +674 -21
- package/README.md +260 -1626
- package/dist/src/agent_workspace.contract.parity.test.js +159 -0
- package/dist/src/agent_workspace.frontend.test.js +10388 -0
- package/dist/src/agent_workspace.locale.contract.test.js +95 -0
- package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
- package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
- package/dist/src/appimage.patchelf.test.js +113 -0
- package/dist/src/appimage.portability.test.js +156 -0
- package/dist/src/backend/FileLoader.js +18 -4
- package/dist/src/backend/FileLoader.test.js +125 -0
- package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
- package/dist/src/backend/GraphBuilder.js +66 -18
- package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
- package/dist/src/backend/GraphMetrics.js +0 -3
- package/dist/src/backend/ResourceIdentity.js +155 -0
- package/dist/src/backend/ResourceIdentity.test.js +113 -0
- package/dist/src/backend/algorithms/CycleDetection.js +0 -1
- package/dist/src/backend/algorithms/HybridEngine.js +0 -3
- package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
- package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
- package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
- package/dist/src/backend/build_dag.js +0 -1
- package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
- package/dist/src/capacitor.runtime.contract.test.js +11 -2
- package/dist/src/copy.assets.contract.test.js +130 -0
- package/dist/src/core/Graph.js +138 -42
- package/dist/src/core/Graph.test.js +74 -0
- package/dist/src/core/NoteConnection.js +2 -2
- package/dist/src/core/PathBridge.js +293 -5
- package/dist/src/core/ResourceReference.js +17 -0
- package/dist/src/desktop.godot.pack.test.js +142 -0
- package/dist/src/desktop.runtime.graph.test.js +66 -0
- package/dist/src/export/WorkspaceExportBundle.js +1174 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +1541 -0
- package/dist/src/export/index.js +18 -0
- package/dist/src/export/types.js +2 -0
- package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
- package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
- package/dist/src/foundation.release.evidence.contract.test.js +524 -0
- package/dist/src/foundation.sqlite.runtime.contract.test.js +88 -0
- package/dist/src/frontend/README.md +260 -1626
- package/dist/src/frontend/agent_workspace.js +6011 -0
- package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
- package/dist/src/frontend/analysis.js +31 -4
- package/dist/src/frontend/app.js +2178 -62
- package/dist/src/frontend/focus_mode_interactions.js +33 -0
- package/dist/src/frontend/godot_future_path_renderer.js +540 -0
- package/dist/src/frontend/godot_tree_interactions.js +178 -0
- package/dist/src/frontend/graph_state.mjs +105 -0
- package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
- package/dist/src/frontend/i18n.mjs +186 -0
- package/dist/src/frontend/index.html +672 -268
- package/dist/src/frontend/knowledge_projection_contract.js +230 -0
- package/dist/src/frontend/knowledge_projection_store.js +214 -0
- package/dist/src/frontend/layout_gpu.js +12 -4
- package/dist/src/frontend/libs/path_core.js +158 -42
- package/dist/src/frontend/locales/en.json +753 -5
- package/dist/src/frontend/locales/zh.json +753 -5
- package/dist/src/frontend/main.mjs +60 -0
- package/dist/src/frontend/markdown_runtime.js +827 -0
- package/dist/src/frontend/mobile_budget_runtime.js +33 -0
- package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
- package/dist/src/frontend/mobile_identity_contract.js +221 -0
- package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
- package/dist/src/frontend/notemd.css +49 -0
- package/dist/src/frontend/notemd.html +7 -1
- package/dist/src/frontend/notemd.js +64 -0
- package/dist/src/frontend/path.html +113 -2
- package/dist/src/frontend/path_app.js +2108 -130
- package/dist/src/frontend/path_layout.mjs +143 -0
- package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
- package/dist/src/frontend/path_modules_bridge.js +486 -0
- package/dist/src/frontend/path_state.mjs +118 -0
- package/dist/src/frontend/path_styles.css +146 -0
- package/dist/src/frontend/path_worker_bridge.mjs +85 -0
- package/dist/src/frontend/reader.js +393 -33
- package/dist/src/frontend/runtime_bridge.js +67 -54
- package/dist/src/frontend/runtime_bridge.mjs +279 -0
- package/dist/src/frontend/settings.js +130 -12
- package/dist/src/frontend/simulationWorker.js +1 -1
- package/dist/src/frontend/source_manager.js +297 -22
- package/dist/src/frontend/storage_provider.js +661 -71
- package/dist/src/frontend/styles.css +2814 -72
- package/dist/src/frontend/workbench_state.mjs +101 -0
- package/dist/src/frontend/workspace_panes.js +10272 -0
- package/dist/src/frontend.locale.contract.test.js +62 -0
- package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
- package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
- package/dist/src/graph.answer.operator.contract.test.js +72 -0
- package/dist/src/index.js +6 -2
- package/dist/src/index.knowledge-root.test.js +118 -0
- package/dist/src/indexing/IndexLifecycle.js +217 -0
- package/dist/src/indexing/IndexLifecycle.test.js +73 -0
- package/dist/src/indexing/SegmentBuilder.js +64 -0
- package/dist/src/indexing/UnitBuilder.js +48 -0
- package/dist/src/indexing/types.js +2 -0
- package/dist/src/knowledge.api.contract.test.js +172 -0
- package/dist/src/knowledge_projection.contract.test.js +134 -0
- package/dist/src/knowledge_projection_store.test.js +200 -0
- package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
- package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +11181 -0
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +745 -0
- package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +3208 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2998 -0
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3936 -0
- package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
- package/dist/src/learning/PublicAnswerContract.test.js +85 -0
- package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
- package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
- package/dist/src/learning/agentConversationExecution.js +211 -0
- package/dist/src/learning/agentConversationExecution.test.js +209 -0
- package/dist/src/learning/agentConversationSerialization.js +266 -0
- package/dist/src/learning/agentConversationSerialization.test.js +165 -0
- package/dist/src/learning/agentResponseBudget.js +179 -0
- package/dist/src/learning/agentResponseBudget.test.js +97 -0
- package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
- package/dist/src/learning/answerReleaseReview.js +5260 -0
- package/dist/src/learning/answerReleaseReview.test.js +4174 -0
- package/dist/src/learning/answerTaskPlan.js +473 -0
- package/dist/src/learning/api.js +2 -0
- package/dist/src/learning/conversationComposer.js +1721 -0
- package/dist/src/learning/conversationComposer.test.js +3220 -0
- package/dist/src/learning/domains/ConversationManager.js +53 -0
- package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
- package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
- package/dist/src/learning/domains/MasteryEngine.js +387 -0
- package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
- package/dist/src/learning/domains/QualityEvaluator.js +307 -0
- package/dist/src/learning/domains/TutorRouter.js +313 -0
- package/dist/src/learning/domains/index.js +33 -0
- package/dist/src/learning/domains/types.js +7 -0
- package/dist/src/learning/errors.js +29 -0
- package/dist/src/learning/evidenceContextAssembler.js +1368 -0
- package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
- package/dist/src/learning/graphAnswerCoverage.js +37 -0
- package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
- package/dist/src/learning/graphAnswerFacts.js +94 -0
- package/dist/src/learning/graphAnswerFacts.test.js +39 -0
- package/dist/src/learning/graphAnswerPlan.js +908 -0
- package/dist/src/learning/graphAnswerPlan.test.js +907 -0
- package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
- package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
- package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
- package/dist/src/learning/graphClaimMatcher.js +104 -0
- package/dist/src/learning/graphConditionedContext.js +109 -0
- package/dist/src/learning/graphConditionedContext.test.js +99 -0
- package/dist/src/learning/graphContextAssembler.js +860 -0
- package/dist/src/learning/graphContextAssembler.test.js +1033 -0
- package/dist/src/learning/graphExpansionPolicy.js +22 -0
- package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
- package/dist/src/learning/identityMetadata.test.js +26 -0
- package/dist/src/learning/index.js +29 -0
- package/dist/src/learning/mobileAnswerProjection.js +104 -0
- package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
- package/dist/src/learning/queryBackend.js +1922 -0
- package/dist/src/learning/queryBackend.test.js +976 -0
- package/dist/src/learning/ragContextPack.js +356 -0
- package/dist/src/learning/ragContextPack.test.js +311 -0
- package/dist/src/learning/ragEvidenceQuality.js +96 -0
- package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
- package/dist/src/learning/ragPublicText.js +101 -0
- package/dist/src/learning/ragPublicText.test.js +57 -0
- package/dist/src/learning/ragSufficiencyJudge.js +171 -0
- package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.js +217 -0
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +207 -0
- package/dist/src/learning/requestNormalization.js +304 -0
- package/dist/src/learning/requestNormalization.test.js +101 -0
- package/dist/src/learning/runtimeCapability.js +4677 -0
- package/dist/src/learning/runtimeCapability.test.js +3635 -0
- package/dist/src/learning/store.js +1344 -0
- package/dist/src/learning/store.test.js +1425 -0
- package/dist/src/learning/tutorAdapter.js +2 -0
- package/dist/src/learning/types.js +2 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +958 -0
- package/dist/src/learning/vectorAccelerationAdapter.test.js +412 -0
- package/dist/src/learning/workspaceHydration.js +168 -0
- package/dist/src/learning/workspaceHydration.test.js +30 -0
- package/dist/src/lfs.asset.policy.contract.test.js +153 -0
- package/dist/src/license.policy.contract.test.js +71 -0
- package/dist/src/markdown/MarkdownGateway.js +4 -0
- package/dist/src/markdown/MarkdownGateway.test.js +59 -0
- package/dist/src/memory/MemoryGovernance.js +74 -0
- package/dist/src/memory/MemoryGovernance.test.js +46 -0
- package/dist/src/memory/types.js +2 -0
- package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
- package/dist/src/middleware/SseResponseWriter.js +122 -0
- package/dist/src/middleware/SseResponseWriter.test.js +54 -0
- package/dist/src/middleware/auth.js +38 -0
- package/dist/src/middleware/auth.test.js +33 -0
- package/dist/src/middleware/body-parser.js +45 -0
- package/dist/src/middleware/cors.js +44 -0
- package/dist/src/middleware/index.js +22 -0
- package/dist/src/middleware/request-trace.js +96 -0
- package/dist/src/mobile.android.evidence.contract.test.js +146 -0
- package/dist/src/mobile.android.signing.contract.test.js +66 -0
- package/dist/src/mobile.artifact.contract.test.js +144 -0
- package/dist/src/mobile.budget.contract.test.js +90 -0
- package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
- package/dist/src/mobile.graph.parity.contract.test.js +207 -0
- package/dist/src/mobile.identity.contract.test.js +66 -0
- package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
- package/dist/src/mobile.identity.corpus.test.js +40 -0
- package/dist/src/mobile.native.recovery.contract.test.js +64 -0
- package/dist/src/mobile.pipeline.test.js +11 -1
- package/dist/src/mobile.profile.contract.test.js +225 -0
- package/dist/src/mobile.semantic.parity.test.js +92 -0
- package/dist/src/mobile_exact_analyzer.test.js +113 -0
- package/dist/src/notemd/AppConfigToml.js +6 -4
- package/dist/src/notemd/ContentGenerator.js +4 -9
- package/dist/src/notemd/FileProcessor.js +4 -9
- package/dist/src/notemd/MermaidProcessor.js +400 -50
- package/dist/src/notemd/NotemdService.js +506 -26
- package/dist/src/notemd/PromptManager.js +15 -0
- package/dist/src/notemd/Translator.js +4 -9
- package/dist/src/notemd/cli/commands.js +357 -0
- package/dist/src/notemd/cli/dispatcher.js +225 -0
- package/dist/src/notemd/cli/index.js +169 -0
- package/dist/src/notemd/cli/parser.js +68 -0
- package/dist/src/notemd/cli/types.js +2 -0
- package/dist/src/notemd/constants.js +43 -0
- package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
- package/dist/src/notemd/diagram/diagramSpec.js +79 -0
- package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
- package/dist/src/notemd/diagram/intent.js +95 -0
- package/dist/src/notemd/diagram/planner.js +71 -0
- package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
- package/dist/src/notemd/diagram/types.js +18 -0
- package/dist/src/notemd/index.js +26 -0
- package/dist/src/notemd/operations/capabilityManifest.js +23 -0
- package/dist/src/notemd/operations/cliContracts.js +17 -0
- package/dist/src/notemd/operations/configProfileCommands.js +85 -0
- package/dist/src/notemd/operations/registry.contract.test.js +95 -0
- package/dist/src/notemd/operations/registry.js +991 -0
- package/dist/src/notemd/operations/types.js +2 -0
- package/dist/src/notemd/progressReporter.js +9 -0
- package/dist/src/notemd/providerDiagnostics.js +220 -0
- package/dist/src/notemd/providerProfiles.js +42 -0
- package/dist/src/notemd/providerTemplates.js +231 -0
- package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
- package/dist/src/notemd/search/SearchManager.js +13 -0
- package/dist/src/notemd/search/SearchProvider.js +2 -0
- package/dist/src/notemd/search/TavilyProvider.js +44 -0
- package/dist/src/notemd.agent.manifest.test.js +85 -0
- package/dist/src/notemd.api.contract.test.js +14 -1
- package/dist/src/notemd.app_config_toml.test.js +2 -1
- package/dist/src/notemd.batch.workflow.test.js +117 -0
- package/dist/src/notemd.cli.e2e.test.js +136 -0
- package/dist/src/notemd.core.test.js +51 -0
- package/dist/src/notemd.diagram.pipeline.test.js +233 -0
- package/dist/src/notemd.providerTemplates.test.js +34 -0
- package/dist/src/notemd.server.integration.test.js +262 -39
- package/dist/src/notemd.workflow.pipeline.test.js +162 -0
- package/dist/src/pathbridge.handshake.contract.test.js +45 -2
- package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
- package/dist/src/pathcore.bundle.contract.test.js +8 -0
- package/dist/src/pathmode.background.contract.test.js +69 -0
- package/dist/src/pathmode.settings.api.contract.test.js +9 -0
- package/dist/src/pkg.sidecar.contract.test.js +9 -3
- package/dist/src/platform/ExportProfile.js +86 -0
- package/dist/src/platform/MobileBudget.js +11 -0
- package/dist/src/platform/PlatformCapabilities.js +59 -0
- package/dist/src/platform/PlatformCapabilities.test.js +36 -0
- package/dist/src/platform/RenderMaterializer.js +33 -0
- package/dist/src/platform/RenderMaterializer.test.js +32 -0
- package/dist/src/query_backend.external_http.integration.test.js +410 -0
- package/dist/src/reader_renderer.js +404 -3
- package/dist/src/reader_renderer.test.js +87 -0
- package/dist/src/release.godot.mirror.contract.test.js +97 -0
- package/dist/src/resources/ResourceRegistry.js +263 -0
- package/dist/src/resources/ResourceRegistry.test.js +97 -0
- package/dist/src/resources/types.js +2 -0
- package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
- package/dist/src/routes/index.js +19 -0
- package/dist/src/routes/knowledge.js +981 -0
- package/dist/src/routes/knowledgePayload.js +185 -0
- package/dist/src/routes/knowledgePayload.test.js +53 -0
- package/dist/src/routes/markdown.js +295 -0
- package/dist/src/routes/notemd.js +1321 -0
- package/dist/src/routes/registry.contract.test.js +133 -0
- package/dist/src/routes/registry.shadow.contract.test.js +22 -0
- package/dist/src/routes/render.js +248 -0
- package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
- package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
- package/dist/src/routes/settings.js +6 -0
- package/dist/src/routes/staticFiles.js +94 -0
- package/dist/src/routes/types.js +2 -0
- package/dist/src/runtime.capabilities.test.js +18 -2
- package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
- package/dist/src/server.js +10342 -1325
- package/dist/src/server.migration.test.js +584 -10
- package/dist/src/server.port.fallback.contract.test.js +63 -0
- package/dist/src/session/SessionStateStore.js +81 -0
- package/dist/src/session/SessionStateStore.test.js +58 -0
- package/dist/src/session/types.js +2 -0
- package/dist/src/settings.runtime.contract.test.js +50 -0
- package/dist/src/shared/types.contract.test.js +107 -0
- package/dist/src/shared/types.js +22 -0
- package/dist/src/sidecar.build.lock.contract.test.js +201 -0
- package/dist/src/sidecar.freshness.contract.test.js +184 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +131 -0
- package/dist/src/sidecar.supply.readiness.contract.test.js +155 -0
- package/dist/src/simulation.worker.offline.test.js +104 -0
- package/dist/src/source_manager.loadflow.test.js +46 -0
- package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
- package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
- package/dist/src/storage.provider.contract.test.js +152 -1
- package/dist/src/tauri.frontend.build.contract.test.js +68 -0
- package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
- package/dist/src/tauri.window.evidence.execution.test.js +68 -0
- package/dist/src/utils/RuntimePaths.js +10 -13
- package/dist/src/utils/RuntimePaths.test.js +27 -0
- package/dist/src/utils/platform.js +153 -0
- package/dist/src/windows.installer.build.test.js +109 -0
- package/dist/src/windows.installer.payload.test.js +76 -0
- package/dist/src/windows.installer.runtime.test.js +69 -0
- package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
- package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
- package/dist/src/workflows/types.js +2 -0
- package/dist/src/workspace/WorkspaceRegistry.js +135 -0
- package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
- package/dist/src/workspace/types.js +2 -0
- package/package.json +80 -15
|
@@ -43,38 +43,39 @@ const FileProcessor_1 = require("./FileProcessor");
|
|
|
43
43
|
const FormulaFixer_1 = require("./FormulaFixer");
|
|
44
44
|
const MermaidProcessor_1 = require("./MermaidProcessor");
|
|
45
45
|
const Translator_1 = require("./Translator");
|
|
46
|
+
const SearchManager_1 = require("./search/SearchManager");
|
|
47
|
+
const diagramGenerationService_1 = require("./diagram/diagramGenerationService");
|
|
48
|
+
const LlmProvider_1 = require("./LlmProvider");
|
|
46
49
|
const types_1 = require("./types");
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
report: () => undefined,
|
|
50
|
-
isCancelled: () => false,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
50
|
+
const progressReporter_1 = require("./progressReporter");
|
|
53
51
|
class NotemdService {
|
|
54
|
-
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()) {
|
|
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()) {
|
|
53
|
+
// ── Batch progress tracking ──
|
|
54
|
+
this.batchOperations = new Map();
|
|
55
55
|
this.fileProcessor = fileProcessor;
|
|
56
56
|
this.translator = translator;
|
|
57
57
|
this.contentGenerator = contentGenerator;
|
|
58
58
|
this.mermaidProcessor = mermaidProcessor;
|
|
59
59
|
this.formulaFixer = formulaFixer;
|
|
60
60
|
this.duplicateDetector = duplicateDetector;
|
|
61
|
+
this.llmProviderClient = llmProviderClient;
|
|
61
62
|
}
|
|
62
|
-
processFile(request, settings, reporter =
|
|
63
|
+
processFile(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
63
64
|
return this.fileProcessor.processFile(request, settings, reporter, signal);
|
|
64
65
|
}
|
|
65
|
-
processFolder(request, settings, reporter =
|
|
66
|
+
processFolder(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
66
67
|
return this.fileProcessor.processFolder(request, settings, reporter, signal);
|
|
67
68
|
}
|
|
68
|
-
translateFile(request, settings, reporter =
|
|
69
|
+
translateFile(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
69
70
|
return this.translator.translateFile(request, settings, reporter, signal);
|
|
70
71
|
}
|
|
71
|
-
translateFolder(folderPath, targetLanguage, settings, reporter =
|
|
72
|
+
translateFolder(folderPath, targetLanguage, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
72
73
|
return this.translator.translateFolder(folderPath, targetLanguage, settings, reporter, signal);
|
|
73
74
|
}
|
|
74
|
-
generateContent(title, context, settings, reporter =
|
|
75
|
+
generateContent(title, context, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
75
76
|
return this.contentGenerator.generateFromTitle({ title, context }, settings, reporter, signal);
|
|
76
77
|
}
|
|
77
|
-
generateFolderContent(folderPath, settings, reporter =
|
|
78
|
+
generateFolderContent(folderPath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
78
79
|
return this.contentGenerator.generateFolderFromTitles(folderPath, settings, reporter, signal);
|
|
79
80
|
}
|
|
80
81
|
async batchFixMermaid(folderPath, inPlace = true) {
|
|
@@ -129,6 +130,51 @@ class NotemdService {
|
|
|
129
130
|
content: fixed.content,
|
|
130
131
|
};
|
|
131
132
|
}
|
|
133
|
+
async batchFixFormulas(folderPath, inPlace = true) {
|
|
134
|
+
const resolvedFolderPath = path.resolve(String(folderPath || '').trim());
|
|
135
|
+
const stats = await fs.promises.stat(resolvedFolderPath);
|
|
136
|
+
if (!stats.isDirectory())
|
|
137
|
+
throw new types_1.ValidationError(`Not a directory: ${resolvedFolderPath}`);
|
|
138
|
+
const files = await this.collectTextFiles(resolvedFolderPath);
|
|
139
|
+
const results = [];
|
|
140
|
+
for (const filePath of files) {
|
|
141
|
+
const result = await this.fixFormulas(filePath, inPlace);
|
|
142
|
+
results.push({
|
|
143
|
+
sourcePath: filePath,
|
|
144
|
+
modified: result.changed,
|
|
145
|
+
replacementCount: result.fixes.length
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
folderPath: resolvedFolderPath,
|
|
150
|
+
totalFiles: files.length,
|
|
151
|
+
fixedFiles: results.filter(r => r.modified).length,
|
|
152
|
+
results
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async collectTextFiles(rootDir) {
|
|
156
|
+
const results = [];
|
|
157
|
+
const queue = [rootDir];
|
|
158
|
+
while (queue.length > 0) {
|
|
159
|
+
const current = queue.shift();
|
|
160
|
+
if (!current)
|
|
161
|
+
continue;
|
|
162
|
+
const entries = await fs.promises.readdir(current, { withFileTypes: true });
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
const fullPath = path.join(current, entry.name);
|
|
165
|
+
if (entry.isDirectory()) {
|
|
166
|
+
queue.push(fullPath);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (!entry.isFile())
|
|
170
|
+
continue;
|
|
171
|
+
if (!constants_1.NOTEMD_SUPPORTED_TEXT_EXTENSIONS.has(path.extname(fullPath).toLowerCase()))
|
|
172
|
+
continue;
|
|
173
|
+
results.push(fullPath);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return results.sort((a, b) => a.localeCompare(b));
|
|
177
|
+
}
|
|
132
178
|
async checkDuplicates(filePath) {
|
|
133
179
|
const resolvedPath = path.resolve(String(filePath || '').trim());
|
|
134
180
|
if (!resolvedPath) {
|
|
@@ -141,7 +187,7 @@ class NotemdService {
|
|
|
141
187
|
duplicateWikiLinks: this.duplicateDetector.detectDuplicateWikiLinks(source),
|
|
142
188
|
};
|
|
143
189
|
}
|
|
144
|
-
async extractConcepts(filePath, settings, reporter =
|
|
190
|
+
async extractConcepts(filePath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
145
191
|
const resolvedPath = path.resolve(String(filePath || '').trim());
|
|
146
192
|
if (!resolvedPath) {
|
|
147
193
|
throw new types_1.ValidationError('Missing filePath.');
|
|
@@ -153,26 +199,460 @@ class NotemdService {
|
|
|
153
199
|
concepts: Array.from(concepts).sort((a, b) => a.localeCompare(b)),
|
|
154
200
|
};
|
|
155
201
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
202
|
+
// ── Workflow Pipeline (NoteConnection native) ──
|
|
203
|
+
async runWorkflow(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
204
|
+
const resolvedPath = path.resolve(String(request.filePath || '').trim());
|
|
205
|
+
if (!resolvedPath)
|
|
159
206
|
throw new types_1.ValidationError('Missing filePath.');
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
const
|
|
163
|
-
const
|
|
207
|
+
const startedAt = Date.now();
|
|
208
|
+
const stages = [];
|
|
209
|
+
const errors = [];
|
|
210
|
+
const ext = path.extname(resolvedPath);
|
|
211
|
+
const baseName = path.basename(resolvedPath, ext);
|
|
212
|
+
const outputFolderPath = request.outputFolderPath
|
|
213
|
+
? path.resolve(request.outputFolderPath)
|
|
214
|
+
: path.join(path.dirname(resolvedPath), `${baseName}_notemd_output`);
|
|
164
215
|
await fs.promises.mkdir(outputFolderPath, { recursive: true });
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
const
|
|
216
|
+
const enableWikilinks = request.addWikiLinks === true;
|
|
217
|
+
const enableGenerate = !request.skipGenerate;
|
|
218
|
+
const enableMermaid = !request.skipMermaidFix;
|
|
219
|
+
const totalStages = 1 + (enableWikilinks ? 1 : 0) + (enableGenerate ? 1 : 0) + (enableMermaid ? 1 : 0);
|
|
220
|
+
let stageNum = 0;
|
|
221
|
+
// Stage 1: Extract Concepts
|
|
222
|
+
stageNum += 1;
|
|
223
|
+
stages.push({ stage: 'extract-concepts', status: 'running', percent: 0, message: 'Extracting concepts from source...' });
|
|
224
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] Extracting concepts from ${baseName}${ext}`, percent: Math.floor((stageNum - 1) / totalStages * 100), operationId: 'workflow-extract' });
|
|
225
|
+
let concepts = [];
|
|
226
|
+
let sourceContent = '';
|
|
227
|
+
try {
|
|
228
|
+
sourceContent = await fs.promises.readFile(resolvedPath, 'utf8');
|
|
229
|
+
concepts = Array.from(await this.fileProcessor.extractConceptsFromText(sourceContent, settings, reporter, signal)).sort((a, b) => a.localeCompare(b));
|
|
230
|
+
await this.scaffoldConceptFiles(outputFolderPath, concepts);
|
|
231
|
+
stages[0] = { stage: 'extract-concepts', status: 'completed', percent: 100, message: `Extracted ${concepts.length} concepts`, details: { count: concepts.length, concepts } };
|
|
232
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] ✓ Extracted ${concepts.length} concepts`, percent: Math.floor(stageNum / totalStages * 100), operationId: 'workflow-extract' });
|
|
233
|
+
}
|
|
234
|
+
catch (e) {
|
|
235
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
236
|
+
stages[0] = { stage: 'extract-concepts', status: 'error', percent: 100, message: msg };
|
|
237
|
+
errors.push(`extract-concepts: ${msg}`);
|
|
238
|
+
reporter.report({ type: 'error', message: `[${stageNum}/${totalStages}] ✕ Concept extraction failed: ${msg}`, percent: Math.floor(stageNum / totalStages * 100), operationId: 'workflow-extract' });
|
|
239
|
+
}
|
|
240
|
+
// Stage 2 (optional): Add Wiki-Links to source
|
|
241
|
+
let wikiLinkCount = 0;
|
|
242
|
+
if (enableWikilinks && concepts.length > 0) {
|
|
243
|
+
stageNum += 1;
|
|
244
|
+
stages.push({ stage: 'add-wikilinks', status: 'running', percent: 0, message: 'Adding wiki-links to source...' });
|
|
245
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] Adding [[wiki-links]] for ${concepts.length} concepts`, percent: Math.floor((stageNum - 1) / totalStages * 100), operationId: 'workflow-wikilinks' });
|
|
246
|
+
try {
|
|
247
|
+
const injected = this.fileProcessor.injectWikiLinks(sourceContent, concepts);
|
|
248
|
+
wikiLinkCount = injected.linkCount;
|
|
249
|
+
// Write wikified output: in-place or _wikified copy
|
|
250
|
+
let wikifiedPath;
|
|
251
|
+
if (request.wikiLinksInPlace) {
|
|
252
|
+
wikifiedPath = resolvedPath;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
wikifiedPath = path.join(path.dirname(resolvedPath), `${baseName}_wikified${ext}`);
|
|
256
|
+
}
|
|
257
|
+
await fs.promises.writeFile(wikifiedPath, injected.content, 'utf8');
|
|
258
|
+
stages.push({ stage: 'add-wikilinks', status: 'completed', percent: 100, message: `Added ${wikiLinkCount} wiki-links`, details: { linkCount: wikiLinkCount, outputPath: wikifiedPath, inPlace: !!request.wikiLinksInPlace } });
|
|
259
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] ✓ Added ${wikiLinkCount} wiki-links → ${path.basename(wikifiedPath)}`, percent: Math.floor(stageNum / totalStages * 100), operationId: 'workflow-wikilinks' });
|
|
260
|
+
}
|
|
261
|
+
catch (e) {
|
|
262
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
263
|
+
stages.push({ stage: 'add-wikilinks', status: 'error', percent: 100, message: msg });
|
|
264
|
+
errors.push(`add-wikilinks: ${msg}`);
|
|
265
|
+
reporter.report({ type: 'error', message: `[${stageNum}/${totalStages}] ✕ Wiki-link injection failed: ${msg}`, percent: Math.floor(stageNum / totalStages * 100), operationId: 'workflow-wikilinks' });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else if (enableWikilinks && concepts.length === 0) {
|
|
269
|
+
stageNum += 1;
|
|
270
|
+
stages.push({ stage: 'add-wikilinks', status: 'skipped', percent: 100, message: 'No concepts to link', details: { linkCount: 0 } });
|
|
271
|
+
}
|
|
272
|
+
// Stage 3 (optional): Generate from Titles
|
|
273
|
+
let generated = { totalFiles: 0, generatedFiles: 0, failedFiles: 0, outputs: [] };
|
|
274
|
+
if (enableGenerate) {
|
|
275
|
+
stageNum += 1;
|
|
276
|
+
stages.push({ stage: 'generate-titles', status: 'running', percent: 0, message: 'Generating content from titles...' });
|
|
277
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] Generating content from titles in ${path.basename(outputFolderPath)}`, percent: Math.floor((stageNum - 1) / totalStages * 100), operationId: 'workflow-generate' });
|
|
278
|
+
try {
|
|
279
|
+
generated = await this.contentGenerator.generateFolderFromTitles(outputFolderPath, settings, reporter, signal);
|
|
280
|
+
stages.push({ stage: 'generate-titles', status: 'completed', percent: 100, message: `Generated ${generated.generatedFiles}/${generated.totalFiles} files`, details: { totalFiles: generated.totalFiles, generatedFiles: generated.generatedFiles, failedFiles: generated.failedFiles, outputs: generated.outputs } });
|
|
281
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] ✓ Generated ${generated.generatedFiles}/${generated.totalFiles} files`, percent: Math.floor(stageNum / totalStages * 100), operationId: 'workflow-generate' });
|
|
282
|
+
}
|
|
283
|
+
catch (e) {
|
|
284
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
285
|
+
stages.push({ stage: 'generate-titles', status: 'error', percent: 100, message: msg });
|
|
286
|
+
errors.push(`generate-titles: ${msg}`);
|
|
287
|
+
reporter.report({ type: 'error', message: `[${stageNum}/${totalStages}] ✕ Content generation failed: ${msg}`, percent: Math.floor(stageNum / totalStages * 100), operationId: 'workflow-generate' });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
// Stage 4 (optional): Mermaid Fix
|
|
291
|
+
let mermaid = { folderPath: outputFolderPath, totalFiles: 0, fixedFiles: 0, results: [] };
|
|
292
|
+
if (enableMermaid) {
|
|
293
|
+
stageNum += 1;
|
|
294
|
+
stages.push({ stage: 'mermaid-fix', status: 'running', percent: 0, message: 'Fixing Mermaid diagrams...' });
|
|
295
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] Fixing Mermaid diagrams in ${path.basename(outputFolderPath)}`, percent: Math.floor((stageNum - 1) / totalStages * 100), operationId: 'workflow-mermaid' });
|
|
296
|
+
try {
|
|
297
|
+
mermaid = await this.batchFixMermaid(outputFolderPath, true);
|
|
298
|
+
stages.push({ stage: 'mermaid-fix', status: 'completed', percent: 100, message: `Fixed ${mermaid.fixedFiles}/${mermaid.totalFiles} files`, details: { fixedFiles: mermaid.fixedFiles, totalFiles: mermaid.totalFiles, results: mermaid.results } });
|
|
299
|
+
reporter.report({ type: 'status', message: `[${stageNum}/${totalStages}] ✓ Fixed ${mermaid.fixedFiles}/${mermaid.totalFiles} Mermaid diagrams`, percent: 100, operationId: 'workflow-mermaid' });
|
|
300
|
+
}
|
|
301
|
+
catch (e) {
|
|
302
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
303
|
+
stages.push({ stage: 'mermaid-fix', status: 'error', percent: 100, message: msg });
|
|
304
|
+
errors.push(`mermaid-fix: ${msg}`);
|
|
305
|
+
reporter.report({ type: 'error', message: `[${stageNum}/${totalStages}] ✕ Mermaid fix failed: ${msg}`, percent: 100, operationId: 'workflow-mermaid' });
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
reporter.report({ type: 'done', message: `Workflow complete for ${baseName}${ext}`, percent: 100, operationId: 'workflow' });
|
|
168
309
|
return {
|
|
169
310
|
sourceFilePath: resolvedPath,
|
|
170
311
|
outputFolderPath,
|
|
312
|
+
stages,
|
|
313
|
+
summary: {
|
|
314
|
+
conceptsExtracted: concepts.length,
|
|
315
|
+
wikiLinksAdded: wikiLinkCount,
|
|
316
|
+
titlesGenerated: generated.generatedFiles,
|
|
317
|
+
titlesFailed: generated.failedFiles,
|
|
318
|
+
mermaidFilesFixed: mermaid.fixedFiles,
|
|
319
|
+
totalElapsedMs: Date.now() - startedAt,
|
|
320
|
+
},
|
|
321
|
+
errors,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
async runBatchWorkflow(request, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
325
|
+
const resolvedFolderPath = path.resolve(String(request.folderPath || '').trim());
|
|
326
|
+
if (!resolvedFolderPath)
|
|
327
|
+
throw new types_1.ValidationError('Missing folderPath.');
|
|
328
|
+
const startedAt = Date.now();
|
|
329
|
+
const stats = await fs.promises.stat(resolvedFolderPath);
|
|
330
|
+
if (!stats.isDirectory())
|
|
331
|
+
throw new types_1.ValidationError(`Not a directory: ${resolvedFolderPath}`);
|
|
332
|
+
const outputBase = request.outputBasePath
|
|
333
|
+
? path.resolve(request.outputBasePath)
|
|
334
|
+
: path.join(resolvedFolderPath, '_notemd_batch_output');
|
|
335
|
+
await fs.promises.mkdir(outputBase, { recursive: true });
|
|
336
|
+
reporter.report({ type: 'status', message: `Scanning ${resolvedFolderPath} for matching files...`, percent: 0, operationId: 'batch-workflow' });
|
|
337
|
+
// Collect matching files
|
|
338
|
+
let files = await this.collectTextFiles(resolvedFolderPath);
|
|
339
|
+
// Apply extension filter
|
|
340
|
+
if (request.fileExtensions && request.fileExtensions.length > 0) {
|
|
341
|
+
const exts = new Set(request.fileExtensions.map(e => e.toLowerCase()));
|
|
342
|
+
files = files.filter(f => exts.has(path.extname(f).toLowerCase()));
|
|
343
|
+
}
|
|
344
|
+
// Apply regex pattern filter
|
|
345
|
+
if (request.filePattern) {
|
|
346
|
+
try {
|
|
347
|
+
const regex = new RegExp(request.filePattern, 'i');
|
|
348
|
+
files = files.filter(f => regex.test(path.basename(f)));
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
throw new types_1.ValidationError(`Invalid regex pattern: ${request.filePattern}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Limit files
|
|
355
|
+
if (request.maxFiles && request.maxFiles > 0) {
|
|
356
|
+
files = files.slice(0, request.maxFiles);
|
|
357
|
+
}
|
|
358
|
+
const totalFiles = files.length;
|
|
359
|
+
reporter.report({ type: 'status', message: `Found ${totalFiles} matching files. Starting batch workflow...`, percent: 5, operationId: 'batch-workflow' });
|
|
360
|
+
const results = [];
|
|
361
|
+
const errors = [];
|
|
362
|
+
for (let i = 0; i < files.length; i++) {
|
|
363
|
+
if (signal?.aborted)
|
|
364
|
+
break;
|
|
365
|
+
const filePath = files[i];
|
|
366
|
+
const fileBaseName = path.basename(filePath, path.extname(filePath));
|
|
367
|
+
const baseProgress = 5 + Math.floor((i / files.length) * 90);
|
|
368
|
+
reporter.report({
|
|
369
|
+
type: 'status',
|
|
370
|
+
message: `[${i + 1}/${totalFiles}] Processing ${path.basename(filePath)}...`,
|
|
371
|
+
percent: baseProgress,
|
|
372
|
+
operationId: 'batch-workflow'
|
|
373
|
+
});
|
|
374
|
+
try {
|
|
375
|
+
const fileOutputFolder = path.join(outputBase, fileBaseName);
|
|
376
|
+
const result = await this.runWorkflow({
|
|
377
|
+
filePath,
|
|
378
|
+
outputFolderPath: fileOutputFolder,
|
|
379
|
+
language: request.language,
|
|
380
|
+
skipGenerate: request.skipGenerate,
|
|
381
|
+
skipMermaidFix: request.skipMermaidFix,
|
|
382
|
+
}, settings, reporter, signal);
|
|
383
|
+
results.push(result);
|
|
384
|
+
}
|
|
385
|
+
catch (e) {
|
|
386
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
387
|
+
errors.push({ filePath, error: msg });
|
|
388
|
+
reporter.report({ type: 'error', message: `Failed ${path.basename(filePath)}: ${msg}`, percent: baseProgress, operationId: 'batch-workflow' });
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
reporter.report({ type: 'done', message: `Batch workflow complete: ${results.length}/${totalFiles} files processed`, percent: 100, operationId: 'batch-workflow' });
|
|
392
|
+
return {
|
|
393
|
+
folderPath: resolvedFolderPath,
|
|
394
|
+
outputBasePath: outputBase,
|
|
395
|
+
filter: { pattern: request.filePattern, extensions: request.fileExtensions },
|
|
396
|
+
totalFiles,
|
|
397
|
+
completedFiles: results.length,
|
|
398
|
+
failedFiles: errors.length,
|
|
399
|
+
results,
|
|
400
|
+
errors,
|
|
401
|
+
totalElapsedMs: Date.now() - startedAt,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
// Backward-compatible wrapper — uses knowledge-base-root-relative output path
|
|
405
|
+
async oneClickExtract(filePath, settings, reporter = (0, progressReporter_1.createNoopProgressReporter)(), signal) {
|
|
406
|
+
const resolvedPath = path.resolve(String(filePath || '').trim());
|
|
407
|
+
const kbRoot = this.resolveKnowledgeBaseRootForFile(resolvedPath);
|
|
408
|
+
const outputFolderPath = path.join(kbRoot, path.basename(resolvedPath, path.extname(resolvedPath)));
|
|
409
|
+
const result = await this.runWorkflow({
|
|
410
|
+
filePath: resolvedPath,
|
|
411
|
+
outputFolderPath,
|
|
412
|
+
}, settings, reporter, signal);
|
|
413
|
+
const findStage = (name) => [...result.stages].reverse().find(s => s.stage === name);
|
|
414
|
+
const conceptsStage = findStage('extract-concepts');
|
|
415
|
+
const concepts = (conceptsStage?.status === 'completed' && conceptsStage?.details?.concepts)
|
|
416
|
+
? conceptsStage.details.concepts
|
|
417
|
+
: [];
|
|
418
|
+
const genStage = findStage('generate-titles');
|
|
419
|
+
const genDetails = (genStage?.details || {});
|
|
420
|
+
const mermaidStage = findStage('mermaid-fix');
|
|
421
|
+
const mermaidDetails = (mermaidStage?.details || {});
|
|
422
|
+
return {
|
|
423
|
+
sourceFilePath: resolvedPath,
|
|
424
|
+
outputFolderPath: result.outputFolderPath,
|
|
171
425
|
concepts,
|
|
172
|
-
generated
|
|
173
|
-
|
|
426
|
+
generated: {
|
|
427
|
+
totalFiles: genDetails.totalFiles || 0,
|
|
428
|
+
generatedFiles: genDetails.generatedFiles || 0,
|
|
429
|
+
failedFiles: genDetails.failedFiles || 0,
|
|
430
|
+
outputs: genDetails.outputs || [],
|
|
431
|
+
},
|
|
432
|
+
mermaid: {
|
|
433
|
+
folderPath: result.outputFolderPath,
|
|
434
|
+
totalFiles: mermaidDetails.totalFiles || 0,
|
|
435
|
+
fixedFiles: mermaidDetails.fixedFiles || 0,
|
|
436
|
+
results: mermaidDetails.results || [],
|
|
437
|
+
},
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
// ── Diagram generation (obsidian-notemd v1.8.4) ──
|
|
441
|
+
async generateDiagram(request, settings, llmInvoker) {
|
|
442
|
+
const content = String(request.content || '').trim();
|
|
443
|
+
if (!content)
|
|
444
|
+
throw new types_1.ValidationError('Missing content for diagram generation.');
|
|
445
|
+
const intent = (request.intent || 'mermaid');
|
|
446
|
+
const compatMode = (request.compatibilityMode ?? settings.experimentalDiagramCompatibilityMode ?? 'legacy-mermaid');
|
|
447
|
+
const errors = [];
|
|
448
|
+
if (llmInvoker) {
|
|
449
|
+
try {
|
|
450
|
+
const result = await (0, diagramGenerationService_1.generateDiagramArtifact)(content, {
|
|
451
|
+
compatibilityMode: compatMode,
|
|
452
|
+
requestedIntent: intent,
|
|
453
|
+
targetLanguage: undefined,
|
|
454
|
+
llmInvoker
|
|
455
|
+
});
|
|
456
|
+
return {
|
|
457
|
+
diagramType: result.spec.intent,
|
|
458
|
+
spec: JSON.stringify(result.spec, null, 2),
|
|
459
|
+
mermaidCode: result.mermaidContent,
|
|
460
|
+
renderErrors: result.renderError ? [result.renderError] : [],
|
|
461
|
+
intent: result.spec.intent,
|
|
462
|
+
generatedAt: new Date().toISOString(),
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
catch (error) {
|
|
466
|
+
errors.push(error instanceof Error ? error.message : String(error));
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
// Fallback: basic Mermaid fix without LLM
|
|
470
|
+
const fixed = this.mermaidProcessor.fixInMarkdown(content);
|
|
471
|
+
return {
|
|
472
|
+
diagramType: intent,
|
|
473
|
+
spec: content,
|
|
474
|
+
mermaidCode: fixed.changed ? fixed.content : content,
|
|
475
|
+
renderErrors: fixed.changed ? ['Auto-fixed Mermaid syntax errors detected.', ...errors] : errors,
|
|
476
|
+
intent,
|
|
477
|
+
generatedAt: new Date().toISOString(),
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
async previewDiagram(request, _settings) {
|
|
481
|
+
const content = String(request.content || '').trim();
|
|
482
|
+
if (!content)
|
|
483
|
+
throw new types_1.ValidationError('Missing content for diagram preview.');
|
|
484
|
+
const fmt = request.format || 'png';
|
|
485
|
+
const fixed = this.mermaidProcessor.fixInMarkdown(content);
|
|
486
|
+
const errors = fixed.changed ? ['Mermaid syntax was auto-fixed in preview.'] : [];
|
|
487
|
+
return {
|
|
488
|
+
format: fmt,
|
|
489
|
+
dataUrl: '',
|
|
490
|
+
errors,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
async exportDiagram(request, _settings) {
|
|
494
|
+
const content = String(request.content || '').trim();
|
|
495
|
+
if (!content)
|
|
496
|
+
throw new types_1.ValidationError('Missing content for diagram export.');
|
|
497
|
+
const outputPath = request.outputPath || '';
|
|
498
|
+
return {
|
|
499
|
+
outputPath,
|
|
500
|
+
format: request.format || 'png',
|
|
501
|
+
size: Buffer.byteLength(content, 'utf8'),
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
// ── Search (obsidian-notemd v1.8.4) ──
|
|
505
|
+
async search(request, settings) {
|
|
506
|
+
const query = String(request.query || '').trim();
|
|
507
|
+
if (!query) {
|
|
508
|
+
throw new types_1.ValidationError('Missing query for search.');
|
|
509
|
+
}
|
|
510
|
+
const provider = SearchManager_1.SearchManager.getProvider(request.provider || settings.searchProvider || 'duckduckgo');
|
|
511
|
+
let apiKey;
|
|
512
|
+
if (provider.name === 'tavily') {
|
|
513
|
+
apiKey = settings.tavilyApiKey;
|
|
514
|
+
if (!apiKey)
|
|
515
|
+
throw new types_1.ValidationError('Tavily API key is required in settings.');
|
|
516
|
+
}
|
|
517
|
+
const results = await provider.search({
|
|
518
|
+
query,
|
|
519
|
+
maxResults: request.maxResults ?? settings.tavilyMaxResults ?? 5,
|
|
520
|
+
searchDepth: request.searchDepth ?? settings.tavilySearchDepth ?? 'basic'
|
|
521
|
+
}, apiKey, settings.ddgFetchTimeout ?? 10000);
|
|
522
|
+
return {
|
|
523
|
+
query,
|
|
524
|
+
provider: provider.name,
|
|
525
|
+
results,
|
|
526
|
+
totalResults: results.length,
|
|
527
|
+
searchedAt: new Date().toISOString(),
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
// ── LLM diagnostics (obsidian-notemd v1.8.4) ──
|
|
531
|
+
async diagnoseLlmProvider(request, settings, llmCallImpl) {
|
|
532
|
+
const providerName = request.provider || settings.activeProvider || 'unknown';
|
|
533
|
+
const modelName = request.model || settings.providers.find(p => p.name === providerName)?.model || 'unknown';
|
|
534
|
+
const provider = settings.providers.find(p => p.name === providerName);
|
|
535
|
+
if (!provider)
|
|
536
|
+
throw new types_1.ValidationError(`Provider not found: ${providerName}`);
|
|
537
|
+
if (!llmCallImpl)
|
|
538
|
+
throw new types_1.ValidationError('LLM call implementation required for diagnostics.');
|
|
539
|
+
const startMs = Date.now();
|
|
540
|
+
try {
|
|
541
|
+
const { buildDefaultProviderDiagnosticPayload } = await Promise.resolve().then(() => __importStar(require('./providerDiagnostics')));
|
|
542
|
+
const payload = buildDefaultProviderDiagnosticPayload(providerName);
|
|
543
|
+
await llmCallImpl(provider, payload.prompt, payload.content, { ...settings, enableApiErrorDebugMode: true, enableStableApiCall: true });
|
|
544
|
+
return { provider: providerName, model: modelName, status: 'ok', latencyMs: Date.now() - startMs };
|
|
545
|
+
}
|
|
546
|
+
catch (e) {
|
|
547
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
548
|
+
return { provider: providerName, model: modelName, status: 'error', latencyMs: Date.now() - startMs, error: msg };
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
async testLlmConnection(request, settings) {
|
|
552
|
+
const requestedProvider = request && typeof request.provider === 'object'
|
|
553
|
+
? request.provider
|
|
554
|
+
: null;
|
|
555
|
+
const requestedProviderName = String((request && typeof request.providerName === 'string' ? request.providerName : '') ||
|
|
556
|
+
(requestedProvider && typeof requestedProvider.name === 'string' ? requestedProvider.name : '') ||
|
|
557
|
+
settings.activeProvider ||
|
|
558
|
+
'').trim();
|
|
559
|
+
const persistedProvider = settings.providers.find((provider) => provider.name === requestedProviderName);
|
|
560
|
+
if (!persistedProvider && !requestedProvider) {
|
|
561
|
+
throw new types_1.ValidationError(`Provider not found: ${requestedProviderName || settings.activeProvider}`);
|
|
562
|
+
}
|
|
563
|
+
const resolvedProviderName = String((persistedProvider && persistedProvider.name) ||
|
|
564
|
+
requestedProviderName ||
|
|
565
|
+
settings.activeProvider).trim();
|
|
566
|
+
const provider = {
|
|
567
|
+
...(persistedProvider || {
|
|
568
|
+
name: resolvedProviderName,
|
|
569
|
+
apiKey: '',
|
|
570
|
+
baseUrl: '',
|
|
571
|
+
model: '',
|
|
572
|
+
temperature: 0.5,
|
|
573
|
+
enabled: true,
|
|
574
|
+
}),
|
|
575
|
+
...(requestedProvider ? {
|
|
576
|
+
name: resolvedProviderName,
|
|
577
|
+
apiKey: String(requestedProvider.apiKey || '').trim(),
|
|
578
|
+
baseUrl: String(requestedProvider.baseUrl || '').trim(),
|
|
579
|
+
model: String(requestedProvider.model || '').trim(),
|
|
580
|
+
temperature: Number.isFinite(Number(requestedProvider.temperature))
|
|
581
|
+
? Number(requestedProvider.temperature)
|
|
582
|
+
: Number((persistedProvider && persistedProvider.temperature) || 0.5),
|
|
583
|
+
apiVersion: String(requestedProvider.apiVersion || '').trim(),
|
|
584
|
+
} : {}),
|
|
585
|
+
};
|
|
586
|
+
const result = await this.llmProviderClient.testConnection(provider);
|
|
587
|
+
return {
|
|
588
|
+
success: result.success,
|
|
589
|
+
message: result.message,
|
|
590
|
+
provider: provider.name,
|
|
591
|
+
model: provider.model,
|
|
174
592
|
};
|
|
175
593
|
}
|
|
594
|
+
// ── Extract original text (obsidian-notemd v1.8.4) ──
|
|
595
|
+
async extractOriginalText(request, _settings, _reporter = (0, progressReporter_1.createNoopProgressReporter)(), _signal) {
|
|
596
|
+
const resolvedPath = path.resolve(String(request.filePath || '').trim());
|
|
597
|
+
if (!resolvedPath)
|
|
598
|
+
throw new types_1.ValidationError('Missing filePath.');
|
|
599
|
+
const source = await fs.promises.readFile(resolvedPath, 'utf8');
|
|
600
|
+
const mergedMode = request.mergedMode ?? false;
|
|
601
|
+
const outputPath = request.outputPath || resolvedPath.replace(/\.md$/, '_original.md');
|
|
602
|
+
const replacedSuffixPath = resolvedPath.replace(/\.md$/, `${request.outputPath ? '' : '_original'}.md`);
|
|
603
|
+
const targetPath = outputPath || replacedSuffixPath;
|
|
604
|
+
if (targetPath !== resolvedPath) {
|
|
605
|
+
await fs.promises.writeFile(targetPath, source, 'utf8');
|
|
606
|
+
}
|
|
607
|
+
return {
|
|
608
|
+
filePath: resolvedPath,
|
|
609
|
+
outputPath: targetPath,
|
|
610
|
+
originalText: mergedMode ? source.replace(/\n/g, ' ').replace(/\[\[([^\]]+)\]\]/g, '$1') : source,
|
|
611
|
+
changed: targetPath !== resolvedPath,
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
getBatchProgress(operationId) {
|
|
615
|
+
if (operationId && this.batchOperations.has(operationId)) {
|
|
616
|
+
return this.batchOperations.get(operationId);
|
|
617
|
+
}
|
|
618
|
+
return {
|
|
619
|
+
operationId: operationId || '',
|
|
620
|
+
status: 'completed',
|
|
621
|
+
totalItems: 0,
|
|
622
|
+
completedItems: 0,
|
|
623
|
+
failedItems: 0,
|
|
624
|
+
logs: [],
|
|
625
|
+
percent: 100,
|
|
626
|
+
startedAt: new Date().toISOString(),
|
|
627
|
+
updatedAt: new Date().toISOString(),
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
startBatchOperation(operationId, totalItems) {
|
|
631
|
+
const progress = {
|
|
632
|
+
operationId,
|
|
633
|
+
status: 'running',
|
|
634
|
+
totalItems,
|
|
635
|
+
completedItems: 0,
|
|
636
|
+
failedItems: 0,
|
|
637
|
+
logs: [],
|
|
638
|
+
percent: 0,
|
|
639
|
+
startedAt: new Date().toISOString(),
|
|
640
|
+
updatedAt: new Date().toISOString(),
|
|
641
|
+
};
|
|
642
|
+
this.batchOperations.set(operationId, progress);
|
|
643
|
+
return progress;
|
|
644
|
+
}
|
|
645
|
+
updateBatchOperation(operationId, update) {
|
|
646
|
+
const existing = this.batchOperations.get(operationId);
|
|
647
|
+
if (!existing)
|
|
648
|
+
return undefined;
|
|
649
|
+
const updated = { ...existing, ...update, updatedAt: new Date().toISOString() };
|
|
650
|
+
if (updated.failedItems > 0 && updated.status === 'running') {
|
|
651
|
+
updated.status = 'error';
|
|
652
|
+
}
|
|
653
|
+
this.batchOperations.set(operationId, updated);
|
|
654
|
+
return updated;
|
|
655
|
+
}
|
|
176
656
|
async scaffoldConceptFiles(outputFolderPath, concepts) {
|
|
177
657
|
for (const concept of concepts) {
|
|
178
658
|
const safeName = concept.replace(/[\\/:*?"<>|]/g, '').trim();
|
|
@@ -33,6 +33,21 @@ const DEFAULT_PROMPTS = {
|
|
|
33
33
|
'Do not paraphrase.',
|
|
34
34
|
'If none found, output: No match found in reference.',
|
|
35
35
|
].join('\n'),
|
|
36
|
+
extractOriginalTextMerged: [
|
|
37
|
+
'For each user query, extract exact matching passages from reference content.',
|
|
38
|
+
'Combine matching passages into a single merged response.',
|
|
39
|
+
'Do not paraphrase. If none found, output: No match found in reference.',
|
|
40
|
+
].join('\n'),
|
|
41
|
+
searchResearch: [
|
|
42
|
+
'Research the given topic using web search results.',
|
|
43
|
+
'Summarize findings in structured markdown with citations.',
|
|
44
|
+
'Include key facts, different perspectives, and references.',
|
|
45
|
+
].join('\n'),
|
|
46
|
+
ragSufficiencyJudge: [
|
|
47
|
+
'Review whether the supplied RAG context is sufficient to answer the user query.',
|
|
48
|
+
'Use only the supplied context and do not write the final answer.',
|
|
49
|
+
'Return exactly one JSON object with status, score, reasons, and degradationState.',
|
|
50
|
+
].join('\n'),
|
|
36
51
|
};
|
|
37
52
|
exports.DEFAULT_PROMPTS = DEFAULT_PROMPTS;
|
|
38
53
|
function safeReplace(template, replacements) {
|
|
@@ -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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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()) {
|