monomind 1.11.13 → 1.12.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/idea.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 +13 -6
- package/.claude/helpers/handlers/session-handler.cjs +11 -4
- package/.claude/helpers/handlers/session-restore-handler.cjs +21 -11
- package/.claude/helpers/handlers/task-handler.cjs +13 -5
- package/.claude/helpers/intelligence.cjs +7 -2
- package/.claude/helpers/loop-tracker.cjs +15 -3
- package/.claude/helpers/memory.cjs +6 -1
- package/.claude/helpers/router.cjs +5 -2
- package/.claude/helpers/session.cjs +2 -0
- package/.claude/helpers/statusline.cjs +10 -2
- package/.claude/helpers/utils/micro-agents.cjs +20 -4
- package/.claude/scheduled_tasks.lock +1 -1
- package/.claude/settings.json +92 -1
- package/.claude/skills/mastermind/_protocol.md +23 -13
- package/.claude/skills/mastermind/architect.md +6 -9
- package/.claude/skills/mastermind/build.md +3 -3
- package/.claude/skills/mastermind/content.md +3 -3
- package/.claude/skills/mastermind/createorg.md +2 -2
- package/.claude/skills/mastermind/finance.md +3 -3
- package/.claude/skills/mastermind/idea.md +5 -3
- package/.claude/skills/mastermind/marketing.md +3 -3
- package/.claude/skills/mastermind/monitor.md +2 -2
- package/.claude/skills/mastermind/release.md +3 -3
- package/.claude/skills/mastermind/research.md +3 -3
- package/.claude/skills/mastermind/review.md +3 -3
- package/.claude/skills/mastermind/runorg.md +153 -86
- package/.claude/skills/mastermind/sales.md +3 -3
- package/README.md +286 -129
- package/package.json +19 -2
- package/packages/@monomind/cli/README.md +286 -129
- package/packages/@monomind/cli/bundled-graph/dist/src/build.js +73 -0
- package/packages/@monomind/cli/bundled-graph/dist/src/cluster.js +120 -0
- package/packages/@monomind/cli/bundled-graph/package.json +57 -0
- package/packages/@monomind/cli/dist/src/agents/halt-signal.d.ts +25 -0
- package/packages/@monomind/cli/dist/src/agents/halt-signal.js +76 -0
- package/packages/@monomind/cli/dist/src/agents/index.d.ts +18 -0
- package/packages/@monomind/cli/dist/src/agents/index.js +13 -0
- package/packages/@monomind/cli/dist/src/agents/managed-agent.d.ts +41 -0
- package/packages/@monomind/cli/dist/src/agents/managed-agent.js +69 -0
- package/packages/@monomind/cli/dist/src/agents/prompt-experiment.d.ts +23 -0
- package/packages/@monomind/cli/dist/src/agents/prompt-experiment.js +49 -0
- package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.d.ts +22 -0
- package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.js +80 -0
- package/packages/@monomind/cli/dist/src/agents/registry-builder.js +2 -0
- package/packages/@monomind/cli/dist/src/agents/registry-query.d.ts +71 -0
- package/packages/@monomind/cli/dist/src/agents/registry-query.js +125 -0
- package/packages/@monomind/cli/dist/src/agents/score-decay.d.ts +19 -0
- package/packages/@monomind/cli/dist/src/agents/score-decay.js +22 -0
- package/packages/@monomind/cli/dist/src/agents/shared-instructions-loader.d.ts +13 -0
- package/packages/@monomind/cli/dist/src/agents/shared-instructions-loader.js +40 -0
- package/packages/@monomind/cli/dist/src/agents/specialization-scorer.d.ts +54 -0
- package/packages/@monomind/cli/dist/src/agents/specialization-scorer.js +212 -0
- package/packages/@monomind/cli/dist/src/agents/termination-watcher.d.ts +30 -0
- package/packages/@monomind/cli/dist/src/agents/termination-watcher.js +84 -0
- package/packages/@monomind/cli/dist/src/agents/trigger-index.d.ts +20 -0
- package/packages/@monomind/cli/dist/src/agents/trigger-index.js +38 -0
- package/packages/@monomind/cli/dist/src/agents/trigger-scanner.d.ts +64 -0
- package/packages/@monomind/cli/dist/src/agents/trigger-scanner.js +308 -0
- package/packages/@monomind/cli/dist/src/agents/version-diff.d.ts +18 -0
- package/packages/@monomind/cli/dist/src/agents/version-diff.js +64 -0
- package/packages/@monomind/cli/dist/src/agents/version-store.d.ts +60 -0
- package/packages/@monomind/cli/dist/src/agents/version-store.js +235 -0
- package/packages/@monomind/cli/dist/src/autopilot-state.js +10 -5
- package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.js +13 -0
- package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.js +20 -9
- package/packages/@monomind/cli/dist/src/benchmarks/pretrain/index.d.ts +45 -0
- package/packages/@monomind/cli/dist/src/benchmarks/pretrain/index.js +404 -0
- package/packages/@monomind/cli/dist/src/browser/actions.js +10 -3
- package/packages/@monomind/cli/dist/src/browser/browser.js +12 -2
- package/packages/@monomind/cli/dist/src/browser/cdp.js +21 -3
- package/packages/@monomind/cli/dist/src/browser/har.js +27 -5
- package/packages/@monomind/cli/dist/src/commands/agent-wasm.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/agent-wasm.js +333 -0
- package/packages/@monomind/cli/dist/src/commands/agent.js +11 -8
- package/packages/@monomind/cli/dist/src/commands/analyze.js +36 -21
- package/packages/@monomind/cli/dist/src/commands/autopilot.js +12 -4
- package/packages/@monomind/cli/dist/src/commands/benchmark.js +51 -8
- package/packages/@monomind/cli/dist/src/commands/browse.js +5 -2
- package/packages/@monomind/cli/dist/src/commands/claims.js +29 -11
- package/packages/@monomind/cli/dist/src/commands/cleanup.js +25 -5
- package/packages/@monomind/cli/dist/src/commands/config.js +15 -7
- package/packages/@monomind/cli/dist/src/commands/daemon.js +6 -0
- package/packages/@monomind/cli/dist/src/commands/deployment.js +34 -19
- package/packages/@monomind/cli/dist/src/commands/doctor.js +151 -20
- package/packages/@monomind/cli/dist/src/commands/guidance.js +15 -2
- package/packages/@monomind/cli/dist/src/commands/hive-mind.js +37 -14
- package/packages/@monomind/cli/dist/src/commands/hooks.js +42 -25
- package/packages/@monomind/cli/dist/src/commands/init.js +9 -4
- package/packages/@monomind/cli/dist/src/commands/issues.js +29 -26
- package/packages/@monomind/cli/dist/src/commands/mcp.js +11 -5
- package/packages/@monomind/cli/dist/src/commands/memory.js +10 -0
- package/packages/@monomind/cli/dist/src/commands/migrate.js +5 -5
- package/packages/@monomind/cli/dist/src/commands/monograph.js +18 -5
- package/packages/@monomind/cli/dist/src/commands/monovector/backup.js +8 -2
- package/packages/@monomind/cli/dist/src/commands/monovector/benchmark.js +20 -7
- package/packages/@monomind/cli/dist/src/commands/monovector/import.js +15 -0
- package/packages/@monomind/cli/dist/src/commands/monovector/migrate.js +4 -1
- package/packages/@monomind/cli/dist/src/commands/monovector/optimize.js +11 -0
- package/packages/@monomind/cli/dist/src/commands/monovector/setup.js +11 -1
- package/packages/@monomind/cli/dist/src/commands/neural.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/performance.js +20 -7
- package/packages/@monomind/cli/dist/src/commands/platforms.js +90 -8
- package/packages/@monomind/cli/dist/src/commands/plugins.js +12 -5
- package/packages/@monomind/cli/dist/src/commands/process.js +33 -10
- package/packages/@monomind/cli/dist/src/commands/progress.js +5 -3
- package/packages/@monomind/cli/dist/src/commands/providers.js +5 -5
- package/packages/@monomind/cli/dist/src/commands/replay.js +8 -2
- package/packages/@monomind/cli/dist/src/commands/route.js +27 -7
- package/packages/@monomind/cli/dist/src/commands/security.js +4 -0
- package/packages/@monomind/cli/dist/src/commands/session.js +12 -1
- package/packages/@monomind/cli/dist/src/commands/start.js +11 -4
- package/packages/@monomind/cli/dist/src/commands/status.js +7 -4
- package/packages/@monomind/cli/dist/src/commands/swarm.js +27 -13
- package/packages/@monomind/cli/dist/src/commands/task.js +26 -11
- package/packages/@monomind/cli/dist/src/commands/tokens.js +7 -2
- package/packages/@monomind/cli/dist/src/commands/transfer-store.js +36 -22
- package/packages/@monomind/cli/dist/src/commands/ui.js +68 -0
- package/packages/@monomind/cli/dist/src/commands/update.js +15 -3
- package/packages/@monomind/cli/dist/src/commands/workflow.js +39 -6
- package/packages/@monomind/cli/dist/src/consensus/audit-writer.js +18 -7
- package/packages/@monomind/cli/dist/src/consensus/index.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/consensus/index.js +6 -0
- package/packages/@monomind/cli/dist/src/consensus/vote-signer.js +25 -8
- package/packages/@monomind/cli/dist/src/context/context-provider.d.ts +44 -0
- package/packages/@monomind/cli/dist/src/context/context-provider.js +25 -0
- package/packages/@monomind/cli/dist/src/context/git-state-provider.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/context/git-state-provider.js +34 -0
- package/packages/@monomind/cli/dist/src/context/index.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/context/index.js +12 -0
- package/packages/@monomind/cli/dist/src/context/project-conventions-provider.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/context/project-conventions-provider.js +19 -0
- package/packages/@monomind/cli/dist/src/context/prompt-assembler.d.ts +26 -0
- package/packages/@monomind/cli/dist/src/context/prompt-assembler.js +93 -0
- package/packages/@monomind/cli/dist/src/context/task-history-provider.d.ts +24 -0
- package/packages/@monomind/cli/dist/src/context/task-history-provider.js +32 -0
- package/packages/@monomind/cli/dist/src/context/user-preferences-provider.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/context/user-preferences-provider.js +27 -0
- package/packages/@monomind/cli/dist/src/dlq/dlq-reader.d.ts +31 -0
- package/packages/@monomind/cli/dist/src/dlq/dlq-reader.js +81 -0
- package/packages/@monomind/cli/dist/src/dlq/dlq-writer.d.ts +24 -0
- package/packages/@monomind/cli/dist/src/dlq/dlq-writer.js +65 -0
- package/packages/@monomind/cli/dist/src/dlq/index.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/dlq/index.js +7 -0
- package/packages/@monomind/cli/dist/src/eval/dataset-manager.d.ts +33 -0
- package/packages/@monomind/cli/dist/src/eval/dataset-manager.js +107 -0
- package/packages/@monomind/cli/dist/src/eval/dataset-runner.d.ts +23 -0
- package/packages/@monomind/cli/dist/src/eval/dataset-runner.js +59 -0
- package/packages/@monomind/cli/dist/src/eval/index.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/eval/index.js +7 -0
- package/packages/@monomind/cli/dist/src/eval/trace-collector.d.ts +40 -0
- package/packages/@monomind/cli/dist/src/eval/trace-collector.js +102 -0
- package/packages/@monomind/cli/dist/src/index.js +7 -3
- package/packages/@monomind/cli/dist/src/infrastructure/in-memory-repositories.d.ts +68 -0
- package/packages/@monomind/cli/dist/src/infrastructure/in-memory-repositories.js +264 -0
- package/packages/@monomind/cli/dist/src/init/executor.js +14 -11
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +20 -4
- package/packages/@monomind/cli/dist/src/init/statusline-generator.js +33 -12
- package/packages/@monomind/cli/dist/src/interactive/interrupt.d.ts +22 -0
- package/packages/@monomind/cli/dist/src/interactive/interrupt.js +71 -0
- package/packages/@monomind/cli/dist/src/mcp/deprecation-injector.d.ts +25 -0
- package/packages/@monomind/cli/dist/src/mcp/deprecation-injector.js +48 -0
- package/packages/@monomind/cli/dist/src/mcp/tool-registry.d.ts +61 -0
- package/packages/@monomind/cli/dist/src/mcp/tool-registry.js +246 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/a2a-tools.js +98 -13
- package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +16 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/analyze-tools.js +80 -17
- package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +84 -22
- package/packages/@monomind/cli/dist/src/mcp-tools/claims-tools.js +35 -7
- package/packages/@monomind/cli/dist/src/mcp-tools/config-tools.js +82 -17
- package/packages/@monomind/cli/dist/src/mcp-tools/coordination-tools.js +37 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +49 -7
- package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +45 -18
- package/packages/@monomind/cli/dist/src/mcp-tools/github-tools.js +75 -25
- package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +32 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +91 -20
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +188 -29
- package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +25 -7
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-compat.js +11 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +148 -26
- package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +44 -9
- package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +45 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.js +7 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/request-tracker.js +15 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/security-tools.js +61 -9
- package/packages/@monomind/cli/dist/src/mcp-tools/session-tools.js +45 -14
- package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +15 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +14 -7
- package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.js +52 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.js +40 -6
- package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.js +37 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/wasm-agent-tools.js +230 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +29 -6
- package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +26 -10
- package/packages/@monomind/cli/dist/src/memory/intelligence.js +80 -19
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +21 -2
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +67 -3
- package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +14 -4
- package/packages/@monomind/cli/dist/src/model/complexity-scorer.d.ts +21 -0
- package/packages/@monomind/cli/dist/src/model/complexity-scorer.js +106 -0
- package/packages/@monomind/cli/dist/src/model/index.d.ts +4 -0
- package/packages/@monomind/cli/dist/src/model/index.js +4 -0
- package/packages/@monomind/cli/dist/src/model/model-settings.d.ts +22 -0
- package/packages/@monomind/cli/dist/src/model/model-settings.js +33 -0
- package/packages/@monomind/cli/dist/src/model/model-tier-resolver.d.ts +24 -0
- package/packages/@monomind/cli/dist/src/model/model-tier-resolver.js +65 -0
- package/packages/@monomind/cli/dist/src/monovector/capabilities.d.ts +34 -0
- package/packages/@monomind/cli/dist/src/monovector/capabilities.js +37 -0
- package/packages/@monomind/cli/dist/src/monovector/command-outcomes.js +43 -7
- package/packages/@monomind/cli/dist/src/monovector/coverage-router.js +8 -4
- package/packages/@monomind/cli/dist/src/monovector/coverage-tools.js +6 -3
- package/packages/@monomind/cli/dist/src/monovector/diff-classifier.js +13 -0
- package/packages/@monomind/cli/dist/src/monovector/route-outcomes.d.ts +2 -1
- package/packages/@monomind/cli/dist/src/monovector/route-outcomes.js +46 -4
- package/packages/@monomind/cli/dist/src/observability/replay-reader.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/orchestration/index.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/orchestration/index.js +6 -0
- package/packages/@monomind/cli/dist/src/orchestration/mode-dispatcher.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/orchestration/mode-dispatcher.js +31 -0
- package/packages/@monomind/cli/dist/src/orchestration/routing-modes.d.ts +68 -0
- package/packages/@monomind/cli/dist/src/orchestration/routing-modes.js +180 -0
- package/packages/@monomind/cli/dist/src/plugins/manager.js +8 -3
- package/packages/@monomind/cli/dist/src/plugins/store/discovery.js +46 -2
- package/packages/@monomind/cli/dist/src/plugins/store/search.js +5 -4
- package/packages/@monomind/cli/dist/src/plugins/tests/demo-plugin-store.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/plugins/tests/demo-plugin-store.js +126 -0
- package/packages/@monomind/cli/dist/src/plugins/tests/standalone-test.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/plugins/tests/standalone-test.js +188 -0
- package/packages/@monomind/cli/dist/src/plugins/tests/test-plugin-store.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/plugins/tests/test-plugin-store.js +206 -0
- package/packages/@monomind/cli/dist/src/production/circuit-breaker.js +17 -3
- package/packages/@monomind/cli/dist/src/production/error-handler.js +3 -0
- package/packages/@monomind/cli/dist/src/production/monitoring.js +20 -3
- package/packages/@monomind/cli/dist/src/production/rate-limiter.js +13 -4
- package/packages/@monomind/cli/dist/src/production/retry.js +17 -9
- package/packages/@monomind/cli/dist/src/routing/embed-worker.js +6 -2
- package/packages/@monomind/cli/dist/src/routing/embedder.js +0 -0
- package/packages/@monomind/cli/dist/src/routing/llm-caller.js +13 -2
- package/packages/@monomind/cli/dist/src/routing/route-layer-factory.js +18 -3
- package/packages/@monomind/cli/dist/src/runtime/headless.d.ts +60 -0
- package/packages/@monomind/cli/dist/src/runtime/headless.js +284 -0
- package/packages/@monomind/cli/dist/src/services/agentic-flow-bridge.d.ts +50 -0
- package/packages/@monomind/cli/dist/src/services/agentic-flow-bridge.js +95 -0
- package/packages/@monomind/cli/dist/src/services/claim-service.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/services/claim-service.js +8 -0
- package/packages/@monomind/cli/dist/src/services/config-file-manager.js +14 -2
- package/packages/@monomind/cli/dist/src/services/container-worker-pool.d.ts +197 -0
- package/packages/@monomind/cli/dist/src/services/container-worker-pool.js +623 -0
- package/packages/@monomind/cli/dist/src/services/headless-worker-executor.js +18 -2
- package/packages/@monomind/cli/dist/src/services/index.d.ts +13 -0
- package/packages/@monomind/cli/dist/src/services/index.js +11 -0
- package/packages/@monomind/cli/dist/src/services/worker-daemon.js +53 -12
- package/packages/@monomind/cli/dist/src/services/worker-queue.d.ts +201 -0
- package/packages/@monomind/cli/dist/src/services/worker-queue.js +594 -0
- package/packages/@monomind/cli/dist/src/swarm/communication-graph.d.ts +25 -0
- package/packages/@monomind/cli/dist/src/swarm/communication-graph.js +77 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.d.ts +31 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.js +61 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.d.ts +19 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.js +68 -0
- package/packages/@monomind/cli/dist/src/transfer/anonymization/index.d.ts +0 -3
- package/packages/@monomind/cli/dist/src/transfer/anonymization/index.js +16 -1
- package/packages/@monomind/cli/dist/src/transfer/deploy-seraphine.d.ts +13 -0
- package/packages/@monomind/cli/dist/src/transfer/deploy-seraphine.js +205 -0
- package/packages/@monomind/cli/dist/src/transfer/export.js +8 -0
- package/packages/@monomind/cli/dist/src/transfer/ipfs/upload.js +33 -3
- package/packages/@monomind/cli/dist/src/transfer/serialization/cfp.js +9 -3
- package/packages/@monomind/cli/dist/src/transfer/storage/gcs.js +37 -3
- package/packages/@monomind/cli/dist/src/transfer/store/discovery.js +45 -3
- package/packages/@monomind/cli/dist/src/transfer/store/download.js +5 -0
- package/packages/@monomind/cli/dist/src/transfer/store/publish.js +13 -1
- package/packages/@monomind/cli/dist/src/transfer/store/registry.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/transfer/store/registry.js +30 -5
- package/packages/@monomind/cli/dist/src/transfer/store/search.js +20 -5
- package/packages/@monomind/cli/dist/src/transfer/store/tests/standalone-test.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/transfer/store/tests/standalone-test.js +190 -0
- package/packages/@monomind/cli/dist/src/transfer/test-seraphine.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/transfer/test-seraphine.js +105 -0
- package/packages/@monomind/cli/dist/src/transfer/tests/test-store.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/transfer/tests/test-store.js +214 -0
- package/packages/@monomind/cli/dist/src/update/checker.js +59 -7
- package/packages/@monomind/cli/dist/src/update/executor.js +50 -3
- package/packages/@monomind/cli/dist/src/update/index.js +18 -1
- package/packages/@monomind/cli/dist/src/update/rate-limiter.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/update/rate-limiter.js +79 -7
- package/packages/@monomind/cli/dist/src/update/validator.js +52 -1
- package/packages/@monomind/cli/dist/src/workflow/condition-evaluator.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/workflow/condition-evaluator.js +82 -0
- package/packages/@monomind/cli/dist/src/workflow/context-resolver.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/workflow/context-resolver.js +23 -0
- package/packages/@monomind/cli/dist/src/workflow/dag-builder.d.ts +17 -0
- package/packages/@monomind/cli/dist/src/workflow/dag-builder.js +129 -0
- package/packages/@monomind/cli/dist/src/workflow/dag-executor.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/workflow/dag-executor.js +116 -0
- package/packages/@monomind/cli/dist/src/workflow/dag-types.d.ts +41 -0
- package/packages/@monomind/cli/dist/src/workflow/dag-types.js +8 -0
- package/packages/@monomind/cli/dist/src/workflow/dsl-parser.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/workflow/dsl-parser.js +20 -0
- package/packages/@monomind/cli/dist/src/workflow/dsl-schema.d.ts +165 -0
- package/packages/@monomind/cli/dist/src/workflow/dsl-schema.js +82 -0
- package/packages/@monomind/cli/dist/src/workflow/index.d.ts +13 -0
- package/packages/@monomind/cli/dist/src/workflow/index.js +11 -0
- package/packages/@monomind/cli/dist/src/workflow/template-engine.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/workflow/template-engine.js +40 -0
- package/packages/@monomind/cli/dist/src/workflow/workflow-executor.d.ts +29 -0
- package/packages/@monomind/cli/dist/src/workflow/workflow-executor.js +227 -0
- package/packages/@monomind/cli/package.json +9 -10
- package/packages/@monomind/guidance/dist/adversarial.d.ts +284 -0
- package/packages/@monomind/guidance/dist/adversarial.js +572 -0
- package/packages/@monomind/guidance/dist/analyzer.d.ts +530 -0
- package/packages/@monomind/guidance/dist/analyzer.js +2518 -0
- package/packages/@monomind/guidance/dist/artifacts.d.ts +283 -0
- package/packages/@monomind/guidance/dist/artifacts.js +356 -0
- package/packages/@monomind/guidance/dist/authority.d.ts +290 -0
- package/packages/@monomind/guidance/dist/authority.js +558 -0
- package/packages/@monomind/guidance/dist/capabilities.d.ts +209 -0
- package/packages/@monomind/guidance/dist/capabilities.js +485 -0
- package/packages/@monomind/guidance/dist/coherence.d.ts +233 -0
- package/packages/@monomind/guidance/dist/coherence.js +372 -0
- package/packages/@monomind/guidance/dist/compiler.d.ts +87 -0
- package/packages/@monomind/guidance/dist/compiler.js +419 -0
- package/packages/@monomind/guidance/dist/conformance-kit.d.ts +225 -0
- package/packages/@monomind/guidance/dist/conformance-kit.js +629 -0
- package/packages/@monomind/guidance/dist/continue-gate.d.ts +214 -0
- package/packages/@monomind/guidance/dist/continue-gate.js +353 -0
- package/packages/@monomind/guidance/dist/crypto-utils.d.ts +17 -0
- package/packages/@monomind/guidance/dist/crypto-utils.js +24 -0
- package/packages/@monomind/guidance/dist/evolution.d.ts +282 -0
- package/packages/@monomind/guidance/dist/evolution.js +500 -0
- package/packages/@monomind/guidance/dist/gates.d.ts +79 -0
- package/packages/@monomind/guidance/dist/gates.js +302 -0
- package/packages/@monomind/guidance/dist/gateway.d.ts +206 -0
- package/packages/@monomind/guidance/dist/gateway.js +452 -0
- package/packages/@monomind/guidance/dist/generators.d.ts +153 -0
- package/packages/@monomind/guidance/dist/generators.js +682 -0
- package/packages/@monomind/guidance/dist/headless.d.ts +177 -0
- package/packages/@monomind/guidance/dist/headless.js +342 -0
- package/packages/@monomind/guidance/dist/hooks.d.ts +109 -0
- package/packages/@monomind/guidance/dist/hooks.js +347 -0
- package/packages/@monomind/guidance/dist/index.d.ts +205 -0
- package/packages/@monomind/guidance/dist/index.js +321 -0
- package/packages/@monomind/guidance/dist/ledger.d.ts +162 -0
- package/packages/@monomind/guidance/dist/ledger.js +375 -0
- package/packages/@monomind/guidance/dist/manifest-validator.d.ts +289 -0
- package/packages/@monomind/guidance/dist/manifest-validator.js +838 -0
- package/packages/@monomind/guidance/dist/memory-gate.d.ts +222 -0
- package/packages/@monomind/guidance/dist/memory-gate.js +382 -0
- package/packages/@monomind/guidance/dist/meta-governance.d.ts +265 -0
- package/packages/@monomind/guidance/dist/meta-governance.js +348 -0
- package/packages/@monomind/guidance/dist/optimizer.d.ts +104 -0
- package/packages/@monomind/guidance/dist/optimizer.js +329 -0
- package/packages/@monomind/guidance/dist/persistence.d.ts +189 -0
- package/packages/@monomind/guidance/dist/persistence.js +464 -0
- package/packages/@monomind/guidance/dist/proof.d.ts +185 -0
- package/packages/@monomind/guidance/dist/proof.js +238 -0
- package/packages/@monomind/guidance/dist/retriever.d.ts +116 -0
- package/packages/@monomind/guidance/dist/retriever.js +394 -0
- package/packages/@monomind/guidance/dist/ruvbot-integration.d.ts +370 -0
- package/packages/@monomind/guidance/dist/ruvbot-integration.js +738 -0
- package/packages/@monomind/guidance/dist/temporal.d.ts +426 -0
- package/packages/@monomind/guidance/dist/temporal.js +658 -0
- package/packages/@monomind/guidance/dist/trust.d.ts +283 -0
- package/packages/@monomind/guidance/dist/trust.js +473 -0
- package/packages/@monomind/guidance/dist/truth-anchors.d.ts +276 -0
- package/packages/@monomind/guidance/dist/truth-anchors.js +488 -0
- package/packages/@monomind/guidance/dist/types.d.ts +378 -0
- package/packages/@monomind/guidance/dist/types.js +10 -0
- package/packages/@monomind/guidance/dist/uncertainty.d.ts +372 -0
- package/packages/@monomind/guidance/dist/uncertainty.js +619 -0
- package/packages/@monomind/guidance/dist/wasm-kernel.d.ts +48 -0
- package/packages/@monomind/guidance/dist/wasm-kernel.js +158 -0
|
@@ -5,13 +5,22 @@
|
|
|
5
5
|
* exported by the published @monoes/monograph@1.2.0. Everything else has been
|
|
6
6
|
* moved to the real package.
|
|
7
7
|
*/
|
|
8
|
-
import { join } from 'path';
|
|
9
|
-
import { existsSync, readFileSync } from 'fs';
|
|
8
|
+
import { join, resolve, relative } from 'path';
|
|
9
|
+
import { existsSync, readFileSync, statSync } from 'fs';
|
|
10
10
|
import { openDb, closeDb, countNodes } from '@monoes/monograph';
|
|
11
|
+
const MAX_GROUP_CONFIG_BYTES = 1 * 1024 * 1024; // 1 MB
|
|
11
12
|
function readGroupConfig(configPath) {
|
|
12
13
|
if (!existsSync(configPath))
|
|
13
14
|
return [];
|
|
14
15
|
try {
|
|
16
|
+
// Guard: only allow paths within cwd to prevent traversal to /etc/passwd etc.
|
|
17
|
+
const resolved = resolve(configPath);
|
|
18
|
+
const rel = relative(process.cwd(), resolved);
|
|
19
|
+
if (rel.startsWith('..') || resolve(rel) === resolve('/'))
|
|
20
|
+
return [];
|
|
21
|
+
// OOM guard: skip files larger than 1 MB
|
|
22
|
+
if (statSync(configPath).size > MAX_GROUP_CONFIG_BYTES)
|
|
23
|
+
return [];
|
|
15
24
|
const raw = readFileSync(configPath, 'utf-8');
|
|
16
25
|
return JSON.parse(raw);
|
|
17
26
|
}
|
|
@@ -54,16 +54,29 @@ const monographQueryTool = {
|
|
|
54
54
|
const { hybridQuery } = await import('@monoes/monograph');
|
|
55
55
|
const db = openDb(getDbPath());
|
|
56
56
|
try {
|
|
57
|
-
|
|
57
|
+
// Cap limit: passed directly to SQLite queries and hybridQuery; an
|
|
58
|
+
// unlimited value saturates memory with rows.
|
|
59
|
+
const MAX_QUERY_LIMIT = 1_000;
|
|
60
|
+
const rawLimit = input.limit ?? 20;
|
|
61
|
+
const limit = Number.isFinite(rawLimit) && rawLimit > 0
|
|
62
|
+
? Math.min(Math.floor(rawLimit), MAX_QUERY_LIMIT)
|
|
63
|
+
: 20;
|
|
64
|
+
// Cap query: passed to FTS5 and hybridQuery; very long queries waste
|
|
65
|
+
// parse time and can stress the FTS tokenizer.
|
|
66
|
+
const MAX_MONOGRAPH_QUERY_LEN = 16 * 1024;
|
|
67
|
+
const rawQuery = input.query;
|
|
68
|
+
const query = typeof rawQuery === 'string' && rawQuery.length > MAX_MONOGRAPH_QUERY_LEN
|
|
69
|
+
? rawQuery.slice(0, MAX_MONOGRAPH_QUERY_LEN)
|
|
70
|
+
: rawQuery;
|
|
58
71
|
const label = input.label;
|
|
59
72
|
if (process.env['MONOGRAPH_EMBEDDINGS'] === 'true') {
|
|
60
|
-
const results = await hybridQuery(db,
|
|
73
|
+
const results = await hybridQuery(db, query, { limit, label });
|
|
61
74
|
if (results.length === 0)
|
|
62
75
|
return text('No results found.');
|
|
63
76
|
const lines = results.map(r => `[${r.label ?? '?'}] ${r.name ?? r.id} ${r.filePath ?? ''} (score: ${r.score.toFixed(4)})`);
|
|
64
77
|
return text(lines.join('\n'));
|
|
65
78
|
}
|
|
66
|
-
const results = ftsSearch(db,
|
|
79
|
+
const results = ftsSearch(db, query, limit, label);
|
|
67
80
|
if (results.length === 0)
|
|
68
81
|
return text('No results found.');
|
|
69
82
|
const lines = results.map(r => `[${r.label}] ${r.name} ${r.filePath ?? ''} (score: ${r.rank.toFixed(3)})`);
|
|
@@ -141,7 +154,12 @@ const monographGodNodesTool = {
|
|
|
141
154
|
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
142
155
|
const db = openDb(getDbPath());
|
|
143
156
|
try {
|
|
144
|
-
|
|
157
|
+
// Cap limit: passed directly to the SQL LIMIT clause.
|
|
158
|
+
const MAX_GOD_NODES_LIMIT = 1_000;
|
|
159
|
+
const rawGodLimit = input.limit ?? 20;
|
|
160
|
+
const limit = Number.isFinite(rawGodLimit) && rawGodLimit > 0
|
|
161
|
+
? Math.min(Math.floor(rawGodLimit), MAX_GOD_NODES_LIMIT)
|
|
162
|
+
: 20;
|
|
145
163
|
const excluded = ['File', 'Folder', 'Community', 'Concept'];
|
|
146
164
|
const rows = db.prepare(`
|
|
147
165
|
SELECT n.id, n.label, n.name, n.file_path,
|
|
@@ -234,12 +252,20 @@ const monographCommunityTool = {
|
|
|
234
252
|
required: ['id'],
|
|
235
253
|
},
|
|
236
254
|
handler: async (input) => {
|
|
255
|
+
// Validate community ID — must be a finite integer. parseInt(NaN) or a float
|
|
256
|
+
// would silently become 0 in SQLite (NaN → NULL → 0 coercion), which would
|
|
257
|
+
// return all nodes in community 0 instead of an error.
|
|
258
|
+
const rawId = typeof input.id === 'number' ? input.id : parseInt(String(input.id), 10);
|
|
259
|
+
if (!Number.isFinite(rawId) || rawId !== Math.floor(rawId)) {
|
|
260
|
+
return text(`Invalid community ID: ${input.id} (must be an integer)`);
|
|
261
|
+
}
|
|
262
|
+
const communityId = rawId;
|
|
237
263
|
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
238
264
|
const db = openDb(getDbPath());
|
|
239
265
|
try {
|
|
240
|
-
const rows = db.prepare('SELECT * FROM nodes WHERE community_id = ?').all(
|
|
266
|
+
const rows = db.prepare('SELECT * FROM nodes WHERE community_id = ?').all(communityId);
|
|
241
267
|
if (rows.length === 0)
|
|
242
|
-
return text(`No nodes in community ${
|
|
268
|
+
return text(`No nodes in community ${communityId}`);
|
|
243
269
|
return text(rows.map(r => `[${r.label}] ${r.name} ${r.file_path ?? ''}`).join('\n'));
|
|
244
270
|
}
|
|
245
271
|
finally {
|
|
@@ -259,7 +285,12 @@ const monographSurprisesTool = {
|
|
|
259
285
|
const { openDb, closeDb } = await import('@monoes/monograph');
|
|
260
286
|
const db = openDb(getDbPath());
|
|
261
287
|
try {
|
|
262
|
-
|
|
288
|
+
// Cap limit: passed directly to the SQL LIMIT clause.
|
|
289
|
+
const MAX_SURPRISES_LIMIT = 1_000;
|
|
290
|
+
const rawSurprisesLimit = input.limit ?? 20;
|
|
291
|
+
const limit = Number.isFinite(rawSurprisesLimit) && rawSurprisesLimit > 0
|
|
292
|
+
? Math.min(Math.floor(rawSurprisesLimit), MAX_SURPRISES_LIMIT)
|
|
293
|
+
: 20;
|
|
263
294
|
const rows = db.prepare(`
|
|
264
295
|
SELECT e.*, n1.name as src_name, n2.name as tgt_name
|
|
265
296
|
FROM edges e
|
|
@@ -293,8 +324,18 @@ const monographSuggestTool = {
|
|
|
293
324
|
const { hybridQuery } = await import('@monoes/monograph');
|
|
294
325
|
const db = openDb(getDbPath());
|
|
295
326
|
try {
|
|
296
|
-
|
|
297
|
-
|
|
327
|
+
// Cap limit and task: limit is passed directly to SQL LIMIT clause;
|
|
328
|
+
// task is forwarded to hybridQuery (embedding path) or FTS.
|
|
329
|
+
const MAX_SUGGEST_LIMIT = 1_000;
|
|
330
|
+
const MAX_SUGGEST_TASK_LEN = 16 * 1024;
|
|
331
|
+
const rawSuggestLimit = input.limit ?? 10;
|
|
332
|
+
const limit = Number.isFinite(rawSuggestLimit) && rawSuggestLimit > 0
|
|
333
|
+
? Math.min(Math.floor(rawSuggestLimit), MAX_SUGGEST_LIMIT)
|
|
334
|
+
: 10;
|
|
335
|
+
const rawTask = input.task ?? '';
|
|
336
|
+
const task = typeof rawTask === 'string' && rawTask.length > MAX_SUGGEST_TASK_LEN
|
|
337
|
+
? rawTask.slice(0, MAX_SUGGEST_TASK_LEN)
|
|
338
|
+
: rawTask;
|
|
298
339
|
// When a task is provided and embeddings are enabled, use semantic search
|
|
299
340
|
// to find relevant nodes and surface edge-level questions about them.
|
|
300
341
|
if (task && process.env['MONOGRAPH_EMBEDDINGS'] === 'true') {
|
|
@@ -357,7 +398,13 @@ const monographVisualizeTool = {
|
|
|
357
398
|
const { openDb, closeDb, toJson, toHtml, toSvg } = await import('@monoes/monograph');
|
|
358
399
|
const db = openDb(getDbPath());
|
|
359
400
|
try {
|
|
360
|
-
|
|
401
|
+
// Cap maxNodes: passed to SQL LIMIT clause for both nodes (n) and edges
|
|
402
|
+
// (n*3). Without a cap an attacker requests all rows from both tables.
|
|
403
|
+
const MAX_EXPORT_NODES = 10_000;
|
|
404
|
+
const rawMaxNodes = input.maxNodes ?? 500;
|
|
405
|
+
const limit = Number.isFinite(rawMaxNodes) && rawMaxNodes > 0
|
|
406
|
+
? Math.min(Math.floor(rawMaxNodes), MAX_EXPORT_NODES)
|
|
407
|
+
: 500;
|
|
361
408
|
const nodes = db.prepare('SELECT * FROM nodes LIMIT ?').all(limit);
|
|
362
409
|
const edges = db.prepare('SELECT * FROM edges LIMIT ?').all(limit * 3);
|
|
363
410
|
const fmt = input.format ?? 'html';
|
|
@@ -479,13 +526,19 @@ const monographSnapshotTool = {
|
|
|
479
526
|
handler: async (input) => {
|
|
480
527
|
const { openDb, closeDb, snapshotFromDb } = await import('@monoes/monograph');
|
|
481
528
|
const { writeFileSync, mkdirSync } = await import('fs');
|
|
529
|
+
const { resolve: resolvePath } = await import('path');
|
|
482
530
|
const db = openDb(getDbPath());
|
|
483
531
|
try {
|
|
484
532
|
const snapshot = snapshotFromDb(db);
|
|
485
|
-
const
|
|
486
|
-
const
|
|
533
|
+
const rawName = input.name ?? new Date().toISOString().replace(/[:.]/g, '-');
|
|
534
|
+
const SAFE_NAME_RE = /^[a-zA-Z0-9_.\-]+$/;
|
|
535
|
+
if (!SAFE_NAME_RE.test(rawName))
|
|
536
|
+
return text(`Invalid snapshot name: ${rawName}`);
|
|
537
|
+
const snapshotDir = resolvePath(join(getProjectCwd(), '.monomind', 'snapshots'));
|
|
487
538
|
mkdirSync(snapshotDir, { recursive: true });
|
|
488
|
-
const outPath = join(snapshotDir, `${
|
|
539
|
+
const outPath = join(snapshotDir, `${rawName}.json`);
|
|
540
|
+
if (!resolvePath(outPath).startsWith(snapshotDir))
|
|
541
|
+
return text(`Path traversal detected in snapshot name`);
|
|
489
542
|
writeFileSync(outPath, JSON.stringify(snapshot, null, 2));
|
|
490
543
|
return text(`Snapshot saved: ${outPath}\n nodes: ${snapshot.nodes.length} edges: ${snapshot.edges.length}`);
|
|
491
544
|
}
|
|
@@ -508,18 +561,37 @@ const monographDiffTool = {
|
|
|
508
561
|
},
|
|
509
562
|
handler: async (input) => {
|
|
510
563
|
const { openDb, closeDb, snapshotFromDb, diffSnapshots } = await import('@monoes/monograph');
|
|
511
|
-
const { readFileSync, existsSync } = await import('fs');
|
|
512
|
-
const
|
|
513
|
-
const
|
|
564
|
+
const { readFileSync, existsSync, statSync: statSyncSnap } = await import('fs');
|
|
565
|
+
const { resolve: resolvePath } = await import('path');
|
|
566
|
+
const MAX_SNAPSHOT_BYTES = 100 * 1024 * 1024; // 100 MB
|
|
567
|
+
const snapshotDir = resolvePath(join(getProjectCwd(), '.monomind', 'snapshots'));
|
|
568
|
+
// Reject snapshot names containing path separators or traversal sequences
|
|
569
|
+
const SAFE_SNAPSHOT_NAME = /^[a-zA-Z0-9_.\-]+$/;
|
|
570
|
+
const beforeName = input.before;
|
|
571
|
+
if (!SAFE_SNAPSHOT_NAME.test(beforeName))
|
|
572
|
+
return text(`Invalid snapshot name: ${beforeName}`);
|
|
573
|
+
const beforePath = join(snapshotDir, `${beforeName}.json`);
|
|
574
|
+
if (!resolvePath(beforePath).startsWith(snapshotDir))
|
|
575
|
+
return text(`Path traversal detected in snapshot name`);
|
|
514
576
|
if (!existsSync(beforePath)) {
|
|
515
577
|
return text(`Snapshot not found: ${beforePath}\nCreate one first with monograph_snapshot.`);
|
|
516
578
|
}
|
|
579
|
+
if (statSyncSnap(beforePath).size > MAX_SNAPSHOT_BYTES) {
|
|
580
|
+
return text(`Snapshot too large to diff: ${beforePath}`);
|
|
581
|
+
}
|
|
517
582
|
const before = JSON.parse(readFileSync(beforePath, 'utf-8'));
|
|
518
583
|
let after;
|
|
519
584
|
if (input.after) {
|
|
520
|
-
const
|
|
585
|
+
const afterName = input.after;
|
|
586
|
+
if (!SAFE_SNAPSHOT_NAME.test(afterName))
|
|
587
|
+
return text(`Invalid snapshot name: ${afterName}`);
|
|
588
|
+
const afterPath = join(snapshotDir, `${afterName}.json`);
|
|
589
|
+
if (!resolvePath(afterPath).startsWith(snapshotDir))
|
|
590
|
+
return text(`Path traversal detected in snapshot name`);
|
|
521
591
|
if (!existsSync(afterPath))
|
|
522
592
|
return text(`Snapshot not found: ${afterPath}`);
|
|
593
|
+
if (statSyncSnap(afterPath).size > MAX_SNAPSHOT_BYTES)
|
|
594
|
+
return text(`Snapshot too large to diff: ${afterPath}`);
|
|
523
595
|
after = JSON.parse(readFileSync(afterPath, 'utf-8'));
|
|
524
596
|
}
|
|
525
597
|
else {
|
|
@@ -614,9 +686,19 @@ const monographContextTool = {
|
|
|
614
686
|
const { getMonographContext } = await import('@monoes/monograph');
|
|
615
687
|
const db = openDb(getDbPath());
|
|
616
688
|
try {
|
|
689
|
+
// Cap name and filePath: forwarded to parameterized SQL via getMonographContext.
|
|
690
|
+
// Very long strings waste memory before the query even executes.
|
|
691
|
+
const MAX_CTX_NAME_LEN = 512;
|
|
692
|
+
const MAX_CTX_PATH_LEN = 4 * 1024;
|
|
693
|
+
const rawCtxName = input.name;
|
|
694
|
+
const ctxName = typeof rawCtxName === 'string' && rawCtxName.length > MAX_CTX_NAME_LEN
|
|
695
|
+
? rawCtxName.slice(0, MAX_CTX_NAME_LEN) : rawCtxName;
|
|
696
|
+
const rawCtxPath = input.filePath;
|
|
697
|
+
const ctxPath = typeof rawCtxPath === 'string' && rawCtxPath.length > MAX_CTX_PATH_LEN
|
|
698
|
+
? rawCtxPath.slice(0, MAX_CTX_PATH_LEN) : rawCtxPath;
|
|
617
699
|
const result = getMonographContext(db, {
|
|
618
|
-
name:
|
|
619
|
-
filePath:
|
|
700
|
+
name: ctxName,
|
|
701
|
+
filePath: ctxPath,
|
|
620
702
|
});
|
|
621
703
|
return text(JSON.stringify(result, null, 2));
|
|
622
704
|
}
|
|
@@ -643,10 +725,22 @@ const monographImpactTool = {
|
|
|
643
725
|
const { getMonographImpact } = await import('@monoes/monograph');
|
|
644
726
|
const db = openDb(getDbPath());
|
|
645
727
|
try {
|
|
728
|
+
// Cap name/filePath; enforce depth ≤ 6 as documented in the schema description.
|
|
729
|
+
const MAX_IMPACT_NAME_LEN = 512;
|
|
730
|
+
const MAX_IMPACT_PATH_LEN = 4 * 1024;
|
|
731
|
+
const rawImpactName = input.name;
|
|
732
|
+
const impactName = typeof rawImpactName === 'string' && rawImpactName.length > MAX_IMPACT_NAME_LEN
|
|
733
|
+
? rawImpactName.slice(0, MAX_IMPACT_NAME_LEN) : rawImpactName;
|
|
734
|
+
const rawImpactPath = input.filePath;
|
|
735
|
+
const impactPath = typeof rawImpactPath === 'string' && rawImpactPath.length > MAX_IMPACT_PATH_LEN
|
|
736
|
+
? rawImpactPath.slice(0, MAX_IMPACT_PATH_LEN) : rawImpactPath;
|
|
737
|
+
const rawDepth = input.depth;
|
|
738
|
+
const depth = typeof rawDepth === 'number' && Number.isFinite(rawDepth) && rawDepth > 0
|
|
739
|
+
? Math.min(Math.floor(rawDepth), 6) : rawDepth;
|
|
646
740
|
const result = getMonographImpact(db, {
|
|
647
|
-
name:
|
|
648
|
-
filePath:
|
|
649
|
-
depth
|
|
741
|
+
name: impactName,
|
|
742
|
+
filePath: impactPath,
|
|
743
|
+
depth,
|
|
650
744
|
});
|
|
651
745
|
return text(JSON.stringify(result, null, 2));
|
|
652
746
|
}
|
|
@@ -818,7 +912,14 @@ const monographCypherTool = {
|
|
|
818
912
|
const { getMonographCypher } = await import('@monoes/monograph');
|
|
819
913
|
const db = openDb(getDbPath());
|
|
820
914
|
try {
|
|
821
|
-
|
|
915
|
+
// Cap query: forwarded to the Cypher query engine; very long strings
|
|
916
|
+
// waste parse time and can stress the query compiler.
|
|
917
|
+
const MAX_CYPHER_QUERY_LEN = 16 * 1024;
|
|
918
|
+
const rawCypherQuery = input.query;
|
|
919
|
+
const cypherQuery = typeof rawCypherQuery === 'string' && rawCypherQuery.length > MAX_CYPHER_QUERY_LEN
|
|
920
|
+
? rawCypherQuery.slice(0, MAX_CYPHER_QUERY_LEN)
|
|
921
|
+
: rawCypherQuery;
|
|
922
|
+
const result = getMonographCypher(db, cypherQuery);
|
|
822
923
|
if (result.error)
|
|
823
924
|
return text(`Error: ${result.error}`);
|
|
824
925
|
if (result.rows.length === 0)
|
|
@@ -865,7 +966,18 @@ const monographGroupQueryTool = {
|
|
|
865
966
|
handler: async (input) => {
|
|
866
967
|
const { runGroupQuery } = await import('@monoes/monograph');
|
|
867
968
|
const configPath = input.configPath ?? join(getProjectCwd(), 'group.yaml');
|
|
868
|
-
|
|
969
|
+
// Cap query and limit forwarded to runGroupQuery.
|
|
970
|
+
const MAX_GROUP_QUERY_LEN = 16 * 1024;
|
|
971
|
+
const MAX_GROUP_LIMIT = 1_000;
|
|
972
|
+
const rawGroupQuery = input.query;
|
|
973
|
+
const groupQuery = typeof rawGroupQuery === 'string' && rawGroupQuery.length > MAX_GROUP_QUERY_LEN
|
|
974
|
+
? rawGroupQuery.slice(0, MAX_GROUP_QUERY_LEN)
|
|
975
|
+
: rawGroupQuery;
|
|
976
|
+
const rawGroupLimit = input.limit;
|
|
977
|
+
const groupLimit = Number.isFinite(rawGroupLimit) && (rawGroupLimit ?? 0) > 0
|
|
978
|
+
? Math.min(Math.floor(rawGroupLimit), MAX_GROUP_LIMIT)
|
|
979
|
+
: rawGroupLimit;
|
|
980
|
+
const results = await runGroupQuery(configPath, groupQuery, groupLimit);
|
|
869
981
|
if (results.length === 0)
|
|
870
982
|
return text('No results found.');
|
|
871
983
|
const lines = results.map(r => `[${r.label}] ${r.name} ${r.filePath ?? ''} repo:${r.repo} (score: ${r.score.toFixed(4)})`);
|
|
@@ -1039,10 +1151,20 @@ const monographAugmentTool = {
|
|
|
1039
1151
|
handler: async (input) => {
|
|
1040
1152
|
const { augmentContext } = await import('@monoes/monograph');
|
|
1041
1153
|
const repoPath = getProjectCwd();
|
|
1154
|
+
// Cap query (forwarded to FTS/embedding in augmentContext) and topK
|
|
1155
|
+
// (controls how many context nodes are retrieved).
|
|
1156
|
+
const MAX_AUGMENT_QUERY_LEN = 16 * 1024;
|
|
1157
|
+
const MAX_AUGMENT_TOP_K = 100;
|
|
1158
|
+
const rawAugmentQuery = input.query;
|
|
1159
|
+
const augmentQuery = typeof rawAugmentQuery === 'string' && rawAugmentQuery.length > MAX_AUGMENT_QUERY_LEN
|
|
1160
|
+
? rawAugmentQuery.slice(0, MAX_AUGMENT_QUERY_LEN) : rawAugmentQuery;
|
|
1161
|
+
const rawTopK = input.topK ?? 10;
|
|
1162
|
+
const topK = Number.isFinite(rawTopK) && rawTopK > 0
|
|
1163
|
+
? Math.min(Math.floor(rawTopK), MAX_AUGMENT_TOP_K) : 10;
|
|
1042
1164
|
const result = await augmentContext({
|
|
1043
|
-
query:
|
|
1165
|
+
query: augmentQuery,
|
|
1044
1166
|
repoPath,
|
|
1045
|
-
topK
|
|
1167
|
+
topK,
|
|
1046
1168
|
format: input.format ?? 'markdown',
|
|
1047
1169
|
});
|
|
1048
1170
|
return text(result);
|
|
@@ -147,7 +147,12 @@ export const neuralTools = [
|
|
|
147
147
|
},
|
|
148
148
|
handler: async (input) => {
|
|
149
149
|
const store = loadNeuralStore();
|
|
150
|
-
|
|
150
|
+
// Cap modelId to prevent DoS via oversized object keys written to the neural store JSON.
|
|
151
|
+
const MAX_MODEL_ID_LEN = 256;
|
|
152
|
+
const rawModelId = input.modelId || `model-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
153
|
+
const modelId = typeof rawModelId === 'string' && rawModelId.length > MAX_MODEL_ID_LEN
|
|
154
|
+
? rawModelId.slice(0, MAX_MODEL_ID_LEN)
|
|
155
|
+
: rawModelId;
|
|
151
156
|
const RESERVED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
152
157
|
if (RESERVED_KEYS.has(modelId)) {
|
|
153
158
|
return { success: false, error: 'Invalid modelId' };
|
|
@@ -160,8 +165,19 @@ export const neuralTools = [
|
|
|
160
165
|
if (Object.keys(store.models ?? {}).length >= MAX_MODELS) {
|
|
161
166
|
return { success: false, error: `Model store full (max ${MAX_MODELS}). Delete old models first.` };
|
|
162
167
|
}
|
|
163
|
-
|
|
164
|
-
|
|
168
|
+
// Runtime-validate modelType against the allowed enum. The JSON schema
|
|
169
|
+
// declares an enum but callers that bypass schema validation (e.g. direct
|
|
170
|
+
// MCP calls) can pass arbitrary strings, which would be stored verbatim.
|
|
171
|
+
const VALID_MODEL_TYPES = new Set(['moe', 'transformer', 'classifier', 'embedding']);
|
|
172
|
+
const rawModelType = input.modelType;
|
|
173
|
+
if (!rawModelType || !VALID_MODEL_TYPES.has(rawModelType)) {
|
|
174
|
+
return { success: false, error: `Invalid modelType "${rawModelType}". Must be one of: moe, transformer, classifier, embedding` };
|
|
175
|
+
}
|
|
176
|
+
const modelType = rawModelType;
|
|
177
|
+
// Cap epochs to prevent storing absurdly large numbers in the JSON store.
|
|
178
|
+
const MAX_EPOCHS = 10000;
|
|
179
|
+
const rawEpochs = typeof input.epochs === 'number' && Number.isFinite(input.epochs) ? input.epochs : 10;
|
|
180
|
+
const epochs = Math.max(1, Math.min(Math.floor(rawEpochs), MAX_EPOCHS));
|
|
165
181
|
const model = {
|
|
166
182
|
id: modelId,
|
|
167
183
|
name: `${modelType}-model`,
|
|
@@ -225,7 +241,7 @@ export const neuralTools = [
|
|
|
225
241
|
try {
|
|
226
242
|
const patternsPath = join(getNeuralDir(), PATTERNS_FILE);
|
|
227
243
|
let existing = [];
|
|
228
|
-
if (existsSync(patternsPath)) {
|
|
244
|
+
if (existsSync(patternsPath) && statSync(patternsPath).size <= MAX_NEURAL_STORE_BYTES) {
|
|
229
245
|
const raw = readFileSync(patternsPath, 'utf-8');
|
|
230
246
|
const parsed = JSON.parse(raw);
|
|
231
247
|
if (Array.isArray(parsed))
|
|
@@ -282,7 +298,12 @@ export const neuralTools = [
|
|
|
282
298
|
},
|
|
283
299
|
handler: async (input) => {
|
|
284
300
|
const store = loadNeuralStore();
|
|
285
|
-
|
|
301
|
+
// Cap modelId to prevent O(n) hash/compare cost on absurdly long keys.
|
|
302
|
+
const MAX_MODEL_ID_LEN_PRED = 256;
|
|
303
|
+
const rawModelIdPred = input.modelId;
|
|
304
|
+
const modelId = typeof rawModelIdPred === 'string' && rawModelIdPred.length > MAX_MODEL_ID_LEN_PRED
|
|
305
|
+
? rawModelIdPred.slice(0, MAX_MODEL_ID_LEN_PRED)
|
|
306
|
+
: rawModelIdPred;
|
|
286
307
|
const inputText = typeof input.input === 'string' ? input.input.slice(0, 16 * 1024) : '';
|
|
287
308
|
const topK = Math.max(1, Math.min(input.topK || 3, 50));
|
|
288
309
|
const RESERVED_KEYS_PRED = new Set(['__proto__', 'constructor', 'prototype']);
|
|
@@ -309,7 +330,7 @@ export const neuralTools = [
|
|
|
309
330
|
const cliPatternsRaw = [];
|
|
310
331
|
try {
|
|
311
332
|
const cliPath = join(getNeuralDir(), PATTERNS_FILE);
|
|
312
|
-
if (existsSync(cliPath)) {
|
|
333
|
+
if (existsSync(cliPath) && statSync(cliPath).size <= MAX_NEURAL_STORE_BYTES) {
|
|
313
334
|
const raw = JSON.parse(readFileSync(cliPath, 'utf-8'));
|
|
314
335
|
if (Array.isArray(raw)) {
|
|
315
336
|
const mcpIds = new Set(mcpPatterns.map(p => p.id));
|
|
@@ -412,7 +433,12 @@ export const neuralTools = [
|
|
|
412
433
|
return { success: false, error: `Pattern store full (max ${MAX_PATTERNS}). Run neural_compress first.` };
|
|
413
434
|
}
|
|
414
435
|
const patternId = `pattern-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
415
|
-
|
|
436
|
+
// Cap name length to prevent DoS in generateEmbedding (hash path is O(n))
|
|
437
|
+
const MAX_PATTERN_NAME_LENGTH = 16 * 1024; // 16 KB
|
|
438
|
+
const rawPatternName = input.name || 'Unnamed pattern';
|
|
439
|
+
const patternName = typeof rawPatternName === 'string' && rawPatternName.length > MAX_PATTERN_NAME_LENGTH
|
|
440
|
+
? rawPatternName.slice(0, MAX_PATTERN_NAME_LENGTH)
|
|
441
|
+
: rawPatternName;
|
|
416
442
|
// Generate embedding from pattern name/content
|
|
417
443
|
const embedding = await generateEmbedding(patternName, 384);
|
|
418
444
|
const pattern = {
|
|
@@ -437,7 +463,12 @@ export const neuralTools = [
|
|
|
437
463
|
};
|
|
438
464
|
}
|
|
439
465
|
if (action === 'search') {
|
|
440
|
-
|
|
466
|
+
// Cap query length to prevent DoS in generateEmbedding (hash path is O(n))
|
|
467
|
+
const MAX_SEARCH_QUERY_LENGTH = 16 * 1024; // 16 KB — matches neural_predict cap
|
|
468
|
+
const rawQuery = input.query;
|
|
469
|
+
const query = typeof rawQuery === 'string' && rawQuery.length > MAX_SEARCH_QUERY_LENGTH
|
|
470
|
+
? rawQuery.slice(0, MAX_SEARCH_QUERY_LENGTH)
|
|
471
|
+
: rawQuery;
|
|
441
472
|
// Generate query embedding for real similarity search
|
|
442
473
|
const queryEmbedding = await generateEmbedding(query, 384);
|
|
443
474
|
// Calculate REAL cosine similarity against stored patterns
|
|
@@ -606,7 +637,11 @@ export const neuralTools = [
|
|
|
606
637
|
handler: async (input) => {
|
|
607
638
|
const store = loadNeuralStore();
|
|
608
639
|
if (input.modelId) {
|
|
609
|
-
const
|
|
640
|
+
const MAX_MODEL_ID_LEN_STATUS = 256;
|
|
641
|
+
const rawModelIdStatus = input.modelId;
|
|
642
|
+
const modelId = typeof rawModelIdStatus === 'string' && rawModelIdStatus.length > MAX_MODEL_ID_LEN_STATUS
|
|
643
|
+
? rawModelIdStatus.slice(0, MAX_MODEL_ID_LEN_STATUS)
|
|
644
|
+
: rawModelIdStatus;
|
|
610
645
|
if (NEURAL_RESERVED_KEYS.has(modelId)) {
|
|
611
646
|
return { success: false, error: 'Invalid modelId' };
|
|
612
647
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Note: Some optimization suggestions are illustrative
|
|
13
13
|
*/
|
|
14
14
|
import { getProjectCwd } from './types.js';
|
|
15
|
-
import { existsSync, readFileSync, writeFileSync, renameSync, unlinkSync, readdirSync, mkdirSync } from 'node:fs';
|
|
15
|
+
import { existsSync, readFileSync, statSync, writeFileSync, renameSync, unlinkSync, readdirSync, mkdirSync } from 'node:fs';
|
|
16
16
|
import { join } from 'node:path';
|
|
17
17
|
import * as os from 'node:os';
|
|
18
18
|
// Storage paths
|
|
@@ -32,10 +32,11 @@ function ensurePerfDir() {
|
|
|
32
32
|
mkdirSync(dir, { recursive: true });
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
const MAX_PERF_STORE_BYTES = 50 * 1024 * 1024; // 50 MB
|
|
35
36
|
function loadPerfStore() {
|
|
36
37
|
try {
|
|
37
38
|
const path = getPerfPath();
|
|
38
|
-
if (existsSync(path)) {
|
|
39
|
+
if (existsSync(path) && statSync(path).size <= MAX_PERF_STORE_BYTES) {
|
|
39
40
|
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
40
41
|
}
|
|
41
42
|
}
|
|
@@ -226,8 +227,20 @@ export const performanceTools = [
|
|
|
226
227
|
},
|
|
227
228
|
handler: async (input) => {
|
|
228
229
|
const store = loadPerfStore();
|
|
229
|
-
|
|
230
|
-
|
|
230
|
+
// Validate suite against enum to prevent uncapped string from being stored
|
|
231
|
+
// as a benchmark key on disk.
|
|
232
|
+
const VALID_SUITES = new Set(['all', 'memory', 'neural', 'swarm', 'io']);
|
|
233
|
+
const rawSuite = input.suite || 'all';
|
|
234
|
+
const suite = VALID_SUITES.has(rawSuite) ? rawSuite : 'all';
|
|
235
|
+
// Cap iterations to prevent event-loop blocking DoS. The `neural`
|
|
236
|
+
// suite runs an O(n³) 64×64 matrix multiply per iteration; at 10 000
|
|
237
|
+
// iterations it already completes in milliseconds. Uncapped, a caller
|
|
238
|
+
// could pass iterations=9_999_999 and block the process for minutes.
|
|
239
|
+
const MAX_BENCHMARK_ITERATIONS = 10_000;
|
|
240
|
+
const rawIterations = typeof input.iterations === 'number' ? input.iterations : 100;
|
|
241
|
+
const iterations = Number.isFinite(rawIterations) && rawIterations > 0
|
|
242
|
+
? Math.min(Math.floor(rawIterations), MAX_BENCHMARK_ITERATIONS)
|
|
243
|
+
: 100;
|
|
231
244
|
const warmup = input.warmup !== false;
|
|
232
245
|
// REAL benchmark functions
|
|
233
246
|
const benchmarkFunctions = {
|
|
@@ -356,7 +369,11 @@ export const performanceTools = [
|
|
|
356
369
|
},
|
|
357
370
|
},
|
|
358
371
|
handler: async (input) => {
|
|
359
|
-
|
|
372
|
+
// Validate target against enum to prevent arbitrary string from being
|
|
373
|
+
// stored in the perf store and echoed in the response.
|
|
374
|
+
const VALID_PROFILE_TARGETS = new Set(['all', 'memory', 'io', 'cpu']);
|
|
375
|
+
const rawTarget = input.target || 'all';
|
|
376
|
+
const target = VALID_PROFILE_TARGETS.has(rawTarget) ? rawTarget : 'all';
|
|
360
377
|
const durationSec = Math.min(input.duration || 1, 10);
|
|
361
378
|
const durationMs = durationSec * 1000;
|
|
362
379
|
const cpuBefore = process.cpuUsage();
|
|
@@ -457,7 +474,11 @@ export const performanceTools = [
|
|
|
457
474
|
},
|
|
458
475
|
},
|
|
459
476
|
handler: async (input) => {
|
|
460
|
-
|
|
477
|
+
// Validate target against enum — the value is echoed in the response and
|
|
478
|
+
// stored to the perf store; an unvalidated string could inflate disk state.
|
|
479
|
+
const VALID_OPT_TARGETS = new Set(['all', 'memory', 'latency', 'throughput']);
|
|
480
|
+
const rawOptTarget = input.target || 'all';
|
|
481
|
+
const target = VALID_OPT_TARGETS.has(rawOptTarget) ? rawOptTarget : 'all';
|
|
461
482
|
const aggressive = input.aggressive === true;
|
|
462
483
|
// Snapshot system state BEFORE optimizations
|
|
463
484
|
const loadBefore = os.loadavg();
|
|
@@ -559,8 +580,15 @@ export const performanceTools = [
|
|
|
559
580
|
},
|
|
560
581
|
},
|
|
561
582
|
handler: async (input) => {
|
|
562
|
-
|
|
563
|
-
|
|
583
|
+
// Validate metric and aggregation against their enums. Both values are
|
|
584
|
+
// later used as property index keys on plain objects — an attacker who
|
|
585
|
+
// passes "__proto__" or "constructor" could cause prototype pollution.
|
|
586
|
+
const VALID_METRICS = new Set(['cpu', 'memory', 'latency', 'throughput', 'all']);
|
|
587
|
+
const VALID_AGGREGATIONS = new Set(['avg', 'min', 'max', 'p50', 'p95', 'p99']);
|
|
588
|
+
const rawMetric = input.metric || 'all';
|
|
589
|
+
const metric = VALID_METRICS.has(rawMetric) ? rawMetric : 'all';
|
|
590
|
+
const rawAggregation = input.aggregation || 'avg';
|
|
591
|
+
const aggregation = VALID_AGGREGATIONS.has(rawAggregation) ? rawAggregation : 'avg';
|
|
564
592
|
// Get REAL system metrics
|
|
565
593
|
const memUsage = process.memoryUsage();
|
|
566
594
|
const loadAvg = os.loadavg();
|
|
@@ -641,11 +669,18 @@ export const performanceTools = [
|
|
|
641
669
|
timestamp: new Date().toISOString(),
|
|
642
670
|
};
|
|
643
671
|
}
|
|
644
|
-
|
|
672
|
+
// Use Object.hasOwn to prevent prototype chain traversal when indexing
|
|
673
|
+
// by caller-supplied metric/aggregation strings.
|
|
674
|
+
const selectedMetric = Object.hasOwn(allMetrics, metric)
|
|
675
|
+
? allMetrics[metric]
|
|
676
|
+
: allMetrics.cpu;
|
|
677
|
+
const aggValue = Object.hasOwn(selectedMetric, aggregation)
|
|
678
|
+
? selectedMetric[aggregation]
|
|
679
|
+
: undefined;
|
|
645
680
|
return {
|
|
646
681
|
_real: ['cpu', 'memory'].includes(metric),
|
|
647
682
|
metric,
|
|
648
|
-
value:
|
|
683
|
+
value: aggValue,
|
|
649
684
|
unit: selectedMetric.unit,
|
|
650
685
|
details: selectedMetric,
|
|
651
686
|
timestamp: new Date().toISOString(),
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module @monomind/cli/mcp-tools/progress
|
|
7
7
|
*/
|
|
8
|
-
import { existsSync, readdirSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'fs';
|
|
8
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync, renameSync, mkdirSync, statSync } from 'fs';
|
|
9
9
|
import { join, basename, dirname } from 'path';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
// Get project root - handles both src and dist paths
|
|
@@ -53,6 +53,9 @@ function countFilesAndLines(dir, ext = '.ts') {
|
|
|
53
53
|
else if (entry.isFile() && entry.name.endsWith(ext)) {
|
|
54
54
|
files++;
|
|
55
55
|
try {
|
|
56
|
+
// Skip files > 1 MB to avoid loading generated/minified bundles into memory.
|
|
57
|
+
if (statSync(fullPath).size > 1024 * 1024)
|
|
58
|
+
continue;
|
|
56
59
|
const content = readFileSync(fullPath, 'utf-8');
|
|
57
60
|
lines += content.split('\n').length;
|
|
58
61
|
}
|
|
@@ -120,7 +123,7 @@ async function calculateProgress() {
|
|
|
120
123
|
// Count CLI commands (from commands/index.ts)
|
|
121
124
|
let cliCommands = 28; // Default to known count
|
|
122
125
|
const commandsIndexPath = join(PACKAGES_DIR, '@monomind/cli/src/commands/index.ts');
|
|
123
|
-
if (existsSync(commandsIndexPath)) {
|
|
126
|
+
if (existsSync(commandsIndexPath) && statSync(commandsIndexPath).size <= 1024 * 1024) {
|
|
124
127
|
try {
|
|
125
128
|
const content = readFileSync(commandsIndexPath, 'utf-8');
|
|
126
129
|
const matches = content.match(/export const commands.*\[([^\]]+)\]/s);
|
|
@@ -133,7 +136,7 @@ async function calculateProgress() {
|
|
|
133
136
|
// Count MCP tools
|
|
134
137
|
let mcpTools = 100; // Approximate
|
|
135
138
|
const toolsIndexPath = join(PACKAGES_DIR, '@monomind/cli/src/mcp-tools/index.ts');
|
|
136
|
-
if (existsSync(toolsIndexPath)) {
|
|
139
|
+
if (existsSync(toolsIndexPath) && statSync(toolsIndexPath).size <= 1024 * 1024) {
|
|
137
140
|
try {
|
|
138
141
|
const content = readFileSync(toolsIndexPath, 'utf-8');
|
|
139
142
|
mcpTools = (content.match(/export.*Tools/g) || []).length * 10 || 100;
|
|
@@ -143,7 +146,7 @@ async function calculateProgress() {
|
|
|
143
146
|
// Count hooks subcommands (count const *Command definitions)
|
|
144
147
|
let hooksSubcommands = 27; // Default to documented count
|
|
145
148
|
const hooksPath = join(PACKAGES_DIR, '@monomind/cli/src/commands/hooks.ts');
|
|
146
|
-
if (existsSync(hooksPath)) {
|
|
149
|
+
if (existsSync(hooksPath) && statSync(hooksPath).size <= 1024 * 1024) {
|
|
147
150
|
try {
|
|
148
151
|
const content = readFileSync(hooksPath, 'utf-8');
|
|
149
152
|
// Count command definitions like "const fooCommand: Command = {"
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* Used by system_metrics to report real request counts.
|
|
5
5
|
*/
|
|
6
6
|
const MAX_TRACKED_TOOLS = 500;
|
|
7
|
+
const MAX_TOOL_NAME_LEN = 256;
|
|
8
|
+
// Keys that would corrupt Object.prototype or its constructor if used as plain
|
|
9
|
+
// object property keys without Object.hasOwn() protection.
|
|
10
|
+
const FORBIDDEN_TOOL_NAMES = new Set(['__proto__', 'constructor', 'prototype']);
|
|
7
11
|
let counts = {
|
|
8
12
|
total: 0,
|
|
9
13
|
success: 0,
|
|
@@ -17,7 +21,17 @@ export function trackRequest(toolName, success) {
|
|
|
17
21
|
counts.success++;
|
|
18
22
|
else
|
|
19
23
|
counts.errors++;
|
|
20
|
-
|
|
24
|
+
// Guard against prototype pollution via toolName.
|
|
25
|
+
// The previous `toolName in counts.byTool` check traversed the prototype
|
|
26
|
+
// chain, so "__proto__" was always truthy and could corrupt Object.prototype.
|
|
27
|
+
// Use Object.hasOwn() instead, and reject forbidden key names outright.
|
|
28
|
+
if (typeof toolName !== 'string' ||
|
|
29
|
+
toolName.length === 0 ||
|
|
30
|
+
toolName.length > MAX_TOOL_NAME_LEN ||
|
|
31
|
+
FORBIDDEN_TOOL_NAMES.has(toolName)) {
|
|
32
|
+
return; // Drop invalid tool names silently
|
|
33
|
+
}
|
|
34
|
+
if (Object.keys(counts.byTool).length < MAX_TRACKED_TOOLS || Object.hasOwn(counts.byTool, toolName)) {
|
|
21
35
|
counts.byTool[toolName] = (counts.byTool[toolName] || 0) + 1;
|
|
22
36
|
}
|
|
23
37
|
}
|