monomind 1.14.6 → 1.15.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/reengineer-squad/boss.md +113 -0
- package/.claude/agents/reengineer-squad/critic-architect.md +132 -0
- package/.claude/agents/reengineer-squad/git-manager.md +145 -0
- package/.claude/agents/reengineer-squad/idea-generator.md +95 -0
- package/.claude/agents/reengineer-squad/implementer.md +112 -0
- package/.claude/agents/reengineer-squad/integration-planner.md +112 -0
- package/.claude/agents/reengineer-squad/source-analyst.md +103 -0
- package/.claude/agents/reengineer-squad/target-analyst.md +118 -0
- package/.claude/agents/reengineer-squad/tester.md +105 -0
- package/.claude/commands/mastermind/master.md +35 -14
- package/.claude/helpers/handlers/capture-handler.cjs +155 -18
- package/.claude/helpers/monolean-activate.cjs +20 -0
- package/.claude/helpers/monolean-config.cjs +76 -0
- package/.claude/helpers/monolean-instructions.cjs +109 -0
- package/.claude/helpers/monolean-propagate.cjs +9 -0
- package/.claude/helpers/monolean-tracker.cjs +18 -0
- package/.claude/helpers/skill-registry.json +2 -2
- package/.claude/settings.json +34 -2
- package/.claude/skills/agent-browser-testing/SKILL.md +301 -18
- package/.claude/skills/mastermind/runorg.md +69 -23
- package/.claude/skills/monodesign/SKILL.md +32 -1
- package/.claude/skills/monodesign/adapt.md +53 -0
- package/.claude/skills/monodesign/agents/monodesign-asset-producer.md +100 -0
- package/.claude/skills/monodesign/animate.md +65 -0
- package/.claude/skills/monodesign/audit.md +89 -0
- package/.claude/skills/monodesign/bolder.md +50 -0
- package/.claude/skills/monodesign/clarify.md +64 -0
- package/.claude/skills/monodesign/colorize.md +68 -0
- package/.claude/skills/monodesign/craft.md +51 -0
- package/.claude/skills/monodesign/critique.md +66 -0
- package/.claude/skills/monodesign/delight.md +47 -0
- package/.claude/skills/monodesign/distill.md +56 -0
- package/.claude/skills/monodesign/document.md +80 -0
- package/.claude/skills/monodesign/extract.md +74 -0
- package/.claude/skills/monodesign/harden.md +65 -0
- package/.claude/skills/monodesign/live.md +59 -0
- package/.claude/skills/monodesign/onboard.md +50 -0
- package/.claude/skills/monodesign/optimize.md +64 -0
- package/.claude/skills/monodesign/overdrive.md +56 -0
- package/.claude/skills/monodesign/polish.md +68 -0
- package/.claude/skills/monodesign/quieter.md +57 -0
- package/.claude/skills/monodesign/reference/antipatterns-catalog.md +248 -76
- package/.claude/skills/monodesign/reference/codex.md +107 -0
- package/.claude/skills/monodesign/reference/craft.md +3 -0
- package/.claude/skills/monodesign/reference/hooks.md +99 -0
- package/.claude/skills/monodesign/reference/image-prompts.md +12 -0
- package/.claude/skills/monodesign/shape.md +71 -0
- package/.claude/skills/monodesign/teach.md +69 -0
- package/.claude/skills/monodesign/typeset.md +59 -0
- package/.claude/skills/monolean/SKILL.md +118 -0
- package/.claude/skills/monolean-audit/SKILL.md +41 -0
- package/.claude/skills/monolean-debt/SKILL.md +46 -0
- package/.claude/skills/monolean-help/SKILL.md +60 -0
- package/.claude/skills/monolean-review/SKILL.md +57 -0
- package/package.json +8 -2
- package/packages/@monomind/cli/bin/cli.js +3 -1
- package/packages/@monomind/cli/dist/dashboard/server.js +137 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-adapters.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-adapters.test.js +51 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.js +68 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-builtin-handlers.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-builtin-handlers.test.js +139 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-cdp.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-cdp.test.js +169 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-dashboard.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-dashboard.test.js +179 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-engine.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-engine.test.js +122 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-expression.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-expression.test.js +54 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-store.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-store.test.js +99 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-workflow-types.test.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-workflow-types.test.js +33 -0
- package/packages/@monomind/cli/dist/src/browser/action-builder/analyzer.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/browser/action-builder/analyzer.js +71 -0
- package/packages/@monomind/cli/dist/src/browser/action-builder/types.d.ts +47 -0
- package/packages/@monomind/cli/dist/src/browser/action-builder/types.js +2 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/gemini.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/gemini.js +16 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/google.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/google.js +17 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/index.d.ts +19 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/index.js +23 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/instagram.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/instagram.js +17 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/linkedin.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/linkedin.js +19 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/microsoft.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/microsoft.js +16 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/x.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/browser/adapters/x.js +19 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/api-types.d.ts +50 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/api-types.js +14 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/server.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +62 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +1811 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/builtin-handlers.d.ts +3 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/builtin-handlers.js +343 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/engine.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/engine.js +127 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/expression.d.ts +4 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/expression.js +64 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/store.d.ts +24 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/store.js +145 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/types.d.ts +48 -0
- package/packages/@monomind/cli/dist/src/browser/workflow/types.js +2 -0
- package/packages/@monomind/cli/dist/src/commands/browse-action.d.ts +4 -0
- package/packages/@monomind/cli/dist/src/commands/browse-action.js +151 -0
- package/packages/@monomind/cli/dist/src/commands/browse-platform.d.ts +4 -0
- package/packages/@monomind/cli/dist/src/commands/browse-platform.js +117 -0
- package/packages/@monomind/cli/dist/src/commands/browse-workflow.d.ts +4 -0
- package/packages/@monomind/cli/dist/src/commands/browse-workflow.js +153 -0
- package/packages/@monomind/cli/dist/src/commands/browse.d.ts +10 -6
- package/packages/@monomind/cli/dist/src/commands/browse.js +11 -2154
- package/packages/@monomind/cli/dist/src/commands/design-detect.d.ts +21 -0
- package/packages/@monomind/cli/dist/src/commands/design-detect.js +127 -0
- package/packages/@monomind/cli/dist/src/commands/design-palette.d.ts +22 -0
- package/packages/@monomind/cli/dist/src/commands/design-palette.js +539 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-core-commands.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-core-commands.js +377 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +1217 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-utils.d.ts +42 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-utils.js +220 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-extended-commands.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-extended-commands.js +579 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-formatting.d.ts +13 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-formatting.js +42 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-routing-commands.d.ts +15 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-routing-commands.js +723 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-workers.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-workers.js +782 -0
- package/packages/@monomind/cli/dist/src/commands/hooks.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/hooks.js +179 -4103
- package/packages/@monomind/cli/dist/src/commands/index.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/commands/index.js +6 -0
- package/packages/@monomind/cli/dist/src/commands/org.js +14 -15
- package/packages/@monomind/cli/dist/src/commands/tokens.js +77 -1
- package/packages/@monomind/cli/dist/src/graph/enrich.mjs +362 -0
- package/packages/@monomind/cli/dist/src/init/executor.js +18 -8
- package/packages/@monomind/cli/dist/src/init/settings-generator.js +39 -5
- package/packages/@monomind/cli/dist/src/init/statusline-generator.js +25 -5
- package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.d.ts +3 -5
- package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +619 -326
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-embedding.d.ts +161 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-embedding.js +506 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.d.ts +26 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.js +1328 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.d.ts +27 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.js +1591 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.d.ts +3 -38
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +5 -3393
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +24 -14
- package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +54 -1
- package/packages/@monomind/cli/dist/src/memory/embedding-operations.d.ts +58 -0
- package/packages/@monomind/cli/dist/src/memory/embedding-operations.js +299 -0
- package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +37 -3
- package/packages/@monomind/cli/dist/src/memory/hnsw-operations.d.ts +130 -0
- package/packages/@monomind/cli/dist/src/memory/hnsw-operations.js +400 -0
- package/packages/@monomind/cli/dist/src/memory/intelligence.js +42 -23
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +52 -8
- package/packages/@monomind/cli/dist/src/memory/memory-crud.d.ts +67 -0
- package/packages/@monomind/cli/dist/src/memory/memory-crud.js +415 -0
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.d.ts +9 -322
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +17 -1794
- package/packages/@monomind/cli/dist/src/memory/memory-migrations.d.ts +30 -0
- package/packages/@monomind/cli/dist/src/memory/memory-migrations.js +134 -0
- package/packages/@monomind/cli/dist/src/memory/memory-read.d.ts +78 -0
- package/packages/@monomind/cli/dist/src/memory/memory-read.js +331 -0
- package/packages/@monomind/cli/dist/src/memory/memory-schema.d.ts +13 -0
- package/packages/@monomind/cli/dist/src/memory/memory-schema.js +167 -0
- package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +37 -4
- package/packages/@monomind/cli/dist/src/monovector/route-outcomes.js +16 -6
- package/packages/@monomind/cli/dist/src/pricing/model-pricing.d.ts +41 -0
- package/packages/@monomind/cli/dist/src/pricing/model-pricing.js +61 -0
- package/packages/@monomind/cli/dist/src/ui/.monomind/capture/active-run.json +1 -0
- package/packages/@monomind/cli/dist/src/ui/collector.mjs +799 -0
- package/packages/@monomind/cli/dist/src/ui/dashboard.html +13986 -0
- package/packages/@monomind/cli/dist/src/ui/data/agent-avatars.html +763 -0
- package/packages/@monomind/cli/dist/src/ui/data/agent-avatars.json +966 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/account-strategist.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/accounts-payable.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/adaptive-coordinator.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/adaptive-coordinator2.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/ai-citation.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/ai-engineer.svg +61 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/analytics-reporter.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/api-tester.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/architecture.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/automation-governance.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/backend-dev.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/benchmarker.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/blockchain-auditor.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/byzantine-coord.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/case-analyst.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/cicd-engineer.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/cloud-architect.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/code-review-swarm.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/coder-v119.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/coder.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/collective-coord.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/compliance-auditor.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/consensus-coordinator.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/content-creator.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/crdt-synchronizer.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/cro-specialist.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/data-consolidator.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/data-engineer.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/database-optimizer.svg +61 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/deal-strategist.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/defender.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/devops-automator.svg +56 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/discovery-coach.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/email-marketing.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/embedded-firmware.svg +61 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/evidence-collector.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/experiment-tracker.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/feedback-synthesizer.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/finance-tracker.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/frontend-developer.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/game-audio-engineer.svg +59 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/game-designer.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/gossip-coordinator.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/hierarchical-coord.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/incident-commander.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/infrastructure.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/input-validator.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/ios-developer.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/issue-tracker.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/judge.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/launch-strategist.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/legal-compliance.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/level-designer.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/load-balancer.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/mcp-builder.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/memory-coordinator.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/mesh-coordinator.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/ml-developer.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/mobile-app-builder.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/mobile-dev.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/model-qa.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/narrative-designer.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/outbound-strategist.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/path-validator.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/payment-agent.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/perf-analyzer.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/pipeline-analyst.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/planner.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/pr-manager.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/pricing-strategist.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/product-manager.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/production-validator.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/project-shepherd.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/proposal-strategist.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/prosecutor.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/pseudocode.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/queen-coordinator.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/quorum-manager.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/raft-manager.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/reality-checker.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/recruitment.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/refinement.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/release-manager.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/repo-architect.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/researcher.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/resource-allocator.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/reviewer.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/safe-executor.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/sales-coach.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/sales-engineer.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/scout-explorer.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/security-architect.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/security-auditor.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/senior-developer.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/senior-pm.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/seo-specialist.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/social-media.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/solidity-engineer.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/sparc-coder.svg +58 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/sparc-coord.svg +56 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/specification.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/sprint-prioritizer.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/sre.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/studio-operations.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/studio-producer.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/support-responder.svg +56 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/system-architect.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/task-orchestrator.svg +56 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/technical-artist.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/technical-writer.svg +59 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/tester.svg +53 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/threat-detection.svg +61 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/trend-researcher.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/trial-director.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/unity-architect.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/visionos-engineer.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/worker-specialist.svg +55 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/workflow-architect.svg +57 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/workflow-automation.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/avatars/zk-steward.svg +54 -0
- package/packages/@monomind/cli/dist/src/ui/data/known-projects.json +1 -0
- package/packages/@monomind/cli/dist/src/ui/data/mastermind-sessions.json +1 -0
- package/packages/@monomind/cli/dist/src/ui/data/sessions/_index.json +1 -0
- package/packages/@monomind/cli/dist/src/ui/orgs.html +2215 -0
- package/packages/@monomind/cli/dist/src/ui/server.mjs +6175 -0
- package/packages/@monomind/cli/dist/src/ui/sse-manager.mjs +119 -0
- package/packages/@monomind/cli/dist/src/update/checker.js +1 -1
- package/packages/@monomind/cli/dist/workflow/builtin-handlers.js +321 -0
- package/packages/@monomind/cli/dist/workflow/engine.js +253 -0
- package/packages/@monomind/cli/dist/workflow/expression.js +98 -0
- package/packages/@monomind/cli/dist/workflow/types.js +2 -0
- package/packages/@monomind/cli/package.json +8 -5
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
// Built-in node handlers registered for every `browse workflow run` invocation.
|
|
2
|
+
//
|
|
3
|
+
// action.http — fetch a URL (GET/POST/etc.) and put the response in item.data
|
|
4
|
+
// action.save_file — write item data or binaryBase64 to a file on disk
|
|
5
|
+
// action.log — console.log each item (useful for debugging workflows)
|
|
6
|
+
// action.gemini_image — generate image via Gemini web app (browser automation + session store)
|
|
7
|
+
// or Imagen REST API (GEMINI_API_KEY), or mock mode
|
|
8
|
+
import { writeFile, readFile, mkdir, chmod } from 'node:fs/promises';
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { dirname, join, resolve } from 'node:path';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
/** Resolve a user-supplied path and assert it stays within the working directory. */
|
|
13
|
+
function safeResolvePath(rawPath) {
|
|
14
|
+
const cwd = process.cwd();
|
|
15
|
+
const safePath = resolve(cwd, rawPath);
|
|
16
|
+
if (safePath !== cwd && !safePath.startsWith(cwd + '/')) {
|
|
17
|
+
throw new Error(`Path traversal blocked: "${rawPath}" resolves outside working directory`);
|
|
18
|
+
}
|
|
19
|
+
return safePath;
|
|
20
|
+
}
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Session persistence (shared format with browse-platform.ts)
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
const SESSIONS_FILE = join(homedir(), '.monomind', 'sessions.json');
|
|
25
|
+
async function loadStoredSession(platform) {
|
|
26
|
+
if (!existsSync(SESSIONS_FILE))
|
|
27
|
+
return null;
|
|
28
|
+
try {
|
|
29
|
+
const sessions = JSON.parse(await readFile(SESSIONS_FILE, 'utf-8'));
|
|
30
|
+
return sessions.find(s => s.platform === platform) ?? null;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function saveStoredSession(platform, cookies, userAgent, username) {
|
|
37
|
+
let sessions = [];
|
|
38
|
+
if (existsSync(SESSIONS_FILE)) {
|
|
39
|
+
try {
|
|
40
|
+
sessions = JSON.parse(await readFile(SESSIONS_FILE, 'utf-8'));
|
|
41
|
+
}
|
|
42
|
+
catch { /* start fresh */ }
|
|
43
|
+
}
|
|
44
|
+
const id = `${platform}:${username}`;
|
|
45
|
+
const now = Date.now();
|
|
46
|
+
const existing = sessions.findIndex(s => s.platform === platform);
|
|
47
|
+
const entry = {
|
|
48
|
+
id, platform, username, userAgent,
|
|
49
|
+
cookies: JSON.stringify(cookies),
|
|
50
|
+
createdAt: existing >= 0 ? sessions[existing].createdAt : now,
|
|
51
|
+
lastUsedAt: now,
|
|
52
|
+
};
|
|
53
|
+
if (existing >= 0)
|
|
54
|
+
sessions[existing] = entry;
|
|
55
|
+
else
|
|
56
|
+
sessions.push(entry);
|
|
57
|
+
await mkdir(join(homedir(), '.monomind'), { recursive: true });
|
|
58
|
+
await writeFile(SESSIONS_FILE, JSON.stringify(sessions, null, 2));
|
|
59
|
+
await chmod(SESSIONS_FILE, 0o600);
|
|
60
|
+
}
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Gemini browser automation
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
const GEMINI_IMAGE_CHECK = `
|
|
65
|
+
(() => {
|
|
66
|
+
const imgs = Array.from(document.querySelectorAll('img'));
|
|
67
|
+
return imgs.some(img =>
|
|
68
|
+
img.complete && img.naturalWidth > 200 && img.naturalHeight > 200 &&
|
|
69
|
+
img.src && !img.src.includes('icon') && !img.src.includes('avatar') &&
|
|
70
|
+
!img.src.includes('logo') && !img.src.includes('profile')
|
|
71
|
+
);
|
|
72
|
+
})()
|
|
73
|
+
`;
|
|
74
|
+
const GEMINI_IMAGE_SRC = `
|
|
75
|
+
(() => {
|
|
76
|
+
const imgs = Array.from(document.querySelectorAll('img'));
|
|
77
|
+
const c = imgs.filter(img =>
|
|
78
|
+
img.complete && img.naturalWidth > 200 && img.naturalHeight > 200 &&
|
|
79
|
+
img.src && !img.src.includes('icon') && !img.src.includes('avatar') &&
|
|
80
|
+
!img.src.includes('logo') && !img.src.includes('profile')
|
|
81
|
+
);
|
|
82
|
+
return c.length ? c[c.length - 1].src : '';
|
|
83
|
+
})()
|
|
84
|
+
`;
|
|
85
|
+
// Generate an image via the Gemini web app, with session management.
|
|
86
|
+
// Flow: connect → restore saved session → if not logged in, wait for user login → generate.
|
|
87
|
+
// Returns the saved file path, or null if Chrome is not available.
|
|
88
|
+
async function generateViaGeminiBrowser(prompt, outputPath, cdpPort) {
|
|
89
|
+
let browser;
|
|
90
|
+
try {
|
|
91
|
+
browser = await import('../index.js');
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
let conn;
|
|
97
|
+
try {
|
|
98
|
+
conn = await browser.connectToTarget(cdpPort);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
const { client, sessionId } = conn;
|
|
104
|
+
const refs = new Map();
|
|
105
|
+
try {
|
|
106
|
+
// Restore stored Gemini session cookies before navigating
|
|
107
|
+
const stored = await loadStoredSession('gemini');
|
|
108
|
+
if (stored?.cookies) {
|
|
109
|
+
try {
|
|
110
|
+
const cookies = JSON.parse(stored.cookies);
|
|
111
|
+
if (cookies.length > 0) {
|
|
112
|
+
await browser.setCookies(client, sessionId, cookies);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch { /* ignore malformed cookies */ }
|
|
116
|
+
}
|
|
117
|
+
// Navigate to Gemini
|
|
118
|
+
await browser.openUrl(client, sessionId, 'https://gemini.google.com/app');
|
|
119
|
+
// Dismiss cookie consent if present
|
|
120
|
+
const refs2 = new Map();
|
|
121
|
+
const consentBtn = await browser.findByRole(client, sessionId, refs2, 'button', { name: 'Accept all' }).catch(() => null);
|
|
122
|
+
if (consentBtn) {
|
|
123
|
+
await browser.clickElement(client, sessionId, consentBtn);
|
|
124
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
125
|
+
}
|
|
126
|
+
// Check if logged in — .ql-editor only appears when authenticated
|
|
127
|
+
let inputRef = await browser.findBySelector(client, sessionId, refs, '.ql-editor').catch(() => null);
|
|
128
|
+
if (!inputRef) {
|
|
129
|
+
// Not logged in — ask the user to authenticate
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log('┌─────────────────────────────────────────────────────────┐');
|
|
132
|
+
console.log('│ Gemini login required │');
|
|
133
|
+
console.log('│ │');
|
|
134
|
+
console.log('│ A browser window has been opened to Gemini. │');
|
|
135
|
+
console.log('│ Please sign in with your Google account. │');
|
|
136
|
+
console.log('│ │');
|
|
137
|
+
console.log('│ The workflow will resume automatically after login. │');
|
|
138
|
+
console.log('│ Waiting up to 5 minutes… │');
|
|
139
|
+
console.log('└─────────────────────────────────────────────────────────┘');
|
|
140
|
+
console.log('');
|
|
141
|
+
// Navigate to Google sign-in
|
|
142
|
+
await browser.openUrl(client, sessionId, 'https://accounts.google.com/signin/v2/identifier');
|
|
143
|
+
// Wait up to 5 min for the user to complete login and land back on Gemini
|
|
144
|
+
const loginDeadline = Date.now() + 5 * 60 * 1000;
|
|
145
|
+
let loggedIn = false;
|
|
146
|
+
while (Date.now() < loginDeadline) {
|
|
147
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
148
|
+
const url = await browser.getCurrentUrl(client, sessionId).catch(() => '');
|
|
149
|
+
if (url.includes('gemini.google.com')) {
|
|
150
|
+
inputRef = await browser.findBySelector(client, sessionId, refs, '.ql-editor').catch(() => null);
|
|
151
|
+
if (inputRef) {
|
|
152
|
+
loggedIn = true;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (!loggedIn) {
|
|
158
|
+
console.log('[action.gemini_image] Login timeout. Run: monomind browse platform connect gemini');
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
console.log('[action.gemini_image] Login detected! Saving session...');
|
|
162
|
+
}
|
|
163
|
+
// Save/refresh cookies after confirming login
|
|
164
|
+
const liveCookies = await browser.getCookies(client, sessionId).catch(() => []);
|
|
165
|
+
const userAgent = await browser.evaluateJs(client, sessionId, 'navigator.userAgent').catch(() => 'unknown');
|
|
166
|
+
const username = await browser.evaluateJs(client, sessionId, "document.querySelector('.gb_A.gb_Sa')?.textContent?.trim() ?? 'gemini-user'").catch(() => 'gemini-user');
|
|
167
|
+
await saveStoredSession('gemini', liveCookies, String(userAgent), String(username));
|
|
168
|
+
// Ensure we're on the app page with the input visible
|
|
169
|
+
if (!inputRef) {
|
|
170
|
+
await browser.openUrl(client, sessionId, 'https://gemini.google.com/app');
|
|
171
|
+
inputRef = await browser.findBySelector(client, sessionId, refs, '.ql-editor').catch(() => null);
|
|
172
|
+
}
|
|
173
|
+
if (!inputRef)
|
|
174
|
+
return null;
|
|
175
|
+
// Fill and submit the prompt
|
|
176
|
+
await browser.fillElement(client, sessionId, inputRef, prompt);
|
|
177
|
+
await new Promise(r => setTimeout(r, 300));
|
|
178
|
+
await browser.pressKey(client, sessionId, 'Return');
|
|
179
|
+
console.log('[action.gemini_image] Prompt submitted to Gemini, waiting for image...');
|
|
180
|
+
// Poll up to 90s for generated image
|
|
181
|
+
const deadline = Date.now() + 90_000;
|
|
182
|
+
while (Date.now() < deadline) {
|
|
183
|
+
const found = await browser.evaluateJs(client, sessionId, GEMINI_IMAGE_CHECK).catch(() => false);
|
|
184
|
+
if (found)
|
|
185
|
+
break;
|
|
186
|
+
await new Promise(r => setTimeout(r, 500));
|
|
187
|
+
}
|
|
188
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
189
|
+
// Extract image URL and download
|
|
190
|
+
const imgSrc = (await browser.evaluateJs(client, sessionId, GEMINI_IMAGE_SRC).catch(() => ''));
|
|
191
|
+
if (imgSrc && (imgSrc.startsWith('https://') || imgSrc.startsWith('http://'))) {
|
|
192
|
+
try {
|
|
193
|
+
const resp = await fetch(imgSrc);
|
|
194
|
+
if (resp.ok) {
|
|
195
|
+
await writeFile(outputPath, Buffer.from(await resp.arrayBuffer()));
|
|
196
|
+
console.log(`[action.gemini_image] Image saved → ${outputPath}`);
|
|
197
|
+
return outputPath;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch { /* fall through to screenshot */ }
|
|
201
|
+
}
|
|
202
|
+
// Fallback: screenshot the response
|
|
203
|
+
const screenshotPath = outputPath.replace(/\.(png|jpe?g|webp)$/i, '') + '-screenshot.png';
|
|
204
|
+
const ss = await browser.captureScreenshot(client, sessionId, { path: screenshotPath, fullPage: true }).catch(() => null);
|
|
205
|
+
if (ss) {
|
|
206
|
+
console.log(`[action.gemini_image] Screenshot saved → ${ss.path}`);
|
|
207
|
+
return ss.path;
|
|
208
|
+
}
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
client.close();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
export function createBuiltinHandlers() {
|
|
216
|
+
const handlers = new Map();
|
|
217
|
+
// action.http
|
|
218
|
+
// config: { url, method?, headers?, body?, responseField? }
|
|
219
|
+
// Puts { statusCode, body, json? } into item.data[responseField ?? 'response']
|
|
220
|
+
handlers.set('action.http', async (items, config) => {
|
|
221
|
+
const url = String(config['url'] ?? '');
|
|
222
|
+
const method = String(config['method'] ?? 'GET').toUpperCase();
|
|
223
|
+
const headers = config['headers'] ?? {};
|
|
224
|
+
const body = config['body'] !== undefined ? JSON.stringify(config['body']) : undefined;
|
|
225
|
+
const responseField = String(config['responseField'] ?? 'response');
|
|
226
|
+
const res = await fetch(url, {
|
|
227
|
+
method,
|
|
228
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
229
|
+
body: method !== 'GET' && method !== 'HEAD' ? body : undefined,
|
|
230
|
+
});
|
|
231
|
+
const text = await res.text();
|
|
232
|
+
let json;
|
|
233
|
+
try {
|
|
234
|
+
json = JSON.parse(text);
|
|
235
|
+
}
|
|
236
|
+
catch { /* not JSON */ }
|
|
237
|
+
return items.map(item => ({
|
|
238
|
+
...item,
|
|
239
|
+
data: {
|
|
240
|
+
...item.data,
|
|
241
|
+
[responseField]: { statusCode: res.status, body: text, json },
|
|
242
|
+
},
|
|
243
|
+
}));
|
|
244
|
+
});
|
|
245
|
+
// action.save_file
|
|
246
|
+
// config: { path, content?, field?, encoding? }
|
|
247
|
+
// Writes item.data[field] (or binaryBase64 decoded) to disk
|
|
248
|
+
handlers.set('action.save_file', async (items, config) => {
|
|
249
|
+
const results = [];
|
|
250
|
+
for (const item of items) {
|
|
251
|
+
const outPath = safeResolvePath(String(config['path'] ?? './output.txt'));
|
|
252
|
+
const field = config['field'];
|
|
253
|
+
const encoding = String(config['encoding'] ?? 'utf8');
|
|
254
|
+
await mkdir(dirname(outPath), { recursive: true });
|
|
255
|
+
if (item.binaryBase64) {
|
|
256
|
+
await writeFile(outPath, Buffer.from(item.binaryBase64, 'base64'));
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
const content = field
|
|
260
|
+
? JSON.stringify(item.data[field] ?? '', null, 2)
|
|
261
|
+
: (config['content'] ?? JSON.stringify(item.data, null, 2));
|
|
262
|
+
await writeFile(outPath, content, encoding);
|
|
263
|
+
}
|
|
264
|
+
results.push({ ...item, data: { ...item.data, savedPath: outPath } });
|
|
265
|
+
}
|
|
266
|
+
return results;
|
|
267
|
+
});
|
|
268
|
+
// action.log
|
|
269
|
+
// config: { label? }
|
|
270
|
+
handlers.set('action.log', async (items, config) => {
|
|
271
|
+
const label = String(config['label'] ?? 'action.log');
|
|
272
|
+
for (const item of items) {
|
|
273
|
+
console.log(`[${label}]`, JSON.stringify(item.data, null, 2));
|
|
274
|
+
}
|
|
275
|
+
return items;
|
|
276
|
+
});
|
|
277
|
+
// action.gemini_image
|
|
278
|
+
// config: { prompt, cdpPort?, outputPath?, apiKey?, model?, aspectRatio? }
|
|
279
|
+
// Priority: (1) Gemini web browser via CDP port 9222, (2) Imagen REST API, (3) mock
|
|
280
|
+
handlers.set('action.gemini_image', async (items, config) => {
|
|
281
|
+
const cdpPort = Number(config['cdpPort'] ?? process.env['GEMINI_CDP_PORT'] ?? 9222);
|
|
282
|
+
const apiKey = String(config['apiKey'] ?? process.env['GEMINI_API_KEY'] ?? process.env['GOOGLE_API_KEY'] ?? '');
|
|
283
|
+
const model = String(config['model'] ?? 'imagen-3.0-generate-001');
|
|
284
|
+
const aspectRatio = String(config['aspectRatio'] ?? '1:1');
|
|
285
|
+
const outputPath = config['outputPath'];
|
|
286
|
+
const results = [];
|
|
287
|
+
for (const item of items) {
|
|
288
|
+
const prompt = String(config['prompt'] ?? item.data['prompt'] ?? '');
|
|
289
|
+
const filePath = safeResolvePath(outputPath ?? `./output/gemini-image-${Date.now()}.png`);
|
|
290
|
+
// Priority 1: Browser automation via authenticated Chrome session
|
|
291
|
+
const browserPath = await generateViaGeminiBrowser(prompt, filePath, cdpPort);
|
|
292
|
+
if (browserPath) {
|
|
293
|
+
results.push({
|
|
294
|
+
...item,
|
|
295
|
+
data: { ...item.data, prompt, generatedImagePath: browserPath, source: 'gemini-browser' },
|
|
296
|
+
});
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
// Priority 2: Gemini Imagen REST API
|
|
300
|
+
if (apiKey) {
|
|
301
|
+
console.log(`[action.gemini_image] Browser unavailable — trying Imagen REST API`);
|
|
302
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:predict?key=${apiKey}`;
|
|
303
|
+
const res = await fetch(url, {
|
|
304
|
+
method: 'POST',
|
|
305
|
+
headers: { 'Content-Type': 'application/json' },
|
|
306
|
+
body: JSON.stringify({
|
|
307
|
+
instances: [{ prompt }],
|
|
308
|
+
parameters: { sampleCount: 1, aspectRatio },
|
|
309
|
+
}),
|
|
310
|
+
});
|
|
311
|
+
if (!res.ok)
|
|
312
|
+
throw new Error(`Gemini Imagen API error ${res.status}: ${await res.text()}`);
|
|
313
|
+
const data = await res.json();
|
|
314
|
+
const prediction = data.predictions?.[0];
|
|
315
|
+
if (!prediction?.bytesBase64Encoded)
|
|
316
|
+
throw new Error('No image data in Gemini response');
|
|
317
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
318
|
+
await writeFile(filePath, Buffer.from(prediction.bytesBase64Encoded, 'base64'));
|
|
319
|
+
results.push({
|
|
320
|
+
...item,
|
|
321
|
+
data: { ...item.data, prompt, generatedImagePath: filePath, mimeType: prediction.mimeType ?? 'image/png', source: 'gemini-api' },
|
|
322
|
+
binaryBase64: prediction.bytesBase64Encoded,
|
|
323
|
+
});
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
// Priority 3: Mock mode — no browser on port 9222 and no API key
|
|
327
|
+
console.log(`[action.gemini_image] No browser on port ${cdpPort} and no API key — mock mode.`);
|
|
328
|
+
console.log(` Prompt: "${prompt}"`);
|
|
329
|
+
results.push({
|
|
330
|
+
...item,
|
|
331
|
+
data: {
|
|
332
|
+
...item.data,
|
|
333
|
+
prompt,
|
|
334
|
+
mockMode: true,
|
|
335
|
+
note: `Set GEMINI_CDP_PORT env var (default: 9222) for browser mode, or GEMINI_API_KEY for REST API`,
|
|
336
|
+
},
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
return results;
|
|
340
|
+
});
|
|
341
|
+
return handlers;
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=builtin-handlers.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { WorkflowDef, NodeDef, Item, RunRecord, StepEvent } from './types.js';
|
|
2
|
+
export declare class DagError extends Error {
|
|
3
|
+
constructor(message: string);
|
|
4
|
+
}
|
|
5
|
+
export declare function buildDag(wf: WorkflowDef): string[];
|
|
6
|
+
export interface RunOptions {
|
|
7
|
+
items?: Item[];
|
|
8
|
+
params?: Record<string, string>;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
onEvent?: (event: StepEvent) => void;
|
|
11
|
+
executeNode?: NodeExecutor;
|
|
12
|
+
}
|
|
13
|
+
export type NodeExecutor = (node: NodeDef, items: Item[], nodeOutputs: Record<string, Item[]>, params: Record<string, string>, signal?: AbortSignal) => Promise<Item[]>;
|
|
14
|
+
export declare function runWorkflow(wf: WorkflowDef, options?: RunOptions): Promise<RunRecord>;
|
|
15
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import { resolveConfig } from './expression.js';
|
|
3
|
+
import { writeRunRecord } from './store.js';
|
|
4
|
+
export class DagError extends Error {
|
|
5
|
+
constructor(message) { super(message); this.name = 'DagError'; }
|
|
6
|
+
}
|
|
7
|
+
export function buildDag(wf) {
|
|
8
|
+
const nodeIds = new Set(wf.nodes.map(n => n.id));
|
|
9
|
+
for (const conn of wf.connections) {
|
|
10
|
+
if (!nodeIds.has(conn.from))
|
|
11
|
+
throw new DagError(`Connection references unknown node: ${conn.from}`);
|
|
12
|
+
if (!nodeIds.has(conn.to))
|
|
13
|
+
throw new DagError(`Connection references unknown node: ${conn.to}`);
|
|
14
|
+
}
|
|
15
|
+
const inDegree = new Map();
|
|
16
|
+
const adjacency = new Map();
|
|
17
|
+
for (const n of wf.nodes) {
|
|
18
|
+
inDegree.set(n.id, 0);
|
|
19
|
+
adjacency.set(n.id, []);
|
|
20
|
+
}
|
|
21
|
+
for (const conn of wf.connections) {
|
|
22
|
+
adjacency.get(conn.from).push(conn.to);
|
|
23
|
+
inDegree.set(conn.to, (inDegree.get(conn.to) ?? 0) + 1);
|
|
24
|
+
}
|
|
25
|
+
const queue = wf.nodes.filter(n => inDegree.get(n.id) === 0).map(n => n.id);
|
|
26
|
+
const order = [];
|
|
27
|
+
while (queue.length > 0) {
|
|
28
|
+
const nodeId = queue.shift();
|
|
29
|
+
order.push(nodeId);
|
|
30
|
+
for (const next of adjacency.get(nodeId) ?? []) {
|
|
31
|
+
const deg = (inDegree.get(next) ?? 1) - 1;
|
|
32
|
+
inDegree.set(next, deg);
|
|
33
|
+
if (deg === 0)
|
|
34
|
+
queue.push(next);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (order.length !== wf.nodes.length)
|
|
38
|
+
throw new DagError('Workflow contains a cycle');
|
|
39
|
+
return order;
|
|
40
|
+
}
|
|
41
|
+
export async function runWorkflow(wf, options = {}) {
|
|
42
|
+
const runId = randomUUID();
|
|
43
|
+
const startedAt = Date.now();
|
|
44
|
+
const items = options.items ?? [{ data: {} }];
|
|
45
|
+
const params = options.params ?? {};
|
|
46
|
+
const emit = options.onEvent ?? (() => { });
|
|
47
|
+
const execute = options.executeNode ?? defaultNodeExecutor;
|
|
48
|
+
const record = {
|
|
49
|
+
id: runId,
|
|
50
|
+
workflowId: wf.id,
|
|
51
|
+
workflowName: wf.name,
|
|
52
|
+
status: 'running',
|
|
53
|
+
startedAt,
|
|
54
|
+
itemsProcessed: 0,
|
|
55
|
+
itemsTotal: items.length,
|
|
56
|
+
};
|
|
57
|
+
emit({ runId, workflowId: wf.id, workflowName: wf.name, nodeId: '', nodeName: '',
|
|
58
|
+
eventType: 'run_started', itemTotal: items.length, timestamp: Date.now() });
|
|
59
|
+
const order = buildDag(wf);
|
|
60
|
+
const nodeMap = new Map(wf.nodes.map(n => [n.id, n]));
|
|
61
|
+
const nodeOutputs = {};
|
|
62
|
+
let currentItems = items;
|
|
63
|
+
try {
|
|
64
|
+
for (const nodeId of order) {
|
|
65
|
+
if (options.signal?.aborted) {
|
|
66
|
+
record.status = 'stopped';
|
|
67
|
+
record.completedAt = Date.now();
|
|
68
|
+
emit({ runId, workflowId: wf.id, workflowName: wf.name, nodeId, nodeName: nodeId,
|
|
69
|
+
eventType: 'run_stopped', timestamp: Date.now() });
|
|
70
|
+
await writeRunRecord(record);
|
|
71
|
+
return record;
|
|
72
|
+
}
|
|
73
|
+
const node = nodeMap.get(nodeId);
|
|
74
|
+
const stepStart = Date.now();
|
|
75
|
+
emit({ runId, workflowId: wf.id, workflowName: wf.name, nodeId, nodeName: node.name ?? nodeId,
|
|
76
|
+
eventType: 'step_started', itemTotal: currentItems.length, timestamp: stepStart });
|
|
77
|
+
try {
|
|
78
|
+
const output = await execute(node, currentItems, nodeOutputs, params, options.signal);
|
|
79
|
+
nodeOutputs[nodeId] = output;
|
|
80
|
+
record.itemsProcessed = output.length;
|
|
81
|
+
emit({ runId, workflowId: wf.id, workflowName: wf.name, nodeId, nodeName: node.name ?? nodeId,
|
|
82
|
+
eventType: 'step_completed', durationMs: Date.now() - stepStart,
|
|
83
|
+
itemTotal: output.length, timestamp: Date.now() });
|
|
84
|
+
if (!node.type.startsWith('trigger.'))
|
|
85
|
+
currentItems = output;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
emit({ runId, workflowId: wf.id, workflowName: wf.name, nodeId, nodeName: node.name ?? nodeId,
|
|
89
|
+
eventType: 'step_failed', error: err.message,
|
|
90
|
+
durationMs: Date.now() - stepStart, timestamp: Date.now() });
|
|
91
|
+
if (node.onError === 'skip')
|
|
92
|
+
continue;
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
record.status = 'completed';
|
|
97
|
+
record.completedAt = Date.now();
|
|
98
|
+
emit({ runId, workflowId: wf.id, workflowName: wf.name, nodeId: '', nodeName: '',
|
|
99
|
+
eventType: 'run_completed', timestamp: Date.now() });
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
record.status = 'failed';
|
|
103
|
+
record.error = err.message;
|
|
104
|
+
record.completedAt = Date.now();
|
|
105
|
+
}
|
|
106
|
+
await writeRunRecord(record);
|
|
107
|
+
return record;
|
|
108
|
+
}
|
|
109
|
+
async function defaultNodeExecutor(node, items, nodeOutputs, params) {
|
|
110
|
+
if (node.type.startsWith('trigger.'))
|
|
111
|
+
return items;
|
|
112
|
+
if (node.type === 'core.filter') {
|
|
113
|
+
const field = node.config['field'];
|
|
114
|
+
const value = node.config['value'];
|
|
115
|
+
return items.filter(item => item.data[field] === value);
|
|
116
|
+
}
|
|
117
|
+
if (node.type === 'core.set') {
|
|
118
|
+
const assignments = node.config['fields'];
|
|
119
|
+
return items.map(item => {
|
|
120
|
+
const resolved = resolveConfig(assignments, item, nodeOutputs, params);
|
|
121
|
+
return { ...item, data: { ...item.data, ...resolved } };
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// action.* nodes — resolved by caller who passes a real executeNode
|
|
125
|
+
return items;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Item } from './types.js';
|
|
2
|
+
export declare function resolveExpression(template: string, item: Item, nodeOutputs: Record<string, Item[]>, params: Record<string, string>): string;
|
|
3
|
+
export declare function resolveConfig(config: Record<string, unknown>, item: Item, nodeOutputs: Record<string, Item[]>, params: Record<string, string>): Record<string, unknown>;
|
|
4
|
+
//# sourceMappingURL=expression.d.ts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const TEMPLATE_RE = /\{\{([^}]+)\}\}/g;
|
|
2
|
+
const cache = new Map();
|
|
3
|
+
function extractTemplates(template) {
|
|
4
|
+
if (cache.has(template))
|
|
5
|
+
return cache.get(template);
|
|
6
|
+
const matches = [...template.matchAll(new RegExp(TEMPLATE_RE.source, 'g'))];
|
|
7
|
+
cache.set(template, matches);
|
|
8
|
+
return matches;
|
|
9
|
+
}
|
|
10
|
+
export function resolveExpression(template, item, nodeOutputs, params) {
|
|
11
|
+
const matches = extractTemplates(template);
|
|
12
|
+
if (matches.length === 0)
|
|
13
|
+
return template;
|
|
14
|
+
let result = template;
|
|
15
|
+
for (const match of matches) {
|
|
16
|
+
const expr = match[1].trim();
|
|
17
|
+
const value = resolveToken(expr, item, nodeOutputs, params);
|
|
18
|
+
result = result.replace(match[0], String(value));
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
function resolveToken(expr, item, nodeOutputs, params) {
|
|
23
|
+
if (expr.startsWith('$json.')) {
|
|
24
|
+
const key = expr.slice(6);
|
|
25
|
+
if (!(key in item.data))
|
|
26
|
+
throw new Error(`Unresolved: $json.${key} not found in item data`);
|
|
27
|
+
return item.data[key];
|
|
28
|
+
}
|
|
29
|
+
if (expr.startsWith('$env.')) {
|
|
30
|
+
const key = expr.slice(5);
|
|
31
|
+
const val = process.env[key];
|
|
32
|
+
if (val === undefined)
|
|
33
|
+
throw new Error(`Unresolved: $env.${key} not set`);
|
|
34
|
+
return val;
|
|
35
|
+
}
|
|
36
|
+
if (expr.startsWith('params.')) {
|
|
37
|
+
const key = expr.slice(7);
|
|
38
|
+
if (!(key in params))
|
|
39
|
+
throw new Error(`Unresolved: params.${key} not provided`);
|
|
40
|
+
return params[key];
|
|
41
|
+
}
|
|
42
|
+
if (expr.startsWith('$node.')) {
|
|
43
|
+
const parts = expr.slice(6).split('.');
|
|
44
|
+
const nodeId = parts[0];
|
|
45
|
+
const field = parts.slice(1).join('.');
|
|
46
|
+
const items = nodeOutputs[nodeId];
|
|
47
|
+
if (!items || items.length === 0)
|
|
48
|
+
throw new Error(`Unresolved: $node.${nodeId} has no output`);
|
|
49
|
+
const val = items[0].data[field];
|
|
50
|
+
if (val === undefined)
|
|
51
|
+
throw new Error(`Unresolved: $node.${nodeId}.${field} not found`);
|
|
52
|
+
return val;
|
|
53
|
+
}
|
|
54
|
+
// Named ref (from find step) — caller resolves these at execution time
|
|
55
|
+
return `{{${expr}}}`;
|
|
56
|
+
}
|
|
57
|
+
export function resolveConfig(config, item, nodeOutputs, params) {
|
|
58
|
+
const result = {};
|
|
59
|
+
for (const [k, v] of Object.entries(config)) {
|
|
60
|
+
result[k] = typeof v === 'string' ? resolveExpression(v, item, nodeOutputs, params) : v;
|
|
61
|
+
}
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=expression.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { WorkflowDef, RunRecord } from './types.js';
|
|
2
|
+
export declare class WorkflowStoreError extends Error {
|
|
3
|
+
readonly cause?: unknown | undefined;
|
|
4
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare function readWorkflow(filePath: string): Promise<WorkflowDef>;
|
|
7
|
+
export declare function writeRunRecord(record: RunRecord): Promise<void>;
|
|
8
|
+
export declare function listRuns(workflowId?: string): Promise<RunRecord[]>;
|
|
9
|
+
export declare function saveSession(session: {
|
|
10
|
+
id: string;
|
|
11
|
+
platform: string;
|
|
12
|
+
username: string;
|
|
13
|
+
cookies: string;
|
|
14
|
+
userAgent?: string;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
export declare function listSessions(): Promise<Array<{
|
|
17
|
+
id: string;
|
|
18
|
+
platform: string;
|
|
19
|
+
username: string;
|
|
20
|
+
lastUsedAt: number;
|
|
21
|
+
}>>;
|
|
22
|
+
export declare function deleteSession(id: string): Promise<void>;
|
|
23
|
+
export declare function getSessionCookies(platform: string, username: string): Promise<string | null>;
|
|
24
|
+
//# sourceMappingURL=store.d.ts.map
|