monomind 1.14.7 → 1.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (314) hide show
  1. package/.claude/agents/reengineer-squad/boss.md +113 -0
  2. package/.claude/agents/reengineer-squad/critic-architect.md +132 -0
  3. package/.claude/agents/reengineer-squad/git-manager.md +145 -0
  4. package/.claude/agents/reengineer-squad/idea-generator.md +95 -0
  5. package/.claude/agents/reengineer-squad/implementer.md +112 -0
  6. package/.claude/agents/reengineer-squad/integration-planner.md +112 -0
  7. package/.claude/agents/reengineer-squad/source-analyst.md +103 -0
  8. package/.claude/agents/reengineer-squad/target-analyst.md +118 -0
  9. package/.claude/agents/reengineer-squad/tester.md +105 -0
  10. package/.claude/commands/mastermind/master.md +35 -14
  11. package/.claude/helpers/handlers/capture-handler.cjs +155 -18
  12. package/.claude/helpers/monolean-activate.cjs +20 -0
  13. package/.claude/helpers/monolean-config.cjs +76 -0
  14. package/.claude/helpers/monolean-instructions.cjs +109 -0
  15. package/.claude/helpers/monolean-propagate.cjs +9 -0
  16. package/.claude/helpers/monolean-tracker.cjs +18 -0
  17. package/.claude/helpers/skill-registry.json +2 -2
  18. package/.claude/settings.json +34 -2
  19. package/.claude/skills/agent-browser-testing/SKILL.md +301 -18
  20. package/.claude/skills/mastermind/runorg.md +69 -23
  21. package/.claude/skills/monodesign/SKILL.md +32 -1
  22. package/.claude/skills/monodesign/adapt.md +53 -0
  23. package/.claude/skills/monodesign/agents/monodesign-asset-producer.md +100 -0
  24. package/.claude/skills/monodesign/animate.md +65 -0
  25. package/.claude/skills/monodesign/audit.md +89 -0
  26. package/.claude/skills/monodesign/bolder.md +50 -0
  27. package/.claude/skills/monodesign/clarify.md +64 -0
  28. package/.claude/skills/monodesign/colorize.md +68 -0
  29. package/.claude/skills/monodesign/craft.md +51 -0
  30. package/.claude/skills/monodesign/critique.md +66 -0
  31. package/.claude/skills/monodesign/delight.md +47 -0
  32. package/.claude/skills/monodesign/distill.md +56 -0
  33. package/.claude/skills/monodesign/document.md +80 -0
  34. package/.claude/skills/monodesign/extract.md +74 -0
  35. package/.claude/skills/monodesign/harden.md +65 -0
  36. package/.claude/skills/monodesign/live.md +59 -0
  37. package/.claude/skills/monodesign/onboard.md +50 -0
  38. package/.claude/skills/monodesign/optimize.md +64 -0
  39. package/.claude/skills/monodesign/overdrive.md +56 -0
  40. package/.claude/skills/monodesign/polish.md +68 -0
  41. package/.claude/skills/monodesign/quieter.md +57 -0
  42. package/.claude/skills/monodesign/reference/antipatterns-catalog.md +248 -76
  43. package/.claude/skills/monodesign/reference/codex.md +107 -0
  44. package/.claude/skills/monodesign/reference/craft.md +3 -0
  45. package/.claude/skills/monodesign/reference/hooks.md +99 -0
  46. package/.claude/skills/monodesign/reference/image-prompts.md +12 -0
  47. package/.claude/skills/monodesign/shape.md +71 -0
  48. package/.claude/skills/monodesign/teach.md +69 -0
  49. package/.claude/skills/monodesign/typeset.md +59 -0
  50. package/.claude/skills/monolean/SKILL.md +118 -0
  51. package/.claude/skills/monolean-audit/SKILL.md +41 -0
  52. package/.claude/skills/monolean-debt/SKILL.md +46 -0
  53. package/.claude/skills/monolean-help/SKILL.md +60 -0
  54. package/.claude/skills/monolean-review/SKILL.md +57 -0
  55. package/package.json +8 -3
  56. package/packages/@monomind/cli/bin/cli.js +3 -1
  57. package/packages/@monomind/cli/dist/dashboard/server.js +137 -0
  58. package/packages/@monomind/cli/dist/src/__tests__/browse-adapters.test.d.ts +2 -0
  59. package/packages/@monomind/cli/dist/src/__tests__/browse-adapters.test.js +51 -0
  60. package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.d.ts +2 -0
  61. package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.js +68 -0
  62. package/packages/@monomind/cli/dist/src/__tests__/browse-builtin-handlers.test.d.ts +2 -0
  63. package/packages/@monomind/cli/dist/src/__tests__/browse-builtin-handlers.test.js +139 -0
  64. package/packages/@monomind/cli/dist/src/__tests__/browse-cdp.test.d.ts +2 -0
  65. package/packages/@monomind/cli/dist/src/__tests__/browse-cdp.test.js +169 -0
  66. package/packages/@monomind/cli/dist/src/__tests__/browse-dashboard.test.d.ts +2 -0
  67. package/packages/@monomind/cli/dist/src/__tests__/browse-dashboard.test.js +179 -0
  68. package/packages/@monomind/cli/dist/src/__tests__/browse-engine.test.d.ts +2 -0
  69. package/packages/@monomind/cli/dist/src/__tests__/browse-engine.test.js +122 -0
  70. package/packages/@monomind/cli/dist/src/__tests__/browse-expression.test.d.ts +2 -0
  71. package/packages/@monomind/cli/dist/src/__tests__/browse-expression.test.js +54 -0
  72. package/packages/@monomind/cli/dist/src/__tests__/browse-store.test.d.ts +2 -0
  73. package/packages/@monomind/cli/dist/src/__tests__/browse-store.test.js +99 -0
  74. package/packages/@monomind/cli/dist/src/__tests__/browse-workflow-types.test.d.ts +2 -0
  75. package/packages/@monomind/cli/dist/src/__tests__/browse-workflow-types.test.js +33 -0
  76. package/packages/@monomind/cli/dist/src/browser/action-builder/analyzer.d.ts +11 -0
  77. package/packages/@monomind/cli/dist/src/browser/action-builder/analyzer.js +71 -0
  78. package/packages/@monomind/cli/dist/src/browser/action-builder/types.d.ts +47 -0
  79. package/packages/@monomind/cli/dist/src/browser/action-builder/types.js +2 -0
  80. package/packages/@monomind/cli/dist/src/browser/adapters/gemini.d.ts +3 -0
  81. package/packages/@monomind/cli/dist/src/browser/adapters/gemini.js +16 -0
  82. package/packages/@monomind/cli/dist/src/browser/adapters/google.d.ts +3 -0
  83. package/packages/@monomind/cli/dist/src/browser/adapters/google.js +17 -0
  84. package/packages/@monomind/cli/dist/src/browser/adapters/index.d.ts +19 -0
  85. package/packages/@monomind/cli/dist/src/browser/adapters/index.js +23 -0
  86. package/packages/@monomind/cli/dist/src/browser/adapters/instagram.d.ts +3 -0
  87. package/packages/@monomind/cli/dist/src/browser/adapters/instagram.js +17 -0
  88. package/packages/@monomind/cli/dist/src/browser/adapters/linkedin.d.ts +3 -0
  89. package/packages/@monomind/cli/dist/src/browser/adapters/linkedin.js +19 -0
  90. package/packages/@monomind/cli/dist/src/browser/adapters/microsoft.d.ts +3 -0
  91. package/packages/@monomind/cli/dist/src/browser/adapters/microsoft.js +16 -0
  92. package/packages/@monomind/cli/dist/src/browser/adapters/x.d.ts +3 -0
  93. package/packages/@monomind/cli/dist/src/browser/adapters/x.js +19 -0
  94. package/packages/@monomind/cli/dist/src/browser/dashboard/api-types.d.ts +50 -0
  95. package/packages/@monomind/cli/dist/src/browser/dashboard/api-types.js +14 -0
  96. package/packages/@monomind/cli/dist/src/browser/dashboard/server.d.ts +9 -0
  97. package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +62 -0
  98. package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +1811 -0
  99. package/packages/@monomind/cli/dist/src/browser/workflow/builtin-handlers.d.ts +3 -0
  100. package/packages/@monomind/cli/dist/src/browser/workflow/builtin-handlers.js +343 -0
  101. package/packages/@monomind/cli/dist/src/browser/workflow/engine.d.ts +15 -0
  102. package/packages/@monomind/cli/dist/src/browser/workflow/engine.js +127 -0
  103. package/packages/@monomind/cli/dist/src/browser/workflow/expression.d.ts +4 -0
  104. package/packages/@monomind/cli/dist/src/browser/workflow/expression.js +64 -0
  105. package/packages/@monomind/cli/dist/src/browser/workflow/store.d.ts +24 -0
  106. package/packages/@monomind/cli/dist/src/browser/workflow/store.js +145 -0
  107. package/packages/@monomind/cli/dist/src/browser/workflow/types.d.ts +48 -0
  108. package/packages/@monomind/cli/dist/src/browser/workflow/types.js +2 -0
  109. package/packages/@monomind/cli/dist/src/commands/browse-action.d.ts +4 -0
  110. package/packages/@monomind/cli/dist/src/commands/browse-action.js +151 -0
  111. package/packages/@monomind/cli/dist/src/commands/browse-platform.d.ts +4 -0
  112. package/packages/@monomind/cli/dist/src/commands/browse-platform.js +117 -0
  113. package/packages/@monomind/cli/dist/src/commands/browse-workflow.d.ts +4 -0
  114. package/packages/@monomind/cli/dist/src/commands/browse-workflow.js +153 -0
  115. package/packages/@monomind/cli/dist/src/commands/browse.d.ts +10 -6
  116. package/packages/@monomind/cli/dist/src/commands/browse.js +11 -2154
  117. package/packages/@monomind/cli/dist/src/commands/design-detect.d.ts +21 -0
  118. package/packages/@monomind/cli/dist/src/commands/design-detect.js +127 -0
  119. package/packages/@monomind/cli/dist/src/commands/design-palette.d.ts +22 -0
  120. package/packages/@monomind/cli/dist/src/commands/design-palette.js +539 -0
  121. package/packages/@monomind/cli/dist/src/commands/hooks-core-commands.d.ts +10 -0
  122. package/packages/@monomind/cli/dist/src/commands/hooks-core-commands.js +377 -0
  123. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +12 -0
  124. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +1217 -0
  125. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-utils.d.ts +42 -0
  126. package/packages/@monomind/cli/dist/src/commands/hooks-coverage-utils.js +220 -0
  127. package/packages/@monomind/cli/dist/src/commands/hooks-extended-commands.d.ts +14 -0
  128. package/packages/@monomind/cli/dist/src/commands/hooks-extended-commands.js +579 -0
  129. package/packages/@monomind/cli/dist/src/commands/hooks-formatting.d.ts +13 -0
  130. package/packages/@monomind/cli/dist/src/commands/hooks-formatting.js +42 -0
  131. package/packages/@monomind/cli/dist/src/commands/hooks-routing-commands.d.ts +15 -0
  132. package/packages/@monomind/cli/dist/src/commands/hooks-routing-commands.js +723 -0
  133. package/packages/@monomind/cli/dist/src/commands/hooks-workers.d.ts +9 -0
  134. package/packages/@monomind/cli/dist/src/commands/hooks-workers.js +782 -0
  135. package/packages/@monomind/cli/dist/src/commands/hooks.d.ts +8 -0
  136. package/packages/@monomind/cli/dist/src/commands/hooks.js +179 -4103
  137. package/packages/@monomind/cli/dist/src/commands/index.d.ts +1 -0
  138. package/packages/@monomind/cli/dist/src/commands/index.js +6 -0
  139. package/packages/@monomind/cli/dist/src/commands/org.js +14 -15
  140. package/packages/@monomind/cli/dist/src/commands/tokens.js +77 -1
  141. package/packages/@monomind/cli/dist/src/graph/enrich.mjs +362 -0
  142. package/packages/@monomind/cli/dist/src/init/executor.js +18 -8
  143. package/packages/@monomind/cli/dist/src/init/settings-generator.js +39 -5
  144. package/packages/@monomind/cli/dist/src/init/statusline-generator.js +25 -5
  145. package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.d.ts +3 -5
  146. package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +619 -326
  147. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-embedding.d.ts +161 -0
  148. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-embedding.js +506 -0
  149. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.d.ts +26 -0
  150. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.js +1328 -0
  151. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.d.ts +27 -0
  152. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.js +1591 -0
  153. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.d.ts +3 -38
  154. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +5 -3393
  155. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +24 -14
  156. package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +54 -1
  157. package/packages/@monomind/cli/dist/src/memory/embedding-operations.d.ts +58 -0
  158. package/packages/@monomind/cli/dist/src/memory/embedding-operations.js +299 -0
  159. package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +37 -3
  160. package/packages/@monomind/cli/dist/src/memory/hnsw-operations.d.ts +130 -0
  161. package/packages/@monomind/cli/dist/src/memory/hnsw-operations.js +400 -0
  162. package/packages/@monomind/cli/dist/src/memory/intelligence.js +42 -23
  163. package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +52 -8
  164. package/packages/@monomind/cli/dist/src/memory/memory-crud.d.ts +67 -0
  165. package/packages/@monomind/cli/dist/src/memory/memory-crud.js +415 -0
  166. package/packages/@monomind/cli/dist/src/memory/memory-initializer.d.ts +9 -322
  167. package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +17 -1794
  168. package/packages/@monomind/cli/dist/src/memory/memory-migrations.d.ts +30 -0
  169. package/packages/@monomind/cli/dist/src/memory/memory-migrations.js +134 -0
  170. package/packages/@monomind/cli/dist/src/memory/memory-read.d.ts +78 -0
  171. package/packages/@monomind/cli/dist/src/memory/memory-read.js +331 -0
  172. package/packages/@monomind/cli/dist/src/memory/memory-schema.d.ts +13 -0
  173. package/packages/@monomind/cli/dist/src/memory/memory-schema.js +167 -0
  174. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +37 -4
  175. package/packages/@monomind/cli/dist/src/monovector/route-outcomes.js +16 -6
  176. package/packages/@monomind/cli/dist/src/pricing/model-pricing.d.ts +41 -0
  177. package/packages/@monomind/cli/dist/src/pricing/model-pricing.js +61 -0
  178. package/packages/@monomind/cli/dist/src/ui/.monomind/capture/active-run.json +1 -0
  179. package/packages/@monomind/cli/dist/src/ui/collector.mjs +799 -0
  180. package/packages/@monomind/cli/dist/src/ui/dashboard.html +13986 -0
  181. package/packages/@monomind/cli/dist/src/ui/data/agent-avatars.html +763 -0
  182. package/packages/@monomind/cli/dist/src/ui/data/agent-avatars.json +966 -0
  183. package/packages/@monomind/cli/dist/src/ui/data/avatars/account-strategist.svg +58 -0
  184. package/packages/@monomind/cli/dist/src/ui/data/avatars/accounts-payable.svg +54 -0
  185. package/packages/@monomind/cli/dist/src/ui/data/avatars/adaptive-coordinator.svg +55 -0
  186. package/packages/@monomind/cli/dist/src/ui/data/avatars/adaptive-coordinator2.svg +54 -0
  187. package/packages/@monomind/cli/dist/src/ui/data/avatars/ai-citation.svg +57 -0
  188. package/packages/@monomind/cli/dist/src/ui/data/avatars/ai-engineer.svg +61 -0
  189. package/packages/@monomind/cli/dist/src/ui/data/avatars/analytics-reporter.svg +53 -0
  190. package/packages/@monomind/cli/dist/src/ui/data/avatars/api-tester.svg +53 -0
  191. package/packages/@monomind/cli/dist/src/ui/data/avatars/architecture.svg +54 -0
  192. package/packages/@monomind/cli/dist/src/ui/data/avatars/automation-governance.svg +55 -0
  193. package/packages/@monomind/cli/dist/src/ui/data/avatars/backend-dev.svg +53 -0
  194. package/packages/@monomind/cli/dist/src/ui/data/avatars/benchmarker.svg +54 -0
  195. package/packages/@monomind/cli/dist/src/ui/data/avatars/blockchain-auditor.svg +53 -0
  196. package/packages/@monomind/cli/dist/src/ui/data/avatars/byzantine-coord.svg +57 -0
  197. package/packages/@monomind/cli/dist/src/ui/data/avatars/case-analyst.svg +57 -0
  198. package/packages/@monomind/cli/dist/src/ui/data/avatars/cicd-engineer.svg +55 -0
  199. package/packages/@monomind/cli/dist/src/ui/data/avatars/cloud-architect.svg +54 -0
  200. package/packages/@monomind/cli/dist/src/ui/data/avatars/code-review-swarm.svg +57 -0
  201. package/packages/@monomind/cli/dist/src/ui/data/avatars/coder-v119.svg +57 -0
  202. package/packages/@monomind/cli/dist/src/ui/data/avatars/coder.svg +58 -0
  203. package/packages/@monomind/cli/dist/src/ui/data/avatars/collective-coord.svg +54 -0
  204. package/packages/@monomind/cli/dist/src/ui/data/avatars/compliance-auditor.svg +58 -0
  205. package/packages/@monomind/cli/dist/src/ui/data/avatars/consensus-coordinator.svg +54 -0
  206. package/packages/@monomind/cli/dist/src/ui/data/avatars/content-creator.svg +54 -0
  207. package/packages/@monomind/cli/dist/src/ui/data/avatars/crdt-synchronizer.svg +53 -0
  208. package/packages/@monomind/cli/dist/src/ui/data/avatars/cro-specialist.svg +58 -0
  209. package/packages/@monomind/cli/dist/src/ui/data/avatars/data-consolidator.svg +54 -0
  210. package/packages/@monomind/cli/dist/src/ui/data/avatars/data-engineer.svg +53 -0
  211. package/packages/@monomind/cli/dist/src/ui/data/avatars/database-optimizer.svg +61 -0
  212. package/packages/@monomind/cli/dist/src/ui/data/avatars/deal-strategist.svg +54 -0
  213. package/packages/@monomind/cli/dist/src/ui/data/avatars/defender.svg +53 -0
  214. package/packages/@monomind/cli/dist/src/ui/data/avatars/devops-automator.svg +56 -0
  215. package/packages/@monomind/cli/dist/src/ui/data/avatars/discovery-coach.svg +54 -0
  216. package/packages/@monomind/cli/dist/src/ui/data/avatars/email-marketing.svg +57 -0
  217. package/packages/@monomind/cli/dist/src/ui/data/avatars/embedded-firmware.svg +61 -0
  218. package/packages/@monomind/cli/dist/src/ui/data/avatars/evidence-collector.svg +57 -0
  219. package/packages/@monomind/cli/dist/src/ui/data/avatars/experiment-tracker.svg +53 -0
  220. package/packages/@monomind/cli/dist/src/ui/data/avatars/feedback-synthesizer.svg +54 -0
  221. package/packages/@monomind/cli/dist/src/ui/data/avatars/finance-tracker.svg +54 -0
  222. package/packages/@monomind/cli/dist/src/ui/data/avatars/frontend-developer.svg +54 -0
  223. package/packages/@monomind/cli/dist/src/ui/data/avatars/game-audio-engineer.svg +59 -0
  224. package/packages/@monomind/cli/dist/src/ui/data/avatars/game-designer.svg +54 -0
  225. package/packages/@monomind/cli/dist/src/ui/data/avatars/gossip-coordinator.svg +54 -0
  226. package/packages/@monomind/cli/dist/src/ui/data/avatars/hierarchical-coord.svg +54 -0
  227. package/packages/@monomind/cli/dist/src/ui/data/avatars/incident-commander.svg +57 -0
  228. package/packages/@monomind/cli/dist/src/ui/data/avatars/infrastructure.svg +54 -0
  229. package/packages/@monomind/cli/dist/src/ui/data/avatars/input-validator.svg +53 -0
  230. package/packages/@monomind/cli/dist/src/ui/data/avatars/ios-developer.svg +54 -0
  231. package/packages/@monomind/cli/dist/src/ui/data/avatars/issue-tracker.svg +53 -0
  232. package/packages/@monomind/cli/dist/src/ui/data/avatars/judge.svg +55 -0
  233. package/packages/@monomind/cli/dist/src/ui/data/avatars/launch-strategist.svg +54 -0
  234. package/packages/@monomind/cli/dist/src/ui/data/avatars/legal-compliance.svg +53 -0
  235. package/packages/@monomind/cli/dist/src/ui/data/avatars/level-designer.svg +53 -0
  236. package/packages/@monomind/cli/dist/src/ui/data/avatars/load-balancer.svg +57 -0
  237. package/packages/@monomind/cli/dist/src/ui/data/avatars/mcp-builder.svg +53 -0
  238. package/packages/@monomind/cli/dist/src/ui/data/avatars/memory-coordinator.svg +55 -0
  239. package/packages/@monomind/cli/dist/src/ui/data/avatars/mesh-coordinator.svg +55 -0
  240. package/packages/@monomind/cli/dist/src/ui/data/avatars/ml-developer.svg +58 -0
  241. package/packages/@monomind/cli/dist/src/ui/data/avatars/mobile-app-builder.svg +53 -0
  242. package/packages/@monomind/cli/dist/src/ui/data/avatars/mobile-dev.svg +54 -0
  243. package/packages/@monomind/cli/dist/src/ui/data/avatars/model-qa.svg +58 -0
  244. package/packages/@monomind/cli/dist/src/ui/data/avatars/narrative-designer.svg +58 -0
  245. package/packages/@monomind/cli/dist/src/ui/data/avatars/outbound-strategist.svg +55 -0
  246. package/packages/@monomind/cli/dist/src/ui/data/avatars/path-validator.svg +54 -0
  247. package/packages/@monomind/cli/dist/src/ui/data/avatars/payment-agent.svg +53 -0
  248. package/packages/@monomind/cli/dist/src/ui/data/avatars/perf-analyzer.svg +58 -0
  249. package/packages/@monomind/cli/dist/src/ui/data/avatars/pipeline-analyst.svg +54 -0
  250. package/packages/@monomind/cli/dist/src/ui/data/avatars/planner.svg +55 -0
  251. package/packages/@monomind/cli/dist/src/ui/data/avatars/pr-manager.svg +54 -0
  252. package/packages/@monomind/cli/dist/src/ui/data/avatars/pricing-strategist.svg +54 -0
  253. package/packages/@monomind/cli/dist/src/ui/data/avatars/product-manager.svg +54 -0
  254. package/packages/@monomind/cli/dist/src/ui/data/avatars/production-validator.svg +54 -0
  255. package/packages/@monomind/cli/dist/src/ui/data/avatars/project-shepherd.svg +54 -0
  256. package/packages/@monomind/cli/dist/src/ui/data/avatars/proposal-strategist.svg +54 -0
  257. package/packages/@monomind/cli/dist/src/ui/data/avatars/prosecutor.svg +57 -0
  258. package/packages/@monomind/cli/dist/src/ui/data/avatars/pseudocode.svg +53 -0
  259. package/packages/@monomind/cli/dist/src/ui/data/avatars/queen-coordinator.svg +55 -0
  260. package/packages/@monomind/cli/dist/src/ui/data/avatars/quorum-manager.svg +53 -0
  261. package/packages/@monomind/cli/dist/src/ui/data/avatars/raft-manager.svg +53 -0
  262. package/packages/@monomind/cli/dist/src/ui/data/avatars/reality-checker.svg +58 -0
  263. package/packages/@monomind/cli/dist/src/ui/data/avatars/recruitment.svg +58 -0
  264. package/packages/@monomind/cli/dist/src/ui/data/avatars/refinement.svg +53 -0
  265. package/packages/@monomind/cli/dist/src/ui/data/avatars/release-manager.svg +54 -0
  266. package/packages/@monomind/cli/dist/src/ui/data/avatars/repo-architect.svg +54 -0
  267. package/packages/@monomind/cli/dist/src/ui/data/avatars/researcher.svg +58 -0
  268. package/packages/@monomind/cli/dist/src/ui/data/avatars/resource-allocator.svg +53 -0
  269. package/packages/@monomind/cli/dist/src/ui/data/avatars/reviewer.svg +53 -0
  270. package/packages/@monomind/cli/dist/src/ui/data/avatars/safe-executor.svg +53 -0
  271. package/packages/@monomind/cli/dist/src/ui/data/avatars/sales-coach.svg +53 -0
  272. package/packages/@monomind/cli/dist/src/ui/data/avatars/sales-engineer.svg +58 -0
  273. package/packages/@monomind/cli/dist/src/ui/data/avatars/scout-explorer.svg +58 -0
  274. package/packages/@monomind/cli/dist/src/ui/data/avatars/security-architect.svg +54 -0
  275. package/packages/@monomind/cli/dist/src/ui/data/avatars/security-auditor.svg +55 -0
  276. package/packages/@monomind/cli/dist/src/ui/data/avatars/senior-developer.svg +58 -0
  277. package/packages/@monomind/cli/dist/src/ui/data/avatars/senior-pm.svg +58 -0
  278. package/packages/@monomind/cli/dist/src/ui/data/avatars/seo-specialist.svg +57 -0
  279. package/packages/@monomind/cli/dist/src/ui/data/avatars/social-media.svg +54 -0
  280. package/packages/@monomind/cli/dist/src/ui/data/avatars/solidity-engineer.svg +58 -0
  281. package/packages/@monomind/cli/dist/src/ui/data/avatars/sparc-coder.svg +58 -0
  282. package/packages/@monomind/cli/dist/src/ui/data/avatars/sparc-coord.svg +56 -0
  283. package/packages/@monomind/cli/dist/src/ui/data/avatars/specification.svg +57 -0
  284. package/packages/@monomind/cli/dist/src/ui/data/avatars/sprint-prioritizer.svg +53 -0
  285. package/packages/@monomind/cli/dist/src/ui/data/avatars/sre.svg +54 -0
  286. package/packages/@monomind/cli/dist/src/ui/data/avatars/studio-operations.svg +53 -0
  287. package/packages/@monomind/cli/dist/src/ui/data/avatars/studio-producer.svg +55 -0
  288. package/packages/@monomind/cli/dist/src/ui/data/avatars/support-responder.svg +56 -0
  289. package/packages/@monomind/cli/dist/src/ui/data/avatars/system-architect.svg +54 -0
  290. package/packages/@monomind/cli/dist/src/ui/data/avatars/task-orchestrator.svg +56 -0
  291. package/packages/@monomind/cli/dist/src/ui/data/avatars/technical-artist.svg +53 -0
  292. package/packages/@monomind/cli/dist/src/ui/data/avatars/technical-writer.svg +59 -0
  293. package/packages/@monomind/cli/dist/src/ui/data/avatars/tester.svg +53 -0
  294. package/packages/@monomind/cli/dist/src/ui/data/avatars/threat-detection.svg +61 -0
  295. package/packages/@monomind/cli/dist/src/ui/data/avatars/trend-researcher.svg +54 -0
  296. package/packages/@monomind/cli/dist/src/ui/data/avatars/trial-director.svg +55 -0
  297. package/packages/@monomind/cli/dist/src/ui/data/avatars/unity-architect.svg +54 -0
  298. package/packages/@monomind/cli/dist/src/ui/data/avatars/visionos-engineer.svg +57 -0
  299. package/packages/@monomind/cli/dist/src/ui/data/avatars/worker-specialist.svg +55 -0
  300. package/packages/@monomind/cli/dist/src/ui/data/avatars/workflow-architect.svg +57 -0
  301. package/packages/@monomind/cli/dist/src/ui/data/avatars/workflow-automation.svg +54 -0
  302. package/packages/@monomind/cli/dist/src/ui/data/avatars/zk-steward.svg +54 -0
  303. package/packages/@monomind/cli/dist/src/ui/data/known-projects.json +1 -0
  304. package/packages/@monomind/cli/dist/src/ui/data/mastermind-sessions.json +1 -0
  305. package/packages/@monomind/cli/dist/src/ui/data/sessions/_index.json +1 -0
  306. package/packages/@monomind/cli/dist/src/ui/orgs.html +2215 -0
  307. package/packages/@monomind/cli/dist/src/ui/server.mjs +6206 -0
  308. package/packages/@monomind/cli/dist/src/ui/sse-manager.mjs +119 -0
  309. package/packages/@monomind/cli/dist/src/update/checker.js +1 -1
  310. package/packages/@monomind/cli/dist/workflow/builtin-handlers.js +321 -0
  311. package/packages/@monomind/cli/dist/workflow/engine.js +253 -0
  312. package/packages/@monomind/cli/dist/workflow/expression.js +98 -0
  313. package/packages/@monomind/cli/dist/workflow/types.js +2 -0
  314. package/packages/@monomind/cli/package.json +8 -6
@@ -0,0 +1,179 @@
1
+ import { describe, it, expect, afterEach } from 'vitest';
2
+ import { startDashboard, getDashboard } from '@monoes/monobrowse';
3
+ import { WebSocket } from 'ws';
4
+ const PORT = 14242; // Use non-conflicting test port
5
+ const SSE_PORT = 14243; // Separate port for SSE streaming tests
6
+ afterEach(() => {
7
+ getDashboard()?.close();
8
+ });
9
+ function makeEvent(overrides = {}) {
10
+ return {
11
+ runId: 'run-1',
12
+ playbookId: 'wf-1',
13
+ playbookName: 'Test WF',
14
+ nodeId: 'node-1',
15
+ nodeName: 'Test Node',
16
+ eventType: 'step_completed',
17
+ timestamp: Date.now(),
18
+ ...overrides,
19
+ };
20
+ }
21
+ describe('startDashboard', () => {
22
+ it('returns a dashboard server instance', async () => {
23
+ const dash = startDashboard(PORT);
24
+ expect(dash).toBeDefined();
25
+ expect(dash.port).toBe(PORT);
26
+ });
27
+ it('returns the same instance on repeated calls', async () => {
28
+ const a = startDashboard(PORT);
29
+ const b = startDashboard(PORT);
30
+ expect(a).toBe(b);
31
+ });
32
+ it('serves HTML at GET /', async () => {
33
+ startDashboard(PORT);
34
+ const res = await fetch(`http://localhost:${PORT}/`);
35
+ expect(res.status).toBe(200);
36
+ expect(res.headers.get('content-type')).toContain('text/html');
37
+ const body = await res.text();
38
+ expect(body).toContain('monomind');
39
+ });
40
+ it('GET /runs returns JSON array', async () => {
41
+ const dash = startDashboard(PORT);
42
+ const run = { id: 'r1', playbookId: 'wf', playbookName: 'WF', status: 'completed', startedAt: Date.now(), itemsProcessed: 1, itemsTotal: 1 };
43
+ dash.addRunRecord(run);
44
+ const res = await fetch(`http://localhost:${PORT}/runs`);
45
+ expect(res.status).toBe(200);
46
+ const body = await res.json();
47
+ expect(body.some(r => r.id === 'r1')).toBe(true);
48
+ });
49
+ it('POST /stop/:runId marks run as stop-requested', async () => {
50
+ const dash = startDashboard(PORT);
51
+ const res = await fetch(`http://localhost:${PORT}/stop/run-abc`, { method: 'POST' });
52
+ expect(res.status).toBe(200);
53
+ expect(dash.isStopRequested('run-abc')).toBe(true);
54
+ });
55
+ it('isStopRequested returns false for unknown runId', () => {
56
+ const dash = startDashboard(PORT);
57
+ expect(dash.isStopRequested('nonexistent')).toBe(false);
58
+ });
59
+ });
60
+ // ---------------------------------------------------------------------------
61
+ // SSE / WebSocket streaming tests
62
+ //
63
+ // The dashboard uses WebSocket (via 'ws') when the package is available, and
64
+ // falls back to Server-Sent Events when it is not. Since 'ws' IS installed in
65
+ // this repo the server runs in WebSocket mode. We test the streaming path
66
+ // (broadcast + ?dir= filter) through the WebSocket interface so the tests are
67
+ // consistent regardless of environment.
68
+ // ---------------------------------------------------------------------------
69
+ /**
70
+ * Open a WebSocket to the dashboard, wait for the initial 'history' message,
71
+ * then return a helper that collects subsequent messages.
72
+ */
73
+ function connectWs(port, dir) {
74
+ return new Promise((resolve, reject) => {
75
+ const url = dir ? `ws://127.0.0.1:${port}/?dir=${encodeURIComponent(dir)}` : `ws://127.0.0.1:${port}/`;
76
+ const ws = new WebSocket(url);
77
+ const messages = [];
78
+ ws.on('open', () => {
79
+ // history message arrives; resolve after we have it
80
+ ws.on('message', (data) => {
81
+ const parsed = JSON.parse(data.toString());
82
+ messages.push(parsed);
83
+ if (messages.length === 1 && parsed.type === 'history') {
84
+ resolve({ ws, messages, close: () => ws.close() });
85
+ }
86
+ });
87
+ });
88
+ ws.on('error', reject);
89
+ setTimeout(() => reject(new Error('WS connect timeout')), 3000);
90
+ });
91
+ }
92
+ describe('broadcast via WebSocket', () => {
93
+ it('delivers events to connected clients', async () => {
94
+ const dash = startDashboard(PORT);
95
+ // Wait a tick for the server to be ready
96
+ await new Promise(r => setTimeout(r, 50));
97
+ const { ws, messages, close } = await connectWs(PORT);
98
+ try {
99
+ // Wait for initial history message, then broadcast
100
+ dash.broadcast(makeEvent({ eventType: 'step_completed', nodeId: 'node-broadcast-1' }));
101
+ await new Promise(r => setTimeout(r, 100));
102
+ const events = messages.filter((m) => m.eventType !== undefined);
103
+ expect(events.length).toBeGreaterThan(0);
104
+ expect(events[0].nodeId).toBe('node-broadcast-1');
105
+ }
106
+ finally {
107
+ close();
108
+ }
109
+ });
110
+ it('?dir= filter — client with matching dir receives event', async () => {
111
+ const dash = startDashboard(PORT);
112
+ await new Promise(r => setTimeout(r, 50));
113
+ const dirA = '/projects/alpha';
114
+ const { messages, close } = await connectWs(PORT, dirA);
115
+ try {
116
+ dash.broadcast(makeEvent({ projectDir: dirA, nodeId: 'node-alpha' }));
117
+ await new Promise(r => setTimeout(r, 100));
118
+ const events = messages.filter((m) => m.eventType !== undefined);
119
+ expect(events.length).toBeGreaterThan(0);
120
+ expect(events[0].nodeId).toBe('node-alpha');
121
+ }
122
+ finally {
123
+ close();
124
+ }
125
+ });
126
+ it('?dir= filter — client with non-matching dir does NOT receive event', async () => {
127
+ const dash = startDashboard(PORT);
128
+ await new Promise(r => setTimeout(r, 50));
129
+ const { messages, close } = await connectWs(PORT, '/projects/beta');
130
+ try {
131
+ dash.broadcast(makeEvent({ projectDir: '/projects/alpha', nodeId: 'node-alpha-only' }));
132
+ await new Promise(r => setTimeout(r, 100));
133
+ const events = messages.filter((m) => m.eventType !== undefined);
134
+ expect(events.length).toBe(0);
135
+ }
136
+ finally {
137
+ close();
138
+ }
139
+ });
140
+ it('client without ?dir= receives all broadcasts', async () => {
141
+ const dash = startDashboard(PORT);
142
+ await new Promise(r => setTimeout(r, 50));
143
+ const { messages, close } = await connectWs(PORT);
144
+ try {
145
+ dash.broadcast(makeEvent({ projectDir: '/projects/alpha', nodeId: 'all-1' }));
146
+ dash.broadcast(makeEvent({ projectDir: '/projects/beta', nodeId: 'all-2' }));
147
+ await new Promise(r => setTimeout(r, 150));
148
+ const events = messages.filter((m) => m.eventType !== undefined);
149
+ expect(events.length).toBeGreaterThanOrEqual(2);
150
+ }
151
+ finally {
152
+ close();
153
+ }
154
+ });
155
+ });
156
+ describe('GET /events SSE endpoint', () => {
157
+ it('returns text/event-stream content-type when ws is unavailable', async () => {
158
+ // The dashboard is already started in ws mode on PORT.
159
+ // We verify the /events endpoint returns 404 in ws mode (ws is installed),
160
+ // which confirms the conditional branching works correctly.
161
+ const dash = startDashboard(PORT);
162
+ await new Promise(r => setTimeout(r, 50));
163
+ const res = await fetch(`http://127.0.0.1:${PORT}/events`, {
164
+ headers: { Accept: 'text/event-stream' },
165
+ });
166
+ // In ws mode the SSE endpoint is not registered — server returns 404
167
+ // In SSE-only mode it would return 200 with text/event-stream
168
+ // We test what the current mode actually does
169
+ if (res.status === 200) {
170
+ expect(res.headers.get('content-type')).toContain('text/event-stream');
171
+ await res.body?.cancel();
172
+ }
173
+ else {
174
+ // ws mode: SSE not registered
175
+ expect(res.status).toBe(404);
176
+ }
177
+ });
178
+ });
179
+ //# sourceMappingURL=browse-dashboard.test.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=browse-engine.test.d.ts.map
@@ -0,0 +1,122 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { runPlaybook } from '@monoes/monobrowse';
3
+ const triggerNode = { id: 'trigger', type: 'trigger.manual', config: {} };
4
+ describe('runPlaybook', () => {
5
+ it('runs a single-node trigger workflow', async () => {
6
+ const def = {
7
+ id: 'wf-1', name: 'Test', nodes: [triggerNode], connections: [],
8
+ };
9
+ const record = await runPlaybook(def);
10
+ expect(record.status).toBe('completed');
11
+ expect(record.playbookId).toBe('wf-1');
12
+ });
13
+ it('rejects cyclic workflow', async () => {
14
+ const def = {
15
+ id: 'cyclic', name: 'Cyclic',
16
+ nodes: [
17
+ { id: 'a', type: 'core.set', config: {} },
18
+ { id: 'b', type: 'core.set', config: {} },
19
+ ],
20
+ connections: [{ from: 'a', to: 'b' }, { from: 'b', to: 'a' }],
21
+ };
22
+ await expect(runPlaybook(def)).rejects.toThrow('cycle');
23
+ });
24
+ it('calls node handlers for action nodes', async () => {
25
+ const handler = vi.fn().mockResolvedValue([{ data: { result: 'ok' } }]);
26
+ const def = {
27
+ id: 'wf-2', name: 'Action Test',
28
+ nodes: [
29
+ triggerNode,
30
+ { id: 'act', type: 'action.linkedin.comment_post', config: { text: 'hi' } },
31
+ ],
32
+ connections: [{ from: 'trigger', to: 'act' }],
33
+ };
34
+ const handlers = new Map([['action.linkedin.comment_post', handler]]);
35
+ const record = await runPlaybook(def, { handlers });
36
+ expect(handler).toHaveBeenCalled();
37
+ expect(record.status).toBe('completed');
38
+ });
39
+ it('emits step events in order', async () => {
40
+ const events = [];
41
+ const def = { id: 'wf-3', name: 'Events', nodes: [triggerNode], connections: [] };
42
+ await runPlaybook(def, { onEvent: e => events.push(e.eventType) });
43
+ expect(events[0]).toBe('run_started');
44
+ expect(events[events.length - 1]).toBe('run_completed');
45
+ });
46
+ it('skips failed node when onError is skip', async () => {
47
+ const handler = vi.fn().mockRejectedValue(new Error('fail'));
48
+ const def = {
49
+ id: 'wf-4', name: 'Skip',
50
+ nodes: [
51
+ triggerNode,
52
+ { id: 'bad', type: 'action.x.fail', config: {}, onError: 'skip' },
53
+ ],
54
+ connections: [{ from: 'trigger', to: 'bad' }],
55
+ };
56
+ const handlers = new Map([['action.x.fail', handler]]);
57
+ const record = await runPlaybook(def, { handlers });
58
+ expect(record.status).toBe('completed');
59
+ });
60
+ it('stops on node failure when onError is stop (default)', async () => {
61
+ const handler = vi.fn().mockRejectedValue(new Error('boom'));
62
+ const def = {
63
+ id: 'wf-5', name: 'Stop',
64
+ nodes: [
65
+ triggerNode,
66
+ { id: 'bad', type: 'action.x.fail', config: {} },
67
+ ],
68
+ connections: [{ from: 'trigger', to: 'bad' }],
69
+ };
70
+ const handlers = new Map([['action.x.fail', handler]]);
71
+ const record = await runPlaybook(def, { handlers });
72
+ expect(record.status).toBe('failed');
73
+ expect(record.error).toContain('boom');
74
+ });
75
+ it('stops when AbortSignal is aborted', async () => {
76
+ const controller = new AbortController();
77
+ controller.abort();
78
+ const def = { id: 'wf-6', name: 'Abort', nodes: [triggerNode], connections: [] };
79
+ const record = await runPlaybook(def, { signal: controller.signal });
80
+ expect(record.status).toBe('stopped');
81
+ });
82
+ it('core.set transforms item fields', async () => {
83
+ const def = {
84
+ id: 'wf-7', name: 'Set',
85
+ nodes: [
86
+ { id: 'trigger', type: 'trigger.manual', config: { items: [{ data: { x: 1 } }] } },
87
+ { id: 'setNode', type: 'core.set', config: { y: 'hardcoded' } },
88
+ ],
89
+ connections: [{ from: 'trigger', to: 'setNode' }],
90
+ };
91
+ const events = [];
92
+ const record = await runPlaybook(def, { onEvent: e => events.push(e) });
93
+ expect(record.status).toBe('completed');
94
+ });
95
+ it('throws for unregistered action handler', async () => {
96
+ const def = {
97
+ id: 'wf-8', name: 'NoHandler',
98
+ nodes: [
99
+ triggerNode,
100
+ { id: 'act', type: 'action.missing.thing', config: {} },
101
+ ],
102
+ connections: [{ from: 'trigger', to: 'act' }],
103
+ };
104
+ const record = await runPlaybook(def);
105
+ expect(record.status).toBe('failed');
106
+ expect(record.error).toContain('No handler registered');
107
+ });
108
+ it('core.filter keeps matching items', async () => {
109
+ const def = {
110
+ id: 'wf-filter', name: 'Filter',
111
+ nodes: [
112
+ { id: 'trigger', type: 'trigger.manual', config: { items: [{ data: { x: 1 } }, { data: { x: 2 } }, { data: { x: 3 } }] } },
113
+ { id: 'filter', type: 'core.filter', config: { expression: '{{$json.x}}' } },
114
+ ],
115
+ connections: [{ from: 'trigger', to: 'filter' }],
116
+ };
117
+ const record = await runPlaybook(def);
118
+ expect(record.status).toBe('completed');
119
+ expect(record.itemsProcessed).toBeGreaterThan(0);
120
+ });
121
+ });
122
+ //# sourceMappingURL=browse-engine.test.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=browse-expression.test.d.ts.map
@@ -0,0 +1,54 @@
1
+ import { describe, it, expect, afterEach, vi } from 'vitest';
2
+ import { resolveExpression, resolveConfig } from '@monoes/monobrowse';
3
+ const item = { data: { url: 'https://linkedin.com/post/123', comment: 'Great post!' } };
4
+ const nodeOutputs = {
5
+ 'trigger': [{ data: { url: 'https://linkedin.com/post/123' } }],
6
+ };
7
+ const params = { text: 'Hello world', post_url: 'https://linkedin.com/post/123' };
8
+ describe('resolveExpression', () => {
9
+ it('resolves $json fields', () => {
10
+ expect(resolveExpression('{{$json.url}}', item, nodeOutputs, params)).toBe('https://linkedin.com/post/123');
11
+ });
12
+ it('resolves $env variables', () => {
13
+ vi.stubEnv('TEST_VAR', 'test-value');
14
+ expect(resolveExpression('{{$env.TEST_VAR}}', item, nodeOutputs, params)).toBe('test-value');
15
+ });
16
+ it('resolves params', () => {
17
+ expect(resolveExpression('{{params.text}}', item, nodeOutputs, params)).toBe('Hello world');
18
+ });
19
+ it('resolves node output references', () => {
20
+ expect(resolveExpression('{{$node.trigger.url}}', item, nodeOutputs, params)).toBe('https://linkedin.com/post/123');
21
+ });
22
+ it('resolves $node bracket notation', () => {
23
+ expect(resolveExpression('{{$node["trigger"].url}}', item, nodeOutputs, params)).toBe('https://linkedin.com/post/123');
24
+ });
25
+ it('returns raw string if no template markers', () => {
26
+ expect(resolveExpression('plain text', item, nodeOutputs, params)).toBe('plain text');
27
+ });
28
+ it('throws on unresolved expression', () => {
29
+ expect(() => resolveExpression('{{$json.missing}}', item, nodeOutputs, params)).toThrow('Unresolved');
30
+ });
31
+ it('replaces duplicate placeholders in a single template', () => {
32
+ const doubled = { data: { x: 'hello' } };
33
+ expect(resolveExpression('{{$json.x}} and {{$json.x}}', doubled, {}, {})).toBe('hello and hello');
34
+ });
35
+ it('throws when $node output array is empty', () => {
36
+ expect(() => resolveExpression('{{$node.empty.field}}', item, { empty: [] }, params)).toThrow('Unresolved');
37
+ });
38
+ it('throws when $node bracket field is missing', () => {
39
+ expect(() => resolveExpression('{{$node["trigger"].missing}}', item, nodeOutputs, params)).toThrow('Unresolved');
40
+ });
41
+ });
42
+ afterEach(() => {
43
+ vi.unstubAllEnvs();
44
+ });
45
+ describe('resolveConfig', () => {
46
+ it('resolves all string values in a config object', () => {
47
+ const config = { post_url: '{{$json.url}}', text: '{{params.text}}', count: 3 };
48
+ const result = resolveConfig(config, item, nodeOutputs, params);
49
+ expect(result.post_url).toBe('https://linkedin.com/post/123');
50
+ expect(result.text).toBe('Hello world');
51
+ expect(result.count).toBe(3);
52
+ });
53
+ });
54
+ //# sourceMappingURL=browse-expression.test.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=browse-store.test.d.ts.map
@@ -0,0 +1,99 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { readPlaybook, writePlaybookRun, listPlaybookRuns, readAction, clearRunStore } from '@monoes/monobrowse';
3
+ import { writeFileSync, mkdirSync, rmSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { tmpdir } from 'node:os';
6
+ const TMP = join(tmpdir(), 'browse-store-test-' + Date.now());
7
+ beforeEach(() => {
8
+ clearRunStore();
9
+ mkdirSync(join(TMP, 'playbooks'), { recursive: true });
10
+ mkdirSync(join(TMP, 'actions'), { recursive: true });
11
+ });
12
+ afterEach(() => {
13
+ rmSync(TMP, { recursive: true, force: true });
14
+ });
15
+ describe('readPlaybook', () => {
16
+ it('parses a valid playbook JSON file', async () => {
17
+ const pb = {
18
+ id: 'test-pb',
19
+ name: 'Test Playbook',
20
+ nodes: [{ id: 'trigger', type: 'trigger.manual', config: {} }],
21
+ connections: [],
22
+ };
23
+ const p = join(TMP, 'playbooks', 'test.json');
24
+ writeFileSync(p, JSON.stringify(pb));
25
+ const result = await readPlaybook(p);
26
+ expect(result.id).toBe('test-pb');
27
+ expect(result.nodes).toHaveLength(1);
28
+ });
29
+ it('throws on missing file', async () => {
30
+ await expect(readPlaybook(join(TMP, 'nonexistent.json'))).rejects.toThrow();
31
+ });
32
+ it('throws on invalid JSON', async () => {
33
+ const p = join(TMP, 'playbooks', 'bad.json');
34
+ writeFileSync(p, 'not json');
35
+ await expect(readPlaybook(p)).rejects.toThrow();
36
+ });
37
+ it('throws if nodes array is missing', async () => {
38
+ const p = join(TMP, 'playbooks', 'no-nodes.json');
39
+ writeFileSync(p, JSON.stringify({ id: 'x', name: 'y', connections: [] }));
40
+ await expect(readPlaybook(p)).rejects.toThrow('nodes');
41
+ });
42
+ });
43
+ describe('readAction', () => {
44
+ it('parses a valid action JSON file', async () => {
45
+ const action = {
46
+ id: 'linkedin:comment_post',
47
+ platform: 'linkedin',
48
+ name: 'Comment on Post',
49
+ params: ['post_url', 'text'],
50
+ steps: [],
51
+ };
52
+ const p = join(TMP, 'actions', 'comment.json');
53
+ writeFileSync(p, JSON.stringify(action));
54
+ const result = await readAction(p);
55
+ expect(result.id).toBe('linkedin:comment_post');
56
+ expect(result.params).toContain('post_url');
57
+ });
58
+ it('throws on missing action file', async () => {
59
+ await expect(readAction(join(TMP, 'actions', 'nonexistent.json'))).rejects.toThrow();
60
+ });
61
+ it('throws on invalid action JSON', async () => {
62
+ const p = join(TMP, 'actions', 'bad.json');
63
+ writeFileSync(p, 'not json');
64
+ await expect(readAction(p)).rejects.toThrow();
65
+ });
66
+ it('throws if action steps array is missing', async () => {
67
+ const p = join(TMP, 'actions', 'no-steps.json');
68
+ writeFileSync(p, JSON.stringify({ id: 'x', platform: 'y', name: 'z', params: [] }));
69
+ await expect(readAction(p)).rejects.toThrow('steps');
70
+ });
71
+ });
72
+ describe('writePlaybookRun + listPlaybookRuns', () => {
73
+ it('stores and retrieves run records', async () => {
74
+ const record = {
75
+ id: 'run-1',
76
+ playbookId: 'pb-1',
77
+ playbookName: 'Test PB',
78
+ status: 'completed',
79
+ startedAt: Date.now(),
80
+ completedAt: Date.now() + 1000,
81
+ itemsProcessed: 5,
82
+ itemsTotal: 5,
83
+ };
84
+ await writePlaybookRun(record);
85
+ const runs = await listPlaybookRuns();
86
+ const found = runs.find(r => r.id === 'run-1');
87
+ expect(found).toBeDefined();
88
+ expect(found?.status).toBe('completed');
89
+ });
90
+ it('filters runs by playbookId', async () => {
91
+ const r1 = { id: 'r1', playbookId: 'pb-a', playbookName: 'A', status: 'completed', startedAt: 1, itemsProcessed: 1, itemsTotal: 1 };
92
+ const r2 = { id: 'r2', playbookId: 'pb-b', playbookName: 'B', status: 'failed', startedAt: 2, itemsProcessed: 0, itemsTotal: 1 };
93
+ await writePlaybookRun(r1);
94
+ await writePlaybookRun(r2);
95
+ const runs = await listPlaybookRuns('pb-a');
96
+ expect(runs.every(r => r.playbookId === 'pb-a')).toBe(true);
97
+ });
98
+ });
99
+ //# sourceMappingURL=browse-store.test.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=browse-workflow-types.test.d.ts.map
@@ -0,0 +1,33 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ describe('PlaybookDef', () => {
3
+ it('accepts a valid playbook definition', () => {
4
+ const wf = {
5
+ id: 'my-playbook',
6
+ name: 'My Playbook',
7
+ nodes: [
8
+ { id: 'n1', type: 'trigger.manual', config: {} },
9
+ { id: 'n2', type: 'action.linkedin.comment_post', config: { post_url: '{{$json.url}}', text: 'hi' } },
10
+ ],
11
+ connections: [{ from: 'n1', to: 'n2' }],
12
+ };
13
+ expect(wf.nodes).toHaveLength(2);
14
+ expect(wf.connections[0].from).toBe('n1');
15
+ });
16
+ it('accepts a valid ActionDef with steps', () => {
17
+ const action = {
18
+ id: 'linkedin:comment_post',
19
+ platform: 'linkedin',
20
+ name: 'Comment on Post',
21
+ params: ['post_url', 'text'],
22
+ steps: [
23
+ { type: 'navigate', url: '{{params.post_url}}' },
24
+ { type: 'find', selectors: ['.comment-box', '[aria-label="Add a comment"]'], as: 'box' },
25
+ { type: 'click', target: '{{box}}' },
26
+ { type: 'type', target: '{{box}}', text: '{{params.text}}', humanDelay: true },
27
+ { type: 'wait', condition: 'network_idle', timeout: 3000 },
28
+ ],
29
+ };
30
+ expect(action.steps).toHaveLength(5);
31
+ });
32
+ });
33
+ //# sourceMappingURL=browse-workflow-types.test.js.map
@@ -0,0 +1,11 @@
1
+ import type { ActionDef } from './types.js';
2
+ export declare function buildPrompt(task: string, domSnapshot: string): string;
3
+ export declare function parseActionResponse(response: string): ActionDef;
4
+ export declare function analyzeAndBuild(options: {
5
+ url: string;
6
+ task: string;
7
+ client: import('@monoes/monobrowse').CdpClient;
8
+ sessionId: string;
9
+ outputDir: string;
10
+ }): Promise<ActionDef>;
11
+ //# sourceMappingURL=analyzer.d.ts.map
@@ -0,0 +1,71 @@
1
+ import { writeFile, mkdir } from 'fs/promises';
2
+ import { join } from 'path';
3
+ const SYSTEM_PROMPT = `You are a browser automation expert. Given a DOM snippet and a task description, generate a JSON action definition that automates the task.
4
+
5
+ Rules:
6
+ - Use ONLY these step types: navigate, find, click, type, wait, extract
7
+ - For "find" steps, provide 2-3 selector alternatives in order of preference (CSS, aria-label, XPath)
8
+ - For "type" steps, set humanDelay: true for form inputs
9
+ - Parameters use {{params.name}} syntax
10
+ - The action id format is "custom:<snake_case_name>"
11
+ - Output ONLY a JSON code block, no explanation before or after
12
+
13
+ JSON schema:
14
+ {
15
+ "id": "custom:action_name",
16
+ "platform": "custom",
17
+ "name": "Human Readable Name",
18
+ "params": ["param1", "param2"],
19
+ "steps": [...]
20
+ }`;
21
+ export function buildPrompt(task, domSnapshot) {
22
+ const truncated = domSnapshot.slice(0, 8000);
23
+ return `Task: ${task}\n\nDOM snapshot:\n${truncated}\n\nGenerate the action JSON.`;
24
+ }
25
+ export function parseActionResponse(response) {
26
+ const match = response.match(/```(?:json)?\s*([\s\S]*?)```/);
27
+ if (!match)
28
+ throw new Error('No JSON block found in Claude response');
29
+ try {
30
+ return JSON.parse(match[1].trim());
31
+ }
32
+ catch (err) {
33
+ throw new Error(`Invalid JSON in response: ${err.message}`);
34
+ }
35
+ }
36
+ export async function analyzeAndBuild(options) {
37
+ const { url, task, client, sessionId, outputDir } = options;
38
+ // Navigate to the URL and wait for load
39
+ await client.send('Page.navigate', { url }, sessionId);
40
+ await new Promise(r => setTimeout(r, 2500)); // allow page to settle
41
+ // Capture DOM snapshot — accessibility tree + visible text
42
+ const domResult = await client.send('DOM.getDocument', { depth: 3, pierce: true }, sessionId);
43
+ const outerHtml = await client.send('DOM.getOuterHTML', { nodeId: domResult.root.nodeId }, sessionId);
44
+ // Strip scripts/styles, keep interactive elements
45
+ const cleanDom = outerHtml.outerHTML
46
+ .replace(/<script[\s\S]*?<\/script>/gi, '')
47
+ .replace(/<style[\s\S]*?<\/style>/gi, '')
48
+ .replace(/\s{2,}/g, ' ')
49
+ .slice(0, 12000);
50
+ // Call Claude API
51
+ const { Anthropic } = await import('@anthropic-ai/sdk');
52
+ const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
53
+ const message = await anthropic.messages.create({
54
+ model: 'claude-sonnet-4-6',
55
+ max_tokens: 2048,
56
+ system: SYSTEM_PROMPT,
57
+ messages: [{ role: 'user', content: buildPrompt(task, cleanDom) }],
58
+ });
59
+ const responseText = message.content
60
+ .filter(c => c.type === 'text')
61
+ .map(c => c.text)
62
+ .join('');
63
+ const action = parseActionResponse(responseText);
64
+ // Write to output directory
65
+ await mkdir(outputDir, { recursive: true });
66
+ const filename = action.id.replace(/[^a-z0-9_-]/gi, '_') + '.json';
67
+ const outPath = join(outputDir, filename);
68
+ await writeFile(outPath, JSON.stringify(action, null, 2));
69
+ return action;
70
+ }
71
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1,47 @@
1
+ export type StepType = 'navigate' | 'find' | 'click' | 'type' | 'wait' | 'extract' | 'condition';
2
+ export interface NavigateStep {
3
+ type: 'navigate';
4
+ url: string;
5
+ }
6
+ export interface FindStep {
7
+ type: 'find';
8
+ selectors: string[];
9
+ as: string;
10
+ }
11
+ export interface ClickStep {
12
+ type: 'click';
13
+ target: string;
14
+ }
15
+ export interface TypeStep {
16
+ type: 'type';
17
+ target: string;
18
+ text: string;
19
+ humanDelay?: boolean;
20
+ }
21
+ export interface WaitStep {
22
+ type: 'wait';
23
+ condition: 'network_idle' | 'selector' | 'duration';
24
+ timeout?: number;
25
+ selector?: string;
26
+ }
27
+ export interface ExtractStep {
28
+ type: 'extract';
29
+ target: string;
30
+ as: string;
31
+ attribute?: string;
32
+ }
33
+ export interface ConditionStep {
34
+ type: 'condition';
35
+ expression: string;
36
+ then: StepDef[];
37
+ else?: StepDef[];
38
+ }
39
+ export type StepDef = NavigateStep | FindStep | ClickStep | TypeStep | WaitStep | ExtractStep | ConditionStep;
40
+ export interface ActionDef {
41
+ id: string;
42
+ platform: string;
43
+ name: string;
44
+ params: string[];
45
+ steps: StepDef[];
46
+ }
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,3 @@
1
+ import type { PlatformAdapter } from './index.js';
2
+ export declare const geminiAdapter: PlatformAdapter;
3
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1,16 @@
1
+ export const geminiAdapter = {
2
+ platform: 'gemini',
3
+ baseURL: 'https://gemini.google.com',
4
+ reservedPaths: ['/app', '/faq', '/privacy', '/terms', '/about'],
5
+ loginURL: () => 'https://accounts.google.com/signin',
6
+ async isLoggedIn(page) {
7
+ const url = await page.url();
8
+ if (url.includes('accounts.google.com'))
9
+ return false;
10
+ return page.evaluate(`!!document.querySelector('bard-sidenav, [data-test-id="bard-sidenav"]')`);
11
+ },
12
+ async extractUsername(page) {
13
+ return page.evaluate(`(document.querySelector('[data-email]')?.getAttribute('data-email') ?? 'unknown')`);
14
+ },
15
+ };
16
+ //# sourceMappingURL=gemini.js.map