monomind 1.8.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/design/design-monodesign.md +121 -0
- package/.claude/agents/github/issue-tracker.md +12 -12
- package/.claude/agents/github/pr-manager.md +10 -10
- package/.claude/agents/github/release-manager.md +49 -105
- package/.claude/agents/github/repo-architect.md +73 -92
- package/.claude/agents/github/sync-coordinator.md +55 -123
- package/.claude/agents/marketing/marketing-competitive-content.md +155 -0
- package/.claude/agents/marketing/marketing-content-creator.md +13 -0
- package/.claude/agents/marketing/marketing-cro-specialist.md +147 -0
- package/.claude/agents/marketing/marketing-email-specialist.md +90 -0
- package/.claude/agents/marketing/marketing-launch-strategist.md +129 -0
- package/.claude/agents/marketing/marketing-pricing-strategist.md +127 -0
- package/.claude/agents/specialists/integration-architect.md +94 -0
- package/.claude/commands/agents/README.md +4 -0
- package/.claude/commands/agents/agent-capabilities.md +6 -2
- package/.claude/commands/agents/agent-coordination.md +4 -0
- package/.claude/commands/agents/agent-spawning.md +4 -0
- package/.claude/commands/agents/agent-types.md +6 -2
- package/.claude/commands/analysis/README.md +14 -5
- package/.claude/commands/analysis/bottleneck-detect.md +30 -123
- package/.claude/commands/analysis/performance-bottlenecks.md +14 -14
- package/.claude/commands/analysis/performance-report.md +38 -11
- package/.claude/commands/analysis/token-efficiency.md +13 -16
- package/.claude/commands/analysis/token-usage.md +34 -12
- package/.claude/commands/automation/README.md +15 -5
- package/.claude/commands/automation/auto-agent.md +49 -85
- package/.claude/commands/automation/self-healing.md +20 -18
- package/.claude/commands/automation/session-memory.md +28 -29
- package/.claude/commands/automation/smart-agents.md +17 -9
- package/.claude/commands/automation/smart-spawn.md +52 -11
- package/.claude/commands/automation/workflow-select.md +46 -11
- package/.claude/commands/browse.md +5 -0
- package/.claude/commands/coordination/README.md +9 -5
- package/.claude/commands/coordination/agent-spawn.md +53 -9
- package/.claude/commands/coordination/swarm-init.md +39 -42
- package/.claude/commands/coordination/task-orchestrate.md +65 -11
- package/.claude/commands/github/README.md +21 -8
- package/.claude/commands/github/github-modes.md +9 -5
- package/.claude/commands/github/issue-tracker.md +34 -33
- package/.claude/commands/github/pr-manager.md +20 -17
- package/.claude/commands/github/release-manager.md +37 -49
- package/.claude/commands/github/repo-architect.md +39 -41
- package/.claude/commands/github/sync-coordinator.md +45 -49
- package/.claude/commands/hive-mind/README.md +42 -17
- package/.claude/commands/hive-mind/hive-mind-consensus.md +68 -4
- package/.claude/commands/hive-mind/hive-mind-init.md +55 -5
- package/.claude/commands/hive-mind/hive-mind-memory.md +69 -4
- package/.claude/commands/hive-mind/hive-mind-spawn.md +71 -10
- package/.claude/commands/hive-mind/hive-mind-status.md +52 -4
- package/.claude/commands/hive-mind/hive-mind-stop.md +51 -4
- package/.claude/commands/hive-mind/hive-mind.md +74 -14
- package/.claude/commands/hooks/README.md +62 -7
- package/.claude/commands/hooks/overview.md +94 -35
- package/.claude/commands/hooks/post-edit.md +48 -87
- package/.claude/commands/hooks/post-task.md +37 -87
- package/.claude/commands/hooks/pre-edit.md +52 -84
- package/.claude/commands/hooks/pre-task.md +46 -81
- package/.claude/commands/hooks/session-end.md +49 -85
- package/.claude/commands/hooks/setup.md +87 -58
- package/.claude/commands/mastermind/_repeat.md +308 -0
- package/.claude/commands/mastermind/architect.md +49 -0
- package/.claude/commands/mastermind/brain.md +98 -0
- package/.claude/commands/mastermind/build.md +22 -0
- package/.claude/commands/mastermind/content.md +22 -0
- package/.claude/commands/mastermind/createorg.md +94 -0
- package/.claude/commands/mastermind/finance.md +22 -0
- package/.claude/commands/mastermind/idea.md +22 -0
- package/.claude/commands/mastermind/marketing.md +22 -0
- package/.claude/commands/mastermind/master.md +379 -0
- package/.claude/commands/mastermind/ops.md +22 -0
- package/.claude/commands/mastermind/release.md +22 -0
- package/.claude/commands/mastermind/research.md +22 -0
- package/.claude/commands/mastermind/review.md +22 -0
- package/.claude/commands/mastermind/runorg.md +106 -0
- package/.claude/commands/mastermind/sales.md +22 -0
- package/.claude/commands/mastermind/techport.md +17 -0
- package/.claude/commands/memory/README.md +75 -5
- package/.claude/commands/memory/memory-search.md +63 -11
- package/.claude/commands/monitoring/README.md +64 -4
- package/.claude/commands/monitoring/agent-metrics.md +50 -10
- package/.claude/commands/monitoring/agents.md +59 -32
- package/.claude/commands/monitoring/status.md +96 -34
- package/.claude/commands/monograph/README.md +102 -0
- package/.claude/commands/monograph/monograph-build.md +79 -0
- package/.claude/commands/monograph/monograph-search.md +96 -0
- package/.claude/commands/monograph/monograph-stats.md +53 -0
- package/.claude/commands/monograph/monograph-watch.md +63 -0
- package/.claude/commands/monograph/monograph-wiki.md +91 -0
- package/.claude/commands/monomind/createtask.md +277 -0
- package/.claude/commands/{monomind-do.md → monomind/do.md} +21 -8
- package/.claude/commands/monomind/help.md +118 -0
- package/.claude/commands/{monomind-idea.md → monomind/idea.md} +22 -28
- package/.claude/commands/{monomind-improve.md → monomind/improve.md} +21 -27
- package/.claude/commands/monomind/memory.md +230 -0
- package/.claude/commands/monomind/repeat.md +201 -0
- package/.claude/commands/monomind/review.md +313 -0
- package/.claude/commands/monomind/specialagents.md +125 -0
- package/.claude/commands/monomind/swarm.md +161 -0
- package/.claude/commands/monomind/understand.md +148 -0
- package/.claude/commands/optimization/README.md +69 -5
- package/.claude/commands/optimization/auto-topology.md +66 -43
- package/.claude/commands/optimization/parallel-execution.md +65 -39
- package/.claude/commands/optimization/performance-optimize.md +79 -0
- package/.claude/commands/pair/README.md +48 -230
- package/.claude/commands/pair/examples.md +85 -441
- package/.claude/commands/pair/modes.md +77 -303
- package/.claude/commands/pair/session.md +76 -359
- package/.claude/commands/sparc/analyzer.md +9 -26
- package/.claude/commands/sparc/architect.md +8 -25
- package/.claude/commands/sparc/ask.md +27 -68
- package/.claude/commands/sparc/batch-executor.md +8 -25
- package/.claude/commands/sparc/code.md +12 -53
- package/.claude/commands/sparc/coder.md +8 -25
- package/.claude/commands/sparc/debug.md +12 -53
- package/.claude/commands/sparc/debugger.md +8 -25
- package/.claude/commands/sparc/designer.md +8 -25
- package/.claude/commands/sparc/devops.md +16 -57
- package/.claude/commands/sparc/docs-writer.md +12 -53
- package/.claude/commands/sparc/documenter.md +8 -25
- package/.claude/commands/sparc/innovator.md +8 -25
- package/.claude/commands/sparc/integration.md +12 -53
- package/.claude/commands/sparc/mcp.md +12 -53
- package/.claude/commands/sparc/memory-manager.md +28 -25
- package/.claude/commands/sparc/optimizer.md +8 -25
- package/.claude/commands/sparc/orchestrator.md +35 -97
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +13 -54
- package/.claude/commands/sparc/refinement-optimization-mode.md +13 -54
- package/.claude/commands/sparc/researcher.md +8 -25
- package/.claude/commands/sparc/reviewer.md +8 -25
- package/.claude/commands/sparc/security-review.md +13 -54
- package/.claude/commands/sparc/sparc-modes.md +97 -151
- package/.claude/commands/sparc/sparc.md +16 -56
- package/.claude/commands/sparc/spec-pseudocode.md +13 -54
- package/.claude/commands/sparc/supabase-admin.md +19 -66
- package/.claude/commands/sparc/swarm-coordinator.md +21 -25
- package/.claude/commands/sparc/tdd.md +8 -25
- package/.claude/commands/sparc/tester.md +8 -25
- package/.claude/commands/sparc/tutorial.md +12 -53
- package/.claude/commands/sparc/workflow-manager.md +8 -25
- package/.claude/commands/sparc.md +76 -130
- package/.claude/commands/stream-chain/pipeline.md +72 -77
- package/.claude/commands/stream-chain/run.md +133 -47
- package/.claude/commands/swarm/README.md +37 -12
- package/.claude/commands/swarm/analysis.md +47 -69
- package/.claude/commands/swarm/development.md +45 -69
- package/.claude/commands/swarm/examples.md +77 -142
- package/.claude/commands/swarm/maintenance.md +47 -74
- package/.claude/commands/swarm/optimization.md +54 -87
- package/.claude/commands/swarm/research.md +47 -107
- package/.claude/commands/swarm/swarm-analysis.md +58 -4
- package/.claude/commands/swarm/swarm-background.md +61 -4
- package/.claude/commands/swarm/swarm-modes.md +63 -4
- package/.claude/commands/swarm/swarm-monitor.md +50 -4
- package/.claude/commands/swarm/swarm-status.md +40 -4
- package/.claude/commands/swarm/swarm-strategies.md +73 -5
- package/.claude/commands/swarm/swarm.md +70 -18
- package/.claude/commands/swarm/testing.md +51 -102
- package/.claude/commands/tokens.md +6 -1
- package/.claude/commands/training/README.md +36 -6
- package/.claude/commands/training/model-update.md +68 -15
- package/.claude/commands/training/neural-patterns.md +54 -55
- package/.claude/commands/training/neural-train.md +70 -16
- package/.claude/commands/training/pattern-learn.md +60 -16
- package/.claude/commands/training/specialization.md +78 -49
- package/.claude/commands/truth/start.md +87 -109
- package/.claude/commands/ts.md +7 -2
- package/.claude/commands/verify/check.md +90 -34
- package/.claude/commands/verify/start.md +71 -94
- package/.claude/commands/workflows/README.md +62 -6
- package/.claude/commands/workflows/development.md +69 -61
- package/.claude/commands/workflows/research.md +73 -47
- package/.claude/commands/workflows/workflow-create.md +75 -16
- package/.claude/commands/workflows/workflow-execute.md +94 -16
- package/.claude/commands/workflows/workflow-export.md +81 -16
- package/.claude/helpers/control-start.cjs +91 -0
- package/.claude/helpers/extras-registry.json +4104 -1991
- package/.claude/helpers/graphify-freshen.cjs +44 -13
- package/.claude/helpers/hook-handler.cjs +256 -1
- package/.claude/helpers/learning-service.mjs +0 -0
- package/.claude/helpers/loop-tracker.cjs +107 -0
- package/.claude/helpers/metrics-db.mjs +0 -0
- package/.claude/helpers/router.cjs +48 -68
- package/.claude/helpers/skill-registry.json +89 -104
- package/.claude/helpers/statusline.cjs +33 -2
- package/.claude/helpers/swarm-hooks.sh +0 -0
- package/.claude/scheduled_tasks.lock +1 -0
- package/.claude/settings.json +15 -0
- package/.claude/skills/.monomind/data/ranked-context.json +5 -0
- package/.claude/skills/.monomind/sessions/current.json +13 -0
- package/.claude/skills/.monomind/sessions/session-1777829336455.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777831614725.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777832095857.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777839814183.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777841847131.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777843309463.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777880867159.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777881884593.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777884090471.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777884808221.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777885672155.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777886852818.json +15 -0
- package/.claude/skills/.monomind/sessions/session-1777896532690.json +15 -0
- package/.claude/skills/agentdb-advanced/SKILL.md +11 -12
- package/.claude/skills/agentdb-learning/SKILL.md +20 -21
- package/.claude/skills/agentdb-memory-patterns/SKILL.md +28 -30
- package/.claude/skills/agentdb-optimization/SKILL.md +11 -12
- package/.claude/skills/agentdb-vector-search/SKILL.md +37 -41
- package/.claude/skills/{v3-integration-deep → agentic-integration}/SKILL.md +20 -13
- package/.claude/skills/agentic-jujutsu/SKILL.md +22 -22
- package/.claude/skills/{v3-cli-modernization → cli-modernization}/SKILL.md +17 -8
- package/.claude/skills/{v3-core-implementation → core-implementation}/SKILL.md +33 -8
- package/.claude/skills/{v3-ddd-architecture → ddd-architecture}/SKILL.md +18 -25
- package/.claude/skills/github-code-review/SKILL.md +82 -83
- package/.claude/skills/github-multi-repo/SKILL.md +42 -46
- package/.claude/skills/github-project-management/SKILL.md +83 -88
- package/.claude/skills/github-release-management/SKILL.md +12 -18
- package/.claude/skills/github-workflow-automation/SKILL.md +70 -74
- package/.claude/skills/hooks-automation/SKILL.md +9 -13
- package/.claude/skills/mastermind/_intake.md +83 -0
- package/.claude/skills/mastermind/_protocol.md +275 -0
- package/.claude/skills/mastermind/architect.md +847 -0
- package/.claude/skills/mastermind/build.md +158 -0
- package/.claude/skills/mastermind/content.md +185 -0
- package/.claude/skills/mastermind/createorg.md +318 -0
- package/.claude/skills/mastermind/finance.md +154 -0
- package/.claude/skills/mastermind/idea.md +158 -0
- package/.claude/skills/mastermind/marketing.md +216 -0
- package/.claude/skills/mastermind/monotask.md +350 -0
- package/.claude/skills/mastermind/ops.md +156 -0
- package/.claude/skills/mastermind/references/copywriting-frameworks.md +181 -0
- package/.claude/skills/mastermind/references/persuasion-psychology.md +158 -0
- package/.claude/skills/mastermind/release.md +156 -0
- package/.claude/skills/mastermind/research.md +156 -0
- package/.claude/skills/mastermind/review.md +157 -0
- package/.claude/skills/mastermind/runorg.md +308 -0
- package/.claude/skills/mastermind/sales.md +158 -0
- package/.claude/skills/mastermind/techport.md +743 -0
- package/.claude/skills/{v3-mcp-optimization → mcp-optimization}/SKILL.md +35 -14
- package/.claude/skills/{v3-memory-unification → memory-unification}/SKILL.md +20 -4
- package/.claude/skills/monodesign/SKILL.md +302 -0
- package/.claude/skills/monodesign/reference/adapt.md +190 -0
- package/.claude/skills/monodesign/reference/animate.md +175 -0
- package/.claude/skills/monodesign/reference/antipatterns-catalog.md +187 -0
- package/.claude/skills/monodesign/reference/audit.md +133 -0
- package/.claude/skills/monodesign/reference/bolder.md +113 -0
- package/.claude/skills/monodesign/reference/brand-workflow.md +180 -0
- package/.claude/skills/monodesign/reference/brand.md +114 -0
- package/.claude/skills/monodesign/reference/clarify.md +174 -0
- package/.claude/skills/monodesign/reference/cognitive-load.md +106 -0
- package/.claude/skills/monodesign/reference/color-and-contrast.md +105 -0
- package/.claude/skills/monodesign/reference/colorize.md +154 -0
- package/.claude/skills/monodesign/reference/component-specs.md +260 -0
- package/.claude/skills/monodesign/reference/component-states.md +274 -0
- package/.claude/skills/monodesign/reference/component-system.md +358 -0
- package/.claude/skills/monodesign/reference/copy-formulas.md +160 -0
- package/.claude/skills/monodesign/reference/craft.md +193 -0
- package/.claude/skills/monodesign/reference/critique.md +213 -0
- package/.claude/skills/monodesign/reference/delight.md +302 -0
- package/.claude/skills/monodesign/reference/design-principles.md +246 -0
- package/.claude/skills/monodesign/reference/distill.md +111 -0
- package/.claude/skills/monodesign/reference/document.md +427 -0
- package/.claude/skills/monodesign/reference/extract.md +69 -0
- package/.claude/skills/monodesign/reference/harden.md +347 -0
- package/.claude/skills/monodesign/reference/heuristics-scoring.md +234 -0
- package/.claude/skills/monodesign/reference/image-prompts.md +118 -0
- package/.claude/skills/monodesign/reference/interaction-design.md +195 -0
- package/.claude/skills/monodesign/reference/layout.md +141 -0
- package/.claude/skills/monodesign/reference/live.md +622 -0
- package/.claude/skills/monodesign/reference/motion-design.md +109 -0
- package/.claude/skills/monodesign/reference/onboard.md +234 -0
- package/.claude/skills/monodesign/reference/optimize.md +258 -0
- package/.claude/skills/monodesign/reference/overdrive.md +130 -0
- package/.claude/skills/monodesign/reference/personas.md +179 -0
- package/.claude/skills/monodesign/reference/polish.md +233 -0
- package/.claude/skills/monodesign/reference/pre-delivery-checklist.md +108 -0
- package/.claude/skills/monodesign/reference/product.md +62 -0
- package/.claude/skills/monodesign/reference/quieter.md +99 -0
- package/.claude/skills/monodesign/reference/responsive-design.md +114 -0
- package/.claude/skills/monodesign/reference/shape.md +151 -0
- package/.claude/skills/monodesign/reference/spatial-design.md +100 -0
- package/.claude/skills/monodesign/reference/teach.md +156 -0
- package/.claude/skills/monodesign/reference/token-architecture.md +222 -0
- package/.claude/skills/monodesign/reference/typeset.md +124 -0
- package/.claude/skills/monodesign/reference/typography.md +159 -0
- package/.claude/skills/monodesign/reference/ux-research.md +143 -0
- package/.claude/skills/monodesign/reference/ux-rules.md +211 -0
- package/.claude/skills/monodesign/reference/ux-writing.md +107 -0
- package/.claude/skills/monomotion/SKILL.md +145 -0
- package/.claude/skills/monomotion/rules/api-control.md +139 -0
- package/.claude/skills/monomotion/rules/effects.md +109 -0
- package/.claude/skills/monomotion/rules/integration.md +140 -0
- package/.claude/skills/monomotion/rules/scroll.md +131 -0
- package/.claude/skills/monomotion/rules/sequencing.md +105 -0
- package/.claude/skills/monomotion/rules/svg.md +101 -0
- package/.claude/skills/monomotion/rules/text.md +119 -0
- package/.claude/skills/pair-programming/SKILL.md +1 -1
- package/.claude/skills/performance-analysis/SKILL.md +3 -3
- package/.claude/skills/{v3-performance-optimization → performance-optimization}/SKILL.md +16 -8
- package/.claude/skills/reasoningbank-agentdb/SKILL.md +17 -19
- package/.claude/skills/reasoningbank-intelligence/SKILL.md +4 -6
- package/.claude/skills/{v3-security-overhaul → security-hardening}/SKILL.md +13 -3
- package/.claude/skills/skill-builder/SKILL.md +19 -19
- package/.claude/skills/sparc-methodology/SKILL.md +55 -211
- package/.claude/skills/stop-slop/SKILL.md +67 -0
- package/.claude/skills/stop-slop/references/examples.md +61 -0
- package/.claude/skills/stop-slop/references/phrases.md +130 -0
- package/.claude/skills/stop-slop/references/structures.md +136 -0
- package/.claude/skills/swarm-advanced/SKILL.md +13 -43
- package/.claude/skills/{v3-swarm-coordination → swarm-coordination}/SKILL.md +39 -21
- package/.claude/skills/swarm-orchestration/SKILL.md +12 -12
- package/.claude/skills/verification-quality/SKILL.md +5 -5
- package/.claude/statusline-command.sh +0 -0
- package/.claude/statusline.sh +0 -0
- package/.claude-plugin/scripts/install.sh +0 -0
- package/.claude-plugin/scripts/uninstall.sh +0 -0
- package/.claude-plugin/scripts/verify.sh +0 -0
- package/README.md +5 -5
- package/package.json +17 -17
- package/packages/@monomind/cli/README.md +441 -0
- package/packages/@monomind/cli/bin/cli.js +78 -13
- package/packages/@monomind/cli/bin/mcp-server.js +0 -0
- package/packages/@monomind/cli/dist/src/agents/halt-signal.js +33 -7
- package/packages/@monomind/cli/dist/src/agents/managed-agent.js +5 -2
- package/packages/@monomind/cli/dist/src/agents/prompt-experiment.d.ts +3 -2
- package/packages/@monomind/cli/dist/src/agents/prompt-experiment.js +1 -1
- package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.d.ts +5 -2
- package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.js +26 -4
- package/packages/@monomind/cli/dist/src/agents/specialization-scorer.js +17 -9
- package/packages/@monomind/cli/dist/src/agents/trigger-scanner.d.ts +5 -3
- package/packages/@monomind/cli/dist/src/agents/trigger-scanner.js +58 -10
- package/packages/@monomind/cli/dist/src/agents/version-store.d.ts +0 -1
- package/packages/@monomind/cli/dist/src/agents/version-store.js +44 -21
- package/packages/@monomind/cli/dist/src/autopilot-state.js +79 -28
- package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.d.ts +7 -2
- package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.js +20 -8
- package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.d.ts +2 -1
- package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.js +25 -2
- package/packages/@monomind/cli/dist/src/commands/agent.js +6 -4
- package/packages/@monomind/cli/dist/src/commands/appliance-advanced.js +23 -0
- package/packages/@monomind/cli/dist/src/commands/autopilot.js +3 -3
- package/packages/@monomind/cli/dist/src/commands/benchmark.js +119 -8
- package/packages/@monomind/cli/dist/src/commands/claims.js +22 -14
- package/packages/@monomind/cli/dist/src/commands/config.js +32 -0
- package/packages/@monomind/cli/dist/src/commands/daemon.js +13 -11
- package/packages/@monomind/cli/dist/src/commands/deployment.js +21 -2
- package/packages/@monomind/cli/dist/src/commands/doctor.js +5 -4
- package/packages/@monomind/cli/dist/src/commands/embeddings.js +124 -48
- package/packages/@monomind/cli/dist/src/commands/hive-mind.js +15 -14
- package/packages/@monomind/cli/dist/src/commands/hooks.js +45 -41
- package/packages/@monomind/cli/dist/src/commands/index.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/commands/index.js +20 -7
- package/packages/@monomind/cli/dist/src/commands/init.js +53 -19
- package/packages/@monomind/cli/dist/src/commands/mcp.js +31 -44
- package/packages/@monomind/cli/dist/src/commands/memory.js +47 -15
- package/packages/@monomind/cli/dist/src/commands/migrate.js +156 -108
- package/packages/@monomind/cli/dist/src/commands/monograph.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/monograph.js +526 -0
- package/packages/@monomind/cli/dist/src/commands/neural.js +96 -56
- package/packages/@monomind/cli/dist/src/commands/performance.js +30 -8
- package/packages/@monomind/cli/dist/src/commands/plugins.js +13 -37
- package/packages/@monomind/cli/dist/src/commands/process.js +25 -2
- package/packages/@monomind/cli/dist/src/commands/providers.js +37 -5
- package/packages/@monomind/cli/dist/src/commands/replay.js +4 -4
- package/packages/@monomind/cli/dist/src/commands/route.js +37 -5
- package/packages/@monomind/cli/dist/src/commands/ruvector/import.js +12 -2
- package/packages/@monomind/cli/dist/src/commands/ruvector/init.js +15 -0
- package/packages/@monomind/cli/dist/src/commands/ruvector/status.js +16 -3
- package/packages/@monomind/cli/dist/src/commands/security.js +342 -193
- package/packages/@monomind/cli/dist/src/commands/session.js +51 -8
- package/packages/@monomind/cli/dist/src/commands/start.js +18 -4
- package/packages/@monomind/cli/dist/src/commands/swarm.js +47 -36
- package/packages/@monomind/cli/dist/src/commands/tokens.js +11 -11
- package/packages/@monomind/cli/dist/src/commands/transfer-store.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/workflow.js +31 -4
- package/packages/@monomind/cli/dist/src/config-adapter.d.ts +2 -1
- package/packages/@monomind/cli/dist/src/consensus/audit-writer.js +46 -13
- package/packages/@monomind/cli/dist/src/consensus/vote-signer.d.ts +0 -3
- package/packages/@monomind/cli/dist/src/consensus/vote-signer.js +9 -1
- package/packages/@monomind/cli/dist/src/dlq/dlq-reader.d.ts +4 -2
- package/packages/@monomind/cli/dist/src/dlq/dlq-reader.js +25 -8
- package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.d.ts +10 -3
- package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.js +50 -16
- package/packages/@monomind/cli/dist/src/dlq/dlq-writer.js +27 -5
- package/packages/@monomind/cli/dist/src/eval/dataset-manager.d.ts +2 -2
- package/packages/@monomind/cli/dist/src/eval/dataset-manager.js +26 -16
- package/packages/@monomind/cli/dist/src/eval/trace-collector.js +23 -3
- package/packages/@monomind/cli/dist/src/index.js +12 -10
- package/packages/@monomind/cli/dist/src/init/claudemd-generator.js +8 -8
- package/packages/@monomind/cli/dist/src/init/executor.js +212 -102
- package/packages/@monomind/cli/dist/src/init/helpers-generator.js +35 -22
- package/packages/@monomind/cli/dist/src/init/mcp-generator.js +3 -3
- package/packages/@monomind/cli/dist/src/init/settings-generator.js +10 -3
- package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +18 -3
- package/packages/@monomind/cli/dist/src/init/statusline-generator.js +3 -1
- package/packages/@monomind/cli/dist/src/init/types.d.ts +35 -11
- package/packages/@monomind/cli/dist/src/init/types.js +5 -9
- package/packages/@monomind/cli/dist/src/interactive/interrupt.js +8 -3
- package/packages/@monomind/cli/dist/src/mcp/tool-registry.js +38 -4
- package/packages/@monomind/cli/dist/src/mcp-client.js +10 -4
- package/packages/@monomind/cli/dist/src/mcp-server.d.ts +9 -2
- package/packages/@monomind/cli/dist/src/mcp-server.js +182 -35
- package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +66 -34
- package/packages/@monomind/cli/dist/src/mcp-tools/agentdb-tools.js +34 -7
- package/packages/@monomind/cli/dist/src/mcp-tools/analyze-tools.js +25 -16
- package/packages/@monomind/cli/dist/src/mcp-tools/auto-install.js +4 -6
- package/packages/@monomind/cli/dist/src/mcp-tools/autopilot-tools.js +12 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +199 -20
- package/packages/@monomind/cli/dist/src/mcp-tools/claims-tools.js +68 -18
- package/packages/@monomind/cli/dist/src/mcp-tools/config-tools.js +33 -5
- package/packages/@monomind/cli/dist/src/mcp-tools/coordination-tools.js +59 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +46 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +46 -5
- package/packages/@monomind/cli/dist/src/mcp-tools/github-tools.js +29 -16
- package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +38 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +96 -33
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +70 -37
- package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +29 -13
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +5867 -56
- package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +121 -37
- package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +21 -8
- package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.js +10 -8
- package/packages/@monomind/cli/dist/src/mcp-tools/request-tracker.js +4 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/ruvllm-tools.js +19 -8
- package/packages/@monomind/cli/dist/src/mcp-tools/session-tools.js +57 -17
- package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +35 -17
- package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +4 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.js +53 -13
- package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.js +63 -14
- package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.js +21 -16
- package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +92 -23
- package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +41 -10
- package/packages/@monomind/cli/dist/src/memory/intelligence.d.ts +2 -2
- package/packages/@monomind/cli/dist/src/memory/intelligence.js +39 -13
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +149 -56
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +107 -45
- package/packages/@monomind/cli/dist/src/memory/sona-optimizer.d.ts +8 -1
- package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +25 -8
- package/packages/@monomind/cli/dist/src/observability/replay-reader.d.ts +40 -0
- package/packages/@monomind/cli/dist/src/observability/replay-reader.js +138 -0
- package/packages/@monomind/cli/dist/src/orchestration/routing-modes.js +35 -5
- package/packages/@monomind/cli/dist/src/parser.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/parser.js +48 -14
- package/packages/@monomind/cli/dist/src/plugins/manager.js +112 -19
- package/packages/@monomind/cli/dist/src/plugins/store/discovery.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/plugins/store/discovery.js +80 -62
- package/packages/@monomind/cli/dist/src/production/circuit-breaker.js +8 -1
- package/packages/@monomind/cli/dist/src/production/error-handler.d.ts +4 -2
- package/packages/@monomind/cli/dist/src/production/error-handler.js +27 -5
- package/packages/@monomind/cli/dist/src/production/monitoring.js +8 -4
- package/packages/@monomind/cli/dist/src/production/rate-limiter.js +30 -22
- package/packages/@monomind/cli/dist/src/ruvector/agent-wasm.js +2 -2
- package/packages/@monomind/cli/dist/src/ruvector/coverage-router.js +19 -9
- package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.js +26 -6
- package/packages/@monomind/cli/dist/src/ruvector/enhanced-model-router.js +24 -2
- package/packages/@monomind/cli/dist/src/ruvector/index.d.ts +1 -2
- package/packages/@monomind/cli/dist/src/ruvector/index.js +2 -2
- package/packages/@monomind/cli/dist/src/ruvector/model-router.d.ts +4 -2
- package/packages/@monomind/cli/dist/src/ruvector/model-router.js +30 -6
- package/packages/@monomind/cli/dist/src/ruvector/moe-router.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/ruvector/moe-router.js +35 -12
- package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.d.ts +7 -1
- package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.js +40 -9
- package/packages/@monomind/cli/dist/src/services/claim-service.d.ts +3 -1
- package/packages/@monomind/cli/dist/src/services/claim-service.js +33 -2
- package/packages/@monomind/cli/dist/src/services/config-file-manager.d.ts +16 -2
- package/packages/@monomind/cli/dist/src/services/config-file-manager.js +105 -17
- package/packages/@monomind/cli/dist/src/services/container-worker-pool.js +51 -11
- package/packages/@monomind/cli/dist/src/services/headless-worker-executor.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/services/headless-worker-executor.js +188 -45
- package/packages/@monomind/cli/dist/src/services/registry-api.js +62 -9
- package/packages/@monomind/cli/dist/src/services/ruvector-training.js +8 -0
- package/packages/@monomind/cli/dist/src/services/worker-daemon.d.ts +4 -1
- package/packages/@monomind/cli/dist/src/services/worker-daemon.js +112 -28
- package/packages/@monomind/cli/dist/src/services/worker-queue.d.ts +9 -2
- package/packages/@monomind/cli/dist/src/services/worker-queue.js +86 -5
- package/packages/@monomind/cli/dist/src/suggest.js +9 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.d.ts +5 -3
- package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.js +17 -5
- package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.js +30 -6
- package/packages/@monomind/cli/dist/src/transfer/anonymization/index.js +5 -3
- package/packages/@monomind/cli/dist/src/transfer/export.js +5 -3
- package/packages/@monomind/cli/dist/src/transfer/ipfs/client.js +84 -7
- package/packages/@monomind/cli/dist/src/transfer/ipfs/upload.js +13 -4
- package/packages/@monomind/cli/dist/src/transfer/storage/gcs.js +19 -10
- package/packages/@monomind/cli/dist/src/transfer/store/discovery.d.ts +9 -2
- package/packages/@monomind/cli/dist/src/transfer/store/discovery.js +68 -13
- package/packages/@monomind/cli/dist/src/transfer/store/download.d.ts +15 -6
- package/packages/@monomind/cli/dist/src/transfer/store/download.js +113 -24
- package/packages/@monomind/cli/dist/src/transfer/store/publish.d.ts +1 -1
- package/packages/@monomind/cli/dist/src/transfer/store/publish.js +13 -14
- package/packages/@monomind/cli/dist/src/transfer/store/registry.d.ts +3 -3
- package/packages/@monomind/cli/dist/src/transfer/store/registry.js +32 -16
- package/packages/@monomind/cli/dist/src/update/checker.js +17 -4
- package/packages/@monomind/cli/dist/src/update/executor.js +25 -20
- package/packages/@monomind/cli/dist/src/update/rate-limiter.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/update/rate-limiter.js +23 -3
- package/packages/@monomind/cli/dist/src/utils/parse-jsonl.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/utils/parse-jsonl.js +22 -0
- package/packages/@monomind/cli/dist/src/workflow/condition-evaluator.js +37 -3
- package/packages/@monomind/cli/dist/src/workflow/dag-builder.js +27 -11
- package/packages/@monomind/cli/dist/src/workflow/dag-executor.js +51 -13
- package/packages/@monomind/cli/dist/src/workflow/dsl-schema.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/workflow/dsl-schema.js +6 -2
- package/packages/@monomind/cli/dist/src/workflow/template-engine.js +7 -0
- package/packages/@monomind/cli/dist/src/workflow/workflow-executor.js +95 -14
- package/packages/@monomind/cli/package.json +5 -3
- package/packages/@monomind/guidance/README.md +1192 -0
- package/packages/@monomind/shared/README.md +322 -0
- package/packages/@monomind/shared/dist/types/consensus-audit.d.ts +3 -1
- package/packages/README.md +513 -0
- package/.claude/agents/design/design-brand-guardian.md +0 -323
- package/.claude/agents/design/design-image-prompt-engineer.md +0 -237
- package/.claude/agents/design/design-inclusive-visuals-specialist.md +0 -72
- package/.claude/agents/design/design-ui-designer.md +0 -384
- package/.claude/agents/design/design-ux-architect.md +0 -470
- package/.claude/agents/design/design-ux-researcher.md +0 -330
- package/.claude/agents/design/design-visual-storyteller.md +0 -150
- package/.claude/agents/design/design-whimsy-injector.md +0 -439
- package/.claude/agents/v3/integration-architect.md +0 -338
- package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +0 -54
- package/.claude/commands/coordination/init.md +0 -44
- package/.claude/commands/coordination/orchestrate.md +0 -43
- package/.claude/commands/coordination/spawn.md +0 -45
- package/.claude/commands/github/code-review-swarm.md +0 -550
- package/.claude/commands/github/code-review.md +0 -25
- package/.claude/commands/github/github-swarm.md +0 -121
- package/.claude/commands/github/issue-triage.md +0 -25
- package/.claude/commands/github/multi-repo-swarm.md +0 -519
- package/.claude/commands/github/pr-enhance.md +0 -26
- package/.claude/commands/github/project-board-sync.md +0 -471
- package/.claude/commands/github/release-swarm.md +0 -590
- package/.claude/commands/github/repo-analyze.md +0 -25
- package/.claude/commands/github/swarm-issue.md +0 -482
- package/.claude/commands/github/swarm-pr.md +0 -310
- package/.claude/commands/github/workflow-automation.md +0 -468
- package/.claude/commands/hive-mind/hive-mind-metrics.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-resume.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-sessions.md +0 -8
- package/.claude/commands/hive-mind/hive-mind-wizard.md +0 -8
- package/.claude/commands/list-agents.md +0 -17
- package/.claude/commands/memory/memory-persist.md +0 -25
- package/.claude/commands/memory/memory-usage.md +0 -25
- package/.claude/commands/memory/neural.md +0 -47
- package/.claude/commands/metrics.md +0 -11
- package/.claude/commands/monitoring/real-time-view.md +0 -25
- package/.claude/commands/monitoring/swarm-monitor.md +0 -25
- package/.claude/commands/monomind-createtask.md +0 -302
- package/.claude/commands/monomind-help.md +0 -103
- package/.claude/commands/monomind-memory.md +0 -107
- package/.claude/commands/monomind-repeat.md +0 -149
- package/.claude/commands/monomind-swarm.md +0 -205
- package/.claude/commands/optimization/cache-manage.md +0 -25
- package/.claude/commands/optimization/topology-optimize.md +0 -25
- package/.claude/commands/pair/commands.md +0 -546
- package/.claude/commands/pair/config.md +0 -510
- package/.claude/commands/pair/start.md +0 -209
- package/.claude/commands/use-agent.md +0 -67
- package/.claude/skills/monomind-createtask/SKILL.md +0 -269
- package/.claude/skills/monomind-task-engine/SKILL.md +0 -358
- /package/.claude/agents/{v3 → specialists}/memory-specialist.md +0 -0
- /package/.claude/agents/{v3 → specialists}/performance-engineer.md +0 -0
- /package/.claude/agents/{v3 → specialists}/queen-coordinator.md +0 -0
- /package/.claude/agents/{v3 → specialists}/security-architect.md +0 -0
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Tool definitions for session management with file persistence.
|
|
5
5
|
*/
|
|
6
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'node:fs';
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'node:fs';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
|
+
import { randomBytes } from 'node:crypto';
|
|
8
9
|
import { getProjectCwd } from './types.js';
|
|
9
10
|
// Storage paths
|
|
10
11
|
const STORAGE_DIR = '.monomind';
|
|
@@ -23,10 +24,13 @@ function ensureSessionDir() {
|
|
|
23
24
|
mkdirSync(dir, { recursive: true });
|
|
24
25
|
}
|
|
25
26
|
}
|
|
27
|
+
const MAX_SESSION_BYTES = 50 * 1024 * 1024;
|
|
26
28
|
function loadSession(sessionId) {
|
|
27
29
|
try {
|
|
28
30
|
const path = getSessionPath(sessionId);
|
|
29
31
|
if (existsSync(path)) {
|
|
32
|
+
if (statSync(path).size > MAX_SESSION_BYTES)
|
|
33
|
+
return null;
|
|
30
34
|
const data = readFileSync(path, 'utf-8');
|
|
31
35
|
return JSON.parse(data);
|
|
32
36
|
}
|
|
@@ -38,16 +42,37 @@ function loadSession(sessionId) {
|
|
|
38
42
|
}
|
|
39
43
|
function saveSession(session) {
|
|
40
44
|
ensureSessionDir();
|
|
41
|
-
|
|
45
|
+
const sessionPath = getSessionPath(session.sessionId);
|
|
46
|
+
// Unique tmp filename so concurrent session_save calls cannot collide on
|
|
47
|
+
// the same .tmp path (which would corrupt the rename target).
|
|
48
|
+
const tmpPath = `${sessionPath}.${process.pid}.${Date.now()}.tmp`;
|
|
49
|
+
writeFileSync(tmpPath, JSON.stringify(session, null, 2), 'utf-8');
|
|
50
|
+
renameSync(tmpPath, sessionPath);
|
|
42
51
|
}
|
|
43
|
-
function listSessions() {
|
|
52
|
+
function listSessions(limit = 200) {
|
|
44
53
|
ensureSessionDir();
|
|
45
54
|
const dir = getSessionDir();
|
|
46
|
-
|
|
55
|
+
// Sort by mtime DESC, then bound reads to `limit` files to prevent DoS
|
|
56
|
+
const files = readdirSync(dir)
|
|
57
|
+
.filter(f => f.endsWith('.json'))
|
|
58
|
+
.map(f => {
|
|
59
|
+
try {
|
|
60
|
+
const stat = statSync(join(dir, f));
|
|
61
|
+
return { name: f, mtimeMs: stat.mtimeMs };
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return { name: f, mtimeMs: 0 };
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
.sort((a, b) => b.mtimeMs - a.mtimeMs)
|
|
68
|
+
.slice(0, Math.max(1, Math.min(limit, 1000)));
|
|
47
69
|
const sessions = [];
|
|
48
70
|
for (const file of files) {
|
|
49
71
|
try {
|
|
50
|
-
const
|
|
72
|
+
const filePath = join(dir, file.name);
|
|
73
|
+
if (statSync(filePath).size > MAX_SESSION_BYTES)
|
|
74
|
+
continue;
|
|
75
|
+
const data = readFileSync(filePath, 'utf-8');
|
|
51
76
|
sessions.push(JSON.parse(data));
|
|
52
77
|
}
|
|
53
78
|
catch {
|
|
@@ -62,7 +87,7 @@ function loadRelatedStores(options) {
|
|
|
62
87
|
if (options.includeMemory) {
|
|
63
88
|
try {
|
|
64
89
|
const memoryPath = join(getProjectCwd(), STORAGE_DIR, 'memory', 'store.json');
|
|
65
|
-
if (existsSync(memoryPath)) {
|
|
90
|
+
if (existsSync(memoryPath) && statSync(memoryPath).size <= MAX_SESSION_BYTES) {
|
|
66
91
|
data.memory = JSON.parse(readFileSync(memoryPath, 'utf-8'));
|
|
67
92
|
}
|
|
68
93
|
}
|
|
@@ -71,7 +96,7 @@ function loadRelatedStores(options) {
|
|
|
71
96
|
if (options.includeTasks) {
|
|
72
97
|
try {
|
|
73
98
|
const taskPath = join(getProjectCwd(), STORAGE_DIR, 'tasks', 'store.json');
|
|
74
|
-
if (existsSync(taskPath)) {
|
|
99
|
+
if (existsSync(taskPath) && statSync(taskPath).size <= MAX_SESSION_BYTES) {
|
|
75
100
|
data.tasks = JSON.parse(readFileSync(taskPath, 'utf-8'));
|
|
76
101
|
}
|
|
77
102
|
}
|
|
@@ -80,7 +105,7 @@ function loadRelatedStores(options) {
|
|
|
80
105
|
if (options.includeAgents) {
|
|
81
106
|
try {
|
|
82
107
|
const agentPath = join(getProjectCwd(), STORAGE_DIR, 'agents', 'store.json');
|
|
83
|
-
if (existsSync(agentPath)) {
|
|
108
|
+
if (existsSync(agentPath) && statSync(agentPath).size <= MAX_SESSION_BYTES) {
|
|
84
109
|
data.agents = JSON.parse(readFileSync(agentPath, 'utf-8'));
|
|
85
110
|
}
|
|
86
111
|
}
|
|
@@ -105,7 +130,7 @@ export const sessionTools = [
|
|
|
105
130
|
required: ['name'],
|
|
106
131
|
},
|
|
107
132
|
handler: async (input) => {
|
|
108
|
-
const sessionId = `session-${Date.now()}-${
|
|
133
|
+
const sessionId = `session-${Date.now()}-${randomBytes(6).toString('hex')}`;
|
|
109
134
|
// Load related data based on options
|
|
110
135
|
const data = loadRelatedStores({
|
|
111
136
|
includeMemory: input.includeMemory,
|
|
@@ -136,7 +161,6 @@ export const sessionTools = [
|
|
|
136
161
|
name: session.name,
|
|
137
162
|
savedAt: session.savedAt,
|
|
138
163
|
stats: session.stats,
|
|
139
|
-
path: getSessionPath(sessionId),
|
|
140
164
|
};
|
|
141
165
|
},
|
|
142
166
|
},
|
|
@@ -176,7 +200,12 @@ export const sessionTools = [
|
|
|
176
200
|
const memoryDir = join(getProjectCwd(), STORAGE_DIR, 'memory');
|
|
177
201
|
if (!existsSync(memoryDir))
|
|
178
202
|
mkdirSync(memoryDir, { recursive: true });
|
|
179
|
-
|
|
203
|
+
const memoryStorePath = join(memoryDir, 'store.json');
|
|
204
|
+
{
|
|
205
|
+
const tmp = `${memoryStorePath}.${process.pid}.${Date.now()}.tmp`;
|
|
206
|
+
writeFileSync(tmp, JSON.stringify(session.data.memory, null, 2), 'utf-8');
|
|
207
|
+
renameSync(tmp, memoryStorePath);
|
|
208
|
+
}
|
|
180
209
|
// Also populate active sql.js SQLite database so memory-tools can find entries
|
|
181
210
|
try {
|
|
182
211
|
const { storeEntry } = await import('../memory/memory-initializer.js');
|
|
@@ -204,13 +233,23 @@ export const sessionTools = [
|
|
|
204
233
|
const taskDir = join(getProjectCwd(), STORAGE_DIR, 'tasks');
|
|
205
234
|
if (!existsSync(taskDir))
|
|
206
235
|
mkdirSync(taskDir, { recursive: true });
|
|
207
|
-
|
|
236
|
+
const taskStorePath = join(taskDir, 'store.json');
|
|
237
|
+
{
|
|
238
|
+
const tmp = `${taskStorePath}.${process.pid}.${Date.now()}.tmp`;
|
|
239
|
+
writeFileSync(tmp, JSON.stringify(session.data.tasks, null, 2), 'utf-8');
|
|
240
|
+
renameSync(tmp, taskStorePath);
|
|
241
|
+
}
|
|
208
242
|
}
|
|
209
243
|
if (session.data?.agents) {
|
|
210
244
|
const agentDir = join(getProjectCwd(), STORAGE_DIR, 'agents');
|
|
211
245
|
if (!existsSync(agentDir))
|
|
212
246
|
mkdirSync(agentDir, { recursive: true });
|
|
213
|
-
|
|
247
|
+
const agentStorePath = join(agentDir, 'store.json');
|
|
248
|
+
{
|
|
249
|
+
const tmp = `${agentStorePath}.${process.pid}.${Date.now()}.tmp`;
|
|
250
|
+
writeFileSync(tmp, JSON.stringify(session.data.agents, null, 2), 'utf-8');
|
|
251
|
+
renameSync(tmp, agentStorePath);
|
|
252
|
+
}
|
|
214
253
|
}
|
|
215
254
|
return {
|
|
216
255
|
sessionId: session.sessionId,
|
|
@@ -251,8 +290,10 @@ export const sessionTools = [
|
|
|
251
290
|
else if (sortBy === 'size') {
|
|
252
291
|
sessions.sort((a, b) => b.stats.totalSize - a.stats.totalSize);
|
|
253
292
|
}
|
|
254
|
-
// Apply limit
|
|
255
|
-
const
|
|
293
|
+
// Apply limit — clamp to [1, 200] to prevent negative-slice and OOM
|
|
294
|
+
const rawLimit = typeof input.limit === 'number' ? input.limit : 10;
|
|
295
|
+
const limit = Math.max(1, Math.min(rawLimit, 200));
|
|
296
|
+
const totalCount = sessions.length;
|
|
256
297
|
sessions = sessions.slice(0, limit);
|
|
257
298
|
return {
|
|
258
299
|
sessions: sessions.map(s => ({
|
|
@@ -262,7 +303,7 @@ export const sessionTools = [
|
|
|
262
303
|
savedAt: s.savedAt,
|
|
263
304
|
stats: s.stats,
|
|
264
305
|
})),
|
|
265
|
-
total:
|
|
306
|
+
total: totalCount,
|
|
266
307
|
limit,
|
|
267
308
|
};
|
|
268
309
|
},
|
|
@@ -320,7 +361,6 @@ export const sessionTools = [
|
|
|
320
361
|
savedAt: session.savedAt,
|
|
321
362
|
stats: session.stats,
|
|
322
363
|
fileSize: stat.size,
|
|
323
|
-
path,
|
|
324
364
|
hasData: {
|
|
325
365
|
memory: !!session.data?.memory,
|
|
326
366
|
tasks: !!session.data?.tasks,
|
|
@@ -4,17 +4,10 @@
|
|
|
4
4
|
* Tool definitions for swarm coordination with file-based state persistence.
|
|
5
5
|
* Replaces previous stub implementations with real state tracking.
|
|
6
6
|
*/
|
|
7
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync,
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, statSync } from 'node:fs';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
|
+
import { randomBytes } from 'node:crypto';
|
|
9
10
|
import { getProjectCwd } from './types.js';
|
|
10
|
-
function logEvent(kind, data) {
|
|
11
|
-
try {
|
|
12
|
-
const dir = join(getProjectCwd(), '.monomind', 'swarm');
|
|
13
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
14
|
-
const event = { ts: new Date().toISOString(), source: 'mcp', kind, ...data };
|
|
15
|
-
appendFileSync(join(dir, 'events.jsonl'), JSON.stringify(event) + '\n');
|
|
16
|
-
} catch { }
|
|
17
|
-
}
|
|
18
11
|
// Swarm state persistence
|
|
19
12
|
const SWARM_DIR = '.monomind/swarm';
|
|
20
13
|
const SWARM_STATE_FILE = 'swarm-state.json';
|
|
@@ -30,10 +23,13 @@ function ensureSwarmDir() {
|
|
|
30
23
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
31
24
|
}
|
|
32
25
|
}
|
|
26
|
+
const MAX_SWARM_STORE_BYTES = 10 * 1024 * 1024;
|
|
33
27
|
function loadSwarmStore() {
|
|
34
28
|
try {
|
|
35
29
|
const path = getSwarmStatePath();
|
|
36
30
|
if (existsSync(path)) {
|
|
31
|
+
if (statSync(path).size > MAX_SWARM_STORE_BYTES)
|
|
32
|
+
return { swarms: {}, version: '3.0.0' };
|
|
37
33
|
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
38
34
|
}
|
|
39
35
|
}
|
|
@@ -42,7 +38,10 @@ function loadSwarmStore() {
|
|
|
42
38
|
}
|
|
43
39
|
function saveSwarmStore(store) {
|
|
44
40
|
ensureSwarmDir();
|
|
45
|
-
|
|
41
|
+
const dest = getSwarmStatePath();
|
|
42
|
+
const tmp = `${dest}.${process.pid}.${Date.now()}.tmp`;
|
|
43
|
+
writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf-8');
|
|
44
|
+
renameSync(tmp, dest);
|
|
46
45
|
}
|
|
47
46
|
// Input validation
|
|
48
47
|
const VALID_TOPOLOGIES = new Set([
|
|
@@ -64,7 +63,7 @@ export const swarmTools = [
|
|
|
64
63
|
},
|
|
65
64
|
handler: async (input) => {
|
|
66
65
|
const topology = input.topology || 'hierarchical-mesh';
|
|
67
|
-
const maxAgents = Math.min(Math.max(input.maxAgents ||
|
|
66
|
+
const maxAgents = Math.min(Math.max(input.maxAgents || 8, 1), 50);
|
|
68
67
|
const strategy = input.strategy || 'specialized';
|
|
69
68
|
const config = (input.config || {});
|
|
70
69
|
if (!VALID_TOPOLOGIES.has(topology)) {
|
|
@@ -73,7 +72,7 @@ export const swarmTools = [
|
|
|
73
72
|
error: `Invalid topology: ${topology}. Valid: ${[...VALID_TOPOLOGIES].join(', ')}`,
|
|
74
73
|
};
|
|
75
74
|
}
|
|
76
|
-
const swarmId = `swarm-${Date.now()}-${
|
|
75
|
+
const swarmId = `swarm-${Date.now()}-${randomBytes(6).toString('hex')}`;
|
|
77
76
|
const now = new Date().toISOString();
|
|
78
77
|
const swarmState = {
|
|
79
78
|
swarmId,
|
|
@@ -94,9 +93,17 @@ export const swarmTools = [
|
|
|
94
93
|
updatedAt: now,
|
|
95
94
|
};
|
|
96
95
|
const store = loadSwarmStore();
|
|
96
|
+
const MAX_SWARMS = 500;
|
|
97
|
+
// Evict terminated swarms first to free space
|
|
98
|
+
for (const [id, s] of Object.entries(store.swarms)) {
|
|
99
|
+
if (s.status === 'terminated')
|
|
100
|
+
delete store.swarms[id];
|
|
101
|
+
}
|
|
102
|
+
if (Object.keys(store.swarms).length >= MAX_SWARMS) {
|
|
103
|
+
return { success: false, error: 'Swarm limit reached' };
|
|
104
|
+
}
|
|
97
105
|
store.swarms[swarmId] = swarmState;
|
|
98
106
|
saveSwarmStore(store);
|
|
99
|
-
logEvent('swarm.init', { swarmId, topology, strategy, maxAgents, config: swarmState.config });
|
|
100
107
|
return {
|
|
101
108
|
success: true,
|
|
102
109
|
swarmId,
|
|
@@ -122,7 +129,11 @@ export const swarmTools = [
|
|
|
122
129
|
handler: async (input) => {
|
|
123
130
|
const store = loadSwarmStore();
|
|
124
131
|
const swarmId = input.swarmId;
|
|
125
|
-
|
|
132
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
133
|
+
if (swarmId && FORBIDDEN_KEYS.has(swarmId)) {
|
|
134
|
+
return { status: 'not_found', message: `Swarm ${swarmId} not found` };
|
|
135
|
+
}
|
|
136
|
+
if (swarmId && Object.hasOwn(store.swarms, swarmId)) {
|
|
126
137
|
const swarm = store.swarms[swarmId];
|
|
127
138
|
return {
|
|
128
139
|
swarmId: swarm.swarmId,
|
|
@@ -176,9 +187,13 @@ export const swarmTools = [
|
|
|
176
187
|
handler: async (input) => {
|
|
177
188
|
const store = loadSwarmStore();
|
|
178
189
|
const swarmId = input.swarmId;
|
|
190
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
191
|
+
if (swarmId && FORBIDDEN_KEYS.has(swarmId)) {
|
|
192
|
+
return { success: false, error: `Swarm ${swarmId} not found` };
|
|
193
|
+
}
|
|
179
194
|
// Find the swarm
|
|
180
195
|
let target;
|
|
181
|
-
if (swarmId && store.swarms
|
|
196
|
+
if (swarmId && Object.hasOwn(store.swarms, swarmId)) {
|
|
182
197
|
target = store.swarms[swarmId];
|
|
183
198
|
}
|
|
184
199
|
else {
|
|
@@ -204,7 +219,6 @@ export const swarmTools = [
|
|
|
204
219
|
target.status = 'terminated';
|
|
205
220
|
target.updatedAt = new Date().toISOString();
|
|
206
221
|
saveSwarmStore(store);
|
|
207
|
-
logEvent('swarm.shutdown', { swarmId: target.swarmId, topology: target.topology, agentCount: target.agents.length, graceful: input.graceful ?? true });
|
|
208
222
|
return {
|
|
209
223
|
success: true,
|
|
210
224
|
swarmId: target.swarmId,
|
|
@@ -228,10 +242,14 @@ export const swarmTools = [
|
|
|
228
242
|
handler: async (input) => {
|
|
229
243
|
const store = loadSwarmStore();
|
|
230
244
|
const swarmId = input.swarmId;
|
|
245
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
246
|
+
if (swarmId && FORBIDDEN_KEYS.has(swarmId)) {
|
|
247
|
+
return { status: 'not_found', healthy: false, checks: [{ name: 'swarm_exists', status: 'fail', message: `Swarm ${swarmId} not found` }], checkedAt: new Date().toISOString() };
|
|
248
|
+
}
|
|
231
249
|
// Find the swarm
|
|
232
250
|
let target;
|
|
233
251
|
if (swarmId) {
|
|
234
|
-
target = store.swarms[swarmId];
|
|
252
|
+
target = Object.hasOwn(store.swarms, swarmId) ? store.swarms[swarmId] : undefined;
|
|
235
253
|
if (!target) {
|
|
236
254
|
return {
|
|
237
255
|
status: 'not_found',
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* - os module for system information
|
|
10
10
|
*/
|
|
11
11
|
import { getProjectCwd } from './types.js';
|
|
12
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'node:fs';
|
|
13
13
|
import { join, dirname } from 'node:path';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import * as os from 'node:os';
|
|
@@ -68,7 +68,9 @@ function loadMetrics() {
|
|
|
68
68
|
function saveMetrics(metrics) {
|
|
69
69
|
ensureSystemDir();
|
|
70
70
|
metrics.lastCheck = new Date().toISOString();
|
|
71
|
-
|
|
71
|
+
const tmpPath = getMetricsPath() + '.tmp';
|
|
72
|
+
writeFileSync(tmpPath, JSON.stringify(metrics, null, 2), 'utf-8');
|
|
73
|
+
renameSync(tmpPath, getMetricsPath());
|
|
72
74
|
}
|
|
73
75
|
export const systemTools = [
|
|
74
76
|
{
|
|
@@ -403,7 +405,6 @@ export const systemTools = [
|
|
|
403
405
|
platform: process.platform,
|
|
404
406
|
arch: process.arch,
|
|
405
407
|
pid: process.pid,
|
|
406
|
-
cwd: getProjectCwd(),
|
|
407
408
|
env: process.env.NODE_ENV || 'development',
|
|
408
409
|
features: {
|
|
409
410
|
swarm: true,
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Tool definitions for task management with file persistence.
|
|
5
5
|
*/
|
|
6
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, statSync } from 'node:fs';
|
|
7
7
|
import { join } from 'node:path';
|
|
8
|
+
import { randomBytes } from 'node:crypto';
|
|
8
9
|
import { getProjectCwd } from './types.js';
|
|
9
10
|
// Storage paths
|
|
10
11
|
const STORAGE_DIR = '.monomind';
|
|
@@ -22,12 +23,18 @@ function ensureTaskDir() {
|
|
|
22
23
|
mkdirSync(dir, { recursive: true });
|
|
23
24
|
}
|
|
24
25
|
}
|
|
26
|
+
const MAX_TASK_STORE_BYTES = 50 * 1024 * 1024;
|
|
25
27
|
function loadTaskStore() {
|
|
26
28
|
try {
|
|
27
29
|
const path = getTaskPath();
|
|
28
30
|
if (existsSync(path)) {
|
|
31
|
+
if (statSync(path).size > MAX_TASK_STORE_BYTES)
|
|
32
|
+
return { tasks: {}, version: '3.0.0' };
|
|
29
33
|
const data = readFileSync(path, 'utf-8');
|
|
30
|
-
|
|
34
|
+
const parsed = JSON.parse(data);
|
|
35
|
+
if (parsed && typeof parsed === 'object' && Object.prototype.hasOwnProperty.call(parsed, '__proto__'))
|
|
36
|
+
return { tasks: {}, version: '3.0.0' };
|
|
37
|
+
return parsed;
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
catch {
|
|
@@ -37,8 +44,14 @@ function loadTaskStore() {
|
|
|
37
44
|
}
|
|
38
45
|
function saveTaskStore(store) {
|
|
39
46
|
ensureTaskDir();
|
|
40
|
-
|
|
47
|
+
const taskPath = getTaskPath();
|
|
48
|
+
// Unique tmp filename — concurrent task_assign/complete calls would
|
|
49
|
+
// otherwise race on the same .tmp file.
|
|
50
|
+
const tmpPath = `${taskPath}.${process.pid}.${Date.now()}.tmp`;
|
|
51
|
+
writeFileSync(tmpPath, JSON.stringify(store, null, 2), 'utf-8');
|
|
52
|
+
renameSync(tmpPath, taskPath);
|
|
41
53
|
}
|
|
54
|
+
const FORBIDDEN_TASK_IDS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
42
55
|
export const taskTools = [
|
|
43
56
|
{
|
|
44
57
|
name: 'task_create',
|
|
@@ -57,7 +70,7 @@ export const taskTools = [
|
|
|
57
70
|
},
|
|
58
71
|
handler: async (input) => {
|
|
59
72
|
const store = loadTaskStore();
|
|
60
|
-
const taskId = `task-${Date.now()}-${
|
|
73
|
+
const taskId = `task-${Date.now()}-${randomBytes(4).toString('hex')}`;
|
|
61
74
|
const task = {
|
|
62
75
|
taskId,
|
|
63
76
|
type: input.type,
|
|
@@ -99,6 +112,8 @@ export const taskTools = [
|
|
|
99
112
|
handler: async (input) => {
|
|
100
113
|
const store = loadTaskStore();
|
|
101
114
|
const taskId = input.taskId;
|
|
115
|
+
if (FORBIDDEN_TASK_IDS.has(taskId))
|
|
116
|
+
return { taskId, status: 'not_found', error: 'Task not found' };
|
|
102
117
|
const task = store.tasks[taskId];
|
|
103
118
|
if (task) {
|
|
104
119
|
return {
|
|
@@ -196,6 +211,8 @@ export const taskTools = [
|
|
|
196
211
|
handler: async (input) => {
|
|
197
212
|
const store = loadTaskStore();
|
|
198
213
|
const taskId = input.taskId;
|
|
214
|
+
if (FORBIDDEN_TASK_IDS.has(taskId))
|
|
215
|
+
return { taskId, status: 'not_found', error: 'Task not found' };
|
|
199
216
|
const task = store.tasks[taskId];
|
|
200
217
|
if (task) {
|
|
201
218
|
task.status = 'completed';
|
|
@@ -209,17 +226,27 @@ export const taskTools = [
|
|
|
209
226
|
try {
|
|
210
227
|
let agentStore = { agents: {} };
|
|
211
228
|
if (existsSync(agentStorePath)) {
|
|
212
|
-
|
|
229
|
+
const agentRaw = JSON.parse(readFileSync(agentStorePath, 'utf-8'));
|
|
230
|
+
if (agentRaw && typeof agentRaw === 'object' && !Object.prototype.hasOwnProperty.call(agentRaw, '__proto__')) {
|
|
231
|
+
agentStore = agentRaw;
|
|
232
|
+
}
|
|
213
233
|
}
|
|
214
234
|
for (const agentId of task.assignedTo) {
|
|
215
|
-
|
|
235
|
+
const FORBIDDEN_AGENT_IDS_TC = new Set(['__proto__', 'constructor', 'prototype']);
|
|
236
|
+
if (typeof agentId === 'string' && agentId.length > 0 && agentId.length <= 128 &&
|
|
237
|
+
!FORBIDDEN_AGENT_IDS_TC.has(agentId) && Object.hasOwn(agentStore.agents, agentId)) {
|
|
216
238
|
agentStore.agents[agentId].status = 'idle';
|
|
217
239
|
agentStore.agents[agentId].currentTask = null;
|
|
218
240
|
agentStore.agents[agentId].taskCount =
|
|
219
241
|
(agentStore.agents[agentId].taskCount || 0) + 1;
|
|
220
242
|
}
|
|
221
243
|
}
|
|
222
|
-
|
|
244
|
+
const agentDir = join(getProjectCwd(), STORAGE_DIR, 'agents');
|
|
245
|
+
if (!existsSync(agentDir))
|
|
246
|
+
mkdirSync(agentDir, { recursive: true });
|
|
247
|
+
const tmpAgent1 = `${agentStorePath}.${process.pid}.${Date.now()}.tmp`;
|
|
248
|
+
writeFileSync(tmpAgent1, JSON.stringify(agentStore, null, 2), 'utf-8');
|
|
249
|
+
renameSync(tmpAgent1, agentStorePath);
|
|
223
250
|
}
|
|
224
251
|
catch {
|
|
225
252
|
// Best-effort agent sync
|
|
@@ -256,6 +283,8 @@ export const taskTools = [
|
|
|
256
283
|
handler: async (input) => {
|
|
257
284
|
const store = loadTaskStore();
|
|
258
285
|
const taskId = input.taskId;
|
|
286
|
+
if (FORBIDDEN_TASK_IDS.has(taskId))
|
|
287
|
+
return { success: false, taskId, error: 'Task not found' };
|
|
259
288
|
const task = store.tasks[taskId];
|
|
260
289
|
if (task) {
|
|
261
290
|
if (input.status) {
|
|
@@ -303,6 +332,8 @@ export const taskTools = [
|
|
|
303
332
|
handler: async (input) => {
|
|
304
333
|
const store = loadTaskStore();
|
|
305
334
|
const taskId = input.taskId;
|
|
335
|
+
if (FORBIDDEN_TASK_IDS.has(taskId))
|
|
336
|
+
return { taskId, error: 'Task not found' };
|
|
306
337
|
const task = store.tasks[taskId];
|
|
307
338
|
if (!task) {
|
|
308
339
|
return { taskId, error: 'Task not found' };
|
|
@@ -317,10 +348,14 @@ export const taskTools = [
|
|
|
317
348
|
}
|
|
318
349
|
}
|
|
319
350
|
catch { /* ignore */ }
|
|
351
|
+
// Reject IDs that would mutate Object.prototype when used as a key in
|
|
352
|
+
// the JSON-loaded plain object `agentStore.agents`.
|
|
353
|
+
const FORBIDDEN_AGENT_IDS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
354
|
+
const isValidAgentId = (id) => typeof id === 'string' && id.length > 0 && id.length <= 128 && !FORBIDDEN_AGENT_IDS.has(id);
|
|
320
355
|
if (input.unassign) {
|
|
321
356
|
// Revert previously assigned agents to idle
|
|
322
357
|
for (const agentId of previouslyAssigned) {
|
|
323
|
-
if (agentStore.agents
|
|
358
|
+
if (isValidAgentId(agentId) && Object.hasOwn(agentStore.agents, agentId)) {
|
|
324
359
|
agentStore.agents[agentId].status = 'idle';
|
|
325
360
|
agentStore.agents[agentId].currentTask = null;
|
|
326
361
|
}
|
|
@@ -328,18 +363,19 @@ export const taskTools = [
|
|
|
328
363
|
task.assignedTo = [];
|
|
329
364
|
}
|
|
330
365
|
else {
|
|
331
|
-
const
|
|
366
|
+
const rawIds = input.agentIds || [];
|
|
367
|
+
const agentIds = rawIds.filter(isValidAgentId);
|
|
332
368
|
// Revert old agents to idle
|
|
333
369
|
for (const agentId of previouslyAssigned) {
|
|
334
|
-
if (!agentIds.includes(agentId) && agentStore.agents
|
|
370
|
+
if (isValidAgentId(agentId) && !agentIds.includes(agentId) && Object.hasOwn(agentStore.agents, agentId)) {
|
|
335
371
|
agentStore.agents[agentId].status = 'idle';
|
|
336
372
|
agentStore.agents[agentId].currentTask = null;
|
|
337
373
|
}
|
|
338
374
|
}
|
|
339
375
|
// Set new agents to active
|
|
340
376
|
for (const agentId of agentIds) {
|
|
341
|
-
if (agentStore.agents
|
|
342
|
-
agentStore.agents[agentId].status = '
|
|
377
|
+
if (Object.hasOwn(agentStore.agents, agentId)) {
|
|
378
|
+
agentStore.agents[agentId].status = 'busy';
|
|
343
379
|
agentStore.agents[agentId].currentTask = taskId;
|
|
344
380
|
}
|
|
345
381
|
}
|
|
@@ -358,7 +394,9 @@ export const taskTools = [
|
|
|
358
394
|
if (!existsSync(agentDir)) {
|
|
359
395
|
mkdirSync(agentDir, { recursive: true });
|
|
360
396
|
}
|
|
361
|
-
|
|
397
|
+
const tmpAgent2 = `${agentStorePath}.${process.pid}.${Date.now()}.tmp`;
|
|
398
|
+
writeFileSync(tmpAgent2, JSON.stringify(agentStore, null, 2), 'utf-8');
|
|
399
|
+
renameSync(tmpAgent2, agentStorePath);
|
|
362
400
|
return {
|
|
363
401
|
taskId: task.taskId,
|
|
364
402
|
assignedTo: task.assignedTo,
|
|
@@ -382,6 +420,8 @@ export const taskTools = [
|
|
|
382
420
|
handler: async (input) => {
|
|
383
421
|
const store = loadTaskStore();
|
|
384
422
|
const taskId = input.taskId;
|
|
423
|
+
if (FORBIDDEN_TASK_IDS.has(taskId))
|
|
424
|
+
return { success: false, taskId, error: 'Task not found' };
|
|
385
425
|
const task = store.tasks[taskId];
|
|
386
426
|
if (task) {
|
|
387
427
|
task.status = 'cancelled';
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Terminal session management with real command execution.
|
|
5
5
|
*/
|
|
6
6
|
import { getProjectCwd } from './types.js';
|
|
7
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'node:fs';
|
|
8
8
|
import { join } from 'node:path';
|
|
9
9
|
import { execSync } from 'node:child_process';
|
|
10
|
+
import { randomBytes } from 'node:crypto';
|
|
10
11
|
// Storage paths
|
|
11
12
|
const STORAGE_DIR = '.monomind';
|
|
12
13
|
const TERMINAL_DIR = 'terminals';
|
|
@@ -37,7 +38,11 @@ function loadTerminalStore() {
|
|
|
37
38
|
}
|
|
38
39
|
function saveTerminalStore(store) {
|
|
39
40
|
ensureTerminalDir();
|
|
40
|
-
|
|
41
|
+
// Unique tmp filename so concurrent handler invocations cannot clobber each
|
|
42
|
+
// other's .tmp mid-write (which would produce a partial JSON on rename).
|
|
43
|
+
const tmpPath = `${getTerminalPath()}.${process.pid}.${Date.now()}.tmp`;
|
|
44
|
+
writeFileSync(tmpPath, JSON.stringify(store, null, 2), 'utf-8');
|
|
45
|
+
renameSync(tmpPath, getTerminalPath());
|
|
41
46
|
}
|
|
42
47
|
export const terminalTools = [
|
|
43
48
|
{
|
|
@@ -54,7 +59,19 @@ export const terminalTools = [
|
|
|
54
59
|
},
|
|
55
60
|
handler: async (input) => {
|
|
56
61
|
const store = loadTerminalStore();
|
|
57
|
-
const
|
|
62
|
+
const MAX_SESSIONS = 1000;
|
|
63
|
+
if (Object.keys(store.sessions).length >= MAX_SESSIONS) {
|
|
64
|
+
return { success: false, error: 'Session limit reached' };
|
|
65
|
+
}
|
|
66
|
+
const FORBIDDEN_ENV_KEYS = new Set(['PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH', 'NODE_OPTIONS', 'NODE_PATH', 'DYLD_INSERT_LIBRARIES', 'DYLD_LIBRARY_PATH']);
|
|
67
|
+
const rawEnv = input.env || {};
|
|
68
|
+
const safeEnv = {};
|
|
69
|
+
for (const [k, v] of Object.entries(rawEnv)) {
|
|
70
|
+
if (!FORBIDDEN_ENV_KEYS.has(k) && /^[A-Z_][A-Z0-9_]*$/i.test(k)) {
|
|
71
|
+
safeEnv[k] = String(v);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const id = `term-${Date.now()}-${randomBytes(4).toString('hex')}`;
|
|
58
75
|
const session = {
|
|
59
76
|
id,
|
|
60
77
|
name: input.name || `Terminal ${Object.keys(store.sessions).length + 1}`,
|
|
@@ -63,7 +80,7 @@ export const terminalTools = [
|
|
|
63
80
|
lastActivity: new Date().toISOString(),
|
|
64
81
|
workingDir: input.workingDir || getProjectCwd(),
|
|
65
82
|
history: [],
|
|
66
|
-
env:
|
|
83
|
+
env: safeEnv,
|
|
67
84
|
};
|
|
68
85
|
store.sessions[id] = session;
|
|
69
86
|
saveTerminalStore(store);
|
|
@@ -95,11 +112,17 @@ export const terminalTools = [
|
|
|
95
112
|
const store = loadTerminalStore();
|
|
96
113
|
const sessionId = input.sessionId;
|
|
97
114
|
const command = input.command;
|
|
115
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
116
|
+
// Reject inherited keys (incl. toString/hasOwnProperty/etc.) so a tampered
|
|
117
|
+
// store.json can't redirect bracket access into Object.prototype.
|
|
118
|
+
if (sessionId && (typeof sessionId !== 'string' || FORBIDDEN_KEYS.has(sessionId) || !Object.hasOwn(store.sessions, sessionId))) {
|
|
119
|
+
return { success: false, error: 'Invalid sessionId' };
|
|
120
|
+
}
|
|
98
121
|
// Find or create default session
|
|
99
122
|
let session = sessionId ? store.sessions[sessionId] : Object.values(store.sessions).find(s => s.status === 'active');
|
|
100
123
|
if (!session) {
|
|
101
124
|
// Create default session
|
|
102
|
-
const id = `term-${Date.now()}-${
|
|
125
|
+
const id = `term-${Date.now()}-${randomBytes(4).toString('hex')}`;
|
|
103
126
|
session = {
|
|
104
127
|
id,
|
|
105
128
|
name: 'Default Terminal',
|
|
@@ -112,7 +135,22 @@ export const terminalTools = [
|
|
|
112
135
|
};
|
|
113
136
|
store.sessions[id] = session;
|
|
114
137
|
}
|
|
115
|
-
|
|
138
|
+
// Reject shell metacharacters AND env-prefix syntax. The previous regex
|
|
139
|
+
// allowed `=`, which `/bin/sh` interprets as a per-command env override
|
|
140
|
+
// (`PATH=/tmp/evil ls`, `LD_PRELOAD=/tmp/x.so cmd`) — turning the
|
|
141
|
+
// metacharacter denylist into RCE. Also reject leading-dash so the
|
|
142
|
+
// first arg can't be misinterpreted by the spawned binary as a flag,
|
|
143
|
+
// and reject glob/expansion characters that may evaluate paths.
|
|
144
|
+
if (/[|;&`$\n\r<>=*?~(){}[\]#!\\"']/.test(command)) {
|
|
145
|
+
return { error: 'Command contains disallowed shell metacharacters', allowed: false };
|
|
146
|
+
}
|
|
147
|
+
if (/^\s*-/.test(command)) {
|
|
148
|
+
return { error: 'Command must not start with "-"', allowed: false };
|
|
149
|
+
}
|
|
150
|
+
const rawTimeout = Number(input.timeout);
|
|
151
|
+
const timeout = Number.isFinite(rawTimeout) && rawTimeout > 0
|
|
152
|
+
? Math.min(rawTimeout, 5 * 60_000)
|
|
153
|
+
: 30_000;
|
|
116
154
|
const cwd = session.workingDir || getProjectCwd();
|
|
117
155
|
const startTime = Date.now();
|
|
118
156
|
let output;
|
|
@@ -134,13 +172,16 @@ export const terminalTools = [
|
|
|
134
172
|
}
|
|
135
173
|
const duration = Date.now() - startTime;
|
|
136
174
|
const timestamp = new Date().toISOString();
|
|
137
|
-
// Record in history
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
});
|
|
175
|
+
// Record in history (cap output size and total entries to prevent unbounded growth)
|
|
176
|
+
const MAX_OUTPUT_BYTES = 64 * 1024;
|
|
177
|
+
const MAX_HISTORY = 200;
|
|
178
|
+
const truncatedOutput = output.length > MAX_OUTPUT_BYTES
|
|
179
|
+
? output.slice(0, MAX_OUTPUT_BYTES) + '\n[... truncated ...]'
|
|
180
|
+
: output;
|
|
181
|
+
session.history.push({ command, output: truncatedOutput, timestamp, exitCode });
|
|
182
|
+
if (session.history.length > MAX_HISTORY) {
|
|
183
|
+
session.history.splice(0, session.history.length - MAX_HISTORY);
|
|
184
|
+
}
|
|
144
185
|
session.lastActivity = timestamp;
|
|
145
186
|
session.status = 'active';
|
|
146
187
|
saveTerminalStore(store);
|
|
@@ -203,7 +244,11 @@ export const terminalTools = [
|
|
|
203
244
|
handler: async (input) => {
|
|
204
245
|
const store = loadTerminalStore();
|
|
205
246
|
const sessionId = input.sessionId;
|
|
206
|
-
const
|
|
247
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
248
|
+
if (!sessionId || FORBIDDEN_KEYS.has(sessionId)) {
|
|
249
|
+
return { success: false, error: 'Invalid sessionId' };
|
|
250
|
+
}
|
|
251
|
+
const session = Object.hasOwn(store.sessions, sessionId) ? store.sessions[sessionId] : undefined;
|
|
207
252
|
if (!session) {
|
|
208
253
|
return { success: false, error: 'Session not found' };
|
|
209
254
|
}
|
|
@@ -233,7 +278,11 @@ export const terminalTools = [
|
|
|
233
278
|
const sessionId = input.sessionId;
|
|
234
279
|
const limit = input.limit || 50;
|
|
235
280
|
const offset = input.offset || 0;
|
|
281
|
+
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
236
282
|
if (sessionId) {
|
|
283
|
+
if (typeof sessionId !== 'string' || FORBIDDEN_KEYS.has(sessionId) || !Object.hasOwn(store.sessions, sessionId)) {
|
|
284
|
+
return { success: false, error: 'Invalid sessionId' };
|
|
285
|
+
}
|
|
237
286
|
const session = store.sessions[sessionId];
|
|
238
287
|
if (!session) {
|
|
239
288
|
return { success: false, error: 'Session not found' };
|