@monoes/monomindcli 1.11.14 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/generated/channel-intelligence-director.md +87 -0
- package/.claude/agents/generated/chief-growth-officer.md +88 -0
- package/.claude/agents/generated/content-seo-strategist.md +90 -0
- package/.claude/agents/generated/developer-community-strategist.md +91 -0
- package/.claude/agents/generated/outreach-partnership-strategist.md +90 -0
- package/.claude/agents/generated/social-media-strategist.md +91 -0
- package/.claude/agents/generated/video-visual-strategist.md +90 -0
- package/.claude/commands/mastermind/master.md +1 -1
- package/.claude/helpers/auto-memory-hook.mjs +13 -4
- package/.claude/helpers/control-start.cjs +5 -0
- package/.claude/helpers/event-logger.cjs +114 -0
- package/.claude/helpers/handlers/adr-draft-handler.cjs +19 -5
- package/.claude/helpers/handlers/agent-start-handler.cjs +13 -4
- package/.claude/helpers/handlers/compact-handler.cjs +2 -0
- package/.claude/helpers/handlers/edit-handler.cjs +1 -1
- package/.claude/helpers/handlers/gates-handler.cjs +3 -0
- package/.claude/helpers/handlers/graph-status-handler.cjs +14 -8
- package/.claude/helpers/handlers/loops-status-handler.cjs +5 -2
- package/.claude/helpers/handlers/route-handler.cjs +24 -10
- package/.claude/helpers/handlers/session-handler.cjs +11 -4
- package/.claude/helpers/handlers/session-restore-handler.cjs +35 -19
- package/.claude/helpers/handlers/task-handler.cjs +13 -5
- package/.claude/helpers/hook-handler.cjs +40 -0
- package/.claude/helpers/intelligence.cjs +130 -53
- package/.claude/helpers/loop-tracker.cjs +15 -3
- package/.claude/helpers/memory-palace.cjs +461 -0
- package/.claude/helpers/memory.cjs +138 -14
- package/.claude/helpers/metrics-db.mjs +87 -0
- package/.claude/helpers/router.cjs +300 -42
- package/.claude/helpers/session.cjs +89 -30
- package/.claude/helpers/statusline.cjs +148 -4
- package/.claude/helpers/toggle-statusline.cjs +73 -0
- package/.claude/helpers/token-tracker.cjs +934 -0
- package/.claude/helpers/utils/micro-agents.cjs +20 -4
- package/.claude/helpers/utils/monograph.cjs +39 -4
- package/.claude/helpers/utils/telemetry.cjs +3 -3
- package/.claude/skills/mastermind/_protocol.md +25 -15
- package/.claude/skills/mastermind/architect.md +3 -3
- package/.claude/skills/mastermind/autodev.md +4 -2
- package/.claude/skills/mastermind/idea.md +10 -0
- package/.claude/skills/mastermind/ops.md +3 -3
- package/.claude/skills/mastermind/runorg.md +153 -86
- package/dist/src/agents/registry-builder.d.ts.map +1 -1
- package/dist/src/agents/registry-builder.js +2 -0
- package/dist/src/agents/registry-builder.js.map +1 -1
- package/dist/src/autopilot-state.d.ts.map +1 -1
- package/dist/src/autopilot-state.js +10 -5
- package/dist/src/autopilot-state.js.map +1 -1
- package/dist/src/benchmarks/benchmark-runner.d.ts.map +1 -1
- package/dist/src/benchmarks/benchmark-runner.js +13 -0
- package/dist/src/benchmarks/benchmark-runner.js.map +1 -1
- package/dist/src/benchmarks/metric-evaluators.d.ts.map +1 -1
- package/dist/src/benchmarks/metric-evaluators.js +20 -9
- package/dist/src/benchmarks/metric-evaluators.js.map +1 -1
- package/dist/src/browser/actions.d.ts.map +1 -1
- package/dist/src/browser/actions.js +10 -3
- package/dist/src/browser/actions.js.map +1 -1
- package/dist/src/browser/browser.d.ts.map +1 -1
- package/dist/src/browser/browser.js +12 -2
- package/dist/src/browser/browser.js.map +1 -1
- package/dist/src/browser/cdp.d.ts.map +1 -1
- package/dist/src/browser/cdp.js +21 -3
- package/dist/src/browser/cdp.js.map +1 -1
- package/dist/src/browser/har.d.ts.map +1 -1
- package/dist/src/browser/har.js +27 -5
- package/dist/src/browser/har.js.map +1 -1
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +11 -8
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/analyze.d.ts.map +1 -1
- package/dist/src/commands/analyze.js +36 -21
- package/dist/src/commands/analyze.js.map +1 -1
- package/dist/src/commands/autopilot.d.ts.map +1 -1
- package/dist/src/commands/autopilot.js +12 -4
- package/dist/src/commands/autopilot.js.map +1 -1
- package/dist/src/commands/benchmark.d.ts.map +1 -1
- package/dist/src/commands/benchmark.js +51 -8
- package/dist/src/commands/benchmark.js.map +1 -1
- package/dist/src/commands/browse.d.ts.map +1 -1
- package/dist/src/commands/browse.js +5 -2
- package/dist/src/commands/browse.js.map +1 -1
- package/dist/src/commands/claims.d.ts.map +1 -1
- package/dist/src/commands/claims.js +29 -11
- package/dist/src/commands/claims.js.map +1 -1
- package/dist/src/commands/cleanup.d.ts.map +1 -1
- package/dist/src/commands/cleanup.js +25 -5
- package/dist/src/commands/cleanup.js.map +1 -1
- package/dist/src/commands/config.d.ts.map +1 -1
- package/dist/src/commands/config.js +15 -7
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/daemon.d.ts.map +1 -1
- package/dist/src/commands/daemon.js +6 -0
- package/dist/src/commands/daemon.js.map +1 -1
- package/dist/src/commands/deployment.d.ts.map +1 -1
- package/dist/src/commands/deployment.js +34 -19
- package/dist/src/commands/deployment.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +133 -15
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/guidance.d.ts.map +1 -1
- package/dist/src/commands/guidance.js +15 -2
- package/dist/src/commands/guidance.js.map +1 -1
- package/dist/src/commands/hive-mind.d.ts.map +1 -1
- package/dist/src/commands/hive-mind.js +37 -14
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +42 -25
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +9 -4
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/issues.d.ts.map +1 -1
- package/dist/src/commands/issues.js +29 -26
- package/dist/src/commands/issues.js.map +1 -1
- package/dist/src/commands/mcp.d.ts.map +1 -1
- package/dist/src/commands/mcp.js +11 -5
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/memory.d.ts.map +1 -1
- package/dist/src/commands/memory.js +10 -0
- package/dist/src/commands/memory.js.map +1 -1
- package/dist/src/commands/migrate.js +5 -5
- package/dist/src/commands/migrate.js.map +1 -1
- package/dist/src/commands/monograph.d.ts.map +1 -1
- package/dist/src/commands/monograph.js +18 -5
- package/dist/src/commands/monograph.js.map +1 -1
- package/dist/src/commands/monovector/backup.d.ts.map +1 -1
- package/dist/src/commands/monovector/backup.js +8 -2
- package/dist/src/commands/monovector/backup.js.map +1 -1
- package/dist/src/commands/monovector/benchmark.d.ts.map +1 -1
- package/dist/src/commands/monovector/benchmark.js +20 -7
- package/dist/src/commands/monovector/benchmark.js.map +1 -1
- package/dist/src/commands/monovector/import.d.ts.map +1 -1
- package/dist/src/commands/monovector/import.js +15 -0
- package/dist/src/commands/monovector/import.js.map +1 -1
- package/dist/src/commands/monovector/migrate.d.ts.map +1 -1
- package/dist/src/commands/monovector/migrate.js +4 -1
- package/dist/src/commands/monovector/migrate.js.map +1 -1
- package/dist/src/commands/monovector/optimize.d.ts.map +1 -1
- package/dist/src/commands/monovector/optimize.js +11 -0
- package/dist/src/commands/monovector/optimize.js.map +1 -1
- package/dist/src/commands/monovector/setup.d.ts.map +1 -1
- package/dist/src/commands/monovector/setup.js +11 -1
- package/dist/src/commands/monovector/setup.js.map +1 -1
- package/dist/src/commands/neural.js +1 -1
- package/dist/src/commands/neural.js.map +1 -1
- package/dist/src/commands/performance.d.ts.map +1 -1
- package/dist/src/commands/performance.js +20 -7
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/platforms.d.ts.map +1 -1
- package/dist/src/commands/platforms.js +90 -8
- package/dist/src/commands/platforms.js.map +1 -1
- package/dist/src/commands/plugins.d.ts.map +1 -1
- package/dist/src/commands/plugins.js +12 -5
- package/dist/src/commands/plugins.js.map +1 -1
- package/dist/src/commands/process.d.ts.map +1 -1
- package/dist/src/commands/process.js +33 -10
- package/dist/src/commands/process.js.map +1 -1
- package/dist/src/commands/progress.d.ts.map +1 -1
- package/dist/src/commands/progress.js +5 -3
- package/dist/src/commands/progress.js.map +1 -1
- package/dist/src/commands/providers.js +5 -5
- package/dist/src/commands/providers.js.map +1 -1
- package/dist/src/commands/replay.d.ts.map +1 -1
- package/dist/src/commands/replay.js +8 -2
- package/dist/src/commands/replay.js.map +1 -1
- package/dist/src/commands/route.d.ts.map +1 -1
- package/dist/src/commands/route.js +27 -7
- package/dist/src/commands/route.js.map +1 -1
- package/dist/src/commands/security.d.ts.map +1 -1
- package/dist/src/commands/security.js +4 -0
- package/dist/src/commands/security.js.map +1 -1
- package/dist/src/commands/session.d.ts.map +1 -1
- package/dist/src/commands/session.js +12 -1
- package/dist/src/commands/session.js.map +1 -1
- package/dist/src/commands/start.d.ts.map +1 -1
- package/dist/src/commands/start.js +11 -4
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/status.d.ts.map +1 -1
- package/dist/src/commands/status.js +7 -4
- package/dist/src/commands/status.js.map +1 -1
- package/dist/src/commands/swarm.d.ts.map +1 -1
- package/dist/src/commands/swarm.js +27 -13
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/commands/task.d.ts.map +1 -1
- package/dist/src/commands/task.js +26 -11
- package/dist/src/commands/task.js.map +1 -1
- package/dist/src/commands/tokens.d.ts.map +1 -1
- package/dist/src/commands/tokens.js +7 -2
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/transfer-store.d.ts.map +1 -1
- package/dist/src/commands/transfer-store.js +36 -22
- package/dist/src/commands/transfer-store.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +15 -3
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/workflow.d.ts.map +1 -1
- package/dist/src/commands/workflow.js +39 -6
- package/dist/src/commands/workflow.js.map +1 -1
- package/dist/src/consensus/audit-writer.d.ts.map +1 -1
- package/dist/src/consensus/audit-writer.js +18 -7
- package/dist/src/consensus/audit-writer.js.map +1 -1
- package/dist/src/consensus/vote-signer.d.ts.map +1 -1
- package/dist/src/consensus/vote-signer.js +25 -8
- package/dist/src/consensus/vote-signer.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +14 -11
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/shared-instructions-generator.d.ts.map +1 -1
- package/dist/src/init/shared-instructions-generator.js +20 -4
- package/dist/src/init/shared-instructions-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +36 -15
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/mcp-tools/a2a-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/a2a-tools.js +98 -13
- package/dist/src/mcp-tools/a2a-tools.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +16 -3
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/analyze-tools.js +80 -17
- package/dist/src/mcp-tools/analyze-tools.js.map +1 -1
- package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/browser-tools.js +84 -22
- package/dist/src/mcp-tools/browser-tools.js.map +1 -1
- package/dist/src/mcp-tools/claims-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/claims-tools.js +35 -7
- package/dist/src/mcp-tools/claims-tools.js.map +1 -1
- package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +82 -17
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/coordination-tools.js +37 -4
- package/dist/src/mcp-tools/coordination-tools.js.map +1 -1
- package/dist/src/mcp-tools/daa-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/daa-tools.js +49 -7
- package/dist/src/mcp-tools/daa-tools.js.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.js +45 -18
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
- package/dist/src/mcp-tools/github-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/github-tools.js +75 -25
- package/dist/src/mcp-tools/github-tools.js.map +1 -1
- package/dist/src/mcp-tools/guidance-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/guidance-tools.js +32 -10
- package/dist/src/mcp-tools/guidance-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.js +91 -20
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +188 -29
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +25 -7
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph-compat.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-compat.js +11 -2
- package/dist/src/mcp-tools/monograph-compat.js.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.js +476 -62
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
- package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/neural-tools.js +44 -9
- package/dist/src/mcp-tools/neural-tools.js.map +1 -1
- package/dist/src/mcp-tools/performance-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/performance-tools.js +45 -10
- package/dist/src/mcp-tools/performance-tools.js.map +1 -1
- package/dist/src/mcp-tools/progress-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/progress-tools.js +7 -4
- package/dist/src/mcp-tools/progress-tools.js.map +1 -1
- package/dist/src/mcp-tools/request-tracker.d.ts.map +1 -1
- package/dist/src/mcp-tools/request-tracker.js +15 -1
- package/dist/src/mcp-tools/request-tracker.js.map +1 -1
- package/dist/src/mcp-tools/security-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/security-tools.js +61 -9
- package/dist/src/mcp-tools/security-tools.js.map +1 -1
- package/dist/src/mcp-tools/session-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/session-tools.js +45 -14
- package/dist/src/mcp-tools/session-tools.js.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.js +15 -3
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
- package/dist/src/mcp-tools/system-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/system-tools.js +14 -7
- package/dist/src/mcp-tools/system-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +52 -10
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.js +40 -6
- package/dist/src/mcp-tools/terminal-tools.js.map +1 -1
- package/dist/src/mcp-tools/transfer-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/transfer-tools.js +37 -4
- package/dist/src/mcp-tools/transfer-tools.js.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.js +29 -6
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
- package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
- package/dist/src/memory/ewc-consolidation.js +26 -10
- package/dist/src/memory/ewc-consolidation.js.map +1 -1
- package/dist/src/memory/intelligence.d.ts.map +1 -1
- package/dist/src/memory/intelligence.js +80 -19
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +21 -2
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-initializer.d.ts.map +1 -1
- package/dist/src/memory/memory-initializer.js +67 -3
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/memory/sona-optimizer.d.ts.map +1 -1
- package/dist/src/memory/sona-optimizer.js +14 -4
- package/dist/src/memory/sona-optimizer.js.map +1 -1
- package/dist/src/monovector/command-outcomes.d.ts.map +1 -1
- package/dist/src/monovector/command-outcomes.js +43 -7
- package/dist/src/monovector/command-outcomes.js.map +1 -1
- package/dist/src/monovector/coverage-router.d.ts.map +1 -1
- package/dist/src/monovector/coverage-router.js +8 -4
- package/dist/src/monovector/coverage-router.js.map +1 -1
- package/dist/src/monovector/coverage-tools.d.ts.map +1 -1
- package/dist/src/monovector/coverage-tools.js +6 -3
- package/dist/src/monovector/coverage-tools.js.map +1 -1
- package/dist/src/monovector/diff-classifier.d.ts.map +1 -1
- package/dist/src/monovector/diff-classifier.js +13 -0
- package/dist/src/monovector/diff-classifier.js.map +1 -1
- package/dist/src/monovector/route-outcomes.d.ts +2 -1
- package/dist/src/monovector/route-outcomes.d.ts.map +1 -1
- package/dist/src/monovector/route-outcomes.js +46 -4
- package/dist/src/monovector/route-outcomes.js.map +1 -1
- package/dist/src/plugins/manager.d.ts.map +1 -1
- package/dist/src/plugins/manager.js +8 -3
- package/dist/src/plugins/manager.js.map +1 -1
- package/dist/src/plugins/store/discovery.d.ts.map +1 -1
- package/dist/src/plugins/store/discovery.js +46 -2
- package/dist/src/plugins/store/discovery.js.map +1 -1
- package/dist/src/plugins/store/search.d.ts.map +1 -1
- package/dist/src/plugins/store/search.js +5 -4
- package/dist/src/plugins/store/search.js.map +1 -1
- package/dist/src/production/circuit-breaker.d.ts.map +1 -1
- package/dist/src/production/circuit-breaker.js +17 -3
- package/dist/src/production/circuit-breaker.js.map +1 -1
- package/dist/src/production/error-handler.d.ts.map +1 -1
- package/dist/src/production/error-handler.js +3 -0
- package/dist/src/production/error-handler.js.map +1 -1
- package/dist/src/production/monitoring.d.ts.map +1 -1
- package/dist/src/production/monitoring.js +20 -3
- package/dist/src/production/monitoring.js.map +1 -1
- package/dist/src/production/rate-limiter.d.ts.map +1 -1
- package/dist/src/production/rate-limiter.js +13 -4
- package/dist/src/production/rate-limiter.js.map +1 -1
- package/dist/src/production/retry.d.ts.map +1 -1
- package/dist/src/production/retry.js +17 -9
- package/dist/src/production/retry.js.map +1 -1
- package/dist/src/routing/embed-worker.js +6 -2
- package/dist/src/routing/embed-worker.js.map +1 -1
- package/dist/src/routing/embedder.d.ts.map +1 -1
- package/dist/src/routing/embedder.js +0 -0
- package/dist/src/routing/embedder.js.map +1 -1
- package/dist/src/routing/llm-caller.d.ts.map +1 -1
- package/dist/src/routing/llm-caller.js +13 -2
- package/dist/src/routing/llm-caller.js.map +1 -1
- package/dist/src/routing/route-layer-factory.d.ts.map +1 -1
- package/dist/src/routing/route-layer-factory.js +18 -3
- package/dist/src/routing/route-layer-factory.js.map +1 -1
- package/dist/src/services/claim-service.d.ts +1 -0
- package/dist/src/services/claim-service.d.ts.map +1 -1
- package/dist/src/services/claim-service.js +8 -0
- package/dist/src/services/claim-service.js.map +1 -1
- package/dist/src/services/config-file-manager.d.ts.map +1 -1
- package/dist/src/services/config-file-manager.js +14 -2
- package/dist/src/services/config-file-manager.js.map +1 -1
- package/dist/src/services/headless-worker-executor.d.ts.map +1 -1
- package/dist/src/services/headless-worker-executor.js +18 -2
- package/dist/src/services/headless-worker-executor.js.map +1 -1
- package/dist/src/services/worker-daemon.d.ts.map +1 -1
- package/dist/src/services/worker-daemon.js +348 -17
- package/dist/src/services/worker-daemon.js.map +1 -1
- package/dist/src/transfer/anonymization/index.d.ts +0 -3
- package/dist/src/transfer/anonymization/index.d.ts.map +1 -1
- package/dist/src/transfer/anonymization/index.js +16 -1
- package/dist/src/transfer/anonymization/index.js.map +1 -1
- package/dist/src/transfer/export.d.ts.map +1 -1
- package/dist/src/transfer/export.js +8 -0
- package/dist/src/transfer/export.js.map +1 -1
- package/dist/src/transfer/ipfs/upload.d.ts.map +1 -1
- package/dist/src/transfer/ipfs/upload.js +33 -3
- package/dist/src/transfer/ipfs/upload.js.map +1 -1
- package/dist/src/transfer/serialization/cfp.d.ts.map +1 -1
- package/dist/src/transfer/serialization/cfp.js +8 -2
- package/dist/src/transfer/serialization/cfp.js.map +1 -1
- package/dist/src/transfer/storage/gcs.d.ts.map +1 -1
- package/dist/src/transfer/storage/gcs.js +37 -3
- package/dist/src/transfer/storage/gcs.js.map +1 -1
- package/dist/src/transfer/store/discovery.d.ts.map +1 -1
- package/dist/src/transfer/store/discovery.js +45 -3
- package/dist/src/transfer/store/discovery.js.map +1 -1
- package/dist/src/transfer/store/download.d.ts.map +1 -1
- package/dist/src/transfer/store/download.js +5 -0
- package/dist/src/transfer/store/download.js.map +1 -1
- package/dist/src/transfer/store/publish.d.ts.map +1 -1
- package/dist/src/transfer/store/publish.js +13 -1
- package/dist/src/transfer/store/publish.js.map +1 -1
- package/dist/src/transfer/store/registry.d.ts +8 -0
- package/dist/src/transfer/store/registry.d.ts.map +1 -1
- package/dist/src/transfer/store/registry.js +30 -5
- package/dist/src/transfer/store/registry.js.map +1 -1
- package/dist/src/transfer/store/search.d.ts.map +1 -1
- package/dist/src/transfer/store/search.js +20 -5
- package/dist/src/transfer/store/search.js.map +1 -1
- package/dist/src/ui/collector.mjs +39 -5
- package/dist/src/ui/dashboard.html +1603 -1284
- package/dist/src/ui/orgs.html +722 -12
- package/dist/src/ui/server.mjs +717 -136
- package/dist/src/update/checker.d.ts.map +1 -1
- package/dist/src/update/checker.js +59 -7
- 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 +50 -3
- package/dist/src/update/executor.js.map +1 -1
- package/dist/src/update/index.d.ts.map +1 -1
- package/dist/src/update/index.js +18 -1
- package/dist/src/update/index.js.map +1 -1
- package/dist/src/update/rate-limiter.d.ts +6 -0
- package/dist/src/update/rate-limiter.d.ts.map +1 -1
- package/dist/src/update/rate-limiter.js +79 -7
- package/dist/src/update/rate-limiter.js.map +1 -1
- package/dist/src/update/validator.d.ts.map +1 -1
- package/dist/src/update/validator.js +52 -1
- package/dist/src/update/validator.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -3
- package/dist/src/ui/data/mastermind-events.jsonl +0 -59
|
@@ -22,6 +22,7 @@ const monographBuildTool = {
|
|
|
22
22
|
path: { type: 'string', description: 'Absolute path to the repo (defaults to project cwd)' },
|
|
23
23
|
codeOnly: { type: 'boolean', description: 'Only index code files (skip docs, config)' },
|
|
24
24
|
force: { type: 'boolean', description: 'Force full rebuild even if index is fresh' },
|
|
25
|
+
incremental: { type: 'boolean', description: 'Skip rebuild when index already matches HEAD (default false). Use when you want a no-op if the graph is fresh.' },
|
|
25
26
|
},
|
|
26
27
|
},
|
|
27
28
|
handler: async (input) => {
|
|
@@ -31,9 +32,12 @@ const monographBuildTool = {
|
|
|
31
32
|
await buildAsync(repoPath, {
|
|
32
33
|
codeOnly: input.codeOnly ?? false,
|
|
33
34
|
force: input.force ?? false,
|
|
35
|
+
incremental: input.incremental ?? false,
|
|
34
36
|
onProgress: (p) => { progressLog += `[${p.phase}] ${p.message ?? ''}\n`; },
|
|
35
37
|
});
|
|
36
|
-
|
|
38
|
+
const skipped = progressLog.includes('skipping rebuild');
|
|
39
|
+
const summary = skipped ? `Index was already fresh — no rebuild needed for ${repoPath}` : `Monograph build complete for ${repoPath}`;
|
|
40
|
+
return text(`${summary}\n${progressLog}`);
|
|
37
41
|
},
|
|
38
42
|
};
|
|
39
43
|
// ── monograph_query ───────────────────────────────────────────────────────────
|
|
@@ -54,19 +58,38 @@ const monographQueryTool = {
|
|
|
54
58
|
const { hybridQuery } = await import('@monoes/monograph');
|
|
55
59
|
const db = openDb(getDbPath());
|
|
56
60
|
try {
|
|
57
|
-
|
|
61
|
+
// Cap limit: passed directly to SQLite queries and hybridQuery; an
|
|
62
|
+
// unlimited value saturates memory with rows.
|
|
63
|
+
const MAX_QUERY_LIMIT = 1_000;
|
|
64
|
+
const rawLimit = input.limit ?? 20;
|
|
65
|
+
const limit = Number.isFinite(rawLimit) && rawLimit > 0
|
|
66
|
+
? Math.min(Math.floor(rawLimit), MAX_QUERY_LIMIT)
|
|
67
|
+
: 20;
|
|
68
|
+
// Cap query: passed to FTS5 and hybridQuery; very long queries waste
|
|
69
|
+
// parse time and can stress the FTS tokenizer.
|
|
70
|
+
const MAX_MONOGRAPH_QUERY_LEN = 16 * 1024;
|
|
71
|
+
const rawQuery = input.query;
|
|
72
|
+
const query = typeof rawQuery === 'string' && rawQuery.length > MAX_MONOGRAPH_QUERY_LEN
|
|
73
|
+
? rawQuery.slice(0, MAX_MONOGRAPH_QUERY_LEN)
|
|
74
|
+
: rawQuery;
|
|
58
75
|
const label = input.label;
|
|
59
76
|
if (process.env['MONOGRAPH_EMBEDDINGS'] === 'true') {
|
|
60
|
-
const results = await hybridQuery(db,
|
|
77
|
+
const results = await hybridQuery(db, query, { limit, label });
|
|
61
78
|
if (results.length === 0)
|
|
62
79
|
return text('No results found.');
|
|
63
|
-
const lines = results.map(r =>
|
|
80
|
+
const lines = results.map(r => {
|
|
81
|
+
const loc = r.filePath ? (r.startLine != null ? `${r.filePath}:${r.startLine}` : r.filePath) : '';
|
|
82
|
+
return `[${r.label ?? '?'}] ${r.name ?? r.id} ${loc} (score: ${r.score.toFixed(4)})`;
|
|
83
|
+
});
|
|
64
84
|
return text(lines.join('\n'));
|
|
65
85
|
}
|
|
66
|
-
const results = ftsSearch(db,
|
|
86
|
+
const results = ftsSearch(db, query, limit, label);
|
|
67
87
|
if (results.length === 0)
|
|
68
88
|
return text('No results found.');
|
|
69
|
-
const lines = results.map(r =>
|
|
89
|
+
const lines = results.map(r => {
|
|
90
|
+
const loc = r.filePath ? (r.startLine != null ? `${r.filePath}:${r.startLine}` : r.filePath) : '';
|
|
91
|
+
return `[${r.label}] ${r.name} ${loc} (score: ${r.rank.toFixed(3)})`;
|
|
92
|
+
});
|
|
70
93
|
return text(lines.join('\n'));
|
|
71
94
|
}
|
|
72
95
|
finally {
|
|
@@ -104,7 +127,9 @@ const monographHealthTool = {
|
|
|
104
127
|
const { execSync } = await import('child_process');
|
|
105
128
|
const db = openDb(getDbPath());
|
|
106
129
|
try {
|
|
107
|
-
|
|
130
|
+
// The orchestrator writes the key as 'last_commit_hash' (orchestrator.ts:68).
|
|
131
|
+
// Fall back to legacy 'lastCommit' for indexes built with older versions.
|
|
132
|
+
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();
|
|
108
133
|
const lastCommit = meta?.value ?? null;
|
|
109
134
|
if (!lastCommit)
|
|
110
135
|
return text('Index has never been built. Run monograph_build first.');
|
|
@@ -141,10 +166,15 @@ const monographGodNodesTool = {
|
|
|
141
166
|
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
142
167
|
const db = openDb(getDbPath());
|
|
143
168
|
try {
|
|
144
|
-
|
|
169
|
+
// Cap limit: passed directly to the SQL LIMIT clause.
|
|
170
|
+
const MAX_GOD_NODES_LIMIT = 1_000;
|
|
171
|
+
const rawGodLimit = input.limit ?? 20;
|
|
172
|
+
const limit = Number.isFinite(rawGodLimit) && rawGodLimit > 0
|
|
173
|
+
? Math.min(Math.floor(rawGodLimit), MAX_GOD_NODES_LIMIT)
|
|
174
|
+
: 20;
|
|
145
175
|
const excluded = ['File', 'Folder', 'Community', 'Concept'];
|
|
146
176
|
const rows = db.prepare(`
|
|
147
|
-
SELECT n.id, n.label, n.name, n.file_path,
|
|
177
|
+
SELECT n.id, n.label, n.name, n.file_path, n.start_line,
|
|
148
178
|
COUNT(DISTINCT e1.id) + COUNT(DISTINCT e2.id) AS degree,
|
|
149
179
|
COUNT(DISTINCT e2.id) AS in_degree,
|
|
150
180
|
COUNT(DISTINCT e1.id) AS out_degree
|
|
@@ -157,7 +187,10 @@ const monographGodNodesTool = {
|
|
|
157
187
|
`).all(...excluded, limit);
|
|
158
188
|
if (rows.length === 0)
|
|
159
189
|
return text('No god nodes found. Run monograph_build first.');
|
|
160
|
-
const lines = rows.map(r =>
|
|
190
|
+
const lines = rows.map(r => {
|
|
191
|
+
const loc = r.file_path ? (r.start_line != null ? `${r.file_path}:${r.start_line}` : r.file_path) : '';
|
|
192
|
+
return `[${r.label}] ${r.name} degree=${r.degree} (↑${r.out_degree} ↓${r.in_degree}) ${loc}`;
|
|
193
|
+
});
|
|
161
194
|
return text(lines.join('\n'));
|
|
162
195
|
}
|
|
163
196
|
finally {
|
|
@@ -215,7 +248,15 @@ const monographShortestPathTool = {
|
|
|
215
248
|
const path = getShortestPath(db, input.source, input.target, input.maxDepth ?? 6);
|
|
216
249
|
if (!path)
|
|
217
250
|
return text(`No path found between ${input.source} and ${input.target}`);
|
|
218
|
-
|
|
251
|
+
// Enrich each node ID with file:line for direct LLM navigation
|
|
252
|
+
const enriched = path.map(nodeId => {
|
|
253
|
+
const row = db.prepare('SELECT label, name, file_path, start_line FROM nodes WHERE id = ? OR name = ? LIMIT 1').get(nodeId, nodeId);
|
|
254
|
+
if (!row)
|
|
255
|
+
return nodeId;
|
|
256
|
+
const loc = row.file_path ? (row.start_line != null ? `${row.file_path}:${row.start_line}` : row.file_path) : '';
|
|
257
|
+
return loc ? `${row.name ?? nodeId} [${loc}]` : (row.name ?? nodeId);
|
|
258
|
+
});
|
|
259
|
+
return text(`Path (${path.length - 1} hops):\n${enriched.join(' → ')}`);
|
|
219
260
|
}
|
|
220
261
|
finally {
|
|
221
262
|
closeDb(db);
|
|
@@ -234,13 +275,24 @@ const monographCommunityTool = {
|
|
|
234
275
|
required: ['id'],
|
|
235
276
|
},
|
|
236
277
|
handler: async (input) => {
|
|
278
|
+
// Validate community ID — must be a finite integer. parseInt(NaN) or a float
|
|
279
|
+
// would silently become 0 in SQLite (NaN → NULL → 0 coercion), which would
|
|
280
|
+
// return all nodes in community 0 instead of an error.
|
|
281
|
+
const rawId = typeof input.id === 'number' ? input.id : parseInt(String(input.id), 10);
|
|
282
|
+
if (!Number.isFinite(rawId) || rawId !== Math.floor(rawId)) {
|
|
283
|
+
return text(`Invalid community ID: ${input.id} (must be an integer)`);
|
|
284
|
+
}
|
|
285
|
+
const communityId = rawId;
|
|
237
286
|
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
238
287
|
const db = openDb(getDbPath());
|
|
239
288
|
try {
|
|
240
|
-
const rows = db.prepare('SELECT
|
|
289
|
+
const rows = db.prepare('SELECT id, label, name, file_path, start_line FROM nodes WHERE community_id = ?').all(communityId);
|
|
241
290
|
if (rows.length === 0)
|
|
242
|
-
return text(`No nodes in community ${
|
|
243
|
-
return text(rows.map(r =>
|
|
291
|
+
return text(`No nodes in community ${communityId}`);
|
|
292
|
+
return text(rows.map(r => {
|
|
293
|
+
const loc = r.file_path ? (r.start_line != null ? `${r.file_path}:${r.start_line}` : r.file_path) : '';
|
|
294
|
+
return `[${r.label}] ${r.name} ${loc}`;
|
|
295
|
+
}).join('\n'));
|
|
244
296
|
}
|
|
245
297
|
finally {
|
|
246
298
|
closeDb(db);
|
|
@@ -259,9 +311,16 @@ const monographSurprisesTool = {
|
|
|
259
311
|
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
260
312
|
const db = openDb(getDbPath());
|
|
261
313
|
try {
|
|
262
|
-
|
|
314
|
+
// Cap limit: passed directly to the SQL LIMIT clause.
|
|
315
|
+
const MAX_SURPRISES_LIMIT = 1_000;
|
|
316
|
+
const rawSurprisesLimit = input.limit ?? 20;
|
|
317
|
+
const limit = Number.isFinite(rawSurprisesLimit) && rawSurprisesLimit > 0
|
|
318
|
+
? Math.min(Math.floor(rawSurprisesLimit), MAX_SURPRISES_LIMIT)
|
|
319
|
+
: 20;
|
|
263
320
|
const rows = db.prepare(`
|
|
264
|
-
SELECT e
|
|
321
|
+
SELECT e.confidence, e.confidence_score, e.relation,
|
|
322
|
+
n1.name as src_name, n1.file_path as src_file, n1.start_line as src_line,
|
|
323
|
+
n2.name as tgt_name, n2.file_path as tgt_file, n2.start_line as tgt_line
|
|
265
324
|
FROM edges e
|
|
266
325
|
JOIN nodes n1 ON n1.id = e.source_id
|
|
267
326
|
JOIN nodes n2 ON n2.id = e.target_id
|
|
@@ -270,7 +329,12 @@ const monographSurprisesTool = {
|
|
|
270
329
|
`).all(limit);
|
|
271
330
|
if (rows.length === 0)
|
|
272
331
|
return text('No surprising connections found.');
|
|
273
|
-
return text(rows.map(r =>
|
|
332
|
+
return text(rows.map(r => {
|
|
333
|
+
const srcLoc = r.src_file ? (r.src_line != null ? `${r.src_file}:${r.src_line}` : r.src_file) : '';
|
|
334
|
+
const tgtLoc = r.tgt_file ? (r.tgt_line != null ? `${r.tgt_file}:${r.tgt_line}` : r.tgt_file) : '';
|
|
335
|
+
const locHint = srcLoc || tgtLoc ? ` [${srcLoc}${tgtLoc ? ` → ${tgtLoc}` : ''}]` : '';
|
|
336
|
+
return `[${r.confidence}] ${r.src_name} --${r.relation}--> ${r.tgt_name} (score: ${r.confidence_score})${locHint}`;
|
|
337
|
+
}).join('\n'));
|
|
274
338
|
}
|
|
275
339
|
finally {
|
|
276
340
|
closeDb(db);
|
|
@@ -293,8 +357,26 @@ const monographSuggestTool = {
|
|
|
293
357
|
const { hybridQuery } = await import('@monoes/monograph');
|
|
294
358
|
const db = openDb(getDbPath());
|
|
295
359
|
try {
|
|
296
|
-
|
|
297
|
-
|
|
360
|
+
// Cap limit and task: limit is passed directly to SQL LIMIT clause;
|
|
361
|
+
// task is forwarded to hybridQuery (embedding path) or FTS.
|
|
362
|
+
const MAX_SUGGEST_LIMIT = 1_000;
|
|
363
|
+
const MAX_SUGGEST_TASK_LEN = 16 * 1024;
|
|
364
|
+
const rawSuggestLimit = input.limit ?? 10;
|
|
365
|
+
const limit = Number.isFinite(rawSuggestLimit) && rawSuggestLimit > 0
|
|
366
|
+
? Math.min(Math.floor(rawSuggestLimit), MAX_SUGGEST_LIMIT)
|
|
367
|
+
: 10;
|
|
368
|
+
const rawTask = input.task ?? '';
|
|
369
|
+
const task = typeof rawTask === 'string' && rawTask.length > MAX_SUGGEST_TASK_LEN
|
|
370
|
+
? rawTask.slice(0, MAX_SUGGEST_TASK_LEN)
|
|
371
|
+
: rawTask;
|
|
372
|
+
// Format a suggestion row as a navigable string for LLM consumption.
|
|
373
|
+
// Includes file:line references so the LLM can jump directly to the code.
|
|
374
|
+
const formatSuggestion = (r) => {
|
|
375
|
+
const srcLoc = r.src_file ? (r.src_line != null ? `${r.src_file}:${r.src_line}` : r.src_file) : '';
|
|
376
|
+
const tgtLoc = r.tgt_file ? (r.tgt_line != null ? `${r.tgt_file}:${r.tgt_line}` : r.tgt_file) : '';
|
|
377
|
+
const locHint = srcLoc ? ` [${srcLoc}${tgtLoc ? ` → ${tgtLoc}` : ''}]` : '';
|
|
378
|
+
return `Why does ${r.src} ${r.relation.toLowerCase()} ${r.tgt}? (${r.confidence})${locHint}`;
|
|
379
|
+
};
|
|
298
380
|
// When a task is provided and embeddings are enabled, use semantic search
|
|
299
381
|
// to find relevant nodes and surface edge-level questions about them.
|
|
300
382
|
if (task && process.env['MONOGRAPH_EMBEDDINGS'] === 'true') {
|
|
@@ -304,7 +386,9 @@ const monographSuggestTool = {
|
|
|
304
386
|
return text('No suggestions for this task. Run monograph_build first or try a different query.');
|
|
305
387
|
}
|
|
306
388
|
const rows = db.prepare(`
|
|
307
|
-
SELECT e.relation, e.confidence, n1.name as src, n2.name as tgt,
|
|
389
|
+
SELECT e.relation, e.confidence, n1.name as src, n2.name as tgt,
|
|
390
|
+
n1.file_path as src_file, n1.start_line as src_line,
|
|
391
|
+
n2.file_path as tgt_file, n2.start_line as tgt_line
|
|
308
392
|
FROM edges e
|
|
309
393
|
JOIN nodes n1 ON n1.id = e.source_id
|
|
310
394
|
JOIN nodes n2 ON n2.id = e.target_id
|
|
@@ -313,11 +397,13 @@ const monographSuggestTool = {
|
|
|
313
397
|
AND e.confidence IN ('AMBIGUOUS', 'INFERRED')
|
|
314
398
|
LIMIT 100
|
|
315
399
|
`).all(...[...hitIds], ...[...hitIds]);
|
|
316
|
-
const questions = rows.map(
|
|
400
|
+
const questions = rows.map(formatSuggestion);
|
|
317
401
|
return text(questions.slice(0, limit).join('\n') || 'No suggestions for this task. Run monograph_build first.');
|
|
318
402
|
}
|
|
319
403
|
const rows = db.prepare(`
|
|
320
|
-
SELECT e.relation, e.confidence, n1.name as src, n2.name as tgt,
|
|
404
|
+
SELECT e.relation, e.confidence, n1.name as src, n2.name as tgt,
|
|
405
|
+
n1.file_path as src_file, n1.start_line as src_line,
|
|
406
|
+
n2.file_path as tgt_file, n2.start_line as tgt_line
|
|
321
407
|
FROM edges e
|
|
322
408
|
JOIN nodes n1 ON n1.id = e.source_id
|
|
323
409
|
JOIN nodes n2 ON n2.id = e.target_id
|
|
@@ -325,7 +411,7 @@ const monographSuggestTool = {
|
|
|
325
411
|
LIMIT 100
|
|
326
412
|
`).all();
|
|
327
413
|
let scored = rows.map(r => ({
|
|
328
|
-
q:
|
|
414
|
+
q: formatSuggestion(r),
|
|
329
415
|
relevance: task ? taskRelevance(task, r.src + ' ' + r.tgt + ' ' + (r.src_file ?? '')) : 0,
|
|
330
416
|
}));
|
|
331
417
|
if (task)
|
|
@@ -357,7 +443,13 @@ const monographVisualizeTool = {
|
|
|
357
443
|
const { openDb, closeDb, toJson, toHtml, toSvg } = await import('@monoes/monograph');
|
|
358
444
|
const db = openDb(getDbPath());
|
|
359
445
|
try {
|
|
360
|
-
|
|
446
|
+
// Cap maxNodes: passed to SQL LIMIT clause for both nodes (n) and edges
|
|
447
|
+
// (n*3). Without a cap an attacker requests all rows from both tables.
|
|
448
|
+
const MAX_EXPORT_NODES = 10_000;
|
|
449
|
+
const rawMaxNodes = input.maxNodes ?? 500;
|
|
450
|
+
const limit = Number.isFinite(rawMaxNodes) && rawMaxNodes > 0
|
|
451
|
+
? Math.min(Math.floor(rawMaxNodes), MAX_EXPORT_NODES)
|
|
452
|
+
: 500;
|
|
361
453
|
const nodes = db.prepare('SELECT * FROM nodes LIMIT ?').all(limit);
|
|
362
454
|
const edges = db.prepare('SELECT * FROM edges LIMIT ?').all(limit * 3);
|
|
363
455
|
const fmt = input.format ?? 'html';
|
|
@@ -420,7 +512,7 @@ const monographReportTool = {
|
|
|
420
512
|
const nodeCount = countNodes(db);
|
|
421
513
|
const edgeCount = countEdges(db);
|
|
422
514
|
const topNodes = db.prepare(`
|
|
423
|
-
SELECT n.name, n.label, n.file_path,
|
|
515
|
+
SELECT n.name, n.label, n.file_path, n.start_line,
|
|
424
516
|
COUNT(DISTINCT e1.id) + COUNT(DISTINCT e2.id) AS degree
|
|
425
517
|
FROM nodes n
|
|
426
518
|
LEFT JOIN edges e1 ON e1.source_id = n.id
|
|
@@ -433,7 +525,10 @@ const monographReportTool = {
|
|
|
433
525
|
`**Generated:** ${new Date().toISOString()}`,
|
|
434
526
|
`**Nodes:** ${nodeCount} **Edges:** ${edgeCount}\n`,
|
|
435
527
|
'## Top 10 Most Connected Entities\n',
|
|
436
|
-
...topNodes.map((n, i) =>
|
|
528
|
+
...topNodes.map((n, i) => {
|
|
529
|
+
const loc = n.file_path ? (n.start_line != null ? `${n.file_path}:${n.start_line}` : n.file_path) : '';
|
|
530
|
+
return `${i + 1}. **${n.name}** (${n.label}) — degree ${n.degree}${loc ? ` \`${loc}\`` : ''}`;
|
|
531
|
+
}),
|
|
437
532
|
].join('\n');
|
|
438
533
|
const outPath = resolve(input.path ?? join(getProjectCwd(), '.monomind', 'GRAPH_REPORT.md'));
|
|
439
534
|
const allowedRoot = resolve(getProjectCwd());
|
|
@@ -442,7 +537,7 @@ const monographReportTool = {
|
|
|
442
537
|
}
|
|
443
538
|
mkdirSync(join(outPath, '..'), { recursive: true });
|
|
444
539
|
writeFileSync(outPath, report);
|
|
445
|
-
return text(
|
|
540
|
+
return text(`${report}\n\nReport written to ${outPath}`);
|
|
446
541
|
}
|
|
447
542
|
finally {
|
|
448
543
|
closeDb(db);
|
|
@@ -462,8 +557,24 @@ const monographStalenessTool = {
|
|
|
462
557
|
handler: async (input) => {
|
|
463
558
|
const { getMonographStaleness } = await import('@monoes/monograph');
|
|
464
559
|
const repoPath = input.path ?? getProjectCwd();
|
|
465
|
-
const
|
|
466
|
-
|
|
560
|
+
const r = await getMonographStaleness(repoPath);
|
|
561
|
+
if (!r.indexedCommit && !r.currentCommit) {
|
|
562
|
+
return text('Index has never been built or repo has no git history. Run monograph_build first.');
|
|
563
|
+
}
|
|
564
|
+
const statusLine = r.isStale
|
|
565
|
+
? `STALE — index at ${r.indexedCommit}, HEAD at ${r.currentCommit}`
|
|
566
|
+
: `FRESH — index matches HEAD (${r.currentCommit})`;
|
|
567
|
+
const lines = [`Staleness: ${statusLine}`];
|
|
568
|
+
if (r.staleSince)
|
|
569
|
+
lines.push(`Stale since: ${r.staleSince}`);
|
|
570
|
+
if (r.changedSince.length > 0) {
|
|
571
|
+
const shown = r.changedSince.slice(0, 10);
|
|
572
|
+
const more = r.changedSince.length - shown.length;
|
|
573
|
+
lines.push(`Changed files (${r.changedSince.length}):${shown.map(f => `\n ${f}`).join('')}${more > 0 ? `\n … ${more} more` : ''}`);
|
|
574
|
+
}
|
|
575
|
+
if (r.isStale)
|
|
576
|
+
lines.push('Action: run monograph_build to re-index');
|
|
577
|
+
return text(lines.join('\n'));
|
|
467
578
|
},
|
|
468
579
|
};
|
|
469
580
|
// ── monograph_snapshot ────────────────────────────────────────────────────────
|
|
@@ -479,13 +590,19 @@ const monographSnapshotTool = {
|
|
|
479
590
|
handler: async (input) => {
|
|
480
591
|
const { openDb, closeDb, snapshotFromDb } = await import('@monoes/monograph');
|
|
481
592
|
const { writeFileSync, mkdirSync } = await import('fs');
|
|
593
|
+
const { resolve: resolvePath } = await import('path');
|
|
482
594
|
const db = openDb(getDbPath());
|
|
483
595
|
try {
|
|
484
596
|
const snapshot = snapshotFromDb(db);
|
|
485
|
-
const
|
|
486
|
-
const
|
|
597
|
+
const rawName = input.name ?? new Date().toISOString().replace(/[:.]/g, '-');
|
|
598
|
+
const SAFE_NAME_RE = /^[a-zA-Z0-9_.\-]+$/;
|
|
599
|
+
if (!SAFE_NAME_RE.test(rawName))
|
|
600
|
+
return text(`Invalid snapshot name: ${rawName}`);
|
|
601
|
+
const snapshotDir = resolvePath(join(getProjectCwd(), '.monomind', 'snapshots'));
|
|
487
602
|
mkdirSync(snapshotDir, { recursive: true });
|
|
488
|
-
const outPath = join(snapshotDir, `${
|
|
603
|
+
const outPath = join(snapshotDir, `${rawName}.json`);
|
|
604
|
+
if (!resolvePath(outPath).startsWith(snapshotDir))
|
|
605
|
+
return text(`Path traversal detected in snapshot name`);
|
|
489
606
|
writeFileSync(outPath, JSON.stringify(snapshot, null, 2));
|
|
490
607
|
return text(`Snapshot saved: ${outPath}\n nodes: ${snapshot.nodes.length} edges: ${snapshot.edges.length}`);
|
|
491
608
|
}
|
|
@@ -508,18 +625,37 @@ const monographDiffTool = {
|
|
|
508
625
|
},
|
|
509
626
|
handler: async (input) => {
|
|
510
627
|
const { openDb, closeDb, snapshotFromDb, diffSnapshots } = await import('@monoes/monograph');
|
|
511
|
-
const { readFileSync, existsSync } = await import('fs');
|
|
512
|
-
const
|
|
513
|
-
const
|
|
628
|
+
const { readFileSync, existsSync, statSync: statSyncSnap } = await import('fs');
|
|
629
|
+
const { resolve: resolvePath } = await import('path');
|
|
630
|
+
const MAX_SNAPSHOT_BYTES = 100 * 1024 * 1024; // 100 MB
|
|
631
|
+
const snapshotDir = resolvePath(join(getProjectCwd(), '.monomind', 'snapshots'));
|
|
632
|
+
// Reject snapshot names containing path separators or traversal sequences
|
|
633
|
+
const SAFE_SNAPSHOT_NAME = /^[a-zA-Z0-9_.\-]+$/;
|
|
634
|
+
const beforeName = input.before;
|
|
635
|
+
if (!SAFE_SNAPSHOT_NAME.test(beforeName))
|
|
636
|
+
return text(`Invalid snapshot name: ${beforeName}`);
|
|
637
|
+
const beforePath = join(snapshotDir, `${beforeName}.json`);
|
|
638
|
+
if (!resolvePath(beforePath).startsWith(snapshotDir))
|
|
639
|
+
return text(`Path traversal detected in snapshot name`);
|
|
514
640
|
if (!existsSync(beforePath)) {
|
|
515
641
|
return text(`Snapshot not found: ${beforePath}\nCreate one first with monograph_snapshot.`);
|
|
516
642
|
}
|
|
643
|
+
if (statSyncSnap(beforePath).size > MAX_SNAPSHOT_BYTES) {
|
|
644
|
+
return text(`Snapshot too large to diff: ${beforePath}`);
|
|
645
|
+
}
|
|
517
646
|
const before = JSON.parse(readFileSync(beforePath, 'utf-8'));
|
|
518
647
|
let after;
|
|
519
648
|
if (input.after) {
|
|
520
|
-
const
|
|
649
|
+
const afterName = input.after;
|
|
650
|
+
if (!SAFE_SNAPSHOT_NAME.test(afterName))
|
|
651
|
+
return text(`Invalid snapshot name: ${afterName}`);
|
|
652
|
+
const afterPath = join(snapshotDir, `${afterName}.json`);
|
|
653
|
+
if (!resolvePath(afterPath).startsWith(snapshotDir))
|
|
654
|
+
return text(`Path traversal detected in snapshot name`);
|
|
521
655
|
if (!existsSync(afterPath))
|
|
522
656
|
return text(`Snapshot not found: ${afterPath}`);
|
|
657
|
+
if (statSyncSnap(afterPath).size > MAX_SNAPSHOT_BYTES)
|
|
658
|
+
return text(`Snapshot too large to diff: ${afterPath}`);
|
|
523
659
|
after = JSON.parse(readFileSync(afterPath, 'utf-8'));
|
|
524
660
|
}
|
|
525
661
|
else {
|
|
@@ -532,13 +668,33 @@ const monographDiffTool = {
|
|
|
532
668
|
}
|
|
533
669
|
}
|
|
534
670
|
const diff = diffSnapshots(before, after);
|
|
671
|
+
const nodeById = new Map();
|
|
672
|
+
const indexNodes = (nodes) => {
|
|
673
|
+
for (const n of nodes) {
|
|
674
|
+
if (n.id)
|
|
675
|
+
nodeById.set(n.id, n);
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
indexNodes(before.nodes);
|
|
679
|
+
indexNodes(after.nodes);
|
|
680
|
+
const resolveEdgeEnd = (id) => {
|
|
681
|
+
const ref = nodeById.get(id);
|
|
682
|
+
if (!ref)
|
|
683
|
+
return id; // fallback to raw id if not found
|
|
684
|
+
const loc = ref.filePath ? (ref.startLine != null ? `${ref.filePath}:${ref.startLine}` : ref.filePath) : '';
|
|
685
|
+
return loc ? `${ref.name} [${loc}]` : ref.name;
|
|
686
|
+
};
|
|
535
687
|
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` : ''}` : '';
|
|
688
|
+
const formatNode = (n) => {
|
|
689
|
+
const loc = n.filePath ? (n.startLine != null ? `${n.filePath}:${n.startLine}` : n.filePath) : '';
|
|
690
|
+
return ` [${n.label ?? '?'}] ${n.name ?? '?'}${loc ? ` ${loc}` : ''}`;
|
|
691
|
+
};
|
|
536
692
|
const lines = [
|
|
537
693
|
`Diff: ${diff.summary}`,
|
|
538
|
-
section('New nodes', diff.newNodes.map(n => ` +
|
|
539
|
-
section('Removed nodes', diff.removedNodes.map(n => ` -
|
|
540
|
-
section('New edges', diff.newEdges.map(e => ` + ${e.sourceId} --[${e.relation}]--> ${e.targetId}`)),
|
|
541
|
-
section('Removed edges', diff.removedEdges.map(e => ` - ${e.sourceId} --[${e.relation}]--> ${e.targetId}`)),
|
|
694
|
+
section('New nodes', diff.newNodes.map(n => ` + ${formatNode(n)}`)),
|
|
695
|
+
section('Removed nodes', diff.removedNodes.map(n => ` - ${formatNode(n)}`)),
|
|
696
|
+
section('New edges', diff.newEdges.map(e => ` + ${resolveEdgeEnd(e.sourceId)} --[${e.relation}]--> ${resolveEdgeEnd(e.targetId)}`)),
|
|
697
|
+
section('Removed edges', diff.removedEdges.map(e => ` - ${resolveEdgeEnd(e.sourceId)} --[${e.relation}]--> ${resolveEdgeEnd(e.targetId)}`)),
|
|
542
698
|
].join('');
|
|
543
699
|
return text(lines);
|
|
544
700
|
},
|
|
@@ -614,11 +770,52 @@ const monographContextTool = {
|
|
|
614
770
|
const { getMonographContext } = await import('@monoes/monograph');
|
|
615
771
|
const db = openDb(getDbPath());
|
|
616
772
|
try {
|
|
773
|
+
// Cap name and filePath: forwarded to parameterized SQL via getMonographContext.
|
|
774
|
+
// Very long strings waste memory before the query even executes.
|
|
775
|
+
const MAX_CTX_NAME_LEN = 512;
|
|
776
|
+
const MAX_CTX_PATH_LEN = 4 * 1024;
|
|
777
|
+
const rawCtxName = input.name;
|
|
778
|
+
const ctxName = typeof rawCtxName === 'string' && rawCtxName.length > MAX_CTX_NAME_LEN
|
|
779
|
+
? rawCtxName.slice(0, MAX_CTX_NAME_LEN) : rawCtxName;
|
|
780
|
+
const rawCtxPath = input.filePath;
|
|
781
|
+
const ctxPath = typeof rawCtxPath === 'string' && rawCtxPath.length > MAX_CTX_PATH_LEN
|
|
782
|
+
? rawCtxPath.slice(0, MAX_CTX_PATH_LEN) : rawCtxPath;
|
|
617
783
|
const result = getMonographContext(db, {
|
|
618
|
-
name:
|
|
619
|
-
filePath:
|
|
784
|
+
name: ctxName,
|
|
785
|
+
filePath: ctxPath,
|
|
620
786
|
});
|
|
621
|
-
|
|
787
|
+
if (!result || !result.node)
|
|
788
|
+
return text(`No symbol found: ${ctxName}`);
|
|
789
|
+
// Format context as structured text for direct LLM consumption
|
|
790
|
+
const n = result.node;
|
|
791
|
+
const loc = n.filePath ? (n.startLine != null ? `${n.filePath}:${n.startLine}` : n.filePath) : '';
|
|
792
|
+
const lines = [
|
|
793
|
+
`[${n.label ?? '?'}] ${n.name} ${loc}`,
|
|
794
|
+
'',
|
|
795
|
+
];
|
|
796
|
+
const formatNodes = (nodes, label) => {
|
|
797
|
+
if (!Array.isArray(nodes) || nodes.length === 0)
|
|
798
|
+
return;
|
|
799
|
+
lines.push(`${label} (${nodes.length}):`);
|
|
800
|
+
for (const node of nodes.slice(0, 20)) {
|
|
801
|
+
const fp = node.filePath ?? node.file_path ?? '';
|
|
802
|
+
const ln = node.startLine ?? node.start_line;
|
|
803
|
+
const nodeLoc = fp ? (ln != null ? `${fp}:${ln}` : fp) : '';
|
|
804
|
+
lines.push(` [${node.label ?? '?'}] ${node.name ?? node.id} ${nodeLoc}`);
|
|
805
|
+
}
|
|
806
|
+
if (nodes.length > 20)
|
|
807
|
+
lines.push(` … ${nodes.length - 20} more`);
|
|
808
|
+
lines.push('');
|
|
809
|
+
};
|
|
810
|
+
formatNodes(result.callers, 'Callers');
|
|
811
|
+
formatNodes(result.callees, 'Callees');
|
|
812
|
+
formatNodes(result.imports, 'Imports');
|
|
813
|
+
formatNodes(result.importedBy, 'ImportedBy');
|
|
814
|
+
if (result.community != null)
|
|
815
|
+
lines.push(`Community: ${result.community}`);
|
|
816
|
+
if (result.communityName)
|
|
817
|
+
lines.push(`Community name: ${result.communityName}`);
|
|
818
|
+
return text(lines.join('\n').trim());
|
|
622
819
|
}
|
|
623
820
|
finally {
|
|
624
821
|
closeDb(db);
|
|
@@ -643,12 +840,52 @@ const monographImpactTool = {
|
|
|
643
840
|
const { getMonographImpact } = await import('@monoes/monograph');
|
|
644
841
|
const db = openDb(getDbPath());
|
|
645
842
|
try {
|
|
843
|
+
// Cap name/filePath; enforce depth ≤ 6 as documented in the schema description.
|
|
844
|
+
const MAX_IMPACT_NAME_LEN = 512;
|
|
845
|
+
const MAX_IMPACT_PATH_LEN = 4 * 1024;
|
|
846
|
+
const rawImpactName = input.name;
|
|
847
|
+
const impactName = typeof rawImpactName === 'string' && rawImpactName.length > MAX_IMPACT_NAME_LEN
|
|
848
|
+
? rawImpactName.slice(0, MAX_IMPACT_NAME_LEN) : rawImpactName;
|
|
849
|
+
const rawImpactPath = input.filePath;
|
|
850
|
+
const impactPath = typeof rawImpactPath === 'string' && rawImpactPath.length > MAX_IMPACT_PATH_LEN
|
|
851
|
+
? rawImpactPath.slice(0, MAX_IMPACT_PATH_LEN) : rawImpactPath;
|
|
852
|
+
const rawDepth = input.depth;
|
|
853
|
+
const depth = typeof rawDepth === 'number' && Number.isFinite(rawDepth) && rawDepth > 0
|
|
854
|
+
? Math.min(Math.floor(rawDepth), 6) : rawDepth;
|
|
646
855
|
const result = getMonographImpact(db, {
|
|
647
|
-
name:
|
|
648
|
-
filePath:
|
|
649
|
-
depth
|
|
856
|
+
name: impactName,
|
|
857
|
+
filePath: impactPath,
|
|
858
|
+
depth,
|
|
650
859
|
});
|
|
651
|
-
|
|
860
|
+
if (!result || !result.root)
|
|
861
|
+
return text(`No symbol found: ${impactName}`);
|
|
862
|
+
// Format impact as structured text for direct LLM consumption
|
|
863
|
+
const root = result.root;
|
|
864
|
+
const rootLoc = root.filePath ? (root.startLine != null ? `${root.filePath}:${root.startLine}` : root.filePath) : '';
|
|
865
|
+
const lines = [
|
|
866
|
+
`[${root.label ?? '?'}] ${root.name} ${rootLoc}`,
|
|
867
|
+
'',
|
|
868
|
+
`Blast radius: ${result.totalAffected ?? 0} symbols affected`,
|
|
869
|
+
];
|
|
870
|
+
if (result.riskScore != null) {
|
|
871
|
+
const riskLabel = result.riskScore >= 0.8 ? 'HIGH' : result.riskScore >= 0.5 ? 'MEDIUM' : 'LOW';
|
|
872
|
+
lines.push(`Risk score: ${result.riskScore.toFixed(2)} (${riskLabel})`);
|
|
873
|
+
}
|
|
874
|
+
lines.push('');
|
|
875
|
+
const affected = (result.affected ?? result.callers ?? []);
|
|
876
|
+
if (affected.length > 0) {
|
|
877
|
+
lines.push(`Affected callers (${affected.length}):`);
|
|
878
|
+
for (const sym of affected.slice(0, 20)) {
|
|
879
|
+
const fp = sym.filePath ?? sym.file_path ?? '';
|
|
880
|
+
const ln = sym.startLine ?? sym.start_line;
|
|
881
|
+
const symLoc = fp ? (ln != null ? `${fp}:${ln}` : fp) : '';
|
|
882
|
+
const depth_marker = sym.depth != null ? ` [depth ${sym.depth}]` : '';
|
|
883
|
+
lines.push(` [${sym.label ?? '?'}] ${sym.name ?? sym.id} ${symLoc}${depth_marker}`);
|
|
884
|
+
}
|
|
885
|
+
if (affected.length > 20)
|
|
886
|
+
lines.push(` … ${affected.length - 20} more`);
|
|
887
|
+
}
|
|
888
|
+
return text(lines.join('\n').trim());
|
|
652
889
|
}
|
|
653
890
|
finally {
|
|
654
891
|
closeDb(db);
|
|
@@ -675,7 +912,35 @@ const monographDetectChangesTool = {
|
|
|
675
912
|
baseBranch: input.baseBranch,
|
|
676
913
|
includeTests: input.includeTests,
|
|
677
914
|
}, getProjectCwd());
|
|
678
|
-
|
|
915
|
+
// Format as structured text for direct LLM navigation instead of raw JSON
|
|
916
|
+
const r = result;
|
|
917
|
+
if (!r || (!r.changedFiles?.length && !r.affectedSymbols?.length)) {
|
|
918
|
+
return text('No changed files found relative to the base branch.');
|
|
919
|
+
}
|
|
920
|
+
const lines = [];
|
|
921
|
+
const base = r.baseBranch ?? 'main';
|
|
922
|
+
const changedFiles = r.changedFiles ?? [];
|
|
923
|
+
lines.push(`Changed files vs ${base}: ${changedFiles.length}`);
|
|
924
|
+
if (changedFiles.length > 0) {
|
|
925
|
+
for (const f of changedFiles.slice(0, 20))
|
|
926
|
+
lines.push(` ${f}`);
|
|
927
|
+
if (changedFiles.length > 20)
|
|
928
|
+
lines.push(` … ${changedFiles.length - 20} more`);
|
|
929
|
+
}
|
|
930
|
+
lines.push('');
|
|
931
|
+
const affected = r.affectedSymbols ?? r.affected ?? [];
|
|
932
|
+
if (affected.length > 0) {
|
|
933
|
+
lines.push(`Affected symbols (${affected.length}):`);
|
|
934
|
+
for (const sym of affected.slice(0, 30)) {
|
|
935
|
+
const fp = sym.filePath ?? sym.file_path ?? '';
|
|
936
|
+
const ln = sym.startLine ?? sym.start_line;
|
|
937
|
+
const loc = fp ? (ln != null ? `${fp}:${ln}` : fp) : '';
|
|
938
|
+
lines.push(` [${sym.label ?? '?'}] ${sym.name ?? sym.id} ${loc}`);
|
|
939
|
+
}
|
|
940
|
+
if (affected.length > 30)
|
|
941
|
+
lines.push(` … ${affected.length - 30} more`);
|
|
942
|
+
}
|
|
943
|
+
return text(lines.join('\n').trim());
|
|
679
944
|
}
|
|
680
945
|
finally {
|
|
681
946
|
closeDb(db);
|
|
@@ -707,7 +972,25 @@ const monographRenameTool = {
|
|
|
707
972
|
filePath: input.filePath,
|
|
708
973
|
dryRun: input.dryRun ?? true,
|
|
709
974
|
});
|
|
710
|
-
|
|
975
|
+
// Format as structured text for direct LLM navigation instead of raw JSON
|
|
976
|
+
const rn = result;
|
|
977
|
+
if (!rn)
|
|
978
|
+
return text(`Symbol not found: ${input.oldName}`);
|
|
979
|
+
const occurrences = rn.occurrences ?? rn.references ?? [];
|
|
980
|
+
const lines = [
|
|
981
|
+
`Rename: ${input.oldName} → ${input.newName} (dry-run)`,
|
|
982
|
+
`Occurrences: ${occurrences.length}`,
|
|
983
|
+
'',
|
|
984
|
+
];
|
|
985
|
+
for (const occ of occurrences.slice(0, 30)) {
|
|
986
|
+
const fp = occ.filePath ?? occ.file_path ?? '';
|
|
987
|
+
const ln = occ.line ?? occ.startLine ?? occ.start_line;
|
|
988
|
+
const loc = fp ? (ln != null ? `${fp}:${ln}` : fp) : '';
|
|
989
|
+
lines.push(` ${loc || occ}`);
|
|
990
|
+
}
|
|
991
|
+
if (occurrences.length > 30)
|
|
992
|
+
lines.push(` … ${occurrences.length - 30} more`);
|
|
993
|
+
return text(lines.join('\n').trim());
|
|
711
994
|
}
|
|
712
995
|
finally {
|
|
713
996
|
closeDb(db);
|
|
@@ -736,7 +1019,17 @@ const monographRouteMapTool = {
|
|
|
736
1019
|
method: input.method,
|
|
737
1020
|
includeMiddleware: input.includeMiddleware,
|
|
738
1021
|
});
|
|
739
|
-
|
|
1022
|
+
if (result.routes.length === 0)
|
|
1023
|
+
return text('No routes found. Run monograph_build first or adjust your filters.');
|
|
1024
|
+
const lines = [`Routes (${result.total} total):`];
|
|
1025
|
+
for (const r of result.routes) {
|
|
1026
|
+
const loc = r.handlerFile
|
|
1027
|
+
? (r.handlerLine != null ? `${r.handlerFile}:${r.handlerLine}` : r.handlerFile)
|
|
1028
|
+
: '';
|
|
1029
|
+
const mw = r.middlewareChain.length > 0 ? ` middleware: ${r.middlewareChain.join(' → ')}` : '';
|
|
1030
|
+
lines.push(` ${r.method} ${r.path}${r.handlerName ? ` → ${r.handlerName}` : ''}${loc ? ` (${loc})` : ''}${mw}`);
|
|
1031
|
+
}
|
|
1032
|
+
return text(lines.join('\n'));
|
|
740
1033
|
}
|
|
741
1034
|
finally {
|
|
742
1035
|
closeDb(db);
|
|
@@ -764,7 +1057,33 @@ const monographApiImpactTool = {
|
|
|
764
1057
|
routePath: input.routePath,
|
|
765
1058
|
method: input.method,
|
|
766
1059
|
});
|
|
767
|
-
|
|
1060
|
+
if (!result.route)
|
|
1061
|
+
return text(`Route not found: ${input.routePath}. Run monograph_build or check the path.`);
|
|
1062
|
+
const riskLabel = result.riskScore >= 0.7 ? 'HIGH' : result.riskScore >= 0.4 ? 'MEDIUM' : 'LOW';
|
|
1063
|
+
const lines = [
|
|
1064
|
+
`Route: ${result.route.method} ${result.route.path} risk=${riskLabel} (${result.riskScore.toFixed(2)})`,
|
|
1065
|
+
];
|
|
1066
|
+
if (result.handler) {
|
|
1067
|
+
const hLoc = result.handler.filePath
|
|
1068
|
+
? (result.handler.startLine != null ? `${result.handler.filePath}:${result.handler.startLine}` : result.handler.filePath)
|
|
1069
|
+
: '';
|
|
1070
|
+
lines.push(`Handler: ${result.handler.name}${hLoc ? ` ${hLoc}` : ''}`);
|
|
1071
|
+
}
|
|
1072
|
+
if (result.callees.length > 0) {
|
|
1073
|
+
lines.push(`Callees (${result.callees.length}):`);
|
|
1074
|
+
for (const c of result.callees.slice(0, 15)) {
|
|
1075
|
+
const loc = c.node.filePath
|
|
1076
|
+
? (c.node.startLine != null ? `${c.node.filePath}:${c.node.startLine}` : c.node.filePath)
|
|
1077
|
+
: '';
|
|
1078
|
+
lines.push(` ${' '.repeat(c.depth)}→ ${c.node.name} [${c.node.label}]${loc ? ` ${loc}` : ''}`);
|
|
1079
|
+
}
|
|
1080
|
+
if (result.callees.length > 15)
|
|
1081
|
+
lines.push(` … ${result.callees.length - 15} more`);
|
|
1082
|
+
}
|
|
1083
|
+
if (result.affectedProcesses.length > 0) {
|
|
1084
|
+
lines.push(`Affected processes: ${result.affectedProcesses.map(p => p.name).join(', ')}`);
|
|
1085
|
+
}
|
|
1086
|
+
return text(lines.join('\n'));
|
|
768
1087
|
}
|
|
769
1088
|
finally {
|
|
770
1089
|
closeDb(db);
|
|
@@ -818,7 +1137,14 @@ const monographCypherTool = {
|
|
|
818
1137
|
const { getMonographCypher } = await import('@monoes/monograph');
|
|
819
1138
|
const db = openDb(getDbPath());
|
|
820
1139
|
try {
|
|
821
|
-
|
|
1140
|
+
// Cap query: forwarded to the Cypher query engine; very long strings
|
|
1141
|
+
// waste parse time and can stress the query compiler.
|
|
1142
|
+
const MAX_CYPHER_QUERY_LEN = 16 * 1024;
|
|
1143
|
+
const rawCypherQuery = input.query;
|
|
1144
|
+
const cypherQuery = typeof rawCypherQuery === 'string' && rawCypherQuery.length > MAX_CYPHER_QUERY_LEN
|
|
1145
|
+
? rawCypherQuery.slice(0, MAX_CYPHER_QUERY_LEN)
|
|
1146
|
+
: rawCypherQuery;
|
|
1147
|
+
const result = getMonographCypher(db, cypherQuery);
|
|
822
1148
|
if (result.error)
|
|
823
1149
|
return text(`Error: ${result.error}`);
|
|
824
1150
|
if (result.rows.length === 0)
|
|
@@ -846,7 +1172,15 @@ const monographGroupListTool = {
|
|
|
846
1172
|
const { getGroupList } = await import('@monoes/monograph');
|
|
847
1173
|
const configPath = input.configPath ?? join(getProjectCwd(), 'group.yaml');
|
|
848
1174
|
const result = await getGroupList(configPath);
|
|
849
|
-
|
|
1175
|
+
if (!result.repos || result.repos.length === 0) {
|
|
1176
|
+
return text(`Group: ${result.group?.name ?? 'unknown'}\nNo repos configured. Check ${configPath}`);
|
|
1177
|
+
}
|
|
1178
|
+
const lines = [`Group: ${result.group?.name ?? 'unknown'} (${result.repos.length} repos)`];
|
|
1179
|
+
for (const r of result.repos) {
|
|
1180
|
+
const indexed = r.indexedAt ? r.indexedAt.slice(0, 10) : 'never';
|
|
1181
|
+
lines.push(` ${r.name} nodes=${r.nodeCount} indexed=${indexed} ${r.path}`);
|
|
1182
|
+
}
|
|
1183
|
+
return text(lines.join('\n'));
|
|
850
1184
|
},
|
|
851
1185
|
};
|
|
852
1186
|
// ── monograph_group_query ─────────────────────────────────────────────────────
|
|
@@ -865,7 +1199,18 @@ const monographGroupQueryTool = {
|
|
|
865
1199
|
handler: async (input) => {
|
|
866
1200
|
const { runGroupQuery } = await import('@monoes/monograph');
|
|
867
1201
|
const configPath = input.configPath ?? join(getProjectCwd(), 'group.yaml');
|
|
868
|
-
|
|
1202
|
+
// Cap query and limit forwarded to runGroupQuery.
|
|
1203
|
+
const MAX_GROUP_QUERY_LEN = 16 * 1024;
|
|
1204
|
+
const MAX_GROUP_LIMIT = 1_000;
|
|
1205
|
+
const rawGroupQuery = input.query;
|
|
1206
|
+
const groupQuery = typeof rawGroupQuery === 'string' && rawGroupQuery.length > MAX_GROUP_QUERY_LEN
|
|
1207
|
+
? rawGroupQuery.slice(0, MAX_GROUP_QUERY_LEN)
|
|
1208
|
+
: rawGroupQuery;
|
|
1209
|
+
const rawGroupLimit = input.limit;
|
|
1210
|
+
const groupLimit = Number.isFinite(rawGroupLimit) && (rawGroupLimit ?? 0) > 0
|
|
1211
|
+
? Math.min(Math.floor(rawGroupLimit), MAX_GROUP_LIMIT)
|
|
1212
|
+
: rawGroupLimit;
|
|
1213
|
+
const results = await runGroupQuery(configPath, groupQuery, groupLimit);
|
|
869
1214
|
if (results.length === 0)
|
|
870
1215
|
return text('No results found.');
|
|
871
1216
|
const lines = results.map(r => `[${r.label}] ${r.name} ${r.filePath ?? ''} repo:${r.repo} (score: ${r.score.toFixed(4)})`);
|
|
@@ -888,7 +1233,12 @@ const monographWikiTool = {
|
|
|
888
1233
|
const db = openDb(getDbPath());
|
|
889
1234
|
try {
|
|
890
1235
|
const result = getWikiToolResult(db, { communityId: input.communityId });
|
|
891
|
-
|
|
1236
|
+
if (result.pages.length === 0) {
|
|
1237
|
+
return text('No wiki pages found. Run monograph_wiki_build to generate community wiki pages.');
|
|
1238
|
+
}
|
|
1239
|
+
// Return pages as readable prose — content is already LLM-generated markdown.
|
|
1240
|
+
const sections = result.pages.map(p => `--- Community ${p.communityId} ---\n${p.content}`);
|
|
1241
|
+
return text(sections.join('\n\n'));
|
|
892
1242
|
}
|
|
893
1243
|
finally {
|
|
894
1244
|
closeDb(db);
|
|
@@ -917,7 +1267,16 @@ const monographWikiBuildTool = {
|
|
|
917
1267
|
force: input.force,
|
|
918
1268
|
model: input.model,
|
|
919
1269
|
});
|
|
920
|
-
|
|
1270
|
+
if (result.error)
|
|
1271
|
+
return text(`Wiki build failed: ${result.error}`);
|
|
1272
|
+
const parts = [];
|
|
1273
|
+
if (result.generated != null)
|
|
1274
|
+
parts.push(`${result.generated} page(s) generated`);
|
|
1275
|
+
if (result.skipped != null && result.skipped > 0)
|
|
1276
|
+
parts.push(`${result.skipped} skipped (already exist)`);
|
|
1277
|
+
if (result.errors != null && result.errors > 0)
|
|
1278
|
+
parts.push(`${result.errors} error(s)`);
|
|
1279
|
+
return text(`Wiki build complete: ${parts.join(', ') || 'nothing to do'}. Use monograph_wiki to read the pages.`);
|
|
921
1280
|
}
|
|
922
1281
|
finally {
|
|
923
1282
|
closeDb(db);
|
|
@@ -965,7 +1324,13 @@ const monographToolMapTool = {
|
|
|
965
1324
|
const results = getToolMap(db, { tool: input.tool });
|
|
966
1325
|
if (results.length === 0)
|
|
967
1326
|
return text('No tools found. Run monograph_build first.');
|
|
968
|
-
|
|
1327
|
+
const lines = results.map(r => {
|
|
1328
|
+
const loc = r.handlerFile
|
|
1329
|
+
? (r.handlerLine != null ? `${r.handlerFile}:${r.handlerLine}` : r.handlerFile)
|
|
1330
|
+
: (r.filePath ?? '');
|
|
1331
|
+
return `${r.name}${r.handlerName ? ` → ${r.handlerName}` : ''}${loc ? ` (${loc})` : ''}`;
|
|
1332
|
+
});
|
|
1333
|
+
return text(`Tools (${results.length}):\n${lines.join('\n')}`);
|
|
969
1334
|
}
|
|
970
1335
|
finally {
|
|
971
1336
|
closeDb(db);
|
|
@@ -993,7 +1358,38 @@ const monographShapeCheckTool = {
|
|
|
993
1358
|
route: input.route,
|
|
994
1359
|
file: input.file,
|
|
995
1360
|
});
|
|
996
|
-
|
|
1361
|
+
// Render as structured text so LLMs can act on it directly without parsing JSON.
|
|
1362
|
+
const lines = [];
|
|
1363
|
+
lines.push(`Shape check: ${result.message}`);
|
|
1364
|
+
if (result.route) {
|
|
1365
|
+
const handlerLoc = result.route.handlerFile
|
|
1366
|
+
? ` Handler: ${result.route.handlerName} [${result.route.handlerFile}]`
|
|
1367
|
+
: ` Handler: ${result.route.handlerName}`;
|
|
1368
|
+
lines.push(`Route: ${result.route.method} ${result.route.path}`);
|
|
1369
|
+
lines.push(handlerLoc);
|
|
1370
|
+
}
|
|
1371
|
+
if (result.shape.returnedKeys.length > 0) {
|
|
1372
|
+
lines.push(` Returned keys: ${result.shape.returnedKeys.join(', ')}`);
|
|
1373
|
+
}
|
|
1374
|
+
if (result.shape.accessedKeys.length > 0) {
|
|
1375
|
+
lines.push(` Accessed keys: ${result.shape.accessedKeys.join(', ')}`);
|
|
1376
|
+
}
|
|
1377
|
+
if (result.shape.mismatches.length > 0) {
|
|
1378
|
+
lines.push(` Mismatches (accessed but not returned): ${result.shape.mismatches.join(', ')}`);
|
|
1379
|
+
}
|
|
1380
|
+
if (result.shape.extra.length > 0) {
|
|
1381
|
+
lines.push(` Unused returned keys: ${result.shape.extra.join(', ')}`);
|
|
1382
|
+
}
|
|
1383
|
+
if (result.consumers.length > 0) {
|
|
1384
|
+
lines.push(` Consumers (${result.consumers.length}):`);
|
|
1385
|
+
for (const c of result.consumers.slice(0, 10)) {
|
|
1386
|
+
lines.push(` - ${c.name} [${c.filePath}]`);
|
|
1387
|
+
}
|
|
1388
|
+
if (result.consumers.length > 10) {
|
|
1389
|
+
lines.push(` … ${result.consumers.length - 10} more`);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
return text(lines.join('\n'));
|
|
997
1393
|
}
|
|
998
1394
|
finally {
|
|
999
1395
|
closeDb(db);
|
|
@@ -1039,10 +1435,20 @@ const monographAugmentTool = {
|
|
|
1039
1435
|
handler: async (input) => {
|
|
1040
1436
|
const { augmentContext } = await import('@monoes/monograph');
|
|
1041
1437
|
const repoPath = getProjectCwd();
|
|
1438
|
+
// Cap query (forwarded to FTS/embedding in augmentContext) and topK
|
|
1439
|
+
// (controls how many context nodes are retrieved).
|
|
1440
|
+
const MAX_AUGMENT_QUERY_LEN = 16 * 1024;
|
|
1441
|
+
const MAX_AUGMENT_TOP_K = 100;
|
|
1442
|
+
const rawAugmentQuery = input.query;
|
|
1443
|
+
const augmentQuery = typeof rawAugmentQuery === 'string' && rawAugmentQuery.length > MAX_AUGMENT_QUERY_LEN
|
|
1444
|
+
? rawAugmentQuery.slice(0, MAX_AUGMENT_QUERY_LEN) : rawAugmentQuery;
|
|
1445
|
+
const rawTopK = input.topK ?? 10;
|
|
1446
|
+
const topK = Number.isFinite(rawTopK) && rawTopK > 0
|
|
1447
|
+
? Math.min(Math.floor(rawTopK), MAX_AUGMENT_TOP_K) : 10;
|
|
1042
1448
|
const result = await augmentContext({
|
|
1043
|
-
query:
|
|
1449
|
+
query: augmentQuery,
|
|
1044
1450
|
repoPath,
|
|
1045
|
-
topK
|
|
1451
|
+
topK,
|
|
1046
1452
|
format: input.format ?? 'markdown',
|
|
1047
1453
|
});
|
|
1048
1454
|
return text(result);
|
|
@@ -1308,11 +1714,19 @@ const monographNeighborsTool = {
|
|
|
1308
1714
|
});
|
|
1309
1715
|
if (!result.node)
|
|
1310
1716
|
return text(`No node found with name: ${input.name}`);
|
|
1717
|
+
const nodeFilePath = result.node.filePath ?? '';
|
|
1718
|
+
const nodeStartLine = result.node.startLine ?? result.node.start_line;
|
|
1719
|
+
const nodeLoc = nodeFilePath ? (nodeStartLine != null ? `${nodeFilePath}:${nodeStartLine}` : nodeFilePath) : '';
|
|
1311
1720
|
const lines = [
|
|
1312
|
-
`[${result.node.label}] ${result.node.name} ${
|
|
1721
|
+
`[${result.node.label}] ${result.node.name} ${nodeLoc}`,
|
|
1313
1722
|
`Neighbors: ${result.neighbors.length}`,
|
|
1314
1723
|
'',
|
|
1315
|
-
...result.neighbors.map(n =>
|
|
1724
|
+
...result.neighbors.map(n => {
|
|
1725
|
+
const fp = n.node.filePath ?? n.node.file_path ?? '';
|
|
1726
|
+
const ln = n.node.startLine ?? n.node.start_line;
|
|
1727
|
+
const loc = fp ? (ln != null ? `${fp}:${ln}` : fp) : '';
|
|
1728
|
+
return ` ${n.direction === 'inbound' ? '←' : '→'} [${n.node.label}] ${n.node.name} (${n.relation}) ${loc}`;
|
|
1729
|
+
}),
|
|
1316
1730
|
];
|
|
1317
1731
|
return text(lines.join('\n'));
|
|
1318
1732
|
}
|