@monoes/monomindcli 2.8.3 → 2.9.1
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/.claude/helpers/auto-memory-hook.mjs +0 -0
- package/.claude/helpers/handlers/route-handler.cjs +12 -0
- package/.claude/helpers/handlers/session-restore-handler.cjs +28 -7
- package/.claude/helpers/hook-handler.cjs +0 -0
- package/.claude/helpers/utils/micro-agents.cjs +22 -0
- package/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +11 -6
- package/.claude/skills/monodesign/scripts/live-inject.mjs +20 -7
- package/.claude/skills/monodesign/scripts/live-server.mjs +38 -2
- package/LICENSE +191 -0
- package/README.md +8 -6
- package/dist/src/browser/dashboard/server.d.ts +5 -0
- package/dist/src/browser/dashboard/server.d.ts.map +1 -1
- package/dist/src/browser/dashboard/server.js +59 -4
- package/dist/src/browser/dashboard/server.js.map +1 -1
- package/dist/src/browser/dashboard/ui.html +18 -8
- package/dist/src/browser/workflow/store.d.ts.map +1 -1
- package/dist/src/browser/workflow/store.js +3 -2
- package/dist/src/browser/workflow/store.js.map +1 -1
- package/dist/src/capabilities/cap-documents.d.ts.map +1 -1
- package/dist/src/capabilities/cap-documents.js +14 -9
- package/dist/src/capabilities/cap-documents.js.map +1 -1
- package/dist/src/commands/design-palette.d.ts +5 -0
- package/dist/src/commands/design-palette.d.ts.map +1 -1
- package/dist/src/commands/design-palette.js +8 -5
- package/dist/src/commands/design-palette.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +22 -18
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/download-embeddings.d.ts +8 -0
- package/dist/src/commands/download-embeddings.d.ts.map +1 -0
- package/dist/src/commands/download-embeddings.js +34 -0
- package/dist/src/commands/download-embeddings.js.map +1 -0
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +14 -0
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +4 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init-wizard.js +1 -1
- package/dist/src/commands/init-wizard.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +48 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/monograph.d.ts.map +1 -1
- package/dist/src/commands/monograph.js +35 -1
- package/dist/src/commands/monograph.js.map +1 -1
- package/dist/src/commands/org-observe.d.ts +10 -0
- package/dist/src/commands/org-observe.d.ts.map +1 -1
- package/dist/src/commands/org-observe.js +195 -31
- package/dist/src/commands/org-observe.js.map +1 -1
- package/dist/src/commands/org.d.ts +1 -0
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +139 -3
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/commands/route.d.ts +1 -9
- package/dist/src/commands/route.d.ts.map +1 -1
- package/dist/src/commands/route.js +42 -65
- package/dist/src/commands/route.js.map +1 -1
- package/dist/src/commands/security-cve.d.ts.map +1 -1
- package/dist/src/commands/security-cve.js +2 -1
- package/dist/src/commands/security-cve.js.map +1 -1
- package/dist/src/index.d.ts +0 -10
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -15
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/copy-assets.d.ts +17 -0
- package/dist/src/init/copy-assets.d.ts.map +1 -0
- package/dist/src/init/copy-assets.js +271 -0
- package/dist/src/init/copy-assets.js.map +1 -0
- package/dist/src/init/executor.d.ts +2 -30
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +56 -2493
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/geminimd-generator.js +2 -2
- package/dist/src/init/helpers-generator.d.ts.map +1 -1
- package/dist/src/init/helpers-generator.js +9 -0
- package/dist/src/init/helpers-generator.js.map +1 -1
- package/dist/src/init/kimi-generator.js +3 -3
- package/dist/src/init/kimi-generator.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +0 -4
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/shared.d.ts +112 -0
- package/dist/src/init/shared.d.ts.map +1 -0
- package/dist/src/init/shared.js +475 -0
- package/dist/src/init/shared.js.map +1 -0
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +37 -0
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/init/types.d.ts +1 -1
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/init/upgrade.d.ts +34 -0
- package/dist/src/init/upgrade.d.ts.map +1 -0
- package/dist/src/init/upgrade.js +477 -0
- package/dist/src/init/upgrade.js.map +1 -0
- package/dist/src/init/write-antigravity.d.ts +13 -0
- package/dist/src/init/write-antigravity.d.ts.map +1 -0
- package/dist/src/init/write-antigravity.js +117 -0
- package/dist/src/init/write-antigravity.js.map +1 -0
- package/dist/src/init/write-capabilities.d.ts +9 -0
- package/dist/src/init/write-capabilities.d.ts.map +1 -0
- package/dist/src/init/write-capabilities.js +392 -0
- package/dist/src/init/write-capabilities.js.map +1 -0
- package/dist/src/init/write-claude.d.ts +25 -0
- package/dist/src/init/write-claude.d.ts.map +1 -0
- package/dist/src/init/write-claude.js +279 -0
- package/dist/src/init/write-claude.js.map +1 -0
- package/dist/src/init/write-kimicode.d.ts +19 -0
- package/dist/src/init/write-kimicode.d.ts.map +1 -0
- package/dist/src/init/write-kimicode.js +223 -0
- package/dist/src/init/write-kimicode.js.map +1 -0
- package/dist/src/init/write-opencode.d.ts +14 -0
- package/dist/src/init/write-opencode.d.ts.map +1 -0
- package/dist/src/init/write-opencode.js +130 -0
- package/dist/src/init/write-opencode.js.map +1 -0
- package/dist/src/init/write-runtime-config.d.ts +14 -0
- package/dist/src/init/write-runtime-config.d.ts.map +1 -0
- package/dist/src/init/write-runtime-config.js +214 -0
- package/dist/src/init/write-runtime-config.js.map +1 -0
- package/dist/src/init/write-sample-org.d.ts +9 -0
- package/dist/src/init/write-sample-org.d.ts.map +1 -0
- package/dist/src/init/write-sample-org.js +39 -0
- package/dist/src/init/write-sample-org.js.map +1 -0
- package/dist/src/knowledge/eval/golden-set.js +1 -1
- package/dist/src/knowledge/eval/golden-set.js.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +7 -3
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.js +2 -25
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -1
- package/dist/src/mcp-tools/auto-install.d.ts.map +1 -1
- package/dist/src/mcp-tools/auto-install.js +2 -1
- package/dist/src/mcp-tools/auto-install.js.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.js +26 -0
- package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +2 -37
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/monodesign-tools.d.ts +19 -0
- package/dist/src/mcp-tools/monodesign-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monodesign-tools.js +233 -0
- package/dist/src/mcp-tools/monodesign-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph/agent-history-tools.d.ts +5 -0
- package/dist/src/mcp-tools/monograph/agent-history-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/agent-history-tools.js +177 -0
- package/dist/src/mcp-tools/monograph/agent-history-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph/build-tools.d.ts +9 -0
- package/dist/src/mcp-tools/monograph/build-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/build-tools.js +299 -0
- package/dist/src/mcp-tools/monograph/build-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph/group-tools.d.ts +10 -0
- package/dist/src/mcp-tools/monograph/group-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/group-tools.js +225 -0
- package/dist/src/mcp-tools/monograph/group-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph/health-tools.d.ts +6 -0
- package/dist/src/mcp-tools/monograph/health-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/health-tools.js +113 -0
- package/dist/src/mcp-tools/monograph/health-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph/impact-tools.d.ts +9 -0
- package/dist/src/mcp-tools/monograph/impact-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/impact-tools.js +532 -0
- package/dist/src/mcp-tools/monograph/impact-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph/index.d.ts +10 -0
- package/dist/src/mcp-tools/monograph/index.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/index.js +73 -0
- package/dist/src/mcp-tools/monograph/index.js.map +1 -0
- package/dist/src/mcp-tools/monograph/query-tools.d.ts +11 -0
- package/dist/src/mcp-tools/monograph/query-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/query-tools.js +500 -0
- package/dist/src/mcp-tools/monograph/query-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph/shared.d.ts +64 -0
- package/dist/src/mcp-tools/monograph/shared.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/shared.js +215 -0
- package/dist/src/mcp-tools/monograph/shared.js.map +1 -0
- package/dist/src/mcp-tools/monograph/visualize-tools.d.ts +10 -0
- package/dist/src/mcp-tools/monograph/visualize-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/monograph/visualize-tools.js +382 -0
- package/dist/src/mcp-tools/monograph/visualize-tools.js.map +1 -0
- package/dist/src/mcp-tools/monograph-tools.d.ts +4 -23
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.js +4 -2439
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
- package/dist/src/mcp-tools/monomind-tools.d.ts +8 -0
- package/dist/src/mcp-tools/monomind-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monomind-tools.js +13 -1
- package/dist/src/mcp-tools/monomind-tools.js.map +1 -1
- package/dist/src/mcp-tools/quality/security-compliance/detect-secrets.d.ts.map +1 -1
- package/dist/src/mcp-tools/quality/security-compliance/detect-secrets.js +31 -2
- package/dist/src/mcp-tools/quality/security-compliance/detect-secrets.js.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.js +31 -1
- package/dist/src/mcp-tools/terminal-tools.js.map +1 -1
- package/dist/src/mcp-tools/types.d.ts +8 -27
- package/dist/src/mcp-tools/types.d.ts.map +1 -1
- package/dist/src/mcp-tools/types.js +9 -91
- package/dist/src/mcp-tools/types.js.map +1 -1
- package/dist/src/memory/file-permissions.d.ts +15 -0
- package/dist/src/memory/file-permissions.d.ts.map +1 -0
- package/dist/src/memory/file-permissions.js +25 -0
- package/dist/src/memory/file-permissions.js.map +1 -0
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +94 -34
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-crud.d.ts.map +1 -1
- package/dist/src/memory/memory-crud.js +298 -275
- package/dist/src/memory/memory-crud.js.map +1 -1
- package/dist/src/memory/memory-initializer.d.ts +2 -4
- package/dist/src/memory/memory-initializer.d.ts.map +1 -1
- package/dist/src/memory/memory-initializer.js +53 -76
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/memory/memory-migrations.d.ts +1 -14
- package/dist/src/memory/memory-migrations.d.ts.map +1 -1
- package/dist/src/memory/memory-migrations.js +52 -105
- package/dist/src/memory/memory-migrations.js.map +1 -1
- package/dist/src/memory/sona-optimizer.d.ts +1 -1
- package/dist/src/memory/sona-optimizer.js +1 -1
- package/dist/src/monovector/index.d.ts +16 -19
- package/dist/src/monovector/index.d.ts.map +1 -1
- package/dist/src/monovector/index.js +50 -8
- package/dist/src/monovector/index.js.map +1 -1
- package/dist/src/orgrt/approvals.d.ts +16 -0
- package/dist/src/orgrt/approvals.d.ts.map +1 -0
- package/dist/src/orgrt/approvals.js +72 -0
- package/dist/src/orgrt/approvals.js.map +1 -0
- package/dist/src/orgrt/bus.d.ts.map +1 -1
- package/dist/src/orgrt/bus.js +21 -0
- package/dist/src/orgrt/bus.js.map +1 -1
- package/dist/src/orgrt/checkpoint-ops.d.ts +19 -0
- package/dist/src/orgrt/checkpoint-ops.d.ts.map +1 -0
- package/dist/src/orgrt/checkpoint-ops.js +219 -0
- package/dist/src/orgrt/checkpoint-ops.js.map +1 -0
- package/dist/src/orgrt/checkpoint.d.ts +33 -1
- package/dist/src/orgrt/checkpoint.d.ts.map +1 -1
- package/dist/src/orgrt/checkpoint.js +50 -6
- package/dist/src/orgrt/checkpoint.js.map +1 -1
- package/dist/src/orgrt/cross-org.d.ts +32 -0
- package/dist/src/orgrt/cross-org.d.ts.map +1 -0
- package/dist/src/orgrt/cross-org.js +256 -0
- package/dist/src/orgrt/cross-org.js.map +1 -0
- package/dist/src/orgrt/daemon.d.ts +131 -157
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +356 -966
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/decisions.d.ts +33 -0
- package/dist/src/orgrt/decisions.d.ts.map +1 -0
- package/dist/src/orgrt/decisions.js +169 -0
- package/dist/src/orgrt/decisions.js.map +1 -0
- package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/kimicode-runner.js +5 -1
- package/dist/src/orgrt/kimicode-runner.js.map +1 -1
- package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/opencode-runner.js +10 -2
- package/dist/src/orgrt/opencode-runner.js.map +1 -1
- package/dist/src/orgrt/org-memory.d.ts +45 -0
- package/dist/src/orgrt/org-memory.d.ts.map +1 -0
- package/dist/src/orgrt/org-memory.js +220 -0
- package/dist/src/orgrt/org-memory.js.map +1 -0
- package/dist/src/orgrt/policy.d.ts +4 -0
- package/dist/src/orgrt/policy.d.ts.map +1 -1
- package/dist/src/orgrt/policy.js +13 -1
- package/dist/src/orgrt/policy.js.map +1 -1
- package/dist/src/orgrt/prechecks.d.ts +15 -0
- package/dist/src/orgrt/prechecks.d.ts.map +1 -0
- package/dist/src/orgrt/prechecks.js +21 -0
- package/dist/src/orgrt/prechecks.js.map +1 -0
- package/dist/src/orgrt/questions.d.ts +39 -0
- package/dist/src/orgrt/questions.d.ts.map +1 -0
- package/dist/src/orgrt/questions.js +135 -0
- package/dist/src/orgrt/questions.js.map +1 -0
- package/dist/src/orgrt/remote.d.ts +25 -0
- package/dist/src/orgrt/remote.d.ts.map +1 -0
- package/dist/src/orgrt/remote.js +73 -0
- package/dist/src/orgrt/remote.js.map +1 -0
- package/dist/src/orgrt/scheduler-integration.d.ts +19 -0
- package/dist/src/orgrt/scheduler-integration.d.ts.map +1 -0
- package/dist/src/orgrt/scheduler-integration.js +90 -0
- package/dist/src/orgrt/scheduler-integration.js.map +1 -0
- package/dist/src/orgrt/server.d.ts.map +1 -1
- package/dist/src/orgrt/server.js +70 -2
- package/dist/src/orgrt/server.js.map +1 -1
- package/dist/src/orgrt/session.d.ts +30 -1
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +184 -53
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/state-detector.d.ts +19 -0
- package/dist/src/orgrt/state-detector.d.ts.map +1 -0
- package/dist/src/orgrt/state-detector.js +59 -0
- package/dist/src/orgrt/state-detector.js.map +1 -0
- package/dist/src/orgrt/task-dag.d.ts +27 -0
- package/dist/src/orgrt/task-dag.d.ts.map +1 -0
- package/dist/src/orgrt/task-dag.js +100 -0
- package/dist/src/orgrt/task-dag.js.map +1 -0
- package/dist/src/orgrt/tool-fence.d.ts +7 -4
- package/dist/src/orgrt/tool-fence.d.ts.map +1 -1
- package/dist/src/orgrt/tool-fence.js +47 -6
- package/dist/src/orgrt/tool-fence.js.map +1 -1
- package/dist/src/orgrt/types.d.ts +57 -2
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +34 -3
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/routing/model-download.d.ts +49 -0
- package/dist/src/routing/model-download.d.ts.map +1 -0
- package/dist/src/routing/model-download.js +106 -0
- package/dist/src/routing/model-download.js.map +1 -0
- package/dist/src/services/crash-reporter.d.ts +5 -0
- package/dist/src/services/crash-reporter.d.ts.map +1 -1
- package/dist/src/services/crash-reporter.js +49 -0
- package/dist/src/services/crash-reporter.js.map +1 -1
- package/dist/src/transfer/anonymization/index.d.ts +18 -15
- package/dist/src/transfer/anonymization/index.d.ts.map +1 -1
- package/dist/src/transfer/anonymization/index.js +7 -119
- package/dist/src/transfer/anonymization/index.js.map +1 -1
- package/dist/src/ui/dashboard.html +606 -7
- package/dist/src/ui/orgs.html +7 -1
- package/dist/src/ui/routes-monograph.mjs +6 -0
- package/dist/src/ui/server.mjs +327 -7
- package/dist/src/update/checker.d.ts.map +1 -1
- package/dist/src/update/checker.js +2 -1
- package/dist/src/update/checker.js.map +1 -1
- package/dist/src/update/executor.d.ts.map +1 -1
- package/dist/src/update/executor.js +7 -3
- package/dist/src/update/executor.js.map +1 -1
- package/dist/src/update/index.d.ts +0 -1
- package/dist/src/update/index.d.ts.map +1 -1
- package/dist/src/update/index.js +5 -24
- package/dist/src/update/index.js.map +1 -1
- package/dist/src/utils/db-mutex.d.ts +11 -0
- package/dist/src/utils/db-mutex.d.ts.map +1 -0
- package/dist/src/utils/db-mutex.js +23 -0
- package/dist/src/utils/db-mutex.js.map +1 -0
- package/dist/src/utils/input-guards.d.ts +23 -0
- package/dist/src/utils/input-guards.d.ts.map +1 -1
- package/dist/src/utils/input-guards.js +72 -0
- package/dist/src/utils/input-guards.js.map +1 -1
- package/dist/src/utils/npm-command.d.ts +10 -0
- package/dist/src/utils/npm-command.d.ts.map +1 -0
- package/dist/src/utils/npm-command.js +12 -0
- package/dist/src/utils/npm-command.js.map +1 -0
- package/dist/src/utils/paths.d.ts +28 -0
- package/dist/src/utils/paths.d.ts.map +1 -0
- package/dist/src/utils/paths.js +108 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/scripts/download-embedding-model.mjs +97 -0
- package/scripts/publish.sh +0 -0
- package/scripts/sync-claude-assets.sh +0 -0
- package/dist/src/production/circuit-breaker.d.ts +0 -121
- package/dist/src/production/circuit-breaker.d.ts.map +0 -1
- package/dist/src/production/circuit-breaker.js +0 -262
- package/dist/src/production/circuit-breaker.js.map +0 -1
- package/dist/src/production/error-handler.d.ts +0 -119
- package/dist/src/production/error-handler.d.ts.map +0 -1
- package/dist/src/production/error-handler.js +0 -324
- package/dist/src/production/error-handler.js.map +0 -1
- package/dist/src/production/index.d.ts +0 -6
- package/dist/src/production/index.d.ts.map +0 -1
- package/dist/src/production/index.js +0 -6
- package/dist/src/production/index.js.map +0 -1
- package/dist/src/production/monitoring.d.ts +0 -181
- package/dist/src/production/monitoring.d.ts.map +0 -1
- package/dist/src/production/monitoring.js +0 -375
- package/dist/src/production/monitoring.js.map +0 -1
- package/dist/src/production/rate-limiter.d.ts +0 -125
- package/dist/src/production/rate-limiter.d.ts.map +0 -1
- package/dist/src/production/rate-limiter.js +0 -218
- package/dist/src/production/rate-limiter.js.map +0 -1
- package/dist/src/production/retry.d.ts +0 -48
- package/dist/src/production/retry.d.ts.map +0 -1
- package/dist/src/production/retry.js +0 -189
- package/dist/src/production/retry.js.map +0 -1
- package/dist/src/transfer/types.d.ts +0 -245
- package/dist/src/transfer/types.d.ts.map +0 -1
- package/dist/src/transfer/types.js +0 -6
- package/dist/src/transfer/types.js.map +0 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { statSync } from 'fs';
|
|
4
|
+
import { getProjectCwd } from '../types.js';
|
|
5
|
+
let _cachedDbPath;
|
|
6
|
+
let _cachedCwd;
|
|
7
|
+
// P2: staleness cache for computeCommitsBehind. Keyed by repoPath, TTL 30s.
|
|
8
|
+
// Cuts the per-call git rev-list spawn from "every monograph_* tool call"
|
|
9
|
+
// down to one per 30s per repo — a 50-100ms saving on the hottest path.
|
|
10
|
+
const _stalenessCache = new Map();
|
|
11
|
+
export function _isValidDb(p) {
|
|
12
|
+
try {
|
|
13
|
+
return statSync(p).size >= 100;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the monograph DB path for a given repo root (defaults to project cwd).
|
|
21
|
+
* Falls back to searching up to the git root when the DB isn't directly under
|
|
22
|
+
* `<cwd>/.monomind` — e.g. when called from a subdirectory of the repo. Only
|
|
23
|
+
* the no-arg (project cwd) form is cached; explicit `repoPath` overrides are
|
|
24
|
+
* cheap one-off lookups (staleness checks with a user-supplied path) so caching
|
|
25
|
+
* them isn't worth the invalidation complexity.
|
|
26
|
+
*/
|
|
27
|
+
export function getDbPath(repoPathOverride) {
|
|
28
|
+
const cwd = repoPathOverride ?? getProjectCwd();
|
|
29
|
+
const useCache = repoPathOverride === undefined;
|
|
30
|
+
// Invalidate cache when project root changes (e.g. MONOMIND_CWD set after initialize)
|
|
31
|
+
if (useCache && _cachedDbPath && _cachedCwd === cwd)
|
|
32
|
+
return _cachedDbPath;
|
|
33
|
+
if (useCache) {
|
|
34
|
+
_cachedCwd = cwd;
|
|
35
|
+
_cachedDbPath = undefined;
|
|
36
|
+
}
|
|
37
|
+
const direct = join(cwd, '.monomind', 'monograph.db');
|
|
38
|
+
if (_isValidDb(direct)) {
|
|
39
|
+
if (useCache)
|
|
40
|
+
_cachedDbPath = direct;
|
|
41
|
+
return direct;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const root = execSync('git rev-parse --show-toplevel', { cwd, encoding: 'utf8' }).trim();
|
|
45
|
+
const candidate = join(root, '.monomind', 'monograph.db');
|
|
46
|
+
if (_isValidDb(candidate)) {
|
|
47
|
+
if (useCache)
|
|
48
|
+
_cachedDbPath = candidate;
|
|
49
|
+
return candidate;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch { /* not in a git repo */ }
|
|
53
|
+
// Don't cache failures — the DB may be created by a subsequent build
|
|
54
|
+
return direct;
|
|
55
|
+
}
|
|
56
|
+
export function text(t) {
|
|
57
|
+
return { content: [{ type: 'text', text: t }] };
|
|
58
|
+
}
|
|
59
|
+
export function applyPprRerank(db, seedNodes, damping, maxResults) {
|
|
60
|
+
const propagated = new Map();
|
|
61
|
+
for (const r of seedNodes) {
|
|
62
|
+
propagated.set(r.id, r.score);
|
|
63
|
+
}
|
|
64
|
+
// P3: batched edge lookup — was one SELECT per seed node (N+1 over the
|
|
65
|
+
// default limit*2=40 seeds). Now a single WHERE source_id IN (?, ?, …)
|
|
66
|
+
// pulls every neighbor in one round-trip. SQLite parameter limit is 999,
|
|
67
|
+
// well above the 40-seed default; fall back to chunking if a caller ever
|
|
68
|
+
// exceeds it.
|
|
69
|
+
const seedIds = seedNodes.map(r => r.id);
|
|
70
|
+
const SEED_CHUNK = 500;
|
|
71
|
+
const sourceToTargets = new Map();
|
|
72
|
+
for (let i = 0; i < seedIds.length; i += SEED_CHUNK) {
|
|
73
|
+
const chunk = seedIds.slice(i, i + SEED_CHUNK);
|
|
74
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
75
|
+
const rows = db.prepare(`SELECT source_id, target_id FROM edges WHERE source_id IN (${placeholders})`).all(...chunk);
|
|
76
|
+
for (const row of rows) {
|
|
77
|
+
const arr = sourceToTargets.get(row.source_id) ?? [];
|
|
78
|
+
arr.push(row.target_id);
|
|
79
|
+
sourceToTargets.set(row.source_id, arr);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
for (const r of seedNodes) {
|
|
83
|
+
const neighbors = sourceToTargets.get(r.id) ?? [];
|
|
84
|
+
for (const n of neighbors) {
|
|
85
|
+
const boost = r.score * damping;
|
|
86
|
+
const current = propagated.get(n) ?? 0;
|
|
87
|
+
propagated.set(n, Math.max(current, boost));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const seedIdSet = new Set(seedNodes.map(r => r.id));
|
|
91
|
+
const ranked = seedNodes.map(r => ({
|
|
92
|
+
...r,
|
|
93
|
+
combinedScore: Math.max(r.score, propagated.get(r.id) ?? 0),
|
|
94
|
+
boostedByNeighbors: false,
|
|
95
|
+
}));
|
|
96
|
+
// P3: batched node lookup for non-seed propagated nodes — was one SELECT
|
|
97
|
+
// per propagated id (~10 per call). Single WHERE id IN (?, ?, …) instead.
|
|
98
|
+
const nonSeedIds = [...propagated.keys()].filter(id => !seedIdSet.has(id));
|
|
99
|
+
const nodeById = new Map();
|
|
100
|
+
for (let i = 0; i < nonSeedIds.length; i += SEED_CHUNK) {
|
|
101
|
+
const chunk = nonSeedIds.slice(i, i + SEED_CHUNK);
|
|
102
|
+
const placeholders = chunk.map(() => '?').join(',');
|
|
103
|
+
const rows = db.prepare(`SELECT id, name, label, file_path, start_line FROM nodes WHERE id IN (${placeholders})`).all(...chunk);
|
|
104
|
+
for (const row of rows)
|
|
105
|
+
nodeById.set(row.id, row);
|
|
106
|
+
}
|
|
107
|
+
for (const [id, score] of propagated) {
|
|
108
|
+
if (!seedIdSet.has(id)) {
|
|
109
|
+
const node = nodeById.get(id);
|
|
110
|
+
if (node) {
|
|
111
|
+
ranked.push({
|
|
112
|
+
id: node.id, name: node.name, label: node.label,
|
|
113
|
+
filePath: node.file_path, startLine: node.start_line,
|
|
114
|
+
score: 0, combinedScore: score, boostedByNeighbors: true,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
ranked.sort((a, b) => b.combinedScore - a.combinedScore);
|
|
120
|
+
return ranked.slice(0, maxResults).map(r => ({
|
|
121
|
+
id: r.id, name: r.name, label: r.label,
|
|
122
|
+
filePath: r.filePath, startLine: r.startLine,
|
|
123
|
+
score: r.combinedScore, boostedByNeighbors: r.boostedByNeighbors,
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
126
|
+
/** Guard against concurrent background buildAsync calls on the same DB. */
|
|
127
|
+
let _buildInProgress = false;
|
|
128
|
+
/**
|
|
129
|
+
* Compute how many commits the index is behind HEAD.
|
|
130
|
+
* Returns { commitsBehind, lastCommit } — or null if the index has never been
|
|
131
|
+
* built or git is unavailable.
|
|
132
|
+
*/
|
|
133
|
+
export async function computeCommitsBehind(repoPath) {
|
|
134
|
+
// P2: cache per-repoPath for 30s. computeCommitsBehind fires on every
|
|
135
|
+
// monograph_query, monograph_suggest, monograph_staleness, and
|
|
136
|
+
// monograph_health call (4 of the hottest tools) — each one was paying
|
|
137
|
+
// ~50-100ms for `openDb + git rev-list --count + closeDb`. The result
|
|
138
|
+
// changes only when the user commits, so a 30s TTL is well inside the
|
|
139
|
+
// dev cycle and cuts repeated calls to a single git spawn per half-minute.
|
|
140
|
+
const cached = _stalenessCache.get(repoPath);
|
|
141
|
+
if (cached && Date.now() - cached.ts < 30_000)
|
|
142
|
+
return cached.value;
|
|
143
|
+
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
144
|
+
const { execSync } = await import('child_process');
|
|
145
|
+
const dbPath = getDbPath(repoPath);
|
|
146
|
+
if (!_isValidDb(dbPath))
|
|
147
|
+
return null;
|
|
148
|
+
// openDb's fileMustExist option isn't in the currently-published
|
|
149
|
+
// @monoes/monograph release this CLI depends on — _isValidDb above is the
|
|
150
|
+
// real guard against openDb silently creating an empty DB at a missing path.
|
|
151
|
+
const db = openDb(dbPath);
|
|
152
|
+
try {
|
|
153
|
+
const meta = db.prepare("SELECT value FROM index_meta WHERE key = 'last_commit_hash'").get() ?? db.prepare("SELECT value FROM index_meta WHERE key = 'lastCommit'").get();
|
|
154
|
+
const lastCommit = meta?.value ?? null;
|
|
155
|
+
if (!lastCommit || !/^[0-9a-f]{7,40}$/i.test(lastCommit))
|
|
156
|
+
return null;
|
|
157
|
+
try {
|
|
158
|
+
const out = execSync(`git rev-list --count ${lastCommit}..HEAD`, {
|
|
159
|
+
cwd: repoPath, encoding: 'utf-8', timeout: 5_000,
|
|
160
|
+
}).trim();
|
|
161
|
+
const value = { commitsBehind: parseInt(out, 10), lastCommit };
|
|
162
|
+
_stalenessCache.set(repoPath, { ts: Date.now(), value });
|
|
163
|
+
return value;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
closeDb(db);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Shared staleness threshold: both monograph_staleness and monograph_suggest (checkStaleness)
|
|
175
|
+
* trigger a background rebuild only when the index is more than this many commits behind HEAD.
|
|
176
|
+
* Using a shared constant prevents conflicting rebuild pressure during active dev sessions.
|
|
177
|
+
* Was 10 → 3 → 1. Even 3 let routine small commits accumulate stale results
|
|
178
|
+
* silently. At 1 (rebuild triggers at 2+ behind), staleness rarely persists
|
|
179
|
+
* across sessions.
|
|
180
|
+
*/
|
|
181
|
+
export const STALENESS_THRESHOLD = 1;
|
|
182
|
+
/**
|
|
183
|
+
* Fire-and-forget background rebuild. Uses a module-level guard so concurrent
|
|
184
|
+
* MCP tool calls (e.g. repeated monograph_suggest checkStaleness) don't pile up builds.
|
|
185
|
+
* threshold: minimum commitsBehind to trigger (default STALENESS_THRESHOLD + 1).
|
|
186
|
+
*/
|
|
187
|
+
export function triggerBackgroundBuildIfNeeded(repoPath, commitsBehind, threshold = STALENESS_THRESHOLD + 1) {
|
|
188
|
+
if (commitsBehind < threshold)
|
|
189
|
+
return false;
|
|
190
|
+
if (_buildInProgress)
|
|
191
|
+
return false;
|
|
192
|
+
_buildInProgress = true;
|
|
193
|
+
void import('@monoes/monograph')
|
|
194
|
+
.then(({ buildAsync }) => buildAsync(repoPath, { codeOnly: true }))
|
|
195
|
+
.catch((e) => {
|
|
196
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
197
|
+
console.error('[triggerBackgroundBuildIfNeeded] staleness-triggered rebuild failed:', e);
|
|
198
|
+
})
|
|
199
|
+
.finally(() => { _buildInProgress = false; });
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* BM25 ranks purely on literal keyword overlap, so a doc/concept node whose
|
|
204
|
+
* prose happens to mention task-related words (e.g. a report mentioning
|
|
205
|
+
* "retry" constants) can outrank the actual code symbol the task is really
|
|
206
|
+
* about, which is conceptually related but lexically different (issue #38).
|
|
207
|
+
* Prefer code-symbol hits (Function/Class/Method/...) over doc-type hits
|
|
208
|
+
* (Document/Concept/Section/...) when there are any, falling back to the
|
|
209
|
+
* full hit list so a genuinely doc-only task still gets results.
|
|
210
|
+
*/
|
|
211
|
+
export function preferSymbolHits(hits, symbolLabels) {
|
|
212
|
+
const symbolHits = hits.filter(h => symbolLabels.has(h.label));
|
|
213
|
+
return symbolHits.length > 0 ? symbolHits : hits;
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../src/mcp-tools/monograph/shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { MCPTool } from '../types.js';
|
|
2
|
+
export declare const monographVisualizeTool: MCPTool;
|
|
3
|
+
export declare const monographExportTool: MCPTool;
|
|
4
|
+
export declare const monographSnapshotTool: MCPTool;
|
|
5
|
+
export declare const monographDiffTool: MCPTool;
|
|
6
|
+
export declare const monographReportTool: MCPTool;
|
|
7
|
+
export declare const monographWikiTool: MCPTool;
|
|
8
|
+
export declare const monographWikiBuildTool: MCPTool;
|
|
9
|
+
export declare const monographServeTool: MCPTool;
|
|
10
|
+
//# sourceMappingURL=visualize-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visualize-tools.d.ts","sourceRoot":"","sources":["../../../../src/mcp-tools/monograph/visualize-tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAY3C,eAAO,MAAM,sBAAsB,EAAE,OA0CpC,CAAC;AAIF,eAAO,MAAM,mBAAmB,EAAE,OA6DjC,CAAC;AAIF,eAAO,MAAM,qBAAqB,EAAE,OA2BnC,CAAC;AAIF,eAAO,MAAM,iBAAiB,EAAE,OAgF/B,CAAC;AAIF,eAAO,MAAM,mBAAmB,EAAE,OAgDjC,CAAC;AAIF,eAAO,MAAM,iBAAiB,EAAE,OAyB/B,CAAC;AAIF,eAAO,MAAM,sBAAsB,EAAE,OA6BpC,CAAC;AAIF,eAAO,MAAM,kBAAkB,EAAE,OAqBhC,CAAC"}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { join, resolve, sep } from 'path';
|
|
2
|
+
import { getProjectCwd } from '../types.js';
|
|
3
|
+
import { getDbPath, text } from './shared.js';
|
|
4
|
+
// Columns needed to render/export the graph — deliberately excludes `embedding`,
|
|
5
|
+
// which can be several KB per node (384D vectors) and would otherwise bloat
|
|
6
|
+
// tool-result payloads and written files by many MB.
|
|
7
|
+
const NODE_RENDER_COLUMNS = 'id, label, name, norm_label, file_path, start_line, end_line, community_id, is_exported, language, properties';
|
|
8
|
+
// ── monograph_visualize ───────────────────────────────────────────────────────
|
|
9
|
+
export const monographVisualizeTool = {
|
|
10
|
+
name: 'monograph_visualize',
|
|
11
|
+
description: 'Render the knowledge graph as HTML (default), SVG, or JSON. Writes output to a file under .monomind/visualize/ and returns the file path (output can be multi-MB at the max node count, too large to return inline).',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
format: { type: 'string', description: 'Output format: html, svg, json (default: html)' },
|
|
16
|
+
maxNodes: { type: 'number', description: 'Max nodes to include (default 500)' },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const { openDb, closeDb, toJson, toHtml, toSvg } = await import('@monoes/monograph');
|
|
21
|
+
const { writeFileSync, mkdirSync } = await import('fs');
|
|
22
|
+
const db = openDb(getDbPath());
|
|
23
|
+
try {
|
|
24
|
+
// Cap maxNodes: passed to SQL LIMIT clause for both nodes (n) and edges
|
|
25
|
+
// (n*3). Without a cap an attacker requests all rows from both tables.
|
|
26
|
+
const MAX_EXPORT_NODES = 10_000;
|
|
27
|
+
const rawMaxNodes = input.maxNodes ?? 500;
|
|
28
|
+
const limit = Number.isFinite(rawMaxNodes) && rawMaxNodes > 0
|
|
29
|
+
? Math.min(Math.floor(rawMaxNodes), MAX_EXPORT_NODES)
|
|
30
|
+
: 500;
|
|
31
|
+
const nodes = db.prepare(`SELECT ${NODE_RENDER_COLUMNS} FROM nodes LIMIT ?`).all(limit);
|
|
32
|
+
// Only include edges where both endpoints are in the visible node set
|
|
33
|
+
const edges = db.prepare(`
|
|
34
|
+
SELECT e.* FROM edges e
|
|
35
|
+
WHERE e.source_id IN (SELECT id FROM nodes LIMIT ?)
|
|
36
|
+
AND e.target_id IN (SELECT id FROM nodes LIMIT ?)
|
|
37
|
+
LIMIT ?
|
|
38
|
+
`).all(limit, limit, limit * 3);
|
|
39
|
+
const fmt = input.format ?? 'html';
|
|
40
|
+
const rendered = fmt === 'json' ? toJson(nodes, edges)
|
|
41
|
+
: fmt === 'svg' ? toSvg(nodes, edges)
|
|
42
|
+
: toHtml(nodes, edges);
|
|
43
|
+
const ext = fmt === 'json' ? 'json' : fmt === 'svg' ? 'svg' : 'html';
|
|
44
|
+
const outDir = resolve(join(getProjectCwd(), '.monomind', 'visualize'));
|
|
45
|
+
mkdirSync(outDir, { recursive: true });
|
|
46
|
+
const outPath = join(outDir, `graph-${Date.now()}.${ext}`);
|
|
47
|
+
writeFileSync(outPath, rendered);
|
|
48
|
+
return text(`Visualization written to ${outPath} (${nodes.length} nodes, ${edges.length} edges)${ext === 'html' ? '\nNote: HTML uses the vis-network CDN script and requires network access to render.' : ''}`);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
closeDb(db);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
// ── monograph_export ────────────────────────────────────────────────────────
|
|
56
|
+
export const monographExportTool = {
|
|
57
|
+
name: 'monograph_export',
|
|
58
|
+
description: 'Export the knowledge graph in various formats: obsidian, canvas, cypher, graphml, svg, json.',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
format: { type: 'string', description: 'Format: obsidian, canvas, cypher, graphml, svg, json' },
|
|
63
|
+
outputPath: { type: 'string', description: 'Output path' },
|
|
64
|
+
},
|
|
65
|
+
required: ['format'],
|
|
66
|
+
},
|
|
67
|
+
handler: async (input) => {
|
|
68
|
+
const { openDb, closeDb, toJson, toSvg, toGraphml, toCypher, toObsidian, toCanvas } = await import('@monoes/monograph');
|
|
69
|
+
const { writeFileSync, mkdirSync } = await import('fs');
|
|
70
|
+
const db = openDb(getDbPath());
|
|
71
|
+
try {
|
|
72
|
+
// Exclude `embedding` — a several-KB-per-node vector column that would
|
|
73
|
+
// otherwise bloat exported files by many MB for no rendering benefit.
|
|
74
|
+
const nodes = db.prepare(`SELECT ${NODE_RENDER_COLUMNS} FROM nodes`).all();
|
|
75
|
+
const edges = db.prepare('SELECT * FROM edges').all();
|
|
76
|
+
const fmt = input.format;
|
|
77
|
+
const requestedOut = input.outputPath ?? join(getProjectCwd(), '.monomind', 'export');
|
|
78
|
+
const outDir = resolve(getProjectCwd(), requestedOut);
|
|
79
|
+
const allowedRoot = resolve(getProjectCwd());
|
|
80
|
+
if (outDir !== allowedRoot && !outDir.startsWith(allowedRoot + sep)) {
|
|
81
|
+
return text(`Error: outputPath must be within the project directory (${allowedRoot})`);
|
|
82
|
+
}
|
|
83
|
+
mkdirSync(outDir, { recursive: true });
|
|
84
|
+
if (fmt === 'json') {
|
|
85
|
+
const p = join(outDir, 'graph.json');
|
|
86
|
+
writeFileSync(p, toJson(nodes, edges));
|
|
87
|
+
return text(`Exported JSON to ${p}`);
|
|
88
|
+
}
|
|
89
|
+
if (fmt === 'svg') {
|
|
90
|
+
const p = join(outDir, 'graph.svg');
|
|
91
|
+
writeFileSync(p, toSvg(nodes, edges));
|
|
92
|
+
return text(`Exported SVG to ${p}`);
|
|
93
|
+
}
|
|
94
|
+
if (fmt === 'graphml') {
|
|
95
|
+
const p = join(outDir, 'graph.graphml');
|
|
96
|
+
writeFileSync(p, toGraphml(nodes, edges));
|
|
97
|
+
return text(`Exported GraphML to ${p}`);
|
|
98
|
+
}
|
|
99
|
+
if (fmt === 'cypher') {
|
|
100
|
+
const p = join(outDir, 'graph.cypher');
|
|
101
|
+
writeFileSync(p, toCypher(nodes, edges));
|
|
102
|
+
return text(`Exported Cypher to ${p}`);
|
|
103
|
+
}
|
|
104
|
+
if (fmt === 'obsidian') {
|
|
105
|
+
toObsidian(nodes, edges, outDir);
|
|
106
|
+
return text(`Exported Obsidian vault to ${outDir}`);
|
|
107
|
+
}
|
|
108
|
+
if (fmt === 'canvas') {
|
|
109
|
+
const p = join(outDir, 'graph.canvas');
|
|
110
|
+
writeFileSync(p, toCanvas(nodes, edges));
|
|
111
|
+
return text(`Exported Canvas to ${p}`);
|
|
112
|
+
}
|
|
113
|
+
return text(`Format ${fmt} export written to ${outDir}`);
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
closeDb(db);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
// ── monograph_snapshot ──────────────────────────────────────────────────────
|
|
121
|
+
export const monographSnapshotTool = {
|
|
122
|
+
name: 'monograph_snapshot',
|
|
123
|
+
description: 'Save current graph state to a named JSON snapshot. Use with monograph_diff to compare before/after changes.',
|
|
124
|
+
inputSchema: {
|
|
125
|
+
type: 'object',
|
|
126
|
+
properties: {
|
|
127
|
+
name: { type: 'string', description: 'Snapshot name (default: ISO timestamp). Used as the filename.' },
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
handler: async (input) => {
|
|
131
|
+
const { openDb, closeDb, snapshotFromDb } = await import('@monoes/monograph');
|
|
132
|
+
const { writeFileSync, mkdirSync } = await import('fs');
|
|
133
|
+
const { resolve: resolvePath } = await import('path');
|
|
134
|
+
const db = openDb(getDbPath());
|
|
135
|
+
try {
|
|
136
|
+
const snapshot = snapshotFromDb(db);
|
|
137
|
+
const rawName = input.name ?? new Date().toISOString().replace(/[:.]/g, '-');
|
|
138
|
+
const SAFE_NAME_RE = /^[a-zA-Z0-9_.\-]+$/;
|
|
139
|
+
if (!SAFE_NAME_RE.test(rawName))
|
|
140
|
+
return text(`Invalid snapshot name: ${rawName}`);
|
|
141
|
+
const snapshotDir = resolvePath(join(getProjectCwd(), '.monomind', 'snapshots'));
|
|
142
|
+
mkdirSync(snapshotDir, { recursive: true });
|
|
143
|
+
const outPath = join(snapshotDir, `${rawName}.json`);
|
|
144
|
+
if (!resolvePath(outPath).startsWith(snapshotDir))
|
|
145
|
+
return text(`Path traversal detected in snapshot name`);
|
|
146
|
+
writeFileSync(outPath, JSON.stringify(snapshot, null, 2));
|
|
147
|
+
return text(`Snapshot saved: ${outPath}\n nodes: ${snapshot.nodes.length} edges: ${snapshot.edges.length}`);
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
closeDb(db);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
// ── monograph_diff ──────────────────────────────────────────────────────────
|
|
155
|
+
export const monographDiffTool = {
|
|
156
|
+
name: 'monograph_diff',
|
|
157
|
+
description: 'Compare two named graph snapshots (saved via monograph_snapshot). Omit "after" to diff the "before" snapshot against the live graph.',
|
|
158
|
+
inputSchema: {
|
|
159
|
+
type: 'object',
|
|
160
|
+
properties: {
|
|
161
|
+
before: { type: 'string', description: 'Name of the before snapshot (without .json extension)' },
|
|
162
|
+
after: { type: 'string', description: 'Name of the after snapshot, or omit to compare against the live graph' },
|
|
163
|
+
},
|
|
164
|
+
required: ['before'],
|
|
165
|
+
},
|
|
166
|
+
handler: async (input) => {
|
|
167
|
+
const { openDb, closeDb, snapshotFromDb, diffSnapshots } = await import('@monoes/monograph');
|
|
168
|
+
const { readFileSync, existsSync, statSync: statSyncSnap } = await import('fs');
|
|
169
|
+
const { resolve: resolvePath } = await import('path');
|
|
170
|
+
const MAX_SNAPSHOT_BYTES = 100 * 1024 * 1024; // 100 MB
|
|
171
|
+
const snapshotDir = resolvePath(join(getProjectCwd(), '.monomind', 'snapshots'));
|
|
172
|
+
// Reject snapshot names containing path separators or traversal sequences
|
|
173
|
+
const SAFE_SNAPSHOT_NAME = /^[a-zA-Z0-9_.\-]+$/;
|
|
174
|
+
const beforeName = input.before;
|
|
175
|
+
if (!SAFE_SNAPSHOT_NAME.test(beforeName))
|
|
176
|
+
return text(`Invalid snapshot name: ${beforeName}`);
|
|
177
|
+
const beforePath = join(snapshotDir, `${beforeName}.json`);
|
|
178
|
+
if (!resolvePath(beforePath).startsWith(snapshotDir))
|
|
179
|
+
return text(`Path traversal detected in snapshot name`);
|
|
180
|
+
if (!existsSync(beforePath)) {
|
|
181
|
+
return text(`Snapshot not found: ${beforePath}\nCreate one first with monograph_snapshot.`);
|
|
182
|
+
}
|
|
183
|
+
if (statSyncSnap(beforePath).size > MAX_SNAPSHOT_BYTES) {
|
|
184
|
+
return text(`Snapshot too large to diff: ${beforePath}`);
|
|
185
|
+
}
|
|
186
|
+
const before = JSON.parse(readFileSync(beforePath, 'utf-8'));
|
|
187
|
+
let after;
|
|
188
|
+
if (input.after) {
|
|
189
|
+
const afterName = input.after;
|
|
190
|
+
if (!SAFE_SNAPSHOT_NAME.test(afterName))
|
|
191
|
+
return text(`Invalid snapshot name: ${afterName}`);
|
|
192
|
+
const afterPath = join(snapshotDir, `${afterName}.json`);
|
|
193
|
+
if (!resolvePath(afterPath).startsWith(snapshotDir))
|
|
194
|
+
return text(`Path traversal detected in snapshot name`);
|
|
195
|
+
if (!existsSync(afterPath))
|
|
196
|
+
return text(`Snapshot not found: ${afterPath}`);
|
|
197
|
+
if (statSyncSnap(afterPath).size > MAX_SNAPSHOT_BYTES)
|
|
198
|
+
return text(`Snapshot too large to diff: ${afterPath}`);
|
|
199
|
+
after = JSON.parse(readFileSync(afterPath, 'utf-8'));
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const db = openDb(getDbPath());
|
|
203
|
+
try {
|
|
204
|
+
after = snapshotFromDb(db);
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
closeDb(db);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const diff = diffSnapshots(before, after);
|
|
211
|
+
const nodeById = new Map();
|
|
212
|
+
const indexNodes = (nodes) => {
|
|
213
|
+
for (const n of nodes) {
|
|
214
|
+
if (n.id)
|
|
215
|
+
nodeById.set(n.id, n);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
indexNodes(before.nodes);
|
|
219
|
+
indexNodes(after.nodes);
|
|
220
|
+
const resolveEdgeEnd = (id) => {
|
|
221
|
+
const ref = nodeById.get(id);
|
|
222
|
+
if (!ref)
|
|
223
|
+
return id; // fallback to raw id if not found
|
|
224
|
+
const loc = ref.filePath ? (ref.startLine != null ? `${ref.filePath}:${ref.startLine}` : ref.filePath) : '';
|
|
225
|
+
return loc ? `${ref.name} [${loc}]` : ref.name;
|
|
226
|
+
};
|
|
227
|
+
const section = (label, items) => items.length > 0 ? `\n${label} (${items.length}):\n${items.slice(0, 10).join('\n')}${items.length > 10 ? `\n … ${items.length - 10} more` : ''}` : '';
|
|
228
|
+
const formatNode = (n) => {
|
|
229
|
+
const loc = n.filePath ? (n.startLine != null ? `${n.filePath}:${n.startLine}` : n.filePath) : '';
|
|
230
|
+
return ` [${n.label ?? '?'}] ${n.name ?? '?'}${loc ? ` ${loc}` : ''}`;
|
|
231
|
+
};
|
|
232
|
+
const lines = [
|
|
233
|
+
`Diff: ${diff.summary}`,
|
|
234
|
+
section('New nodes', diff.newNodes.map(n => ` + ${formatNode(n)}`)),
|
|
235
|
+
section('Removed nodes', diff.removedNodes.map(n => ` - ${formatNode(n)}`)),
|
|
236
|
+
section('New edges', diff.newEdges.map(e => ` + ${resolveEdgeEnd(e.sourceId)} --[${e.relation}]--> ${resolveEdgeEnd(e.targetId)}`)),
|
|
237
|
+
section('Removed edges', diff.removedEdges.map(e => ` - ${resolveEdgeEnd(e.sourceId)} --[${e.relation}]--> ${resolveEdgeEnd(e.targetId)}`)),
|
|
238
|
+
].join('');
|
|
239
|
+
return text(lines);
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
// ── monograph_report ────────────────────────────────────────────────────────
|
|
243
|
+
export const monographReportTool = {
|
|
244
|
+
name: 'monograph_report',
|
|
245
|
+
description: 'Generate a GRAPH_REPORT.md summarizing the codebase knowledge graph.',
|
|
246
|
+
inputSchema: {
|
|
247
|
+
type: 'object',
|
|
248
|
+
properties: {
|
|
249
|
+
path: { type: 'string', description: 'Output path (default: .monomind/GRAPH_REPORT.md)' },
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
handler: async (input) => {
|
|
253
|
+
const { openDb, closeDb, countNodes, countEdges } = await import('@monoes/monograph');
|
|
254
|
+
const { writeFileSync, mkdirSync } = await import('fs');
|
|
255
|
+
const db = openDb(getDbPath());
|
|
256
|
+
try {
|
|
257
|
+
const nodeCount = countNodes(db);
|
|
258
|
+
const edgeCount = countEdges(db);
|
|
259
|
+
const topNodes = db.prepare(`
|
|
260
|
+
SELECT n.name, n.label, n.file_path, n.start_line,
|
|
261
|
+
COUNT(DISTINCT e1.id) + COUNT(DISTINCT e2.id) AS degree
|
|
262
|
+
FROM nodes n
|
|
263
|
+
LEFT JOIN edges e1 ON e1.source_id = n.id
|
|
264
|
+
LEFT JOIN edges e2 ON e2.target_id = n.id
|
|
265
|
+
WHERE n.label NOT IN ('File','Folder','Community','Concept')
|
|
266
|
+
GROUP BY n.id ORDER BY degree DESC LIMIT 10
|
|
267
|
+
`).all();
|
|
268
|
+
const report = [
|
|
269
|
+
'# Graph Report\n',
|
|
270
|
+
`**Generated:** ${new Date().toISOString()}`,
|
|
271
|
+
`**Nodes:** ${nodeCount} **Edges:** ${edgeCount}\n`,
|
|
272
|
+
'## Top 10 Most Connected Entities\n',
|
|
273
|
+
...topNodes.map((n, i) => {
|
|
274
|
+
const loc = n.file_path ? (n.start_line != null ? `${n.file_path}:${n.start_line}` : n.file_path) : '';
|
|
275
|
+
return `${i + 1}. **${n.name}** (${n.label}) — degree ${n.degree}${loc ? ` \`${loc}\`` : ''}`;
|
|
276
|
+
}),
|
|
277
|
+
].join('\n');
|
|
278
|
+
const rawOutPath = input.path ?? join(getProjectCwd(), '.monomind', 'GRAPH_REPORT.md');
|
|
279
|
+
const outPath = resolve(getProjectCwd(), rawOutPath);
|
|
280
|
+
const allowedRoot = resolve(getProjectCwd());
|
|
281
|
+
if (outPath !== allowedRoot && !outPath.startsWith(allowedRoot + sep)) {
|
|
282
|
+
return text(`Error: path must be within the project directory (${allowedRoot})`);
|
|
283
|
+
}
|
|
284
|
+
mkdirSync(join(outPath, '..'), { recursive: true });
|
|
285
|
+
writeFileSync(outPath, report);
|
|
286
|
+
return text(`${report}\n\nReport written to ${outPath}`);
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
closeDb(db);
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
// ── monograph_wiki ──────────────────────────────────────────────────────────
|
|
294
|
+
export const monographWikiTool = {
|
|
295
|
+
name: 'monograph_wiki',
|
|
296
|
+
description: 'Retrieve LLM-generated wiki pages for code communities. Returns one page by communityId or all pages if no filter provided.',
|
|
297
|
+
inputSchema: {
|
|
298
|
+
type: 'object',
|
|
299
|
+
properties: {
|
|
300
|
+
communityId: { type: 'string', description: 'Community ID to retrieve (omit to list all pages)' },
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
handler: async (input) => {
|
|
304
|
+
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
305
|
+
const { getWikiToolResult } = await import('@monoes/monograph');
|
|
306
|
+
const db = openDb(getDbPath());
|
|
307
|
+
try {
|
|
308
|
+
const result = getWikiToolResult(db, { communityId: input.communityId });
|
|
309
|
+
if (result.pages.length === 0) {
|
|
310
|
+
return text('No wiki pages found. Run monograph_wiki_build to generate community wiki pages.');
|
|
311
|
+
}
|
|
312
|
+
// Return pages as readable prose — content is already LLM-generated markdown.
|
|
313
|
+
const sections = result.pages.map(p => `--- Community ${p.communityId} ---\n${p.content}`);
|
|
314
|
+
return text(sections.join('\n\n'));
|
|
315
|
+
}
|
|
316
|
+
finally {
|
|
317
|
+
closeDb(db);
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
// ── monograph_wiki_build ────────────────────────────────────────────────────
|
|
322
|
+
export const monographWikiBuildTool = {
|
|
323
|
+
name: 'monograph_wiki_build',
|
|
324
|
+
description: 'Generate wiki pages for code communities using Claude Code CLI (no API key needed — reuses Claude Code auth).',
|
|
325
|
+
inputSchema: {
|
|
326
|
+
type: 'object',
|
|
327
|
+
properties: {
|
|
328
|
+
communityId: { type: 'string', description: 'Only generate for this community ID (omit for all communities)' },
|
|
329
|
+
force: { type: 'boolean', description: 'Regenerate even if page already exists (default false)' },
|
|
330
|
+
model: { type: 'string', description: 'Anthropic model to use (default: claude-haiku-4-5-20251001)' },
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
handler: async (input) => {
|
|
334
|
+
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
335
|
+
const { runWikiBuildTool } = await import('@monoes/monograph');
|
|
336
|
+
const db = openDb(getDbPath());
|
|
337
|
+
try {
|
|
338
|
+
const result = await runWikiBuildTool(db, {
|
|
339
|
+
communityId: input.communityId,
|
|
340
|
+
force: input.force,
|
|
341
|
+
model: input.model,
|
|
342
|
+
});
|
|
343
|
+
if (result.error)
|
|
344
|
+
return text(`Wiki build failed: ${result.error}`);
|
|
345
|
+
const parts = [];
|
|
346
|
+
if (result.generated != null)
|
|
347
|
+
parts.push(`${result.generated} page(s) generated`);
|
|
348
|
+
if (result.skipped != null && result.skipped > 0)
|
|
349
|
+
parts.push(`${result.skipped} skipped (already exist)`);
|
|
350
|
+
if (result.errors != null && result.errors > 0)
|
|
351
|
+
parts.push(`${result.errors} error(s)`);
|
|
352
|
+
return text(`Wiki build complete: ${parts.join(', ') || 'nothing to do'}. Use monograph_wiki to read the pages.`);
|
|
353
|
+
}
|
|
354
|
+
finally {
|
|
355
|
+
closeDb(db);
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
// ── monograph_serve ─────────────────────────────────────────────────────────
|
|
360
|
+
export const monographServeTool = {
|
|
361
|
+
name: 'monograph_serve',
|
|
362
|
+
description: 'Start a web UI server that visualizes the knowledge graph interactively using Sigma.js. Returns the URL where the dashboard is accessible.',
|
|
363
|
+
inputSchema: {
|
|
364
|
+
type: 'object',
|
|
365
|
+
properties: {
|
|
366
|
+
port: { type: 'number', description: 'Port to listen on (default 7374)' },
|
|
367
|
+
open: { type: 'boolean', description: 'Open the URL in the default browser after starting (default false)' },
|
|
368
|
+
},
|
|
369
|
+
},
|
|
370
|
+
handler: async (input) => {
|
|
371
|
+
const { openDb } = await import('@monoes/monograph');
|
|
372
|
+
const { serveMonograph } = await import('@monoes/monograph');
|
|
373
|
+
const db = openDb(getDbPath());
|
|
374
|
+
const result = await serveMonograph({
|
|
375
|
+
port: input.port ?? 7374,
|
|
376
|
+
open: input.open ?? false,
|
|
377
|
+
db,
|
|
378
|
+
});
|
|
379
|
+
return text(`Monograph web UI ${result.status === 'already_running' ? 'already running' : 'started'} at ${result.url}`);
|
|
380
|
+
},
|
|
381
|
+
};
|
|
382
|
+
//# sourceMappingURL=visualize-tools.js.map
|