@monoes/monomindcli 1.19.0 → 2.0.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/github/issue-tracker.md +0 -2
- package/.claude/agents/github/pr-manager.md +0 -2
- package/.claude/agents/github/repo-architect.md +3 -11
- package/.claude/agents/goal/goal-planner.md +0 -1
- package/.claude/commands/github/issue-tracker.md +0 -2
- package/.claude/commands/github/pr-manager.md +0 -2
- package/.claude/commands/github/repo-architect.md +3 -10
- package/.claude/commands/mastermind/help.md +3 -3
- package/.claude/commands/workflows/README.md +0 -1
- package/.claude/commands/workflows/workflow-create.md +0 -1
- package/.claude/commands/workflows/workflow-execute.md +1 -3
- package/.claude/commands/workflows/workflow-export.md +0 -2
- package/.claude/helpers/handlers/agent-start-handler.cjs +18 -1
- package/.claude/helpers/handlers/edit-handler.cjs +15 -0
- package/.claude/helpers/handlers/gates-handler.cjs +2 -8
- package/.claude/helpers/handlers/route-handler.cjs +149 -7
- package/.claude/helpers/handlers/session-handler.cjs +47 -25
- package/.claude/helpers/handlers/session-restore-handler.cjs +80 -43
- package/.claude/helpers/handlers/task-handler.cjs +8 -4
- package/.claude/helpers/hook-handler.cjs +69 -16
- package/.claude/helpers/intelligence.cjs +100 -9
- package/.claude/helpers/router.cjs +78 -5
- package/.claude/helpers/skill-registry.json +0 -189
- package/.claude/skills/github-toolkit/SKILL.md +60 -0
- package/.claude/skills/hive-mind-advanced/SKILL.md +0 -15
- package/.claude/skills/hooks-automation/SKILL.md +0 -1
- package/.claude/skills/mastermind-skills/_protocol.md +1 -1
- package/.claude/skills/mastermind-skills/build.md +1 -2
- package/.claude/skills/memory-toolkit/SKILL.md +75 -0
- package/.claude/skills/specialagent/SKILL.md +2 -4
- package/.claude/skills/swarm-advanced/SKILL.md +0 -1
- package/README.md +2 -5
- package/dist/src/autopilot-state.d.ts.map +1 -1
- package/dist/src/autopilot-state.js +4 -5
- package/dist/src/autopilot-state.js.map +1 -1
- package/dist/src/browser/dashboard/server.d.ts.map +1 -1
- package/dist/src/browser/dashboard/server.js +69 -1
- package/dist/src/browser/dashboard/server.js.map +1 -1
- package/dist/src/browser/dashboard/ui.html +214 -1764
- package/dist/src/capabilities/index.d.ts +0 -2
- package/dist/src/capabilities/index.d.ts.map +1 -1
- package/dist/src/capabilities/index.js +0 -1
- package/dist/src/capabilities/index.js.map +1 -1
- package/dist/src/commands/agent-lifecycle.d.ts.map +1 -1
- package/dist/src/commands/agent-lifecycle.js +2 -6
- package/dist/src/commands/agent-lifecycle.js.map +1 -1
- package/dist/src/commands/analyze.d.ts +0 -4
- package/dist/src/commands/analyze.d.ts.map +1 -1
- package/dist/src/commands/analyze.js +1 -29
- package/dist/src/commands/analyze.js.map +1 -1
- package/dist/src/commands/completions.d.ts.map +1 -1
- package/dist/src/commands/completions.js +3 -22
- package/dist/src/commands/completions.js.map +1 -1
- package/dist/src/commands/config.d.ts.map +1 -1
- package/dist/src/commands/config.js +0 -6
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/doctor-project-checks.d.ts +12 -2
- package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
- package/dist/src/commands/doctor-project-checks.js +130 -22
- package/dist/src/commands/doctor-project-checks.js.map +1 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +6 -5
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/guidance.d.ts +5 -1
- package/dist/src/commands/guidance.d.ts.map +1 -1
- package/dist/src/commands/guidance.js +11 -556
- package/dist/src/commands/guidance.js.map +1 -1
- package/dist/src/commands/hive-mind-comms.d.ts.map +1 -1
- package/dist/src/commands/hive-mind-comms.js +11 -4
- package/dist/src/commands/hive-mind-comms.js.map +1 -1
- package/dist/src/commands/hive-mind.d.ts +4 -4
- package/dist/src/commands/hive-mind.d.ts.map +1 -1
- package/dist/src/commands/hive-mind.js +9 -6
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/hooks-formatting.d.ts +1 -5
- package/dist/src/commands/hooks-formatting.d.ts.map +1 -1
- package/dist/src/commands/hooks-formatting.js +1 -18
- package/dist/src/commands/hooks-formatting.js.map +1 -1
- package/dist/src/commands/hooks-workers.d.ts +1 -1
- package/dist/src/commands/hooks-workers.d.ts.map +1 -1
- package/dist/src/commands/hooks-workers.js +82 -330
- package/dist/src/commands/hooks-workers.js.map +1 -1
- package/dist/src/commands/index.d.ts +0 -5
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +0 -45
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/init-wizard.js +1 -1
- package/dist/src/commands/init-wizard.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +4 -24
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/neural-core.js +11 -11
- package/dist/src/commands/neural-core.js.map +1 -1
- package/dist/src/commands/neural-optimize.d.ts.map +1 -1
- package/dist/src/commands/neural-optimize.js +9 -11
- package/dist/src/commands/neural-optimize.js.map +1 -1
- package/dist/src/commands/neural-registry.js +10 -10
- package/dist/src/commands/neural-registry.js.map +1 -1
- package/dist/src/commands/providers.d.ts.map +1 -1
- package/dist/src/commands/providers.js +90 -1
- package/dist/src/commands/providers.js.map +1 -1
- package/dist/src/commands/search-universal.d.ts +7 -1
- package/dist/src/commands/search-universal.d.ts.map +1 -1
- package/dist/src/commands/search-universal.js +59 -5
- package/dist/src/commands/search-universal.js.map +1 -1
- package/dist/src/commands/security-cve.d.ts.map +1 -1
- package/dist/src/commands/security-cve.js +3 -5
- package/dist/src/commands/security-cve.js.map +1 -1
- package/dist/src/commands/session.d.ts.map +1 -1
- package/dist/src/commands/session.js +143 -3
- package/dist/src/commands/session.js.map +1 -1
- package/dist/src/commands/start.d.ts.map +1 -1
- package/dist/src/commands/start.js +0 -18
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/swarm.d.ts.map +1 -1
- package/dist/src/commands/swarm.js +112 -65
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/consensus/audit-writer.d.ts.map +1 -1
- package/dist/src/consensus/audit-writer.js +43 -1
- package/dist/src/consensus/audit-writer.js.map +1 -1
- package/dist/src/consensus/tally.d.ts +19 -0
- package/dist/src/consensus/tally.d.ts.map +1 -0
- package/dist/src/consensus/tally.js +34 -0
- package/dist/src/consensus/tally.js.map +1 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -12
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/claudemd-generator.d.ts.map +1 -1
- package/dist/src/init/claudemd-generator.js +10 -14
- package/dist/src/init/claudemd-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +39 -86
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +0 -12
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +62 -0
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/init/types.d.ts +2 -6
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/init/types.js +0 -3
- package/dist/src/init/types.js.map +1 -1
- package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +18 -8
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +0 -2
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-server.d.ts.map +1 -1
- package/dist/src/mcp-server.js +12 -14
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/coherence/coherence-check.d.ts.map +1 -1
- package/dist/src/mcp-tools/coherence/coherence-check.js +1 -19
- package/dist/src/mcp-tools/coherence/coherence-check.js.map +1 -1
- package/dist/src/mcp-tools/coherence/types.d.ts +3 -2
- package/dist/src/mcp-tools/coherence/types.d.ts.map +1 -1
- package/dist/src/mcp-tools/coherence/types.js +3 -18
- package/dist/src/mcp-tools/coherence/types.js.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.js +1 -7
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
- package/dist/src/mcp-tools/graphify-tools.js +2 -2
- package/dist/src/mcp-tools/graphify-tools.js.map +1 -1
- package/dist/src/mcp-tools/guidance-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/guidance-tools.js +7 -17
- package/dist/src/mcp-tools/guidance-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.js +174 -38
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-advanced.d.ts +18 -0
- package/dist/src/mcp-tools/hooks-advanced.d.ts.map +1 -0
- package/dist/src/mcp-tools/hooks-advanced.js +25 -0
- package/dist/src/mcp-tools/hooks-advanced.js.map +1 -0
- package/dist/src/mcp-tools/hooks-intelligence.d.ts +4 -8
- package/dist/src/mcp-tools/hooks-intelligence.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-intelligence.js +33 -482
- package/dist/src/mcp-tools/hooks-intelligence.js.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.d.ts +1 -0
- package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.js +51 -43
- package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
- package/dist/src/mcp-tools/hooks-synthesis.d.ts +31 -0
- package/dist/src/mcp-tools/hooks-synthesis.d.ts.map +1 -0
- package/dist/src/mcp-tools/hooks-synthesis.js +196 -0
- package/dist/src/mcp-tools/hooks-synthesis.js.map +1 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +10 -8
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +0 -1
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +0 -1
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +20 -29
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.d.ts +6 -0
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.js +78 -220
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
- package/dist/src/mcp-tools/neural-tools.d.ts +9 -4
- package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/neural-tools.js +242 -506
- package/dist/src/mcp-tools/neural-tools.js.map +1 -1
- package/dist/src/mcp-tools/security-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/security-tools.js +103 -0
- package/dist/src/mcp-tools/security-tools.js.map +1 -1
- package/dist/src/memory/intelligence.d.ts +2 -1
- package/dist/src/memory/intelligence.d.ts.map +1 -1
- package/dist/src/memory/intelligence.js +56 -43
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +14 -9
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-read.d.ts.map +1 -1
- package/dist/src/memory/memory-read.js +1 -19
- package/dist/src/memory/memory-read.js.map +1 -1
- package/dist/src/suggest.d.ts.map +1 -1
- package/dist/src/suggest.js +1 -7
- package/dist/src/suggest.js.map +1 -1
- package/dist/src/transfer/store/discovery.d.ts +3 -2
- package/dist/src/transfer/store/discovery.d.ts.map +1 -1
- package/dist/src/transfer/store/discovery.js +22 -70
- package/dist/src/transfer/store/discovery.js.map +1 -1
- package/dist/src/update/checker.d.ts.map +1 -1
- package/dist/src/update/checker.js +0 -1
- package/dist/src/update/checker.js.map +1 -1
- package/dist/src/utils/cosine-similarity.d.ts +22 -0
- package/dist/src/utils/cosine-similarity.d.ts.map +1 -0
- package/dist/src/utils/cosine-similarity.js +38 -0
- package/dist/src/utils/cosine-similarity.js.map +1 -0
- package/dist/src/utils/input-guards.d.ts +51 -0
- package/dist/src/utils/input-guards.d.ts.map +1 -0
- package/dist/src/utils/input-guards.js +223 -0
- package/dist/src/utils/input-guards.js.map +1 -0
- package/dist/src/utils/json-file.d.ts +33 -0
- package/dist/src/utils/json-file.d.ts.map +1 -0
- package/dist/src/utils/json-file.js +57 -0
- package/dist/src/utils/json-file.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -6
- package/scripts/sync-claude-assets.sh +16 -20
- package/.claude/agents/generated/case-analyst.md +0 -50
- package/.claude/agents/generated/channel-intelligence-director.md +0 -87
- package/.claude/agents/generated/chief-growth-officer.md +0 -88
- package/.claude/agents/generated/churn-analyst.md +0 -53
- package/.claude/agents/generated/code-reviewer.md +0 -55
- package/.claude/agents/generated/code-validator.md +0 -57
- package/.claude/agents/generated/complexity-scanner.md +0 -56
- package/.claude/agents/generated/content-seo-strategist.md +0 -90
- package/.claude/agents/generated/copy-editor.md +0 -45
- package/.claude/agents/generated/court-reporter.md +0 -50
- package/.claude/agents/generated/defender.md +0 -51
- package/.claude/agents/generated/devbot-orchestrator.md +0 -58
- package/.claude/agents/generated/devbot-planner.md +0 -63
- package/.claude/agents/generated/developer-community-strategist.md +0 -91
- package/.claude/agents/generated/editor-in-chief.md +0 -45
- package/.claude/agents/generated/fact-checker.md +0 -45
- package/.claude/agents/generated/impact-assessor.md +0 -54
- package/.claude/agents/generated/judge.md +0 -51
- package/.claude/agents/generated/outreach-partnership-strategist.md +0 -90
- package/.claude/agents/generated/prosecutor.md +0 -51
- package/.claude/agents/generated/reporter.md +0 -45
- package/.claude/agents/generated/social-media-strategist.md +0 -91
- package/.claude/agents/generated/video-visual-strategist.md +0 -90
- package/.claude/agents/reengineer-squad/boss.md +0 -113
- package/.claude/agents/reengineer-squad/critic-architect.md +0 -132
- package/.claude/agents/reengineer-squad/git-manager.md +0 -145
- package/.claude/agents/reengineer-squad/idea-generator.md +0 -95
- package/.claude/agents/reengineer-squad/implementer.md +0 -112
- package/.claude/agents/reengineer-squad/integration-planner.md +0 -112
- package/.claude/agents/reengineer-squad/source-analyst.md +0 -103
- package/.claude/agents/reengineer-squad/target-analyst.md +0 -118
- package/.claude/agents/reengineer-squad/tester.md +0 -105
- package/.claude/agents/sparc/architecture.md +0 -453
- package/.claude/agents/sparc/pseudocode.md +0 -299
- package/.claude/agents/sparc/refinement.md +0 -504
- package/.claude/agents/sparc/specification.md +0 -258
- package/.claude/agents/templates/implementer-sparc-coder.md +0 -231
- package/.claude/commands/sparc/analyzer.md +0 -35
- package/.claude/commands/sparc/architect.md +0 -36
- package/.claude/commands/sparc/ask.md +0 -56
- package/.claude/commands/sparc/batch-executor.md +0 -37
- package/.claude/commands/sparc/code.md +0 -48
- package/.claude/commands/sparc/coder.md +0 -37
- package/.claude/commands/sparc/debug.md +0 -42
- package/.claude/commands/sparc/debugger.md +0 -37
- package/.claude/commands/sparc/designer.md +0 -36
- package/.claude/commands/sparc/devops.md +0 -68
- package/.claude/commands/sparc/docs-writer.md +0 -39
- package/.claude/commands/sparc/documenter.md +0 -37
- package/.claude/commands/sparc/innovator.md +0 -37
- package/.claude/commands/sparc/integration.md +0 -42
- package/.claude/commands/sparc/mcp.md +0 -76
- package/.claude/commands/sparc/memory-manager.md +0 -57
- package/.claude/commands/sparc/optimizer.md +0 -37
- package/.claude/commands/sparc/orchestrator.md +0 -70
- package/.claude/commands/sparc/post-deployment-monitoring-mode.md +0 -42
- package/.claude/commands/sparc/refinement-optimization-mode.md +0 -42
- package/.claude/commands/sparc/researcher.md +0 -37
- package/.claude/commands/sparc/reviewer.md +0 -37
- package/.claude/commands/sparc/security-review.md +0 -39
- package/.claude/commands/sparc/sparc-modes.md +0 -120
- package/.claude/commands/sparc/sparc.md +0 -71
- package/.claude/commands/sparc/spec-pseudocode.md +0 -39
- package/.claude/commands/sparc/supabase-admin.md +0 -301
- package/.claude/commands/sparc/swarm-coordinator.md +0 -50
- package/.claude/commands/sparc/tdd.md +0 -37
- package/.claude/commands/sparc/tester.md +0 -37
- package/.claude/commands/sparc/tutorial.md +0 -38
- package/.claude/commands/sparc/workflow-manager.md +0 -37
- package/.claude/commands/sparc.md +0 -112
- package/.claude/skills/sparc-methodology/SKILL.md +0 -950
- package/dist/src/capabilities/enrichment.d.ts +0 -44
- package/dist/src/capabilities/enrichment.d.ts.map +0 -1
- package/dist/src/capabilities/enrichment.js +0 -141
- package/dist/src/capabilities/enrichment.js.map +0 -1
- package/dist/src/commands/analyze-boundaries.d.ts +0 -14
- package/dist/src/commands/analyze-boundaries.d.ts.map +0 -1
- package/dist/src/commands/analyze-boundaries.js +0 -295
- package/dist/src/commands/analyze-boundaries.js.map +0 -1
- package/dist/src/commands/analyze-graph.d.ts +0 -14
- package/dist/src/commands/analyze-graph.d.ts.map +0 -1
- package/dist/src/commands/analyze-graph.js +0 -304
- package/dist/src/commands/analyze-graph.js.map +0 -1
- package/dist/src/commands/claims.d.ts +0 -10
- package/dist/src/commands/claims.d.ts.map +0 -1
- package/dist/src/commands/claims.js +0 -650
- package/dist/src/commands/claims.js.map +0 -1
- package/dist/src/commands/daemon.d.ts +0 -8
- package/dist/src/commands/daemon.d.ts.map +0 -1
- package/dist/src/commands/daemon.js +0 -681
- package/dist/src/commands/daemon.js.map +0 -1
- package/dist/src/commands/enrich.d.ts +0 -10
- package/dist/src/commands/enrich.d.ts.map +0 -1
- package/dist/src/commands/enrich.js +0 -58
- package/dist/src/commands/enrich.js.map +0 -1
- package/dist/src/commands/issues.d.ts +0 -21
- package/dist/src/commands/issues.d.ts.map +0 -1
- package/dist/src/commands/issues.js +0 -575
- package/dist/src/commands/issues.js.map +0 -1
- package/dist/src/commands/workflow.d.ts +0 -8
- package/dist/src/commands/workflow.d.ts.map +0 -1
- package/dist/src/commands/workflow.js +0 -575
- package/dist/src/commands/workflow.js.map +0 -1
- package/dist/src/mcp-tools/workflow-tools.d.ts +0 -8
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +0 -1
- package/dist/src/mcp-tools/workflow-tools.js +0 -717
- package/dist/src/mcp-tools/workflow-tools.js.map +0 -1
- package/dist/src/services/claim-service.d.ts +0 -198
- package/dist/src/services/claim-service.d.ts.map +0 -1
- package/dist/src/services/claim-service.js +0 -890
- package/dist/src/services/claim-service.js.map +0 -1
- package/dist/src/services/headless-worker-executor.d.ts +0 -311
- package/dist/src/services/headless-worker-executor.d.ts.map +0 -1
- package/dist/src/services/headless-worker-executor.js +0 -1183
- package/dist/src/services/headless-worker-executor.js.map +0 -1
- package/dist/src/services/worker-daemon.d.ts +0 -230
- package/dist/src/services/worker-daemon.d.ts.map +0 -1
- package/dist/src/services/worker-daemon.js +0 -1350
- package/dist/src/services/worker-daemon.js.map +0 -1
- package/dist/src/ui/.monomind/capture/active-run.json +0 -1
- package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/real-events-1782290897.convs.jsonl +0 -3
- package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/real-events-1782290897.jsonl +0 -11
- package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/rigid-qa-restart-1782288201.jsonl +0 -540
- package/dist/src/ui/.monomind/orgs/system-trial-qa-threads.jsonl +0 -3
- package/dist/src/ui/.monomind/orgs/test-event-fix/runs/rigid-qa-restart-1782288201.jsonl +0 -2
|
@@ -1,717 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workflow MCP Tools for CLI
|
|
3
|
-
*
|
|
4
|
-
* Tool definitions for workflow automation and orchestration.
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, statSync } from 'node:fs';
|
|
7
|
-
import { join } from 'node:path';
|
|
8
|
-
import { randomBytes } from 'node:crypto';
|
|
9
|
-
import { getProjectCwd } from './types.js';
|
|
10
|
-
const MAX_WORKFLOW_STORE_BYTES = 50 * 1024 * 1024; // 50 MB
|
|
11
|
-
// Storage paths
|
|
12
|
-
const STORAGE_DIR = '.monomind';
|
|
13
|
-
const WORKFLOW_DIR = 'workflows';
|
|
14
|
-
const WORKFLOW_FILE = 'store.json';
|
|
15
|
-
function getWorkflowDir() {
|
|
16
|
-
return join(getProjectCwd(), STORAGE_DIR, WORKFLOW_DIR);
|
|
17
|
-
}
|
|
18
|
-
function getWorkflowPath() {
|
|
19
|
-
return join(getWorkflowDir(), WORKFLOW_FILE);
|
|
20
|
-
}
|
|
21
|
-
function ensureWorkflowDir() {
|
|
22
|
-
const dir = getWorkflowDir();
|
|
23
|
-
if (!existsSync(dir)) {
|
|
24
|
-
mkdirSync(dir, { recursive: true });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function loadWorkflowStore() {
|
|
28
|
-
try {
|
|
29
|
-
const path = getWorkflowPath();
|
|
30
|
-
if (existsSync(path)) {
|
|
31
|
-
if (statSync(path).size > MAX_WORKFLOW_STORE_BYTES) {
|
|
32
|
-
return { workflows: {}, templates: {}, version: '3.0.0' };
|
|
33
|
-
}
|
|
34
|
-
const data = readFileSync(path, 'utf-8');
|
|
35
|
-
return JSON.parse(data);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
// Return default store on error
|
|
40
|
-
}
|
|
41
|
-
return { workflows: {}, templates: {}, version: '3.0.0' };
|
|
42
|
-
}
|
|
43
|
-
function saveWorkflowStore(store) {
|
|
44
|
-
// Cap completed/failed/cancelled workflows so the file doesn't grow without
|
|
45
|
-
// bound. Each save serializes the entire store to disk; without eviction
|
|
46
|
-
// a long-running daemon would blow up to GBs of JSON.
|
|
47
|
-
const MAX_WORKFLOWS = 500;
|
|
48
|
-
const MAX_TEMPLATES = 200;
|
|
49
|
-
const TERMINAL = new Set(['completed', 'failed', 'cancelled']);
|
|
50
|
-
const finished = Object.entries(store.workflows ?? {})
|
|
51
|
-
.filter(([, w]) => TERMINAL.has(w.status ?? ''))
|
|
52
|
-
.sort(([, a], [, b]) => {
|
|
53
|
-
const aw = a;
|
|
54
|
-
const bw = b;
|
|
55
|
-
return (aw.completedAt ?? aw.createdAt ?? '').localeCompare(bw.completedAt ?? bw.createdAt ?? '');
|
|
56
|
-
});
|
|
57
|
-
if (finished.length > MAX_WORKFLOWS) {
|
|
58
|
-
for (const [id] of finished.slice(0, finished.length - MAX_WORKFLOWS)) {
|
|
59
|
-
delete store.workflows[id];
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
const templates = Object.keys(store.templates ?? {});
|
|
63
|
-
if (templates.length > MAX_TEMPLATES) {
|
|
64
|
-
for (const id of templates.slice(0, templates.length - MAX_TEMPLATES)) {
|
|
65
|
-
delete store.templates[id];
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
ensureWorkflowDir();
|
|
69
|
-
const dest = getWorkflowPath();
|
|
70
|
-
const tmp = `${dest}.${process.pid}.${Date.now()}.tmp`;
|
|
71
|
-
writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf-8');
|
|
72
|
-
renameSync(tmp, dest);
|
|
73
|
-
}
|
|
74
|
-
const FORBIDDEN_WORKFLOW_IDS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
75
|
-
export const workflowTools = [
|
|
76
|
-
{
|
|
77
|
-
name: 'workflow_run',
|
|
78
|
-
description: 'Create a swarm workflow stage record from a template (feature/bugfix/refactor/security). This tracks multi-agent orchestration stages — it does NOT execute a browser automation playbook. To run a playbook use `playbook_run`.',
|
|
79
|
-
category: 'workflow',
|
|
80
|
-
inputSchema: {
|
|
81
|
-
type: 'object',
|
|
82
|
-
properties: {
|
|
83
|
-
template: { type: 'string', description: 'Template name to run' },
|
|
84
|
-
file: { type: 'string', description: 'Workflow file path' },
|
|
85
|
-
task: { type: 'string', description: 'Task description' },
|
|
86
|
-
options: {
|
|
87
|
-
type: 'object',
|
|
88
|
-
description: 'Workflow options',
|
|
89
|
-
properties: {
|
|
90
|
-
parallel: { type: 'boolean', description: 'Run stages in parallel' },
|
|
91
|
-
maxAgents: { type: 'number', description: 'Maximum agents to use' },
|
|
92
|
-
timeout: { type: 'number', description: 'Timeout in seconds' },
|
|
93
|
-
dryRun: { type: 'boolean', description: 'Validate without executing' },
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
handler: async (input) => {
|
|
99
|
-
const store = loadWorkflowStore();
|
|
100
|
-
const template = input.template;
|
|
101
|
-
// Cap task description to prevent DoS via unbounded string stored in
|
|
102
|
-
// workflow record and serialised to disk.
|
|
103
|
-
const MAX_WORKFLOW_TASK_LEN = 16 * 1024;
|
|
104
|
-
const rawTask = input.task;
|
|
105
|
-
const task = typeof rawTask === 'string' && rawTask.length > MAX_WORKFLOW_TASK_LEN
|
|
106
|
-
? rawTask.slice(0, MAX_WORKFLOW_TASK_LEN) : rawTask;
|
|
107
|
-
const options = input.options || {};
|
|
108
|
-
const dryRun = options.dryRun;
|
|
109
|
-
// Build workflow from template or inline
|
|
110
|
-
const workflowId = `workflow-${Date.now()}-${randomBytes(6).toString('hex')}`;
|
|
111
|
-
const stages = [];
|
|
112
|
-
// Generate stages based on template
|
|
113
|
-
const templateName = template || 'custom';
|
|
114
|
-
const stageNames = (() => {
|
|
115
|
-
switch (templateName) {
|
|
116
|
-
case 'feature':
|
|
117
|
-
return ['Research', 'Design', 'Implement', 'Test', 'Review'];
|
|
118
|
-
case 'bugfix':
|
|
119
|
-
return ['Investigate', 'Fix', 'Test', 'Review'];
|
|
120
|
-
case 'refactor':
|
|
121
|
-
return ['Analyze', 'Refactor', 'Test', 'Review'];
|
|
122
|
-
case 'security':
|
|
123
|
-
return ['Scan', 'Analyze', 'Report'];
|
|
124
|
-
default:
|
|
125
|
-
return ['Execute'];
|
|
126
|
-
}
|
|
127
|
-
})();
|
|
128
|
-
for (const name of stageNames) {
|
|
129
|
-
stages.push({
|
|
130
|
-
name,
|
|
131
|
-
status: dryRun ? 'validated' : 'pending',
|
|
132
|
-
agents: [],
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
if (!dryRun) {
|
|
136
|
-
// Create and save the workflow
|
|
137
|
-
const steps = stageNames.map((name, i) => ({
|
|
138
|
-
stepId: `step-${i + 1}`,
|
|
139
|
-
name,
|
|
140
|
-
type: 'task',
|
|
141
|
-
config: { task: task || name },
|
|
142
|
-
status: 'pending',
|
|
143
|
-
}));
|
|
144
|
-
const workflow = {
|
|
145
|
-
workflowId,
|
|
146
|
-
name: task || `${templateName} workflow`,
|
|
147
|
-
description: task,
|
|
148
|
-
steps,
|
|
149
|
-
status: 'running',
|
|
150
|
-
currentStep: 0,
|
|
151
|
-
variables: { template: templateName, ...options },
|
|
152
|
-
createdAt: new Date().toISOString(),
|
|
153
|
-
startedAt: new Date().toISOString(),
|
|
154
|
-
};
|
|
155
|
-
store.workflows[workflowId] = workflow;
|
|
156
|
-
saveWorkflowStore(store);
|
|
157
|
-
}
|
|
158
|
-
return {
|
|
159
|
-
workflowId,
|
|
160
|
-
template: templateName,
|
|
161
|
-
status: dryRun ? 'validated' : 'running',
|
|
162
|
-
stages,
|
|
163
|
-
metrics: {
|
|
164
|
-
totalStages: stages.length,
|
|
165
|
-
completedStages: 0,
|
|
166
|
-
agentsSpawned: 0,
|
|
167
|
-
estimatedDuration: `${stages.length * 30}s`,
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
name: 'workflow_create',
|
|
174
|
-
description: 'Create a new workflow',
|
|
175
|
-
category: 'workflow',
|
|
176
|
-
inputSchema: {
|
|
177
|
-
type: 'object',
|
|
178
|
-
properties: {
|
|
179
|
-
name: { type: 'string', description: 'Workflow name' },
|
|
180
|
-
description: { type: 'string', description: 'Workflow description' },
|
|
181
|
-
steps: {
|
|
182
|
-
type: 'array',
|
|
183
|
-
description: 'Workflow steps',
|
|
184
|
-
items: {
|
|
185
|
-
type: 'object',
|
|
186
|
-
properties: {
|
|
187
|
-
name: { type: 'string' },
|
|
188
|
-
type: { type: 'string', enum: ['task', 'condition', 'parallel', 'loop', 'wait'] },
|
|
189
|
-
config: { type: 'object' },
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
variables: { type: 'object', description: 'Initial variables' },
|
|
194
|
-
},
|
|
195
|
-
required: ['name'],
|
|
196
|
-
},
|
|
197
|
-
handler: async (input) => {
|
|
198
|
-
const store = loadWorkflowStore();
|
|
199
|
-
const workflowId = `workflow-${Date.now()}-${randomBytes(6).toString('hex')}`;
|
|
200
|
-
// Cap string fields before storing to disk.
|
|
201
|
-
const MAX_WF_NAME_LEN = 512;
|
|
202
|
-
const MAX_WF_DESC_LEN = 16 * 1024;
|
|
203
|
-
const MAX_WF_STEPS = 500;
|
|
204
|
-
const rawWfName = input.name;
|
|
205
|
-
const wfName = typeof rawWfName === 'string' && rawWfName.length > MAX_WF_NAME_LEN
|
|
206
|
-
? rawWfName.slice(0, MAX_WF_NAME_LEN) : rawWfName;
|
|
207
|
-
const rawWfDesc = input.description;
|
|
208
|
-
const wfDesc = typeof rawWfDesc === 'string' && rawWfDesc.length > MAX_WF_DESC_LEN
|
|
209
|
-
? rawWfDesc.slice(0, MAX_WF_DESC_LEN) : rawWfDesc;
|
|
210
|
-
const rawSteps = input.steps || [];
|
|
211
|
-
const cappedSteps = rawSteps.slice(0, MAX_WF_STEPS);
|
|
212
|
-
const steps = cappedSteps.map((s, i) => ({
|
|
213
|
-
stepId: `step-${i + 1}`,
|
|
214
|
-
name: s.name || `Step ${i + 1}`,
|
|
215
|
-
type: s.type || 'task',
|
|
216
|
-
config: s.config || {},
|
|
217
|
-
status: 'pending',
|
|
218
|
-
}));
|
|
219
|
-
const workflow = {
|
|
220
|
-
workflowId,
|
|
221
|
-
name: wfName,
|
|
222
|
-
description: wfDesc,
|
|
223
|
-
steps,
|
|
224
|
-
status: steps.length > 0 ? 'ready' : 'draft',
|
|
225
|
-
currentStep: 0,
|
|
226
|
-
variables: input.variables || {},
|
|
227
|
-
createdAt: new Date().toISOString(),
|
|
228
|
-
};
|
|
229
|
-
store.workflows[workflowId] = workflow;
|
|
230
|
-
saveWorkflowStore(store);
|
|
231
|
-
return {
|
|
232
|
-
workflowId,
|
|
233
|
-
name: workflow.name,
|
|
234
|
-
status: workflow.status,
|
|
235
|
-
stepCount: steps.length,
|
|
236
|
-
createdAt: workflow.createdAt,
|
|
237
|
-
};
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
name: 'workflow_execute',
|
|
242
|
-
description: 'Execute a workflow',
|
|
243
|
-
category: 'workflow',
|
|
244
|
-
inputSchema: {
|
|
245
|
-
type: 'object',
|
|
246
|
-
properties: {
|
|
247
|
-
workflowId: { type: 'string', description: 'Workflow ID to execute' },
|
|
248
|
-
variables: { type: 'object', description: 'Runtime variables to inject' },
|
|
249
|
-
startFromStep: { type: 'number', description: 'Step to start from (0-indexed)' },
|
|
250
|
-
},
|
|
251
|
-
required: ['workflowId'],
|
|
252
|
-
},
|
|
253
|
-
handler: async (input) => {
|
|
254
|
-
const workflowId = input.workflowId;
|
|
255
|
-
if (!workflowId || typeof workflowId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(workflowId)) {
|
|
256
|
-
return { workflowId, error: 'Workflow not found' };
|
|
257
|
-
}
|
|
258
|
-
const store = loadWorkflowStore();
|
|
259
|
-
// Object.hasOwn defends against bracket-access into Object.prototype
|
|
260
|
-
// members (toString, hasOwnProperty, etc.) — the FORBIDDEN_WORKFLOW_IDS
|
|
261
|
-
// blocklist alone misses these inherited names.
|
|
262
|
-
const workflow = Object.hasOwn(store.workflows, workflowId)
|
|
263
|
-
? store.workflows[workflowId]
|
|
264
|
-
: undefined;
|
|
265
|
-
if (!workflow) {
|
|
266
|
-
return { workflowId, error: 'Workflow not found' };
|
|
267
|
-
}
|
|
268
|
-
if (workflow.status === 'running') {
|
|
269
|
-
return { workflowId, error: 'Workflow already running' };
|
|
270
|
-
}
|
|
271
|
-
// Inject runtime variables
|
|
272
|
-
if (input.variables) {
|
|
273
|
-
workflow.variables = { ...workflow.variables, ...input.variables };
|
|
274
|
-
}
|
|
275
|
-
workflow.status = 'running';
|
|
276
|
-
workflow.startedAt = new Date().toISOString();
|
|
277
|
-
workflow.currentStep = input.startFromStep || 0;
|
|
278
|
-
// Set steps to pending — actual execution requires agent assignment via task tools
|
|
279
|
-
const results = [];
|
|
280
|
-
for (let i = workflow.currentStep; i < workflow.steps.length; i++) {
|
|
281
|
-
const step = workflow.steps[i];
|
|
282
|
-
step.status = 'pending';
|
|
283
|
-
results.push({
|
|
284
|
-
stepId: step.stepId,
|
|
285
|
-
status: step.status,
|
|
286
|
-
_note: 'Workflow execution tracks state. Actual step execution requires agent assignment via task tools.',
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
saveWorkflowStore(store);
|
|
290
|
-
return {
|
|
291
|
-
workflowId,
|
|
292
|
-
status: workflow.status,
|
|
293
|
-
totalSteps: results.length,
|
|
294
|
-
results,
|
|
295
|
-
startedAt: workflow.startedAt,
|
|
296
|
-
_note: 'Workflow is now running. Steps are in pending state and must be executed via task tools.',
|
|
297
|
-
};
|
|
298
|
-
},
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
name: 'workflow_status',
|
|
302
|
-
description: 'Get workflow status',
|
|
303
|
-
category: 'workflow',
|
|
304
|
-
inputSchema: {
|
|
305
|
-
type: 'object',
|
|
306
|
-
properties: {
|
|
307
|
-
workflowId: { type: 'string', description: 'Workflow ID' },
|
|
308
|
-
verbose: { type: 'boolean', description: 'Include step details' },
|
|
309
|
-
},
|
|
310
|
-
required: ['workflowId'],
|
|
311
|
-
},
|
|
312
|
-
handler: async (input) => {
|
|
313
|
-
const workflowId = input.workflowId;
|
|
314
|
-
if (!workflowId || typeof workflowId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(workflowId)) {
|
|
315
|
-
return { workflowId, error: 'Workflow not found' };
|
|
316
|
-
}
|
|
317
|
-
const store = loadWorkflowStore();
|
|
318
|
-
const workflow = Object.hasOwn(store.workflows, workflowId) ? store.workflows[workflowId] : undefined;
|
|
319
|
-
if (!workflow) {
|
|
320
|
-
return { workflowId, error: 'Workflow not found' };
|
|
321
|
-
}
|
|
322
|
-
const completedSteps = workflow.steps.filter(s => s.status === 'completed').length;
|
|
323
|
-
const progress = workflow.steps.length > 0 ? (completedSteps / workflow.steps.length) * 100 : 0;
|
|
324
|
-
const status = {
|
|
325
|
-
workflowId: workflow.workflowId,
|
|
326
|
-
name: workflow.name,
|
|
327
|
-
status: workflow.status,
|
|
328
|
-
progress,
|
|
329
|
-
currentStep: workflow.currentStep,
|
|
330
|
-
totalSteps: workflow.steps.length,
|
|
331
|
-
completedSteps,
|
|
332
|
-
createdAt: workflow.createdAt,
|
|
333
|
-
startedAt: workflow.startedAt,
|
|
334
|
-
completedAt: workflow.completedAt,
|
|
335
|
-
};
|
|
336
|
-
if (input.verbose) {
|
|
337
|
-
return {
|
|
338
|
-
...status,
|
|
339
|
-
description: workflow.description,
|
|
340
|
-
variables: workflow.variables,
|
|
341
|
-
steps: workflow.steps.map(s => ({
|
|
342
|
-
stepId: s.stepId,
|
|
343
|
-
name: s.name,
|
|
344
|
-
type: s.type,
|
|
345
|
-
status: s.status,
|
|
346
|
-
startedAt: s.startedAt,
|
|
347
|
-
completedAt: s.completedAt,
|
|
348
|
-
})),
|
|
349
|
-
error: workflow.error,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
return status;
|
|
353
|
-
},
|
|
354
|
-
},
|
|
355
|
-
{
|
|
356
|
-
name: 'workflow_list',
|
|
357
|
-
description: 'List all workflows',
|
|
358
|
-
category: 'workflow',
|
|
359
|
-
inputSchema: {
|
|
360
|
-
type: 'object',
|
|
361
|
-
properties: {
|
|
362
|
-
status: { type: 'string', description: 'Filter by status' },
|
|
363
|
-
limit: { type: 'number', description: 'Max workflows to return' },
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
handler: async (input) => {
|
|
367
|
-
const store = loadWorkflowStore();
|
|
368
|
-
let workflows = Object.values(store.workflows);
|
|
369
|
-
// Apply filters
|
|
370
|
-
if (input.status) {
|
|
371
|
-
workflows = workflows.filter(w => w.status === input.status);
|
|
372
|
-
}
|
|
373
|
-
// Sort by creation date (newest first)
|
|
374
|
-
workflows.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
375
|
-
// Apply limit — cap to 1 000 to prevent returning the full (potentially
|
|
376
|
-
// large) in-memory workflow store in one response, which could cause OOM
|
|
377
|
-
// or excessive serialisation latency.
|
|
378
|
-
const MAX_WORKFLOW_LIMIT = 1_000;
|
|
379
|
-
const rawLimit = typeof input.limit === 'number' ? input.limit : 20;
|
|
380
|
-
const limit = Number.isFinite(rawLimit) && rawLimit > 0
|
|
381
|
-
? Math.min(Math.floor(rawLimit), MAX_WORKFLOW_LIMIT)
|
|
382
|
-
: 20;
|
|
383
|
-
const totalCount = workflows.length;
|
|
384
|
-
workflows = workflows.slice(0, limit);
|
|
385
|
-
return {
|
|
386
|
-
workflows: workflows.map(w => ({
|
|
387
|
-
workflowId: w.workflowId,
|
|
388
|
-
name: w.name,
|
|
389
|
-
status: w.status,
|
|
390
|
-
stepCount: w.steps.length,
|
|
391
|
-
createdAt: w.createdAt,
|
|
392
|
-
completedAt: w.completedAt,
|
|
393
|
-
})),
|
|
394
|
-
total: totalCount,
|
|
395
|
-
filters: { status: input.status },
|
|
396
|
-
};
|
|
397
|
-
},
|
|
398
|
-
},
|
|
399
|
-
{
|
|
400
|
-
name: 'workflow_pause',
|
|
401
|
-
description: 'Pause a running workflow',
|
|
402
|
-
category: 'workflow',
|
|
403
|
-
inputSchema: {
|
|
404
|
-
type: 'object',
|
|
405
|
-
properties: {
|
|
406
|
-
workflowId: { type: 'string', description: 'Workflow ID' },
|
|
407
|
-
},
|
|
408
|
-
required: ['workflowId'],
|
|
409
|
-
},
|
|
410
|
-
handler: async (input) => {
|
|
411
|
-
const workflowId = input.workflowId;
|
|
412
|
-
if (!workflowId || typeof workflowId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(workflowId)) {
|
|
413
|
-
return { workflowId, error: 'Workflow not found' };
|
|
414
|
-
}
|
|
415
|
-
const store = loadWorkflowStore();
|
|
416
|
-
const workflow = Object.hasOwn(store.workflows, workflowId) ? store.workflows[workflowId] : undefined;
|
|
417
|
-
if (!workflow) {
|
|
418
|
-
return { workflowId, error: 'Workflow not found' };
|
|
419
|
-
}
|
|
420
|
-
if (workflow.status !== 'running') {
|
|
421
|
-
return { workflowId, error: 'Workflow not running' };
|
|
422
|
-
}
|
|
423
|
-
workflow.status = 'paused';
|
|
424
|
-
saveWorkflowStore(store);
|
|
425
|
-
return {
|
|
426
|
-
workflowId,
|
|
427
|
-
status: workflow.status,
|
|
428
|
-
pausedAt: new Date().toISOString(),
|
|
429
|
-
currentStep: workflow.currentStep,
|
|
430
|
-
};
|
|
431
|
-
},
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
name: 'workflow_resume',
|
|
435
|
-
description: 'Resume a paused workflow',
|
|
436
|
-
category: 'workflow',
|
|
437
|
-
inputSchema: {
|
|
438
|
-
type: 'object',
|
|
439
|
-
properties: {
|
|
440
|
-
workflowId: { type: 'string', description: 'Workflow ID' },
|
|
441
|
-
},
|
|
442
|
-
required: ['workflowId'],
|
|
443
|
-
},
|
|
444
|
-
handler: async (input) => {
|
|
445
|
-
const workflowId = input.workflowId;
|
|
446
|
-
if (!workflowId || typeof workflowId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(workflowId)) {
|
|
447
|
-
return { workflowId, error: 'Workflow not found' };
|
|
448
|
-
}
|
|
449
|
-
const store = loadWorkflowStore();
|
|
450
|
-
const workflow = Object.hasOwn(store.workflows, workflowId) ? store.workflows[workflowId] : undefined;
|
|
451
|
-
if (!workflow) {
|
|
452
|
-
return { workflowId, error: 'Workflow not found' };
|
|
453
|
-
}
|
|
454
|
-
if (workflow.status !== 'paused') {
|
|
455
|
-
return { workflowId, error: 'Workflow not paused' };
|
|
456
|
-
}
|
|
457
|
-
workflow.status = 'running';
|
|
458
|
-
saveWorkflowStore(store);
|
|
459
|
-
// Report current step states — do not auto-complete them
|
|
460
|
-
const stepStates = workflow.steps.map(step => ({
|
|
461
|
-
stepId: step.stepId,
|
|
462
|
-
name: step.name,
|
|
463
|
-
status: step.status,
|
|
464
|
-
}));
|
|
465
|
-
const remainingSteps = workflow.steps.length - workflow.currentStep;
|
|
466
|
-
return {
|
|
467
|
-
workflowId,
|
|
468
|
-
status: workflow.status,
|
|
469
|
-
resumed: true,
|
|
470
|
-
currentStep: workflow.currentStep,
|
|
471
|
-
remainingSteps,
|
|
472
|
-
steps: stepStates,
|
|
473
|
-
_note: 'Workflow resumed. Steps remain in their current state and must be executed via task tools.',
|
|
474
|
-
};
|
|
475
|
-
},
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
name: 'workflow_cancel',
|
|
479
|
-
description: 'Cancel a workflow',
|
|
480
|
-
category: 'workflow',
|
|
481
|
-
inputSchema: {
|
|
482
|
-
type: 'object',
|
|
483
|
-
properties: {
|
|
484
|
-
workflowId: { type: 'string', description: 'Workflow ID' },
|
|
485
|
-
reason: { type: 'string', description: 'Cancellation reason' },
|
|
486
|
-
},
|
|
487
|
-
required: ['workflowId'],
|
|
488
|
-
},
|
|
489
|
-
handler: async (input) => {
|
|
490
|
-
const workflowId = input.workflowId;
|
|
491
|
-
if (!workflowId || typeof workflowId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(workflowId)) {
|
|
492
|
-
return { workflowId, error: 'Workflow not found' };
|
|
493
|
-
}
|
|
494
|
-
const store = loadWorkflowStore();
|
|
495
|
-
const workflow = Object.hasOwn(store.workflows, workflowId)
|
|
496
|
-
? store.workflows[workflowId]
|
|
497
|
-
: undefined;
|
|
498
|
-
if (!workflow) {
|
|
499
|
-
return { workflowId, error: 'Workflow not found' };
|
|
500
|
-
}
|
|
501
|
-
if (workflow.status === 'completed' || workflow.status === 'failed' || workflow.status === 'cancelled') {
|
|
502
|
-
return { workflowId, error: 'Workflow already finished' };
|
|
503
|
-
}
|
|
504
|
-
workflow.status = 'cancelled';
|
|
505
|
-
workflow.error = input.reason || 'Cancelled by user';
|
|
506
|
-
workflow.completedAt = new Date().toISOString();
|
|
507
|
-
// Mark remaining steps as skipped
|
|
508
|
-
for (let i = workflow.currentStep; i < workflow.steps.length; i++) {
|
|
509
|
-
workflow.steps[i].status = 'skipped';
|
|
510
|
-
}
|
|
511
|
-
saveWorkflowStore(store);
|
|
512
|
-
return {
|
|
513
|
-
workflowId,
|
|
514
|
-
status: workflow.status,
|
|
515
|
-
cancelledAt: workflow.completedAt,
|
|
516
|
-
reason: workflow.error,
|
|
517
|
-
skippedSteps: workflow.steps.length - workflow.currentStep,
|
|
518
|
-
};
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
{
|
|
522
|
-
name: 'workflow_delete',
|
|
523
|
-
description: 'Delete a workflow',
|
|
524
|
-
category: 'workflow',
|
|
525
|
-
inputSchema: {
|
|
526
|
-
type: 'object',
|
|
527
|
-
properties: {
|
|
528
|
-
workflowId: { type: 'string', description: 'Workflow ID' },
|
|
529
|
-
},
|
|
530
|
-
required: ['workflowId'],
|
|
531
|
-
},
|
|
532
|
-
handler: async (input) => {
|
|
533
|
-
const workflowId = input.workflowId;
|
|
534
|
-
if (!workflowId || typeof workflowId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(workflowId)) {
|
|
535
|
-
return { workflowId, error: 'Workflow not found' };
|
|
536
|
-
}
|
|
537
|
-
const store = loadWorkflowStore();
|
|
538
|
-
if (!Object.hasOwn(store.workflows, workflowId)) {
|
|
539
|
-
return { workflowId, error: 'Workflow not found' };
|
|
540
|
-
}
|
|
541
|
-
const workflow = store.workflows[workflowId];
|
|
542
|
-
if (workflow.status === 'running') {
|
|
543
|
-
return { workflowId, error: 'Cannot delete running workflow' };
|
|
544
|
-
}
|
|
545
|
-
delete store.workflows[workflowId];
|
|
546
|
-
saveWorkflowStore(store);
|
|
547
|
-
return {
|
|
548
|
-
workflowId,
|
|
549
|
-
deleted: true,
|
|
550
|
-
deletedAt: new Date().toISOString(),
|
|
551
|
-
};
|
|
552
|
-
},
|
|
553
|
-
},
|
|
554
|
-
{
|
|
555
|
-
name: 'workflow_template',
|
|
556
|
-
description: 'Save workflow as template or create from template',
|
|
557
|
-
category: 'workflow',
|
|
558
|
-
inputSchema: {
|
|
559
|
-
type: 'object',
|
|
560
|
-
properties: {
|
|
561
|
-
action: { type: 'string', enum: ['save', 'create', 'list'], description: 'Template action' },
|
|
562
|
-
workflowId: { type: 'string', description: 'Workflow ID (for save)' },
|
|
563
|
-
templateId: { type: 'string', description: 'Template ID (for create)' },
|
|
564
|
-
templateName: { type: 'string', description: 'Template name (for save)' },
|
|
565
|
-
newName: { type: 'string', description: 'New workflow name (for create)' },
|
|
566
|
-
},
|
|
567
|
-
required: ['action'],
|
|
568
|
-
},
|
|
569
|
-
handler: async (input) => {
|
|
570
|
-
const store = loadWorkflowStore();
|
|
571
|
-
const action = input.action;
|
|
572
|
-
if (action === 'save') {
|
|
573
|
-
const rawWorkflowId = input.workflowId;
|
|
574
|
-
if (!rawWorkflowId || typeof rawWorkflowId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(rawWorkflowId) || !Object.hasOwn(store.workflows, rawWorkflowId)) {
|
|
575
|
-
return { action, error: 'Workflow not found' };
|
|
576
|
-
}
|
|
577
|
-
const workflow = store.workflows[rawWorkflowId];
|
|
578
|
-
if (!workflow) {
|
|
579
|
-
return { action, error: 'Workflow not found' };
|
|
580
|
-
}
|
|
581
|
-
const templateId = `template-${Date.now()}-${randomBytes(6).toString('hex')}`;
|
|
582
|
-
const template = {
|
|
583
|
-
...workflow,
|
|
584
|
-
workflowId: templateId,
|
|
585
|
-
name: input.templateName || `${workflow.name} Template`,
|
|
586
|
-
status: 'draft',
|
|
587
|
-
currentStep: 0,
|
|
588
|
-
createdAt: new Date().toISOString(),
|
|
589
|
-
startedAt: undefined,
|
|
590
|
-
completedAt: undefined,
|
|
591
|
-
};
|
|
592
|
-
// Reset step statuses
|
|
593
|
-
template.steps = template.steps.map(s => ({
|
|
594
|
-
...s,
|
|
595
|
-
status: 'pending',
|
|
596
|
-
result: undefined,
|
|
597
|
-
startedAt: undefined,
|
|
598
|
-
completedAt: undefined,
|
|
599
|
-
}));
|
|
600
|
-
store.templates[templateId] = template;
|
|
601
|
-
saveWorkflowStore(store);
|
|
602
|
-
return {
|
|
603
|
-
action,
|
|
604
|
-
templateId,
|
|
605
|
-
name: template.name,
|
|
606
|
-
savedAt: new Date().toISOString(),
|
|
607
|
-
};
|
|
608
|
-
}
|
|
609
|
-
if (action === 'create') {
|
|
610
|
-
const rawTemplateId = input.templateId;
|
|
611
|
-
if (!rawTemplateId || typeof rawTemplateId !== 'string' || FORBIDDEN_WORKFLOW_IDS.has(rawTemplateId) || !Object.hasOwn(store.templates, rawTemplateId)) {
|
|
612
|
-
return { action, error: 'Template not found' };
|
|
613
|
-
}
|
|
614
|
-
const template = store.templates[rawTemplateId];
|
|
615
|
-
if (!template) {
|
|
616
|
-
return { action, error: 'Template not found' };
|
|
617
|
-
}
|
|
618
|
-
const workflowId = `workflow-${Date.now()}-${randomBytes(6).toString('hex')}`;
|
|
619
|
-
const workflow = {
|
|
620
|
-
...template,
|
|
621
|
-
workflowId,
|
|
622
|
-
name: input.newName || template.name.replace(' Template', ''),
|
|
623
|
-
status: 'ready',
|
|
624
|
-
createdAt: new Date().toISOString(),
|
|
625
|
-
steps: template.steps.map(s => ({ ...s, status: 'pending', result: undefined })),
|
|
626
|
-
variables: { ...template.variables },
|
|
627
|
-
};
|
|
628
|
-
store.workflows[workflowId] = workflow;
|
|
629
|
-
saveWorkflowStore(store);
|
|
630
|
-
return {
|
|
631
|
-
action,
|
|
632
|
-
workflowId,
|
|
633
|
-
name: workflow.name,
|
|
634
|
-
fromTemplate: input.templateId,
|
|
635
|
-
createdAt: workflow.createdAt,
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
if (action === 'list') {
|
|
639
|
-
return {
|
|
640
|
-
action,
|
|
641
|
-
templates: Object.values(store.templates).map(t => ({
|
|
642
|
-
templateId: t.workflowId,
|
|
643
|
-
name: t.name,
|
|
644
|
-
stepCount: t.steps.length,
|
|
645
|
-
createdAt: t.createdAt,
|
|
646
|
-
})),
|
|
647
|
-
total: Object.keys(store.templates).length,
|
|
648
|
-
};
|
|
649
|
-
}
|
|
650
|
-
return { action, error: 'Unknown action' };
|
|
651
|
-
},
|
|
652
|
-
},
|
|
653
|
-
{
|
|
654
|
-
name: 'playbook_run',
|
|
655
|
-
description: 'Run a browser automation playbook (JSON file with browser/service/HTTP nodes) via @monoes/monobrowse. Executes the full playbook engine with all handlers: browser CDP nodes (browser.open, browser.click, etc.), service nodes (gmail, github, google_drive, google_sheets), and builtins (action.http, action.log, action.save_file, action.gemini_image).',
|
|
656
|
-
category: 'workflow',
|
|
657
|
-
inputSchema: {
|
|
658
|
-
type: 'object',
|
|
659
|
-
properties: {
|
|
660
|
-
file: { type: 'string', description: 'Absolute or CWD-relative path to a playbook JSON file' },
|
|
661
|
-
params: {
|
|
662
|
-
type: 'object',
|
|
663
|
-
description: 'Key/value pairs substituted as {{params.key}} in playbook node configs',
|
|
664
|
-
additionalProperties: { type: 'string' },
|
|
665
|
-
},
|
|
666
|
-
port: { type: 'number', description: 'CDP port for browser automation (default 9222)' },
|
|
667
|
-
timeoutSeconds: { type: 'number', description: 'Max run duration in seconds (default 300)' },
|
|
668
|
-
},
|
|
669
|
-
required: ['file'],
|
|
670
|
-
},
|
|
671
|
-
handler: async (input) => {
|
|
672
|
-
const filePath = input.file;
|
|
673
|
-
if (typeof filePath !== 'string' || !filePath)
|
|
674
|
-
throw new Error('playbook_run: file is required');
|
|
675
|
-
if (filePath.startsWith('-'))
|
|
676
|
-
throw new Error('playbook_run: file path must not start with "-"');
|
|
677
|
-
const { resolve } = await import('node:path');
|
|
678
|
-
const absPath = resolve(process.cwd(), filePath);
|
|
679
|
-
const timeoutMs = (input.timeoutSeconds ?? 300) * 1000;
|
|
680
|
-
const rawParams = input.params ?? {};
|
|
681
|
-
// Sanitize params — string values only
|
|
682
|
-
const params = Object.fromEntries(Object.entries(rawParams).map(([k, v]) => [k, String(v)]));
|
|
683
|
-
const { spawn } = await import('node:child_process');
|
|
684
|
-
const _args = ['run', '--file', absPath, '--json'];
|
|
685
|
-
for (const [k, v] of Object.entries(params))
|
|
686
|
-
_args.push('--param', `${k}=${v}`);
|
|
687
|
-
const env = { ...process.env };
|
|
688
|
-
if (input.port !== undefined)
|
|
689
|
-
env['CDP_PORT'] = String(input.port);
|
|
690
|
-
const record = await new Promise((resolve) => {
|
|
691
|
-
const child = spawn('monoes', _args, { env });
|
|
692
|
-
let stdout = '';
|
|
693
|
-
let stderr = '';
|
|
694
|
-
child.stdout?.on('data', (d) => { stdout += d; });
|
|
695
|
-
child.stderr?.on('data', (d) => { stderr += d; });
|
|
696
|
-
const _kill = setTimeout(() => { child.kill(); resolve({ status: 'timeout', error: `Timed out after ${timeoutMs}ms` }); }, timeoutMs);
|
|
697
|
-
child.on('close', (code) => {
|
|
698
|
-
clearTimeout(_kill);
|
|
699
|
-
if (code === 0) {
|
|
700
|
-
try {
|
|
701
|
-
resolve({ status: 'complete', output: JSON.parse(stdout) });
|
|
702
|
-
}
|
|
703
|
-
catch {
|
|
704
|
-
resolve({ status: 'complete', output: stdout.trim() });
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
else {
|
|
708
|
-
resolve({ status: 'failed', error: (stderr.trim() || stdout.trim()) });
|
|
709
|
-
}
|
|
710
|
-
});
|
|
711
|
-
child.on('error', (e) => { clearTimeout(_kill); resolve({ status: 'failed', error: e.message }); });
|
|
712
|
-
});
|
|
713
|
-
return record;
|
|
714
|
-
},
|
|
715
|
-
},
|
|
716
|
-
];
|
|
717
|
-
//# sourceMappingURL=workflow-tools.js.map
|