@memoarchitect/tools 0.4.4
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 +21 -0
- package/README.md +171 -0
- package/package.json +86 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.js +42 -0
- package/packages/tools/lib/__tests__/archetype-parsing.test.js.map +1 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.js +82 -0
- package/packages/tools/lib/__tests__/architecture-discovery.test.js.map +1 -0
- package/packages/tools/lib/__tests__/behavior.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/behavior.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/behavior.test.js +766 -0
- package/packages/tools/lib/__tests__/behavior.test.js.map +1 -0
- package/packages/tools/lib/__tests__/builder.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/builder.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/builder.test.js +728 -0
- package/packages/tools/lib/__tests__/builder.test.js.map +1 -0
- package/packages/tools/lib/__tests__/config-loader.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/config-loader.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/config-loader.test.js +196 -0
- package/packages/tools/lib/__tests__/config-loader.test.js.map +1 -0
- package/packages/tools/lib/__tests__/conformance.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/conformance.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/conformance.test.js +467 -0
- package/packages/tools/lib/__tests__/conformance.test.js.map +1 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.js +195 -0
- package/packages/tools/lib/__tests__/constraint-eval.test.js.map +1 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.js +163 -0
- package/packages/tools/lib/__tests__/constraint-grammar.test.js.map +1 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.js +150 -0
- package/packages/tools/lib/__tests__/constraint-loader.test.js.map +1 -0
- package/packages/tools/lib/__tests__/csv-io.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/csv-io.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/csv-io.test.js +317 -0
- package/packages/tools/lib/__tests__/csv-io.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.js +94 -0
- package/packages/tools/lib/__tests__/dhf-doc-store.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.js +39 -0
- package/packages/tools/lib/__tests__/dhf-template-resolver.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dhf.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dhf.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dhf.test.js +393 -0
- package/packages/tools/lib/__tests__/dhf.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.js +85 -0
- package/packages/tools/lib/__tests__/dimension-filter.test.js.map +1 -0
- package/packages/tools/lib/__tests__/dsm.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/dsm.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/dsm.test.js +112 -0
- package/packages/tools/lib/__tests__/dsm.test.js.map +1 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.js +707 -0
- package/packages/tools/lib/__tests__/e2e-workflow.test.js.map +1 -0
- package/packages/tools/lib/__tests__/file-watcher.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/file-watcher.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/file-watcher.test.js +31 -0
- package/packages/tools/lib/__tests__/file-watcher.test.js.map +1 -0
- package/packages/tools/lib/__tests__/impact.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/impact.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/impact.test.js +82 -0
- package/packages/tools/lib/__tests__/impact.test.js.map +1 -0
- package/packages/tools/lib/__tests__/importer.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/importer.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/importer.test.js +336 -0
- package/packages/tools/lib/__tests__/importer.test.js.map +1 -0
- package/packages/tools/lib/__tests__/kind-registry.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/kind-registry.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/kind-registry.test.js +132 -0
- package/packages/tools/lib/__tests__/kind-registry.test.js.map +1 -0
- package/packages/tools/lib/__tests__/llm.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/llm.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/llm.test.js +275 -0
- package/packages/tools/lib/__tests__/llm.test.js.map +1 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.js +97 -0
- package/packages/tools/lib/__tests__/manifest-resolver.test.js.map +1 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.js +74 -0
- package/packages/tools/lib/__tests__/markdown-to-ir.test.js.map +1 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.js +59 -0
- package/packages/tools/lib/__tests__/methodology-scope.test.js.map +1 -0
- package/packages/tools/lib/__tests__/parser.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/parser.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/parser.test.js +938 -0
- package/packages/tools/lib/__tests__/parser.test.js.map +1 -0
- package/packages/tools/lib/__tests__/plugin.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/plugin.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/plugin.test.js +308 -0
- package/packages/tools/lib/__tests__/plugin.test.js.map +1 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.js +96 -0
- package/packages/tools/lib/__tests__/relationship-registry.test.js.map +1 -0
- package/packages/tools/lib/__tests__/rule-registry.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/rule-registry.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/rule-registry.test.js +53 -0
- package/packages/tools/lib/__tests__/rule-registry.test.js.map +1 -0
- package/packages/tools/lib/__tests__/toolchain.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/toolchain.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/toolchain.test.js +94 -0
- package/packages/tools/lib/__tests__/toolchain.test.js.map +1 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.js +39 -0
- package/packages/tools/lib/__tests__/view-deriver-samples.test.js.map +1 -0
- package/packages/tools/lib/__tests__/view-kinds.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/view-kinds.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/view-kinds.test.js +263 -0
- package/packages/tools/lib/__tests__/view-kinds.test.js.map +1 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.d.ts +2 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.d.ts.map +1 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.js +61 -0
- package/packages/tools/lib/__tests__/view-layout-store.test.js.map +1 -0
- package/packages/tools/lib/analysis/dsm.d.ts +47 -0
- package/packages/tools/lib/analysis/dsm.d.ts.map +1 -0
- package/packages/tools/lib/analysis/dsm.js +172 -0
- package/packages/tools/lib/analysis/dsm.js.map +1 -0
- package/packages/tools/lib/analysis/impact.d.ts +35 -0
- package/packages/tools/lib/analysis/impact.d.ts.map +1 -0
- package/packages/tools/lib/analysis/impact.js +97 -0
- package/packages/tools/lib/analysis/impact.js.map +1 -0
- package/packages/tools/lib/bin/memo.d.ts +3 -0
- package/packages/tools/lib/bin/memo.d.ts.map +1 -0
- package/packages/tools/lib/bin/memo.js +461 -0
- package/packages/tools/lib/bin/memo.js.map +1 -0
- package/packages/tools/lib/browser/index.d.ts +13 -0
- package/packages/tools/lib/browser/index.d.ts.map +1 -0
- package/packages/tools/lib/browser/index.js +11 -0
- package/packages/tools/lib/browser/index.js.map +1 -0
- package/packages/tools/lib/commands/archetype-loader.d.ts +15 -0
- package/packages/tools/lib/commands/archetype-loader.d.ts.map +1 -0
- package/packages/tools/lib/commands/archetype-loader.js +31 -0
- package/packages/tools/lib/commands/archetype-loader.js.map +1 -0
- package/packages/tools/lib/commands/ask.d.ts +6 -0
- package/packages/tools/lib/commands/ask.d.ts.map +1 -0
- package/packages/tools/lib/commands/ask.js +79 -0
- package/packages/tools/lib/commands/ask.js.map +1 -0
- package/packages/tools/lib/commands/check.d.ts +6 -0
- package/packages/tools/lib/commands/check.d.ts.map +1 -0
- package/packages/tools/lib/commands/check.js +214 -0
- package/packages/tools/lib/commands/check.js.map +1 -0
- package/packages/tools/lib/commands/create-package.d.ts +12 -0
- package/packages/tools/lib/commands/create-package.d.ts.map +1 -0
- package/packages/tools/lib/commands/create-package.js +293 -0
- package/packages/tools/lib/commands/create-package.js.map +1 -0
- package/packages/tools/lib/commands/dev.d.ts +6 -0
- package/packages/tools/lib/commands/dev.d.ts.map +1 -0
- package/packages/tools/lib/commands/dev.js +316 -0
- package/packages/tools/lib/commands/dev.js.map +1 -0
- package/packages/tools/lib/commands/dhf-draft.d.ts +8 -0
- package/packages/tools/lib/commands/dhf-draft.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf-draft.js +115 -0
- package/packages/tools/lib/commands/dhf-draft.js.map +1 -0
- package/packages/tools/lib/commands/dhf-init.d.ts +4 -0
- package/packages/tools/lib/commands/dhf-init.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf-init.js +270 -0
- package/packages/tools/lib/commands/dhf-init.js.map +1 -0
- package/packages/tools/lib/commands/dhf-preview.d.ts +4 -0
- package/packages/tools/lib/commands/dhf-preview.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf-preview.js +285 -0
- package/packages/tools/lib/commands/dhf-preview.js.map +1 -0
- package/packages/tools/lib/commands/dhf.d.ts +27 -0
- package/packages/tools/lib/commands/dhf.d.ts.map +1 -0
- package/packages/tools/lib/commands/dhf.js +334 -0
- package/packages/tools/lib/commands/dhf.js.map +1 -0
- package/packages/tools/lib/commands/export.d.ts +9 -0
- package/packages/tools/lib/commands/export.d.ts.map +1 -0
- package/packages/tools/lib/commands/export.js +136 -0
- package/packages/tools/lib/commands/export.js.map +1 -0
- package/packages/tools/lib/commands/generate.d.ts +6 -0
- package/packages/tools/lib/commands/generate.d.ts.map +1 -0
- package/packages/tools/lib/commands/generate.js +80 -0
- package/packages/tools/lib/commands/generate.js.map +1 -0
- package/packages/tools/lib/commands/import-ea.d.ts +32 -0
- package/packages/tools/lib/commands/import-ea.d.ts.map +1 -0
- package/packages/tools/lib/commands/import-ea.js +156 -0
- package/packages/tools/lib/commands/import-ea.js.map +1 -0
- package/packages/tools/lib/commands/import-owl.d.ts +19 -0
- package/packages/tools/lib/commands/import-owl.d.ts.map +1 -0
- package/packages/tools/lib/commands/import-owl.js +103 -0
- package/packages/tools/lib/commands/import-owl.js.map +1 -0
- package/packages/tools/lib/commands/import-sysand.d.ts +11 -0
- package/packages/tools/lib/commands/import-sysand.d.ts.map +1 -0
- package/packages/tools/lib/commands/import-sysand.js +87 -0
- package/packages/tools/lib/commands/import-sysand.js.map +1 -0
- package/packages/tools/lib/commands/import.d.ts +30 -0
- package/packages/tools/lib/commands/import.d.ts.map +1 -0
- package/packages/tools/lib/commands/import.js +250 -0
- package/packages/tools/lib/commands/import.js.map +1 -0
- package/packages/tools/lib/commands/init-wizard.d.ts +10 -0
- package/packages/tools/lib/commands/init-wizard.d.ts.map +1 -0
- package/packages/tools/lib/commands/init-wizard.js +69 -0
- package/packages/tools/lib/commands/init-wizard.js.map +1 -0
- package/packages/tools/lib/commands/init.d.ts +30 -0
- package/packages/tools/lib/commands/init.d.ts.map +1 -0
- package/packages/tools/lib/commands/init.js +238 -0
- package/packages/tools/lib/commands/init.js.map +1 -0
- package/packages/tools/lib/commands/install.d.ts +8 -0
- package/packages/tools/lib/commands/install.d.ts.map +1 -0
- package/packages/tools/lib/commands/install.js +238 -0
- package/packages/tools/lib/commands/install.js.map +1 -0
- package/packages/tools/lib/commands/lock.d.ts +2 -0
- package/packages/tools/lib/commands/lock.d.ts.map +1 -0
- package/packages/tools/lib/commands/lock.js +29 -0
- package/packages/tools/lib/commands/lock.js.map +1 -0
- package/packages/tools/lib/commands/ontology.d.ts +14 -0
- package/packages/tools/lib/commands/ontology.d.ts.map +1 -0
- package/packages/tools/lib/commands/ontology.js +464 -0
- package/packages/tools/lib/commands/ontology.js.map +1 -0
- package/packages/tools/lib/commands/pack.d.ts +4 -0
- package/packages/tools/lib/commands/pack.d.ts.map +1 -0
- package/packages/tools/lib/commands/pack.js +89 -0
- package/packages/tools/lib/commands/pack.js.map +1 -0
- package/packages/tools/lib/commands/plugin.d.ts +10 -0
- package/packages/tools/lib/commands/plugin.d.ts.map +1 -0
- package/packages/tools/lib/commands/plugin.js +195 -0
- package/packages/tools/lib/commands/plugin.js.map +1 -0
- package/packages/tools/lib/commands/req.d.ts +10 -0
- package/packages/tools/lib/commands/req.d.ts.map +1 -0
- package/packages/tools/lib/commands/req.js +64 -0
- package/packages/tools/lib/commands/req.js.map +1 -0
- package/packages/tools/lib/commands/roundtrip.d.ts +6 -0
- package/packages/tools/lib/commands/roundtrip.d.ts.map +1 -0
- package/packages/tools/lib/commands/roundtrip.js +162 -0
- package/packages/tools/lib/commands/roundtrip.js.map +1 -0
- package/packages/tools/lib/commands/rules.d.ts +15 -0
- package/packages/tools/lib/commands/rules.d.ts.map +1 -0
- package/packages/tools/lib/commands/rules.js +282 -0
- package/packages/tools/lib/commands/rules.js.map +1 -0
- package/packages/tools/lib/commands/sysand-publish.d.ts +6 -0
- package/packages/tools/lib/commands/sysand-publish.d.ts.map +1 -0
- package/packages/tools/lib/commands/sysand-publish.js +231 -0
- package/packages/tools/lib/commands/sysand-publish.js.map +1 -0
- package/packages/tools/lib/commands/validate.d.ts +6 -0
- package/packages/tools/lib/commands/validate.d.ts.map +1 -0
- package/packages/tools/lib/commands/validate.js +269 -0
- package/packages/tools/lib/commands/validate.js.map +1 -0
- package/packages/tools/lib/completeness/tracker.d.ts +11 -0
- package/packages/tools/lib/completeness/tracker.d.ts.map +1 -0
- package/packages/tools/lib/completeness/tracker.js +86 -0
- package/packages/tools/lib/completeness/tracker.js.map +1 -0
- package/packages/tools/lib/dhf/dhf-config-v2.d.ts +102 -0
- package/packages/tools/lib/dhf/dhf-config-v2.d.ts.map +1 -0
- package/packages/tools/lib/dhf/dhf-config-v2.js +82 -0
- package/packages/tools/lib/dhf/dhf-config-v2.js.map +1 -0
- package/packages/tools/lib/dhf/dhf-config.d.ts +53 -0
- package/packages/tools/lib/dhf/dhf-config.d.ts.map +1 -0
- package/packages/tools/lib/dhf/dhf-config.js +44 -0
- package/packages/tools/lib/dhf/dhf-config.js.map +1 -0
- package/packages/tools/lib/dhf/directive-parser.d.ts +31 -0
- package/packages/tools/lib/dhf/directive-parser.d.ts.map +1 -0
- package/packages/tools/lib/dhf/directive-parser.js +83 -0
- package/packages/tools/lib/dhf/directive-parser.js.map +1 -0
- package/packages/tools/lib/dhf/document-compiler.d.ts +68 -0
- package/packages/tools/lib/dhf/document-compiler.d.ts.map +1 -0
- package/packages/tools/lib/dhf/document-compiler.js +209 -0
- package/packages/tools/lib/dhf/document-compiler.js.map +1 -0
- package/packages/tools/lib/dhf/document-ir.d.ts +170 -0
- package/packages/tools/lib/dhf/document-ir.d.ts.map +1 -0
- package/packages/tools/lib/dhf/document-ir.js +47 -0
- package/packages/tools/lib/dhf/document-ir.js.map +1 -0
- package/packages/tools/lib/dhf/document-registry.d.ts +45 -0
- package/packages/tools/lib/dhf/document-registry.d.ts.map +1 -0
- package/packages/tools/lib/dhf/document-registry.js +342 -0
- package/packages/tools/lib/dhf/document-registry.js.map +1 -0
- package/packages/tools/lib/dhf/export-plugin.d.ts +24 -0
- package/packages/tools/lib/dhf/export-plugin.d.ts.map +1 -0
- package/packages/tools/lib/dhf/export-plugin.js +24 -0
- package/packages/tools/lib/dhf/export-plugin.js.map +1 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.d.ts +15 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.d.ts.map +1 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.js +159 -0
- package/packages/tools/lib/dhf/exporters/docx-exporter.js.map +1 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.d.ts +9 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.d.ts.map +1 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.js +248 -0
- package/packages/tools/lib/dhf/exporters/html-exporter.js.map +1 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.d.ts +9 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.d.ts.map +1 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.js +147 -0
- package/packages/tools/lib/dhf/exporters/markdown-exporter.js.map +1 -0
- package/packages/tools/lib/dhf/index.d.ts +15 -0
- package/packages/tools/lib/dhf/index.d.ts.map +1 -0
- package/packages/tools/lib/dhf/index.js +21 -0
- package/packages/tools/lib/dhf/index.js.map +1 -0
- package/packages/tools/lib/dhf/markdown-to-ir.d.ts +19 -0
- package/packages/tools/lib/dhf/markdown-to-ir.d.ts.map +1 -0
- package/packages/tools/lib/dhf/markdown-to-ir.js +193 -0
- package/packages/tools/lib/dhf/markdown-to-ir.js.map +1 -0
- package/packages/tools/lib/dhf/query-engine.d.ts +61 -0
- package/packages/tools/lib/dhf/query-engine.d.ts.map +1 -0
- package/packages/tools/lib/dhf/query-engine.js +109 -0
- package/packages/tools/lib/dhf/query-engine.js.map +1 -0
- package/packages/tools/lib/dhf/query-executor.d.ts +33 -0
- package/packages/tools/lib/dhf/query-executor.d.ts.map +1 -0
- package/packages/tools/lib/dhf/query-executor.js +222 -0
- package/packages/tools/lib/dhf/query-executor.js.map +1 -0
- package/packages/tools/lib/dhf/script-runner.d.ts +4 -0
- package/packages/tools/lib/dhf/script-runner.d.ts.map +1 -0
- package/packages/tools/lib/dhf/script-runner.js +62 -0
- package/packages/tools/lib/dhf/script-runner.js.map +1 -0
- package/packages/tools/lib/dhf/snapshot.d.ts +60 -0
- package/packages/tools/lib/dhf/snapshot.d.ts.map +1 -0
- package/packages/tools/lib/dhf/snapshot.js +185 -0
- package/packages/tools/lib/dhf/snapshot.js.map +1 -0
- package/packages/tools/lib/dhf/template-engine.d.ts +18 -0
- package/packages/tools/lib/dhf/template-engine.d.ts.map +1 -0
- package/packages/tools/lib/dhf/template-engine.js +339 -0
- package/packages/tools/lib/dhf/template-engine.js.map +1 -0
- package/packages/tools/lib/dhf/template-resolver.d.ts +42 -0
- package/packages/tools/lib/dhf/template-resolver.d.ts.map +1 -0
- package/packages/tools/lib/dhf/template-resolver.js +196 -0
- package/packages/tools/lib/dhf/template-resolver.js.map +1 -0
- package/packages/tools/lib/import/column-mapper.d.ts +35 -0
- package/packages/tools/lib/import/column-mapper.d.ts.map +1 -0
- package/packages/tools/lib/import/column-mapper.js +171 -0
- package/packages/tools/lib/import/column-mapper.js.map +1 -0
- package/packages/tools/lib/import/import-diff.d.ts +49 -0
- package/packages/tools/lib/import/import-diff.d.ts.map +1 -0
- package/packages/tools/lib/import/import-diff.js +102 -0
- package/packages/tools/lib/import/import-diff.js.map +1 -0
- package/packages/tools/lib/import/recipes.d.ts +43 -0
- package/packages/tools/lib/import/recipes.d.ts.map +1 -0
- package/packages/tools/lib/import/recipes.js +133 -0
- package/packages/tools/lib/import/recipes.js.map +1 -0
- package/packages/tools/lib/importer/cameo-importer.d.ts +103 -0
- package/packages/tools/lib/importer/cameo-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/cameo-importer.js +384 -0
- package/packages/tools/lib/importer/cameo-importer.js.map +1 -0
- package/packages/tools/lib/importer/ea-importer.d.ts +115 -0
- package/packages/tools/lib/importer/ea-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/ea-importer.js +325 -0
- package/packages/tools/lib/importer/ea-importer.js.map +1 -0
- package/packages/tools/lib/importer/index.d.ts +5 -0
- package/packages/tools/lib/importer/index.d.ts.map +1 -0
- package/packages/tools/lib/importer/index.js +15 -0
- package/packages/tools/lib/importer/index.js.map +1 -0
- package/packages/tools/lib/importer/owl-importer.d.ts +91 -0
- package/packages/tools/lib/importer/owl-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/owl-importer.js +429 -0
- package/packages/tools/lib/importer/owl-importer.js.map +1 -0
- package/packages/tools/lib/importer/sysand-importer.d.ts +78 -0
- package/packages/tools/lib/importer/sysand-importer.d.ts.map +1 -0
- package/packages/tools/lib/importer/sysand-importer.js +188 -0
- package/packages/tools/lib/importer/sysand-importer.js.map +1 -0
- package/packages/tools/lib/index.d.ts +44 -0
- package/packages/tools/lib/index.d.ts.map +1 -0
- package/packages/tools/lib/index.js +56 -0
- package/packages/tools/lib/index.js.map +1 -0
- package/packages/tools/lib/language/generated/ast.d.ts +629 -0
- package/packages/tools/lib/language/generated/ast.d.ts.map +1 -0
- package/packages/tools/lib/language/generated/ast.js +961 -0
- package/packages/tools/lib/language/generated/ast.js.map +1 -0
- package/packages/tools/lib/language/generated/grammar.d.ts +7 -0
- package/packages/tools/lib/language/generated/grammar.d.ts.map +1 -0
- package/packages/tools/lib/language/generated/grammar.js +5676 -0
- package/packages/tools/lib/language/generated/grammar.js.map +1 -0
- package/packages/tools/lib/language/generated/module.d.ts +14 -0
- package/packages/tools/lib/language/generated/module.d.ts.map +1 -0
- package/packages/tools/lib/language/generated/module.js +21 -0
- package/packages/tools/lib/language/generated/module.js.map +1 -0
- package/packages/tools/lib/language/memo-sysml-module.d.ts +24 -0
- package/packages/tools/lib/language/memo-sysml-module.d.ts.map +1 -0
- package/packages/tools/lib/language/memo-sysml-module.js +20 -0
- package/packages/tools/lib/language/memo-sysml-module.js.map +1 -0
- package/packages/tools/lib/llm/ask-engine.d.ts +17 -0
- package/packages/tools/lib/llm/ask-engine.d.ts.map +1 -0
- package/packages/tools/lib/llm/ask-engine.js +43 -0
- package/packages/tools/lib/llm/ask-engine.js.map +1 -0
- package/packages/tools/lib/llm/draft-engine.d.ts +32 -0
- package/packages/tools/lib/llm/draft-engine.d.ts.map +1 -0
- package/packages/tools/lib/llm/draft-engine.js +270 -0
- package/packages/tools/lib/llm/draft-engine.js.map +1 -0
- package/packages/tools/lib/llm/generate-engine.d.ts +21 -0
- package/packages/tools/lib/llm/generate-engine.d.ts.map +1 -0
- package/packages/tools/lib/llm/generate-engine.js +83 -0
- package/packages/tools/lib/llm/generate-engine.js.map +1 -0
- package/packages/tools/lib/llm/index.d.ts +6 -0
- package/packages/tools/lib/llm/index.d.ts.map +1 -0
- package/packages/tools/lib/llm/index.js +11 -0
- package/packages/tools/lib/llm/index.js.map +1 -0
- package/packages/tools/lib/llm/llm-provider.d.ts +40 -0
- package/packages/tools/lib/llm/llm-provider.d.ts.map +1 -0
- package/packages/tools/lib/llm/llm-provider.js +121 -0
- package/packages/tools/lib/llm/llm-provider.js.map +1 -0
- package/packages/tools/lib/llm/model-context.d.ts +28 -0
- package/packages/tools/lib/llm/model-context.d.ts.map +1 -0
- package/packages/tools/lib/llm/model-context.js +162 -0
- package/packages/tools/lib/llm/model-context.js.map +1 -0
- package/packages/tools/lib/lock.d.ts +43 -0
- package/packages/tools/lib/lock.d.ts.map +1 -0
- package/packages/tools/lib/lock.js +225 -0
- package/packages/tools/lib/lock.js.map +1 -0
- package/packages/tools/lib/model/builder.d.ts +22 -0
- package/packages/tools/lib/model/builder.d.ts.map +1 -0
- package/packages/tools/lib/model/builder.js +708 -0
- package/packages/tools/lib/model/builder.js.map +1 -0
- package/packages/tools/lib/model/config-loader.d.ts +34 -0
- package/packages/tools/lib/model/config-loader.d.ts.map +1 -0
- package/packages/tools/lib/model/config-loader.js +257 -0
- package/packages/tools/lib/model/config-loader.js.map +1 -0
- package/packages/tools/lib/model/config.d.ts +220 -0
- package/packages/tools/lib/model/config.d.ts.map +1 -0
- package/packages/tools/lib/model/config.js +14 -0
- package/packages/tools/lib/model/config.js.map +1 -0
- package/packages/tools/lib/model/content-store.d.ts +8 -0
- package/packages/tools/lib/model/content-store.d.ts.map +1 -0
- package/packages/tools/lib/model/content-store.js +59 -0
- package/packages/tools/lib/model/content-store.js.map +1 -0
- package/packages/tools/lib/model/dimension-filter.d.ts +33 -0
- package/packages/tools/lib/model/dimension-filter.d.ts.map +1 -0
- package/packages/tools/lib/model/dimension-filter.js +57 -0
- package/packages/tools/lib/model/dimension-filter.js.map +1 -0
- package/packages/tools/lib/model/kind-registry.d.ts +72 -0
- package/packages/tools/lib/model/kind-registry.d.ts.map +1 -0
- package/packages/tools/lib/model/kind-registry.js +178 -0
- package/packages/tools/lib/model/kind-registry.js.map +1 -0
- package/packages/tools/lib/model/layer-resolver.d.ts +25 -0
- package/packages/tools/lib/model/layer-resolver.d.ts.map +1 -0
- package/packages/tools/lib/model/layer-resolver.js +82 -0
- package/packages/tools/lib/model/layer-resolver.js.map +1 -0
- package/packages/tools/lib/model/manifest.d.ts +23 -0
- package/packages/tools/lib/model/manifest.d.ts.map +1 -0
- package/packages/tools/lib/model/manifest.js +117 -0
- package/packages/tools/lib/model/manifest.js.map +1 -0
- package/packages/tools/lib/model/methodology-loader.d.ts +56 -0
- package/packages/tools/lib/model/methodology-loader.d.ts.map +1 -0
- package/packages/tools/lib/model/methodology-loader.js +203 -0
- package/packages/tools/lib/model/methodology-loader.js.map +1 -0
- package/packages/tools/lib/model/ontology-loader.d.ts +113 -0
- package/packages/tools/lib/model/ontology-loader.d.ts.map +1 -0
- package/packages/tools/lib/model/ontology-loader.js +901 -0
- package/packages/tools/lib/model/ontology-loader.js.map +1 -0
- package/packages/tools/lib/model/package-registry.d.ts +62 -0
- package/packages/tools/lib/model/package-registry.d.ts.map +1 -0
- package/packages/tools/lib/model/package-registry.js +164 -0
- package/packages/tools/lib/model/package-registry.js.map +1 -0
- package/packages/tools/lib/model/parser-utils.d.ts +23 -0
- package/packages/tools/lib/model/parser-utils.d.ts.map +1 -0
- package/packages/tools/lib/model/parser-utils.js +63 -0
- package/packages/tools/lib/model/parser-utils.js.map +1 -0
- package/packages/tools/lib/model/paths.d.ts +18 -0
- package/packages/tools/lib/model/paths.d.ts.map +1 -0
- package/packages/tools/lib/model/paths.js +26 -0
- package/packages/tools/lib/model/paths.js.map +1 -0
- package/packages/tools/lib/model/relationship-registry.d.ts +64 -0
- package/packages/tools/lib/model/relationship-registry.d.ts.map +1 -0
- package/packages/tools/lib/model/relationship-registry.js +141 -0
- package/packages/tools/lib/model/relationship-registry.js.map +1 -0
- package/packages/tools/lib/model/semantic.d.ts +175 -0
- package/packages/tools/lib/model/semantic.d.ts.map +1 -0
- package/packages/tools/lib/model/semantic.js +61 -0
- package/packages/tools/lib/model/semantic.js.map +1 -0
- package/packages/tools/lib/model/short-id.d.ts +32 -0
- package/packages/tools/lib/model/short-id.d.ts.map +1 -0
- package/packages/tools/lib/model/short-id.js +136 -0
- package/packages/tools/lib/model/short-id.js.map +1 -0
- package/packages/tools/lib/model/toolchain.d.ts +12 -0
- package/packages/tools/lib/model/toolchain.d.ts.map +1 -0
- package/packages/tools/lib/model/toolchain.js +92 -0
- package/packages/tools/lib/model/toolchain.js.map +1 -0
- package/packages/tools/lib/model/view-deriver.d.ts +22 -0
- package/packages/tools/lib/model/view-deriver.d.ts.map +1 -0
- package/packages/tools/lib/model/view-deriver.js +160 -0
- package/packages/tools/lib/model/view-deriver.js.map +1 -0
- package/packages/tools/lib/model/view-kinds.d.ts +29 -0
- package/packages/tools/lib/model/view-kinds.d.ts.map +1 -0
- package/packages/tools/lib/model/view-kinds.js +80 -0
- package/packages/tools/lib/model/view-kinds.js.map +1 -0
- package/packages/tools/lib/ontology/owl-exporter.d.ts +43 -0
- package/packages/tools/lib/ontology/owl-exporter.d.ts.map +1 -0
- package/packages/tools/lib/ontology/owl-exporter.js +70 -0
- package/packages/tools/lib/ontology/owl-exporter.js.map +1 -0
- package/packages/tools/lib/operations/index.d.ts +8 -0
- package/packages/tools/lib/operations/index.d.ts.map +1 -0
- package/packages/tools/lib/operations/index.js +8 -0
- package/packages/tools/lib/operations/index.js.map +1 -0
- package/packages/tools/lib/operations/project-snapshot.d.ts +17 -0
- package/packages/tools/lib/operations/project-snapshot.d.ts.map +1 -0
- package/packages/tools/lib/operations/project-snapshot.js +103 -0
- package/packages/tools/lib/operations/project-snapshot.js.map +1 -0
- package/packages/tools/lib/plugin/index.d.ts +5 -0
- package/packages/tools/lib/plugin/index.d.ts.map +1 -0
- package/packages/tools/lib/plugin/index.js +10 -0
- package/packages/tools/lib/plugin/index.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-loader.d.ts +26 -0
- package/packages/tools/lib/plugin/plugin-loader.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-loader.js +216 -0
- package/packages/tools/lib/plugin/plugin-loader.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-registry.d.ts +49 -0
- package/packages/tools/lib/plugin/plugin-registry.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-registry.js +121 -0
- package/packages/tools/lib/plugin/plugin-registry.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-scaffold.d.ts +17 -0
- package/packages/tools/lib/plugin/plugin-scaffold.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-scaffold.js +223 -0
- package/packages/tools/lib/plugin/plugin-scaffold.js.map +1 -0
- package/packages/tools/lib/plugin/plugin-types.d.ts +115 -0
- package/packages/tools/lib/plugin/plugin-types.d.ts.map +1 -0
- package/packages/tools/lib/plugin/plugin-types.js +11 -0
- package/packages/tools/lib/plugin/plugin-types.js.map +1 -0
- package/packages/tools/lib/protocol/messages.d.ts +470 -0
- package/packages/tools/lib/protocol/messages.d.ts.map +1 -0
- package/packages/tools/lib/protocol/messages.js +6 -0
- package/packages/tools/lib/protocol/messages.js.map +1 -0
- package/packages/tools/lib/serializer/csv-io.d.ts +113 -0
- package/packages/tools/lib/serializer/csv-io.d.ts.map +1 -0
- package/packages/tools/lib/serializer/csv-io.js +394 -0
- package/packages/tools/lib/serializer/csv-io.js.map +1 -0
- package/packages/tools/lib/serializer/sysml-generator.d.ts +32 -0
- package/packages/tools/lib/serializer/sysml-generator.d.ts.map +1 -0
- package/packages/tools/lib/serializer/sysml-generator.js +120 -0
- package/packages/tools/lib/serializer/sysml-generator.js.map +1 -0
- package/packages/tools/lib/server/config-resolver.d.ts +14 -0
- package/packages/tools/lib/server/config-resolver.d.ts.map +1 -0
- package/packages/tools/lib/server/config-resolver.js +54 -0
- package/packages/tools/lib/server/config-resolver.js.map +1 -0
- package/packages/tools/lib/server/dev-server.d.ts +17 -0
- package/packages/tools/lib/server/dev-server.d.ts.map +1 -0
- package/packages/tools/lib/server/dev-server.js +939 -0
- package/packages/tools/lib/server/dev-server.js.map +1 -0
- package/packages/tools/lib/server/dhf-doc-store.d.ts +11 -0
- package/packages/tools/lib/server/dhf-doc-store.d.ts.map +1 -0
- package/packages/tools/lib/server/dhf-doc-store.js +181 -0
- package/packages/tools/lib/server/dhf-doc-store.js.map +1 -0
- package/packages/tools/lib/server/file-watcher.d.ts +20 -0
- package/packages/tools/lib/server/file-watcher.d.ts.map +1 -0
- package/packages/tools/lib/server/file-watcher.js +140 -0
- package/packages/tools/lib/server/file-watcher.js.map +1 -0
- package/packages/tools/lib/server/persistor.d.ts +25 -0
- package/packages/tools/lib/server/persistor.d.ts.map +1 -0
- package/packages/tools/lib/server/persistor.js +100 -0
- package/packages/tools/lib/server/persistor.js.map +1 -0
- package/packages/tools/lib/server/view-layout-store.d.ts +8 -0
- package/packages/tools/lib/server/view-layout-store.d.ts.map +1 -0
- package/packages/tools/lib/server/view-layout-store.js +73 -0
- package/packages/tools/lib/server/view-layout-store.js.map +1 -0
- package/packages/tools/lib/types/index.d.ts +4 -0
- package/packages/tools/lib/types/index.d.ts.map +1 -0
- package/packages/tools/lib/types/index.js +6 -0
- package/packages/tools/lib/types/index.js.map +1 -0
- package/packages/tools/lib/validator/behavior-validator.d.ts +12 -0
- package/packages/tools/lib/validator/behavior-validator.d.ts.map +1 -0
- package/packages/tools/lib/validator/behavior-validator.js +124 -0
- package/packages/tools/lib/validator/behavior-validator.js.map +1 -0
- package/packages/tools/lib/validator/constraint-eval.d.ts +90 -0
- package/packages/tools/lib/validator/constraint-eval.d.ts.map +1 -0
- package/packages/tools/lib/validator/constraint-eval.js +478 -0
- package/packages/tools/lib/validator/constraint-eval.js.map +1 -0
- package/packages/tools/lib/validator/constraint-loader.d.ts +10 -0
- package/packages/tools/lib/validator/constraint-loader.d.ts.map +1 -0
- package/packages/tools/lib/validator/constraint-loader.js +113 -0
- package/packages/tools/lib/validator/constraint-loader.js.map +1 -0
- package/packages/tools/lib/validator/rule-engine.d.ts +13 -0
- package/packages/tools/lib/validator/rule-engine.d.ts.map +1 -0
- package/packages/tools/lib/validator/rule-engine.js +38 -0
- package/packages/tools/lib/validator/rule-engine.js.map +1 -0
- package/packages/tools/lib/validator/rule-registry.d.ts +61 -0
- package/packages/tools/lib/validator/rule-registry.d.ts.map +1 -0
- package/packages/tools/lib/validator/rule-registry.js +142 -0
- package/packages/tools/lib/validator/rule-registry.js.map +1 -0
- package/packages/tools/lib/validator/types.d.ts +59 -0
- package/packages/tools/lib/validator/types.d.ts.map +1 -0
- package/packages/tools/lib/validator/types.js +3 -0
- package/packages/tools/lib/validator/types.js.map +1 -0
- package/packages/tools/lib/validator/view-validator.d.ts +11 -0
- package/packages/tools/lib/validator/view-validator.d.ts.map +1 -0
- package/packages/tools/lib/validator/view-validator.js +48 -0
- package/packages/tools/lib/validator/view-validator.js.map +1 -0
- package/packages/tools/src/grammar/memo-sysml.langium +450 -0
|
@@ -0,0 +1,939 @@
|
|
|
1
|
+
// ─── Dev Server ──────────────────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// HTTP server with:
|
|
4
|
+
// - Optional client middleware supplied by a higher-level application
|
|
5
|
+
// - WebSocket endpoint for pushing model updates to browser
|
|
6
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
import { createServer as createHttpServer } from 'node:http';
|
|
8
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
9
|
+
import { existsSync, readFileSync, realpathSync, writeFileSync, mkdirSync, createReadStream, statSync } from 'node:fs';
|
|
10
|
+
import { extname } from 'node:path';
|
|
11
|
+
import { findMemoManifests } from '@memoarchitect/tools';
|
|
12
|
+
import { loadViewLayouts, saveViewLayout } from './view-layout-store.js';
|
|
13
|
+
import { loadDhfDocs, saveDhfDoc, deleteDhfDoc, loadDhfSettings, saveDhfSettings, listRepoTemplates, readRepoTemplate, } from './dhf-doc-store.js';
|
|
14
|
+
// ─── User-diagram persistence helpers ──────────────────────────────────────
|
|
15
|
+
function userDiagramsPath(projectRoot) {
|
|
16
|
+
return resolve(projectRoot, '.memo', 'user-diagrams.json');
|
|
17
|
+
}
|
|
18
|
+
function loadUserDiagrams(projectRoot) {
|
|
19
|
+
const p = userDiagramsPath(projectRoot);
|
|
20
|
+
if (!existsSync(p))
|
|
21
|
+
return [];
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(readFileSync(p, 'utf8'));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function saveUserDiagrams(projectRoot, diagrams) {
|
|
30
|
+
const dir = resolve(projectRoot, '.memo');
|
|
31
|
+
if (!existsSync(dir))
|
|
32
|
+
mkdirSync(dir, { recursive: true });
|
|
33
|
+
writeFileSync(userDiagramsPath(projectRoot), JSON.stringify(diagrams, null, 2), 'utf8');
|
|
34
|
+
}
|
|
35
|
+
const STATIC_MIME = {
|
|
36
|
+
'.html': 'text/html; charset=utf-8',
|
|
37
|
+
'.css': 'text/css',
|
|
38
|
+
'.js': 'application/javascript',
|
|
39
|
+
'.json': 'application/json',
|
|
40
|
+
'.svg': 'image/svg+xml',
|
|
41
|
+
'.png': 'image/png',
|
|
42
|
+
'.ico': 'image/x-icon',
|
|
43
|
+
'.woff2': 'font/woff2',
|
|
44
|
+
'.woff': 'font/woff',
|
|
45
|
+
'.xml': 'application/xml',
|
|
46
|
+
'.gz': 'application/gzip',
|
|
47
|
+
};
|
|
48
|
+
function streamFile(res, fullPath, status = 200) {
|
|
49
|
+
const mime = STATIC_MIME[extname(fullPath)] ?? 'application/octet-stream';
|
|
50
|
+
const size = statSync(fullPath).size;
|
|
51
|
+
res.writeHead(status, { 'Content-Type': mime, 'Content-Length': size });
|
|
52
|
+
createReadStream(fullPath).pipe(res);
|
|
53
|
+
}
|
|
54
|
+
export async function createDevServer(options) {
|
|
55
|
+
const { port, webPackagePath, initialMessages } = options;
|
|
56
|
+
const host = '127.0.0.1';
|
|
57
|
+
// A source client can use Vite middleware. A packaged client can provide a
|
|
58
|
+
// prebuilt dist/ directory. Tools does not resolve or depend on that client.
|
|
59
|
+
const hasWebSource = existsSync(resolve(webPackagePath, 'index.html'));
|
|
60
|
+
const webDistPath = resolve(webPackagePath, 'dist');
|
|
61
|
+
const hasWebDist = existsSync(resolve(webDistPath, 'index.html'));
|
|
62
|
+
// Dynamic import Vite for a caller-provided source client.
|
|
63
|
+
let vite;
|
|
64
|
+
if (hasWebSource) {
|
|
65
|
+
try {
|
|
66
|
+
vite = await import('vite');
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Vite not available — fall back to static serving
|
|
70
|
+
console.warn(hasWebDist
|
|
71
|
+
? 'Vite not found, serving the prebuilt web app from dist/'
|
|
72
|
+
: 'Vite not found, using static file serving');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
let server;
|
|
76
|
+
let viteServer;
|
|
77
|
+
// Resolve docs/dist relative to the repo root (two levels up from cli package)
|
|
78
|
+
const docsDistPath = resolve(webPackagePath, '../../docs/dist');
|
|
79
|
+
const hasLocalDocs = existsSync(resolve(docsDistPath, 'index.html'));
|
|
80
|
+
/** Serve a static file from docsDistPath. Returns true if handled. */
|
|
81
|
+
function serveHelp(req, res) {
|
|
82
|
+
if (!hasLocalDocs)
|
|
83
|
+
return false;
|
|
84
|
+
const url = req.url ?? '/';
|
|
85
|
+
if (!url.startsWith('/help'))
|
|
86
|
+
return false;
|
|
87
|
+
// Strip /help prefix, default to index.html
|
|
88
|
+
let filePath = url.slice('/help'.length) || '/';
|
|
89
|
+
if (filePath.endsWith('/'))
|
|
90
|
+
filePath += 'index.html';
|
|
91
|
+
const fullPath = resolve(docsDistPath, filePath.replace(/^\//, ''));
|
|
92
|
+
if (!existsSync(fullPath)) {
|
|
93
|
+
// MkDocs 404 page
|
|
94
|
+
const notFound = resolve(docsDistPath, '404.html');
|
|
95
|
+
if (existsSync(notFound)) {
|
|
96
|
+
res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
97
|
+
createReadStream(notFound).pipe(res);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
res.writeHead(404);
|
|
101
|
+
res.end('Not found');
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
streamFile(res, fullPath);
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
/** Serve the caller-provided prebuilt client as an SPA. */
|
|
109
|
+
function serveWebDist(req, res) {
|
|
110
|
+
if (!hasWebDist)
|
|
111
|
+
return false;
|
|
112
|
+
const url = (req.url ?? '/').split('?')[0];
|
|
113
|
+
const requested = resolve(webDistPath, url.replace(/^\//, ''));
|
|
114
|
+
// Path traversal guard + SPA fallback: unknown routes get index.html.
|
|
115
|
+
// A string-prefix check is insufficient: a sibling such as dist-backup
|
|
116
|
+
// also starts with the dist path.
|
|
117
|
+
const requestedRelative = relative(webDistPath, requested);
|
|
118
|
+
const isWithinDist = requestedRelative !== '..'
|
|
119
|
+
&& !requestedRelative.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)
|
|
120
|
+
&& !requestedRelative.startsWith('../')
|
|
121
|
+
&& !requestedRelative.startsWith('..\\');
|
|
122
|
+
const fullPath = isWithinDist && existsSync(requested) && statSync(requested).isFile()
|
|
123
|
+
? requested
|
|
124
|
+
: resolve(webDistPath, 'index.html');
|
|
125
|
+
streamFile(res, fullPath);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
if (vite) {
|
|
129
|
+
// Create Vite dev server in middleware mode
|
|
130
|
+
viteServer = await vite.createServer({
|
|
131
|
+
root: webPackagePath,
|
|
132
|
+
server: { middlewareMode: true, host },
|
|
133
|
+
appType: 'spa',
|
|
134
|
+
});
|
|
135
|
+
server = createHttpServer((req, res) => {
|
|
136
|
+
if (serveHelp(req, res))
|
|
137
|
+
return;
|
|
138
|
+
viteServer.middlewares(req, res);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else if (hasWebDist) {
|
|
142
|
+
// Packaged install: serve the prebuilt web app statically
|
|
143
|
+
server = createHttpServer((req, res) => {
|
|
144
|
+
if (serveHelp(req, res))
|
|
145
|
+
return;
|
|
146
|
+
serveWebDist(req, res);
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// Fallback: serve a basic page that connects via WebSocket
|
|
151
|
+
server = createHttpServer((req, res) => {
|
|
152
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
153
|
+
res.end(`
|
|
154
|
+
<!DOCTYPE html>
|
|
155
|
+
<html>
|
|
156
|
+
<head><title>MEMO Dev</title></head>
|
|
157
|
+
<body>
|
|
158
|
+
<h1>MEMO Dev Server</h1>
|
|
159
|
+
<p>Architect client not found at ${webPackagePath}. Run this server through @memoarchitect/architect.</p>
|
|
160
|
+
<pre id="log"></pre>
|
|
161
|
+
<script>
|
|
162
|
+
const ws = new WebSocket('ws://' + location.host);
|
|
163
|
+
ws.onmessage = (e) => {
|
|
164
|
+
const msg = JSON.parse(e.data);
|
|
165
|
+
document.getElementById('log').textContent += JSON.stringify(msg.type) + '\\n';
|
|
166
|
+
};
|
|
167
|
+
</script>
|
|
168
|
+
</body>
|
|
169
|
+
</html>
|
|
170
|
+
`);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// WebSocket setup
|
|
174
|
+
const { WebSocketServer } = await import('ws');
|
|
175
|
+
const wss = new WebSocketServer({ server });
|
|
176
|
+
const clients = new Set();
|
|
177
|
+
const currentDiagrams = () => {
|
|
178
|
+
const model = initialMessages.find(m => m.type === 'model:update');
|
|
179
|
+
return model?.payload.diagrams ?? [];
|
|
180
|
+
};
|
|
181
|
+
/** Push an updated model:update message (with modified diagrams) to all clients */
|
|
182
|
+
function broadcastDiagramChange(changedDiagram, op) {
|
|
183
|
+
const modelMsgIdx = initialMessages.findIndex(m => m.type === 'model:update');
|
|
184
|
+
if (modelMsgIdx < 0)
|
|
185
|
+
return;
|
|
186
|
+
const prev = initialMessages[modelMsgIdx];
|
|
187
|
+
let diagrams = prev.payload.diagrams ?? [];
|
|
188
|
+
if (op === 'create') {
|
|
189
|
+
diagrams = [...diagrams, changedDiagram];
|
|
190
|
+
}
|
|
191
|
+
else if (op === 'update') {
|
|
192
|
+
diagrams = diagrams.map(d => d.id === changedDiagram.id ? { ...d, ...changedDiagram } : d);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
diagrams = diagrams.filter(d => d.id !== changedDiagram.id);
|
|
196
|
+
}
|
|
197
|
+
const updatedMsg = { type: 'model:update', payload: { ...prev.payload, diagrams } };
|
|
198
|
+
initialMessages[modelMsgIdx] = updatedMsg;
|
|
199
|
+
for (const client of clients) {
|
|
200
|
+
if (client.readyState === 1)
|
|
201
|
+
client.send(JSON.stringify(updatedMsg));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/** Convert a DhfBlock (from document IR) to a markdown string */
|
|
205
|
+
function blockToMarkdown(block) {
|
|
206
|
+
switch (block.type) {
|
|
207
|
+
case 'heading': return `${'#'.repeat(block.level)} ${block.text}\n`;
|
|
208
|
+
case 'paragraph': return block.inlines.map((i) => i.text ?? '').join('') + '\n';
|
|
209
|
+
case 'list': return block.items.map((item) => `- ${item.map((i) => i.text ?? '').join('')}`).join('\n') + '\n';
|
|
210
|
+
case 'table': {
|
|
211
|
+
const header = `| ${block.headers.join(' | ')} |`;
|
|
212
|
+
const sep = `| ${block.headers.map(() => '---').join(' | ')} |`;
|
|
213
|
+
const rows = block.rows.map((r) => `| ${r.map(cell => cell.map((i) => i.text ?? '').join('')).join(' | ')} |`);
|
|
214
|
+
return [header, sep, ...rows].join('\n') + '\n';
|
|
215
|
+
}
|
|
216
|
+
case 'divider': return '---\n';
|
|
217
|
+
default: return '';
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/** Extract element IDs from a SysML text snippet by matching names against the model */
|
|
221
|
+
function extractElementIdsFromText(text, elements) {
|
|
222
|
+
// Match `part|requirement|action|port|item|attribute <name> :` patterns
|
|
223
|
+
const regex = /\b(?:part|requirement|action|port|item|attribute|connection)\s+(\w+)\s*:/g;
|
|
224
|
+
const ids = [];
|
|
225
|
+
let m;
|
|
226
|
+
while ((m = regex.exec(text)) !== null) {
|
|
227
|
+
const name = m[1];
|
|
228
|
+
if (elements[name])
|
|
229
|
+
ids.push(name);
|
|
230
|
+
}
|
|
231
|
+
return ids;
|
|
232
|
+
}
|
|
233
|
+
/** Resolve only the project-local .sysml source declared by the diagram. */
|
|
234
|
+
function diagramSource(diagramId) {
|
|
235
|
+
const diagram = currentDiagrams().find(d => d.id === diagramId);
|
|
236
|
+
if (!diagram)
|
|
237
|
+
throw new Error('Diagram not found.');
|
|
238
|
+
if (!diagram.sourceFile)
|
|
239
|
+
throw new Error('This diagram is not backed by an editable SysML file.');
|
|
240
|
+
const projectRoot = realpathSync(resolve(options.projectRoot));
|
|
241
|
+
const requestedPath = resolve(projectRoot, diagram.sourceFile);
|
|
242
|
+
if (!existsSync(requestedPath))
|
|
243
|
+
throw new Error('The diagram source file does not exist.');
|
|
244
|
+
// Resolve symlinks before checking containment so an in-tree symlink
|
|
245
|
+
// cannot be used to read or write a file outside the project.
|
|
246
|
+
const path = realpathSync(requestedPath);
|
|
247
|
+
const rel = relative(projectRoot, path);
|
|
248
|
+
const outsideProject = rel === '..' || rel.startsWith('../') || rel.startsWith('..\\') || isAbsolute(rel);
|
|
249
|
+
if (outsideProject || extname(path).toLowerCase() !== '.sysml') {
|
|
250
|
+
throw new Error('The diagram source must be a project-local .sysml file.');
|
|
251
|
+
}
|
|
252
|
+
return { sourceFile: rel, path };
|
|
253
|
+
}
|
|
254
|
+
wss.on('connection', (ws) => {
|
|
255
|
+
clients.add(ws);
|
|
256
|
+
// Send initial state to new connections
|
|
257
|
+
for (const msg of initialMessages) {
|
|
258
|
+
ws.send(JSON.stringify(msg));
|
|
259
|
+
}
|
|
260
|
+
// Send all sidecar layouts on connect
|
|
261
|
+
const layouts = loadViewLayouts(options.projectRoot, currentDiagrams());
|
|
262
|
+
if (Object.keys(layouts).length > 0) {
|
|
263
|
+
ws.send(JSON.stringify({ type: 'diagram:layout', payload: { layouts } }));
|
|
264
|
+
}
|
|
265
|
+
// Send persisted DHF documents and settings on connect
|
|
266
|
+
try {
|
|
267
|
+
const docs = loadDhfDocs(options.projectRoot);
|
|
268
|
+
ws.send(JSON.stringify({ type: 'dhf:docs', payload: { docs } }));
|
|
269
|
+
const dhfSettings = loadDhfSettings(options.projectRoot);
|
|
270
|
+
if (dhfSettings) {
|
|
271
|
+
ws.send(JSON.stringify({ type: 'dhf:settings', payload: { settings: dhfSettings } }));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
console.error('[DHF] initial load failed:', e);
|
|
276
|
+
}
|
|
277
|
+
// Announce LLM availability on connect
|
|
278
|
+
{
|
|
279
|
+
const hasAnthropic = !!(process.env.ANTHROPIC_API_KEY);
|
|
280
|
+
const hasOpenAI = !!(process.env.OPENAI_API_KEY);
|
|
281
|
+
const available = hasAnthropic || hasOpenAI;
|
|
282
|
+
const provider = hasAnthropic ? 'anthropic' : hasOpenAI ? 'openai' : undefined;
|
|
283
|
+
const model = process.env.MEMO_LLM_MODEL
|
|
284
|
+
|| (hasAnthropic ? 'claude-sonnet-4-20250514' : hasOpenAI ? 'gpt-4o' : undefined);
|
|
285
|
+
ws.send(JSON.stringify({ type: 'llm:status', payload: { available, provider, model } }));
|
|
286
|
+
}
|
|
287
|
+
ws.on('close', () => clients.delete(ws));
|
|
288
|
+
ws.on('message', async (data) => {
|
|
289
|
+
try {
|
|
290
|
+
const msg = JSON.parse(data.toString());
|
|
291
|
+
if (msg.type === 'request:refresh') {
|
|
292
|
+
// Re-send current state
|
|
293
|
+
for (const m of initialMessages) {
|
|
294
|
+
ws.send(JSON.stringify(m));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
else if (msg.type === 'element:update' || msg.type === 'element:create') {
|
|
298
|
+
// 1. Persist to FS
|
|
299
|
+
const { saveElementToFile } = await import('./persistor.js');
|
|
300
|
+
const { projectRoot } = options;
|
|
301
|
+
const result = saveElementToFile(projectRoot, msg.payload);
|
|
302
|
+
if (result.success) {
|
|
303
|
+
// The file watcher will catch this change and broadcast to all clients
|
|
304
|
+
console.log(`[Persisted] ${msg.type} to ${result.filePath}`);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
else if (msg.type === 'diagram:create') {
|
|
308
|
+
const { projectRoot } = options;
|
|
309
|
+
const diagram = { ...msg.payload, auto: false };
|
|
310
|
+
const userDiagrams = loadUserDiagrams(projectRoot);
|
|
311
|
+
userDiagrams.push(diagram);
|
|
312
|
+
saveUserDiagrams(projectRoot, userDiagrams);
|
|
313
|
+
broadcastDiagramChange(diagram, 'create');
|
|
314
|
+
console.log(`[Diagram] Created: ${diagram.name} (${diagram.id})`);
|
|
315
|
+
}
|
|
316
|
+
else if (msg.type === 'diagram:update') {
|
|
317
|
+
const { projectRoot } = options;
|
|
318
|
+
const userDiagrams = loadUserDiagrams(projectRoot);
|
|
319
|
+
const idx = userDiagrams.findIndex(d => d.id === msg.payload.id);
|
|
320
|
+
if (idx >= 0) {
|
|
321
|
+
userDiagrams[idx] = { ...userDiagrams[idx], ...msg.payload };
|
|
322
|
+
saveUserDiagrams(projectRoot, userDiagrams);
|
|
323
|
+
broadcastDiagramChange(userDiagrams[idx], 'update');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
else if (msg.type === 'diagram:delete') {
|
|
327
|
+
const { projectRoot } = options;
|
|
328
|
+
const userDiagrams = loadUserDiagrams(projectRoot);
|
|
329
|
+
const filtered = userDiagrams.filter(d => d.id !== msg.payload.id);
|
|
330
|
+
saveUserDiagrams(projectRoot, filtered);
|
|
331
|
+
broadcastDiagramChange({ id: msg.payload.id }, 'delete');
|
|
332
|
+
console.log(`[Diagram] Deleted: ${msg.payload.id}`);
|
|
333
|
+
}
|
|
334
|
+
else if (msg.type === 'diagram:layout:update') {
|
|
335
|
+
const { diagramId, layout } = msg.payload;
|
|
336
|
+
const diagram = currentDiagrams().find(d => d.id === diagramId)
|
|
337
|
+
?? { id: diagramId, name: diagramId, diagramType: 'bdd', viewpointId: '__model', auto: false };
|
|
338
|
+
const savedPath = saveViewLayout(options.projectRoot, diagram, layout);
|
|
339
|
+
console.log(`[Diagram] Saved layout: ${savedPath}`);
|
|
340
|
+
// Broadcast to other clients (not the sender)
|
|
341
|
+
const layoutMsg = JSON.stringify({ type: 'diagram:layout', payload: { layouts: { [diagramId]: layout } } });
|
|
342
|
+
for (const client of clients) {
|
|
343
|
+
if (client !== ws && client.readyState === 1)
|
|
344
|
+
client.send(layoutMsg);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
else if (msg.type === 'relationship:add') {
|
|
348
|
+
const { saveRelationshipToFile } = await import('./persistor.js');
|
|
349
|
+
const { projectRoot } = options;
|
|
350
|
+
const result = saveRelationshipToFile(projectRoot, msg.payload);
|
|
351
|
+
if (result.success) {
|
|
352
|
+
console.log(`[Persisted] relationship:add (${msg.payload.type}) to ${result.filePath}`);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
console.error(`[Error] relationship:add failed: ${result.error}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else if (msg.type === 'element:remap-kinds') {
|
|
359
|
+
// Remap orphaned kind references: for each element whose kind is in the
|
|
360
|
+
// mappings, persist the element with the new kind. The file watcher will
|
|
361
|
+
// pick up changes and broadcast an updated model.
|
|
362
|
+
const { projectRoot } = options;
|
|
363
|
+
const mappings = msg.payload?.mappings ?? {};
|
|
364
|
+
if (Object.keys(mappings).length > 0) {
|
|
365
|
+
const modelMsg = initialMessages.find(m => m.type === 'model:update');
|
|
366
|
+
const elements = modelMsg?.payload?.elements ?? {};
|
|
367
|
+
const { saveElementToFile } = await import('./persistor.js');
|
|
368
|
+
let remappedCount = 0;
|
|
369
|
+
for (const element of Object.values(elements)) {
|
|
370
|
+
const newKind = mappings[element.kind];
|
|
371
|
+
if (newKind) {
|
|
372
|
+
const result = saveElementToFile(projectRoot, { ...element, kind: newKind });
|
|
373
|
+
if (result.success)
|
|
374
|
+
remappedCount++;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
console.log(`[Remap] Remapped ${remappedCount} elements across ${Object.keys(mappings).length} kind(s)`);
|
|
378
|
+
ws.send(JSON.stringify({ type: 'remap:result', payload: { success: true, count: remappedCount } }));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else if (msg.type === 'open-file') {
|
|
382
|
+
// N-ONTO §6.5 — right-click "Open source" from the ontology viewer.
|
|
383
|
+
// Resolve the path against projectRoot, confirm it's within the tree,
|
|
384
|
+
// then hand off to the system-default opener.
|
|
385
|
+
const { projectRoot } = options;
|
|
386
|
+
const requested = String(msg.payload?.path ?? '');
|
|
387
|
+
if (!requested)
|
|
388
|
+
return;
|
|
389
|
+
try {
|
|
390
|
+
const absPath = resolve(projectRoot, requested);
|
|
391
|
+
const relRoot = resolve(projectRoot);
|
|
392
|
+
// Guardrail: only open files inside the project tree
|
|
393
|
+
if (!absPath.startsWith(relRoot)) {
|
|
394
|
+
console.warn(`[OpenFile] Refused path outside project: ${absPath}`);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (!existsSync(absPath)) {
|
|
398
|
+
console.warn(`[OpenFile] Path does not exist: ${absPath}`);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const { execFile } = await import('node:child_process');
|
|
402
|
+
const platform = process.platform;
|
|
403
|
+
const cmd = platform === 'darwin' ? 'open'
|
|
404
|
+
: platform === 'win32' ? 'explorer'
|
|
405
|
+
: 'xdg-open';
|
|
406
|
+
execFile(cmd, [absPath], (err) => {
|
|
407
|
+
if (err)
|
|
408
|
+
console.warn(`[OpenFile] ${cmd} failed for ${absPath}:`, err.message);
|
|
409
|
+
else
|
|
410
|
+
console.log(`[OpenFile] Opened ${absPath}`);
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
catch (e) {
|
|
414
|
+
console.warn('[OpenFile] Failed:', e?.message ?? e);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
else if (msg.type === 'diagram:parse') {
|
|
418
|
+
// Extract element IDs from SysML text by name-matching against current model
|
|
419
|
+
const modelMsg = initialMessages.find(m => m.type === 'model:update');
|
|
420
|
+
const elementIds = extractElementIdsFromText(msg.payload.text, modelMsg?.payload?.elements ?? {});
|
|
421
|
+
ws.send(JSON.stringify({
|
|
422
|
+
type: 'diagram:parse:result',
|
|
423
|
+
payload: { diagramId: msg.payload.diagramId, elementIds, errors: [] },
|
|
424
|
+
}));
|
|
425
|
+
}
|
|
426
|
+
else if (msg.type === 'diagram:source:request') {
|
|
427
|
+
const { requestId, diagramId } = msg.payload ?? {};
|
|
428
|
+
try {
|
|
429
|
+
const source = diagramSource(String(diagramId ?? ''));
|
|
430
|
+
const text = readFileSync(source.path, 'utf8');
|
|
431
|
+
ws.send(JSON.stringify({
|
|
432
|
+
type: 'diagram:source:result',
|
|
433
|
+
payload: {
|
|
434
|
+
requestId, diagramId, operation: 'load', success: true,
|
|
435
|
+
sourceFile: source.sourceFile, text,
|
|
436
|
+
},
|
|
437
|
+
}));
|
|
438
|
+
}
|
|
439
|
+
catch (e) {
|
|
440
|
+
ws.send(JSON.stringify({
|
|
441
|
+
type: 'diagram:source:result',
|
|
442
|
+
payload: { requestId, diagramId, operation: 'load', success: false, error: e?.message ?? String(e) },
|
|
443
|
+
}));
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
else if (msg.type === 'diagram:source:save') {
|
|
447
|
+
const { requestId, diagramId, text } = msg.payload ?? {};
|
|
448
|
+
try {
|
|
449
|
+
if (typeof text !== 'string')
|
|
450
|
+
throw new Error('SysML source text is required.');
|
|
451
|
+
const source = diagramSource(String(diagramId ?? ''));
|
|
452
|
+
writeFileSync(source.path, text, 'utf8');
|
|
453
|
+
ws.send(JSON.stringify({
|
|
454
|
+
type: 'diagram:source:result',
|
|
455
|
+
payload: {
|
|
456
|
+
requestId, diagramId, operation: 'save', success: true,
|
|
457
|
+
sourceFile: source.sourceFile,
|
|
458
|
+
},
|
|
459
|
+
}));
|
|
460
|
+
// The project watcher rebuilds and broadcasts the resulting model.
|
|
461
|
+
console.log(`[Diagram] Saved SysML source: ${source.sourceFile}`);
|
|
462
|
+
}
|
|
463
|
+
catch (e) {
|
|
464
|
+
ws.send(JSON.stringify({
|
|
465
|
+
type: 'diagram:source:result',
|
|
466
|
+
payload: { requestId, diagramId, operation: 'save', success: false, error: e?.message ?? String(e) },
|
|
467
|
+
}));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
else if (msg.type === 'ontology:save-selection') {
|
|
471
|
+
// Persist ontology selection to disk (SysML + YAML), then signal
|
|
472
|
+
// restart-required. No rebuild — ontology must not be hot-swapped.
|
|
473
|
+
const { projectRoot } = options;
|
|
474
|
+
const selected = msg.payload?.selected ?? [];
|
|
475
|
+
let changedFile = resolve(projectRoot, 'memo.config.yaml');
|
|
476
|
+
// ── 1. Write SysML import declarations ──────────────────────
|
|
477
|
+
try {
|
|
478
|
+
const { mkdirSync: mkd } = await import('node:fs');
|
|
479
|
+
const modelDir = resolve(projectRoot, 'model');
|
|
480
|
+
if (!existsSync(modelDir))
|
|
481
|
+
mkd(modelDir, { recursive: true });
|
|
482
|
+
const contentManifests = findMemoManifests(projectRoot);
|
|
483
|
+
const namespaces = [...new Set(selected.map(name => contentManifests.find(entry => name in entry.manifest.packages)?.manifest.init.rootImport
|
|
484
|
+
?? name.replace(/^@/, '').replace(/[/\-]/g, '_').toUpperCase()))];
|
|
485
|
+
const importLines = namespaces
|
|
486
|
+
.map(ns => ` import ${ns}::*;`)
|
|
487
|
+
.join('\n');
|
|
488
|
+
const sysmlContent = [
|
|
489
|
+
'// ── Ontology Selection ───────────────────────────────────────────────────────',
|
|
490
|
+
'//',
|
|
491
|
+
'// Auto-generated by MEMO when the user saves their ontology selection.',
|
|
492
|
+
'// Do not edit manually — use the Ontology Viewer instead.',
|
|
493
|
+
'//',
|
|
494
|
+
'// This file is the SysML v2 source-of-truth for which ontology packages are',
|
|
495
|
+
'// active in this project. Restart the dev server after changing selection.',
|
|
496
|
+
'// ─────────────────────────────────────────────────────────────────────────────',
|
|
497
|
+
'',
|
|
498
|
+
'package OntologySelection {',
|
|
499
|
+
importLines,
|
|
500
|
+
'}',
|
|
501
|
+
'',
|
|
502
|
+
].join('\n');
|
|
503
|
+
const sysmlPath = resolve(modelDir, 'ontology-selection.sysml');
|
|
504
|
+
writeFileSync(sysmlPath, sysmlContent, 'utf8');
|
|
505
|
+
changedFile = sysmlPath;
|
|
506
|
+
console.log(`[Ontology] Wrote SysML import declarations to ${sysmlPath}`);
|
|
507
|
+
}
|
|
508
|
+
catch (e) {
|
|
509
|
+
console.error('[Ontology] Failed to write SysML selection file:', e);
|
|
510
|
+
}
|
|
511
|
+
// ── 2. Update YAML config ──────────────────────────────────
|
|
512
|
+
const configCandidates = ['memo.package.yaml', 'memo.package.yml', 'memo.config.yaml', 'memo.config.yml'];
|
|
513
|
+
let configPath = '';
|
|
514
|
+
for (const name of configCandidates) {
|
|
515
|
+
const p = resolve(projectRoot, name);
|
|
516
|
+
if (existsSync(p)) {
|
|
517
|
+
configPath = p;
|
|
518
|
+
break;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (configPath) {
|
|
522
|
+
try {
|
|
523
|
+
const { parse, stringify } = require('yaml');
|
|
524
|
+
const content = readFileSync(configPath, 'utf8');
|
|
525
|
+
const doc = parse(content);
|
|
526
|
+
const existingMap = new Map((doc.ontologies ?? []).map((e) => [e.name, e]));
|
|
527
|
+
doc.ontologies = selected.map(name => existingMap.get(name) ?? { name });
|
|
528
|
+
writeFileSync(configPath, stringify(doc), 'utf8');
|
|
529
|
+
console.log(`[Ontology] Updated config selection (${selected.length} packages) in ${configPath}`);
|
|
530
|
+
}
|
|
531
|
+
catch (e) {
|
|
532
|
+
console.error('[Ontology] Failed to update config:', e);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
// ── 3. Signal restart-required — do NOT rebuild ─────────────
|
|
536
|
+
const restartMsg = {
|
|
537
|
+
type: 'app:restart-required',
|
|
538
|
+
reason: 'ontology-selection-changed',
|
|
539
|
+
changedFile,
|
|
540
|
+
instruction: 'Ontology selection saved. Stop dev server (Ctrl+C) and run `memo-architect dev` again to apply.',
|
|
541
|
+
};
|
|
542
|
+
for (const client of clients) {
|
|
543
|
+
if (client.readyState === 1)
|
|
544
|
+
client.send(JSON.stringify(restartMsg));
|
|
545
|
+
}
|
|
546
|
+
console.log('[Ontology] Selection saved — restart required to apply.');
|
|
547
|
+
}
|
|
548
|
+
else if (msg.type === 'ontology:install') {
|
|
549
|
+
// Install an ontology from git URL, npm package, or local path
|
|
550
|
+
const { projectRoot } = options;
|
|
551
|
+
const source = msg.payload?.source;
|
|
552
|
+
if (!source) {
|
|
553
|
+
ws.send(JSON.stringify({ type: 'ontology:install:result', payload: { success: false, error: 'No source provided' } }));
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
try {
|
|
557
|
+
const { execSync } = await import('node:child_process');
|
|
558
|
+
const { detectInstallMode } = await import('../commands/install.js');
|
|
559
|
+
const mode = detectInstallMode(source);
|
|
560
|
+
const memoPkgsDir = resolve(projectRoot, 'memo_packages');
|
|
561
|
+
if (!existsSync(memoPkgsDir))
|
|
562
|
+
mkdirSync(memoPkgsDir, { recursive: true });
|
|
563
|
+
if (mode === 'git') {
|
|
564
|
+
// Clone into memo_packages/<repo-name>
|
|
565
|
+
const repoName = source.split('/').pop()?.replace('.git', '') ?? 'ontology';
|
|
566
|
+
const destDir = resolve(memoPkgsDir, repoName);
|
|
567
|
+
if (!existsSync(destDir)) {
|
|
568
|
+
execSync(`git clone --depth 1 ${source} ${destDir}`, { stdio: 'pipe' });
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
else if (mode === 'local') {
|
|
572
|
+
// Symlink local path
|
|
573
|
+
const { basename: bn } = await import('node:path');
|
|
574
|
+
const { symlinkSync } = await import('node:fs');
|
|
575
|
+
const resolvedSource = resolve(projectRoot, source);
|
|
576
|
+
const destDir = resolve(memoPkgsDir, bn(resolvedSource));
|
|
577
|
+
if (!existsSync(destDir)) {
|
|
578
|
+
symlinkSync(resolvedSource, destDir);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
// Refresh packages and broadcast
|
|
582
|
+
const { getPackageMetadata } = await import('@memoarchitect/tools');
|
|
583
|
+
const packages = getPackageMetadata(projectRoot);
|
|
584
|
+
const pkgMsg = { type: 'ontology:packages', payload: { packages } };
|
|
585
|
+
for (const client of clients) {
|
|
586
|
+
if (client.readyState === 1)
|
|
587
|
+
client.send(JSON.stringify(pkgMsg));
|
|
588
|
+
}
|
|
589
|
+
ws.send(JSON.stringify({
|
|
590
|
+
type: 'ontology:install:result',
|
|
591
|
+
payload: { success: true, packageName: source },
|
|
592
|
+
}));
|
|
593
|
+
console.log(`[Ontology] Installed package from ${source}`);
|
|
594
|
+
}
|
|
595
|
+
catch (e) {
|
|
596
|
+
ws.send(JSON.stringify({
|
|
597
|
+
type: 'ontology:install:result',
|
|
598
|
+
payload: { success: false, error: e?.message ?? String(e) },
|
|
599
|
+
}));
|
|
600
|
+
console.error('[Ontology] Install failed:', e);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
else if (msg.type === 'csv:import') {
|
|
605
|
+
// Bulk import elements and/or relationships from CSV text.
|
|
606
|
+
// Generates a .sysml file; the file watcher broadcasts a model update.
|
|
607
|
+
const { projectRoot } = options;
|
|
608
|
+
const { elementsCsv, relationshipsCsv, packageName, targetFile } = msg.payload ?? {};
|
|
609
|
+
try {
|
|
610
|
+
const { parseElementsCsv, parseRelationshipsCsv, generateFile, attachProvenance, findConfigFile, } = await import('@memoarchitect/tools');
|
|
611
|
+
const { loadAndResolveConfig } = await import('./config-resolver.js');
|
|
612
|
+
const configPath = findConfigFile(projectRoot);
|
|
613
|
+
if (!configPath) {
|
|
614
|
+
ws.send(JSON.stringify({
|
|
615
|
+
type: 'import:result',
|
|
616
|
+
payload: { success: false, elementsImported: 0, relationshipsImported: 0, errors: ['No memo config found'], warnings: [] },
|
|
617
|
+
}));
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
const config = await loadAndResolveConfig(configPath);
|
|
621
|
+
const errors = [];
|
|
622
|
+
const warnings = [];
|
|
623
|
+
let elementsImported = 0;
|
|
624
|
+
let relationshipsImported = 0;
|
|
625
|
+
let elements = [];
|
|
626
|
+
let relationships = [];
|
|
627
|
+
if (elementsCsv) {
|
|
628
|
+
const result = parseElementsCsv(elementsCsv, config);
|
|
629
|
+
errors.push(...result.errors);
|
|
630
|
+
warnings.push(...result.warnings);
|
|
631
|
+
// Attach provenance
|
|
632
|
+
const sessionId = `ws-${Date.now().toString(36)}`;
|
|
633
|
+
elements = attachProvenance(result.items, {
|
|
634
|
+
sourceFile: targetFile ?? 'web-import',
|
|
635
|
+
importTimestamp: new Date().toISOString(),
|
|
636
|
+
importSessionId: sessionId,
|
|
637
|
+
});
|
|
638
|
+
elementsImported = elements.length;
|
|
639
|
+
}
|
|
640
|
+
if (relationshipsCsv) {
|
|
641
|
+
const knownIds = elementsImported > 0
|
|
642
|
+
? new Set(elements.map((e) => e.id))
|
|
643
|
+
: undefined;
|
|
644
|
+
const result = parseRelationshipsCsv(relationshipsCsv, config, knownIds);
|
|
645
|
+
errors.push(...result.errors);
|
|
646
|
+
warnings.push(...result.warnings);
|
|
647
|
+
relationships = result.items;
|
|
648
|
+
relationshipsImported = relationships.length;
|
|
649
|
+
}
|
|
650
|
+
if (errors.length > 0 && elements.length === 0 && relationships.length === 0) {
|
|
651
|
+
ws.send(JSON.stringify({
|
|
652
|
+
type: 'import:result',
|
|
653
|
+
payload: { success: false, elementsImported: 0, relationshipsImported: 0, errors, warnings },
|
|
654
|
+
}));
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
const pkgName = (packageName || 'imported').replace(/[^a-zA-Z0-9_]/g, '_');
|
|
658
|
+
const sysml = generateFile(elements, relationships, pkgName);
|
|
659
|
+
const outFile = targetFile || `${pkgName}.sysml`;
|
|
660
|
+
const outPath = resolve(projectRoot, outFile);
|
|
661
|
+
writeFileSync(outPath, sysml, 'utf-8');
|
|
662
|
+
console.log(`[Import] Wrote ${elementsImported} element(s) + ${relationshipsImported} rel(s) → ${outFile}`);
|
|
663
|
+
ws.send(JSON.stringify({
|
|
664
|
+
type: 'import:result',
|
|
665
|
+
payload: { success: true, elementsImported, relationshipsImported, errors, warnings, generatedFile: outFile },
|
|
666
|
+
}));
|
|
667
|
+
}
|
|
668
|
+
catch (e) {
|
|
669
|
+
console.error('[Import] csv:import failed:', e);
|
|
670
|
+
ws.send(JSON.stringify({
|
|
671
|
+
type: 'import:result',
|
|
672
|
+
payload: { success: false, elementsImported: 0, relationshipsImported: 0, errors: [e?.message ?? String(e)], warnings: [] },
|
|
673
|
+
}));
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
else if (msg.type === 'llm:ask') {
|
|
677
|
+
// Q&A about the model via LLM (#52)
|
|
678
|
+
const { requestId, question } = msg.payload ?? {};
|
|
679
|
+
try {
|
|
680
|
+
const { resolveLLMConfig, createProvider } = await import('@memoarchitect/tools');
|
|
681
|
+
const { createQueryContext, findConfigFile } = await import('@memoarchitect/tools');
|
|
682
|
+
const { askModel } = await import('@memoarchitect/tools');
|
|
683
|
+
const { loadAndResolveConfig } = await import('./config-resolver.js');
|
|
684
|
+
const llmConfig = resolveLLMConfig();
|
|
685
|
+
if (!llmConfig) {
|
|
686
|
+
ws.send(JSON.stringify({ type: 'llm:ask:result', payload: { requestId, error: 'No LLM provider configured. Set ANTHROPIC_API_KEY or OPENAI_API_KEY.' } }));
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
const modelMsg = initialMessages.find((m) => m.type === 'model:update');
|
|
690
|
+
const validMsg = initialMessages.find((m) => m.type === 'validation:update');
|
|
691
|
+
const compMsg = initialMessages.find((m) => m.type === 'completeness:update');
|
|
692
|
+
const configPath = findConfigFile(options.projectRoot);
|
|
693
|
+
const config = configPath ? await loadAndResolveConfig(configPath) : {};
|
|
694
|
+
const ctx = createQueryContext(modelMsg?.payload ?? {}, validMsg?.payload ?? { violations: [] }, compMsg?.payload ?? { overall: 0, layers: [] }, config);
|
|
695
|
+
const provider = createProvider(llmConfig);
|
|
696
|
+
const result = await askModel(question, ctx, provider);
|
|
697
|
+
ws.send(JSON.stringify({ type: 'llm:ask:result', payload: { requestId, answer: result.answer } }));
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
catch (e) {
|
|
701
|
+
console.error('[LLM] ask failed:', e);
|
|
702
|
+
ws.send(JSON.stringify({ type: 'llm:ask:result', payload: { requestId, error: e?.message ?? String(e) } }));
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
else if (msg.type === 'llm:generate') {
|
|
706
|
+
// Generate SysML v2 from natural language (#54)
|
|
707
|
+
const { requestId, description } = msg.payload ?? {};
|
|
708
|
+
try {
|
|
709
|
+
const { resolveLLMConfig, createProvider, generateSysml, findConfigFile } = await import('@memoarchitect/tools');
|
|
710
|
+
const { loadAndResolveConfig } = await import('./config-resolver.js');
|
|
711
|
+
const llmConfig = resolveLLMConfig();
|
|
712
|
+
if (!llmConfig) {
|
|
713
|
+
ws.send(JSON.stringify({ type: 'llm:generate:result', payload: { requestId, error: 'No LLM provider configured.' } }));
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
const configPath = findConfigFile(options.projectRoot);
|
|
717
|
+
const config = configPath ? await loadAndResolveConfig(configPath) : {};
|
|
718
|
+
const provider = createProvider(llmConfig);
|
|
719
|
+
const result = await generateSysml(description, config, provider);
|
|
720
|
+
ws.send(JSON.stringify({ type: 'llm:generate:result', payload: { requestId, sysml: result.sysml, explanation: result.explanation, suggestedFile: result.suggestedFile } }));
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
catch (e) {
|
|
724
|
+
console.error('[LLM] generate failed:', e);
|
|
725
|
+
ws.send(JSON.stringify({ type: 'llm:generate:result', payload: { requestId, error: e?.message ?? String(e) } }));
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
else if (msg.type === 'llm:draft') {
|
|
729
|
+
// Draft DHF document sections via LLM (#55)
|
|
730
|
+
const { requestId, documentTypeId, targetSections } = msg.payload ?? {};
|
|
731
|
+
try {
|
|
732
|
+
const { resolveLLMConfig, createProvider, createQueryContext, findConfigFile, getDocumentType } = await import('@memoarchitect/tools');
|
|
733
|
+
const { draftDocument } = await import('@memoarchitect/tools');
|
|
734
|
+
const { loadAndResolveConfig } = await import('./config-resolver.js');
|
|
735
|
+
const llmConfig = resolveLLMConfig();
|
|
736
|
+
if (!llmConfig) {
|
|
737
|
+
ws.send(JSON.stringify({ type: 'llm:draft:result', payload: { requestId, error: 'No LLM provider configured.' } }));
|
|
738
|
+
}
|
|
739
|
+
else {
|
|
740
|
+
const modelMsg = initialMessages.find((m) => m.type === 'model:update');
|
|
741
|
+
const validMsg = initialMessages.find((m) => m.type === 'validation:update');
|
|
742
|
+
const compMsg = initialMessages.find((m) => m.type === 'completeness:update');
|
|
743
|
+
const configPath = findConfigFile(options.projectRoot);
|
|
744
|
+
const config = configPath ? await loadAndResolveConfig(configPath) : {};
|
|
745
|
+
const ctx = createQueryContext(modelMsg?.payload ?? {}, validMsg?.payload ?? { violations: [] }, compMsg?.payload ?? { overall: 0, layers: [] }, config);
|
|
746
|
+
const docType = getDocumentType(documentTypeId);
|
|
747
|
+
if (!docType) {
|
|
748
|
+
ws.send(JSON.stringify({ type: 'llm:draft:result', payload: { requestId, error: `Unknown document type: ${documentTypeId}` } }));
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
const provider = createProvider(llmConfig);
|
|
752
|
+
const result = await draftDocument(ctx, provider, { documentType: docType, targetSections });
|
|
753
|
+
// Serialize sections as Markdown for the web UI
|
|
754
|
+
const lines = [`# ${docType.title}\n`];
|
|
755
|
+
for (const sec of result.document.sections) {
|
|
756
|
+
lines.push(`## ${sec.title}\n`);
|
|
757
|
+
for (const block of sec.blocks) {
|
|
758
|
+
lines.push(blockToMarkdown(block));
|
|
759
|
+
}
|
|
760
|
+
lines.push('');
|
|
761
|
+
}
|
|
762
|
+
ws.send(JSON.stringify({ type: 'llm:draft:result', payload: { requestId, markdown: lines.join('\n'), summary: result.summary } }));
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
catch (e) {
|
|
767
|
+
console.error('[LLM] draft failed:', e);
|
|
768
|
+
ws.send(JSON.stringify({ type: 'llm:draft:result', payload: { requestId, error: e?.message ?? String(e) } }));
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
else if (msg.type === 'llm:suggest') {
|
|
772
|
+
// Completeness suggestions via LLM (#53)
|
|
773
|
+
const { requestId } = msg.payload ?? {};
|
|
774
|
+
try {
|
|
775
|
+
const { resolveLLMConfig, createProvider, createQueryContext, findConfigFile, serializeModelContext } = await import('@memoarchitect/tools');
|
|
776
|
+
const { loadAndResolveConfig } = await import('./config-resolver.js');
|
|
777
|
+
const llmConfig = resolveLLMConfig();
|
|
778
|
+
if (!llmConfig) {
|
|
779
|
+
ws.send(JSON.stringify({ type: 'llm:suggest:result', payload: { requestId, error: 'No LLM provider configured.' } }));
|
|
780
|
+
}
|
|
781
|
+
else {
|
|
782
|
+
const modelMsg = initialMessages.find((m) => m.type === 'model:update');
|
|
783
|
+
const validMsg = initialMessages.find((m) => m.type === 'validation:update');
|
|
784
|
+
const compMsg = initialMessages.find((m) => m.type === 'completeness:update');
|
|
785
|
+
const configPath = findConfigFile(options.projectRoot);
|
|
786
|
+
const config = configPath ? await loadAndResolveConfig(configPath) : {};
|
|
787
|
+
const ctx = createQueryContext(modelMsg?.payload ?? {}, validMsg?.payload ?? { violations: [] }, compMsg?.payload ?? { overall: 0, layers: [] }, config);
|
|
788
|
+
const modelContext = serializeModelContext(ctx, { includeGaps: true, maxElements: 200 });
|
|
789
|
+
const provider = createProvider(llmConfig);
|
|
790
|
+
const result = await provider.complete({
|
|
791
|
+
messages: [
|
|
792
|
+
{
|
|
793
|
+
role: 'system',
|
|
794
|
+
content: `You are MEMO Completeness Assistant, an expert in medical device systems engineering and SysML v2 modeling. Analyze the provided model and suggest the top 5-8 most impactful next modeling steps to improve completeness and regulatory compliance (ISO 14971, IEC 62304, ISO 13485).
|
|
795
|
+
|
|
796
|
+
Return ONLY a JSON array of strings. Each string is a concise, actionable suggestion (one sentence). Example format:
|
|
797
|
+
["Add RiskControl elements for 3 unmitigated Hazard elements", "Define VerificationActivity for each TestCase requirement"]`,
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
role: 'user',
|
|
801
|
+
content: `Model context:\n\n${modelContext}\n\nSuggest the top modeling improvements as a JSON array of strings.`,
|
|
802
|
+
},
|
|
803
|
+
],
|
|
804
|
+
temperature: 0.3,
|
|
805
|
+
maxTokens: 1024,
|
|
806
|
+
});
|
|
807
|
+
let suggestions = [];
|
|
808
|
+
try {
|
|
809
|
+
const arrMatch = result.content.match(/\[[\s\S]*\]/);
|
|
810
|
+
if (arrMatch)
|
|
811
|
+
suggestions = JSON.parse(arrMatch[0]);
|
|
812
|
+
}
|
|
813
|
+
catch {
|
|
814
|
+
suggestions = [result.content];
|
|
815
|
+
}
|
|
816
|
+
ws.send(JSON.stringify({ type: 'llm:suggest:result', payload: { requestId, suggestions } }));
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
catch (e) {
|
|
820
|
+
console.error('[LLM] suggest failed:', e);
|
|
821
|
+
ws.send(JSON.stringify({ type: 'llm:suggest:result', payload: { requestId, error: e?.message ?? String(e) } }));
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
else if (msg.type === 'dhf:docs:load') {
|
|
825
|
+
const docs = loadDhfDocs(options.projectRoot);
|
|
826
|
+
ws.send(JSON.stringify({ type: 'dhf:docs', payload: { docs } }));
|
|
827
|
+
}
|
|
828
|
+
else if (msg.type === 'dhf:doc:save') {
|
|
829
|
+
const doc = msg.payload?.doc;
|
|
830
|
+
if (doc?.id) {
|
|
831
|
+
saveDhfDoc(options.projectRoot, doc);
|
|
832
|
+
// Keep other connected clients in sync
|
|
833
|
+
const docsMsg = JSON.stringify({ type: 'dhf:docs', payload: { docs: loadDhfDocs(options.projectRoot) } });
|
|
834
|
+
for (const client of clients) {
|
|
835
|
+
if (client !== ws && client.readyState === 1)
|
|
836
|
+
client.send(docsMsg);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
else if (msg.type === 'dhf:doc:delete') {
|
|
841
|
+
const docId = msg.payload?.docId;
|
|
842
|
+
if (docId) {
|
|
843
|
+
deleteDhfDoc(options.projectRoot, docId);
|
|
844
|
+
const docsMsg = JSON.stringify({ type: 'dhf:docs', payload: { docs: loadDhfDocs(options.projectRoot) } });
|
|
845
|
+
for (const client of clients) {
|
|
846
|
+
if (client !== ws && client.readyState === 1)
|
|
847
|
+
client.send(docsMsg);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
else if (msg.type === 'dhf:settings:save') {
|
|
852
|
+
if (msg.payload?.settings) {
|
|
853
|
+
saveDhfSettings(options.projectRoot, msg.payload.settings);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
else if (msg.type === 'dhf:templates:list') {
|
|
857
|
+
const { requestId } = msg.payload ?? {};
|
|
858
|
+
const templates = listRepoTemplates(options.projectRoot);
|
|
859
|
+
ws.send(JSON.stringify({ type: 'dhf:templates:result', payload: { requestId, templates } }));
|
|
860
|
+
}
|
|
861
|
+
else if (msg.type === 'dhf:template:read') {
|
|
862
|
+
const { requestId, path } = msg.payload ?? {};
|
|
863
|
+
try {
|
|
864
|
+
const content = readRepoTemplate(options.projectRoot, path);
|
|
865
|
+
ws.send(JSON.stringify({ type: 'dhf:template:content', payload: { requestId, path, content } }));
|
|
866
|
+
}
|
|
867
|
+
catch (e) {
|
|
868
|
+
ws.send(JSON.stringify({ type: 'dhf:template:content', payload: { requestId, path, error: e?.message ?? String(e) } }));
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
else if (msg.type === 'ontology:remove') {
|
|
872
|
+
// Remove an installed ontology package
|
|
873
|
+
const { projectRoot } = options;
|
|
874
|
+
const pkgName = msg.payload?.packageName;
|
|
875
|
+
if (!pkgName) {
|
|
876
|
+
ws.send(JSON.stringify({ type: 'ontology:remove:result', payload: { success: false, packageName: '', error: 'No package name' } }));
|
|
877
|
+
}
|
|
878
|
+
else {
|
|
879
|
+
try {
|
|
880
|
+
const shortName = pkgName.replace('@memoarchitect/', '');
|
|
881
|
+
const memoPkgsPath = resolve(projectRoot, 'memo_packages', shortName);
|
|
882
|
+
if (existsSync(memoPkgsPath)) {
|
|
883
|
+
const { rmSync } = await import('node:fs');
|
|
884
|
+
rmSync(memoPkgsPath, { recursive: true, force: true });
|
|
885
|
+
}
|
|
886
|
+
// Refresh and broadcast
|
|
887
|
+
const { getPackageMetadata } = await import('@memoarchitect/tools');
|
|
888
|
+
const packages = getPackageMetadata(projectRoot);
|
|
889
|
+
const pkgMsg = { type: 'ontology:packages', payload: { packages } };
|
|
890
|
+
for (const client of clients) {
|
|
891
|
+
if (client.readyState === 1)
|
|
892
|
+
client.send(JSON.stringify(pkgMsg));
|
|
893
|
+
}
|
|
894
|
+
ws.send(JSON.stringify({
|
|
895
|
+
type: 'ontology:remove:result',
|
|
896
|
+
payload: { success: true, packageName: pkgName },
|
|
897
|
+
}));
|
|
898
|
+
console.log(`[Ontology] Removed package ${pkgName}`);
|
|
899
|
+
}
|
|
900
|
+
catch (e) {
|
|
901
|
+
ws.send(JSON.stringify({
|
|
902
|
+
type: 'ontology:remove:result',
|
|
903
|
+
payload: { success: false, packageName: pkgName, error: e?.message ?? String(e) },
|
|
904
|
+
}));
|
|
905
|
+
console.error('[Ontology] Remove failed:', e);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
catch (e) {
|
|
911
|
+
console.error('WebSocket Error:', e);
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
});
|
|
915
|
+
// Start listening
|
|
916
|
+
await new Promise((resolve) => {
|
|
917
|
+
server.listen(port, host, () => resolve());
|
|
918
|
+
});
|
|
919
|
+
return {
|
|
920
|
+
broadcast(messages) {
|
|
921
|
+
// Update initial messages for new connections
|
|
922
|
+
initialMessages.length = 0;
|
|
923
|
+
initialMessages.push(...messages);
|
|
924
|
+
for (const client of clients) {
|
|
925
|
+
if (client.readyState === 1) { // WebSocket.OPEN
|
|
926
|
+
for (const msg of messages) {
|
|
927
|
+
client.send(JSON.stringify(msg));
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
},
|
|
932
|
+
close() {
|
|
933
|
+
wss.close();
|
|
934
|
+
viteServer?.close();
|
|
935
|
+
server.close();
|
|
936
|
+
},
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
//# sourceMappingURL=dev-server.js.map
|