@monoes/monomindcli 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/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/bin/cli.js +3 -1
- package/dist/dashboard/server.js +137 -0
- package/dist/src/__tests__/browse-adapters.test.d.ts +2 -0
- package/dist/src/__tests__/browse-adapters.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-adapters.test.js +51 -0
- package/dist/src/__tests__/browse-adapters.test.js.map +1 -0
- package/dist/src/__tests__/browse-analyzer.test.d.ts +2 -0
- package/dist/src/__tests__/browse-analyzer.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-analyzer.test.js +68 -0
- package/dist/src/__tests__/browse-analyzer.test.js.map +1 -0
- package/dist/src/__tests__/browse-builtin-handlers.test.d.ts +2 -0
- package/dist/src/__tests__/browse-builtin-handlers.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-builtin-handlers.test.js +139 -0
- package/dist/src/__tests__/browse-builtin-handlers.test.js.map +1 -0
- package/dist/src/__tests__/browse-cdp.test.d.ts +2 -0
- package/dist/src/__tests__/browse-cdp.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-cdp.test.js +169 -0
- package/dist/src/__tests__/browse-cdp.test.js.map +1 -0
- package/dist/src/__tests__/browse-dashboard.test.d.ts +2 -0
- package/dist/src/__tests__/browse-dashboard.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-dashboard.test.js +179 -0
- package/dist/src/__tests__/browse-dashboard.test.js.map +1 -0
- package/dist/src/__tests__/browse-engine.test.d.ts +2 -0
- package/dist/src/__tests__/browse-engine.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-engine.test.js +122 -0
- package/dist/src/__tests__/browse-engine.test.js.map +1 -0
- package/dist/src/__tests__/browse-expression.test.d.ts +2 -0
- package/dist/src/__tests__/browse-expression.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-expression.test.js +54 -0
- package/dist/src/__tests__/browse-expression.test.js.map +1 -0
- package/dist/src/__tests__/browse-store.test.d.ts +2 -0
- package/dist/src/__tests__/browse-store.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-store.test.js +99 -0
- package/dist/src/__tests__/browse-store.test.js.map +1 -0
- package/dist/src/__tests__/browse-workflow-types.test.d.ts +2 -0
- package/dist/src/__tests__/browse-workflow-types.test.d.ts.map +1 -0
- package/dist/src/__tests__/browse-workflow-types.test.js +33 -0
- package/dist/src/__tests__/browse-workflow-types.test.js.map +1 -0
- package/dist/src/browser/action-builder/analyzer.d.ts +11 -0
- package/dist/src/browser/action-builder/analyzer.d.ts.map +1 -0
- package/dist/src/browser/action-builder/analyzer.js +71 -0
- package/dist/src/browser/action-builder/analyzer.js.map +1 -0
- package/dist/src/browser/action-builder/types.d.ts +47 -0
- package/dist/src/browser/action-builder/types.d.ts.map +1 -0
- package/dist/src/browser/action-builder/types.js +2 -0
- package/dist/src/browser/action-builder/types.js.map +1 -0
- package/dist/src/browser/adapters/gemini.d.ts +3 -0
- package/dist/src/browser/adapters/gemini.d.ts.map +1 -0
- package/dist/src/browser/adapters/gemini.js +16 -0
- package/dist/src/browser/adapters/gemini.js.map +1 -0
- package/dist/src/browser/adapters/google.d.ts +3 -0
- package/dist/src/browser/adapters/google.d.ts.map +1 -0
- package/dist/src/browser/adapters/google.js +17 -0
- package/dist/src/browser/adapters/google.js.map +1 -0
- package/dist/src/browser/adapters/index.d.ts +19 -0
- package/dist/src/browser/adapters/index.d.ts.map +1 -0
- package/dist/src/browser/adapters/index.js +23 -0
- package/dist/src/browser/adapters/index.js.map +1 -0
- package/dist/src/browser/adapters/instagram.d.ts +3 -0
- package/dist/src/browser/adapters/instagram.d.ts.map +1 -0
- package/dist/src/browser/adapters/instagram.js +17 -0
- package/dist/src/browser/adapters/instagram.js.map +1 -0
- package/dist/src/browser/adapters/linkedin.d.ts +3 -0
- package/dist/src/browser/adapters/linkedin.d.ts.map +1 -0
- package/dist/src/browser/adapters/linkedin.js +19 -0
- package/dist/src/browser/adapters/linkedin.js.map +1 -0
- package/dist/src/browser/adapters/microsoft.d.ts +3 -0
- package/dist/src/browser/adapters/microsoft.d.ts.map +1 -0
- package/dist/src/browser/adapters/microsoft.js +16 -0
- package/dist/src/browser/adapters/microsoft.js.map +1 -0
- package/dist/src/browser/adapters/x.d.ts +3 -0
- package/dist/src/browser/adapters/x.d.ts.map +1 -0
- package/dist/src/browser/adapters/x.js +19 -0
- package/dist/src/browser/adapters/x.js.map +1 -0
- package/dist/src/browser/dashboard/api-types.d.ts +50 -0
- package/dist/src/browser/dashboard/api-types.d.ts.map +1 -0
- package/dist/src/browser/dashboard/api-types.js +14 -0
- package/dist/src/browser/dashboard/api-types.js.map +1 -0
- package/dist/src/browser/dashboard/server.d.ts +9 -0
- package/dist/src/browser/dashboard/server.d.ts.map +1 -0
- package/dist/src/browser/dashboard/server.js +62 -0
- package/dist/src/browser/dashboard/server.js.map +1 -0
- package/dist/src/browser/dashboard/ui.html +1811 -0
- package/dist/src/browser/workflow/builtin-handlers.d.ts +3 -0
- package/dist/src/browser/workflow/builtin-handlers.d.ts.map +1 -0
- package/dist/src/browser/workflow/builtin-handlers.js +343 -0
- package/dist/src/browser/workflow/builtin-handlers.js.map +1 -0
- package/dist/src/browser/workflow/engine.d.ts +15 -0
- package/dist/src/browser/workflow/engine.d.ts.map +1 -0
- package/dist/src/browser/workflow/engine.js +127 -0
- package/dist/src/browser/workflow/engine.js.map +1 -0
- package/dist/src/browser/workflow/expression.d.ts +4 -0
- package/dist/src/browser/workflow/expression.d.ts.map +1 -0
- package/dist/src/browser/workflow/expression.js +64 -0
- package/dist/src/browser/workflow/expression.js.map +1 -0
- package/dist/src/browser/workflow/store.d.ts +24 -0
- package/dist/src/browser/workflow/store.d.ts.map +1 -0
- package/dist/src/browser/workflow/store.js +145 -0
- package/dist/src/browser/workflow/store.js.map +1 -0
- package/dist/src/browser/workflow/types.d.ts +48 -0
- package/dist/src/browser/workflow/types.d.ts.map +1 -0
- package/dist/src/browser/workflow/types.js +2 -0
- package/dist/src/browser/workflow/types.js.map +1 -0
- package/dist/src/commands/browse-action.d.ts +4 -0
- package/dist/src/commands/browse-action.d.ts.map +1 -0
- package/dist/src/commands/browse-action.js +151 -0
- package/dist/src/commands/browse-action.js.map +1 -0
- package/dist/src/commands/browse-platform.d.ts +4 -0
- package/dist/src/commands/browse-platform.d.ts.map +1 -0
- package/dist/src/commands/browse-platform.js +117 -0
- package/dist/src/commands/browse-platform.js.map +1 -0
- package/dist/src/commands/browse-workflow.d.ts +4 -0
- package/dist/src/commands/browse-workflow.d.ts.map +1 -0
- package/dist/src/commands/browse-workflow.js +153 -0
- package/dist/src/commands/browse-workflow.js.map +1 -0
- package/dist/src/commands/browse.d.ts +10 -6
- package/dist/src/commands/browse.d.ts.map +1 -1
- package/dist/src/commands/browse.js +11 -2154
- package/dist/src/commands/browse.js.map +1 -1
- package/dist/src/commands/design-detect.d.ts +21 -0
- package/dist/src/commands/design-detect.d.ts.map +1 -0
- package/dist/src/commands/design-detect.js +127 -0
- package/dist/src/commands/design-detect.js.map +1 -0
- package/dist/src/commands/design-palette.d.ts +22 -0
- package/dist/src/commands/design-palette.d.ts.map +1 -0
- package/dist/src/commands/design-palette.js +539 -0
- package/dist/src/commands/design-palette.js.map +1 -0
- package/dist/src/commands/hooks-core-commands.d.ts +10 -0
- package/dist/src/commands/hooks-core-commands.d.ts.map +1 -0
- package/dist/src/commands/hooks-core-commands.js +377 -0
- package/dist/src/commands/hooks-core-commands.js.map +1 -0
- package/dist/src/commands/hooks-coverage-commands.d.ts +12 -0
- package/dist/src/commands/hooks-coverage-commands.d.ts.map +1 -0
- package/dist/src/commands/hooks-coverage-commands.js +1217 -0
- package/dist/src/commands/hooks-coverage-commands.js.map +1 -0
- package/dist/src/commands/hooks-coverage-utils.d.ts +42 -0
- package/dist/src/commands/hooks-coverage-utils.d.ts.map +1 -0
- package/dist/src/commands/hooks-coverage-utils.js +220 -0
- package/dist/src/commands/hooks-coverage-utils.js.map +1 -0
- package/dist/src/commands/hooks-extended-commands.d.ts +14 -0
- package/dist/src/commands/hooks-extended-commands.d.ts.map +1 -0
- package/dist/src/commands/hooks-extended-commands.js +579 -0
- package/dist/src/commands/hooks-extended-commands.js.map +1 -0
- package/dist/src/commands/hooks-formatting.d.ts +13 -0
- package/dist/src/commands/hooks-formatting.d.ts.map +1 -0
- package/dist/src/commands/hooks-formatting.js +42 -0
- package/dist/src/commands/hooks-formatting.js.map +1 -0
- package/dist/src/commands/hooks-routing-commands.d.ts +15 -0
- package/dist/src/commands/hooks-routing-commands.d.ts.map +1 -0
- package/dist/src/commands/hooks-routing-commands.js +723 -0
- package/dist/src/commands/hooks-routing-commands.js.map +1 -0
- package/dist/src/commands/hooks-workers.d.ts +9 -0
- package/dist/src/commands/hooks-workers.d.ts.map +1 -0
- package/dist/src/commands/hooks-workers.js +782 -0
- package/dist/src/commands/hooks-workers.js.map +1 -0
- package/dist/src/commands/hooks.d.ts +8 -0
- package/dist/src/commands/hooks.d.ts.map +1 -1
- package/dist/src/commands/hooks.js +179 -4103
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/index.d.ts +1 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +6 -0
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +14 -15
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/commands/tokens.d.ts.map +1 -1
- package/dist/src/commands/tokens.js +77 -1
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +18 -8
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +39 -5
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +25 -5
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/mcp-tools/browser-tools.d.ts +3 -5
- package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/browser-tools.js +619 -326
- package/dist/src/mcp-tools/browser-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-embedding.d.ts +161 -0
- package/dist/src/mcp-tools/hooks-embedding.d.ts.map +1 -0
- package/dist/src/mcp-tools/hooks-embedding.js +506 -0
- package/dist/src/mcp-tools/hooks-embedding.js.map +1 -0
- package/dist/src/mcp-tools/hooks-intelligence.d.ts +26 -0
- package/dist/src/mcp-tools/hooks-intelligence.d.ts.map +1 -0
- package/dist/src/mcp-tools/hooks-intelligence.js +1328 -0
- package/dist/src/mcp-tools/hooks-intelligence.js.map +1 -0
- package/dist/src/mcp-tools/hooks-routing.d.ts +27 -0
- package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -0
- package/dist/src/mcp-tools/hooks-routing.js +1591 -0
- package/dist/src/mcp-tools/hooks-routing.js.map +1 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts +3 -38
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +5 -3393
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.js +24 -14
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.js +54 -1
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
- package/dist/src/memory/embedding-operations.d.ts +58 -0
- package/dist/src/memory/embedding-operations.d.ts.map +1 -0
- package/dist/src/memory/embedding-operations.js +299 -0
- package/dist/src/memory/embedding-operations.js.map +1 -0
- package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
- package/dist/src/memory/ewc-consolidation.js +37 -3
- package/dist/src/memory/ewc-consolidation.js.map +1 -1
- package/dist/src/memory/hnsw-operations.d.ts +130 -0
- package/dist/src/memory/hnsw-operations.d.ts.map +1 -0
- package/dist/src/memory/hnsw-operations.js +400 -0
- package/dist/src/memory/hnsw-operations.js.map +1 -0
- package/dist/src/memory/intelligence.d.ts.map +1 -1
- package/dist/src/memory/intelligence.js +42 -23
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +52 -8
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-crud.d.ts +67 -0
- package/dist/src/memory/memory-crud.d.ts.map +1 -0
- package/dist/src/memory/memory-crud.js +415 -0
- package/dist/src/memory/memory-crud.js.map +1 -0
- package/dist/src/memory/memory-initializer.d.ts +9 -322
- package/dist/src/memory/memory-initializer.d.ts.map +1 -1
- package/dist/src/memory/memory-initializer.js +17 -1794
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/memory/memory-migrations.d.ts +30 -0
- package/dist/src/memory/memory-migrations.d.ts.map +1 -0
- package/dist/src/memory/memory-migrations.js +134 -0
- package/dist/src/memory/memory-migrations.js.map +1 -0
- package/dist/src/memory/memory-read.d.ts +78 -0
- package/dist/src/memory/memory-read.d.ts.map +1 -0
- package/dist/src/memory/memory-read.js +331 -0
- package/dist/src/memory/memory-read.js.map +1 -0
- package/dist/src/memory/memory-schema.d.ts +13 -0
- package/dist/src/memory/memory-schema.d.ts.map +1 -0
- package/dist/src/memory/memory-schema.js +167 -0
- package/dist/src/memory/memory-schema.js.map +1 -0
- package/dist/src/memory/sona-optimizer.d.ts.map +1 -1
- package/dist/src/memory/sona-optimizer.js +37 -4
- package/dist/src/memory/sona-optimizer.js.map +1 -1
- package/dist/src/monovector/route-outcomes.d.ts.map +1 -1
- package/dist/src/monovector/route-outcomes.js +16 -6
- package/dist/src/monovector/route-outcomes.js.map +1 -1
- package/dist/src/pricing/model-pricing.d.ts +41 -0
- package/dist/src/pricing/model-pricing.d.ts.map +1 -0
- package/dist/src/pricing/model-pricing.js +61 -0
- package/dist/src/pricing/model-pricing.js.map +1 -0
- package/dist/src/ui/.monomind/capture/active-run.json +1 -0
- package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/real-events-1782290897.convs.jsonl +3 -0
- package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/real-events-1782290897.jsonl +11 -0
- package/dist/src/ui/.monomind/orgs/system-trial-qa/runs/rigid-qa-restart-1782288201.jsonl +540 -0
- package/dist/src/ui/.monomind/orgs/system-trial-qa-threads.jsonl +3 -0
- package/dist/src/ui/.monomind/orgs/test-event-fix/runs/rigid-qa-restart-1782288201.jsonl +2 -0
- package/dist/src/ui/MODULARIZATION_PLAN.md +79 -0
- package/dist/src/ui/collector.mjs +23 -13
- package/dist/src/ui/dashboard.html +1652 -13
- package/dist/src/ui/data/known-projects.json +1 -0
- package/dist/src/ui/data/mastermind-events.jsonl +553 -0
- package/dist/src/ui/data/sessions/_index.json +1 -0
- package/dist/src/ui/data/sessions/final-sess-001.jsonl +542 -0
- package/dist/src/ui/data/unknown-events.jsonl +1 -0
- package/dist/src/ui/orgs.html +154 -10
- package/dist/src/ui/server.mjs +1131 -168
- package/dist/src/ui/sse-manager.mjs +119 -0
- package/dist/src/update/checker.js +1 -1
- package/dist/src/update/checker.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/workflow/builtin-handlers.js +321 -0
- package/dist/workflow/engine.js +253 -0
- package/dist/workflow/expression.js +98 -0
- package/dist/workflow/types.js +2 -0
- package/package.json +8 -5
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.startDashboard = startDashboard;
|
|
5
|
+
exports.getDashboard = getDashboard;
|
|
6
|
+
var node_http_1 = require("node:http");
|
|
7
|
+
var node_fs_1 = require("node:fs");
|
|
8
|
+
var node_path_1 = require("node:path");
|
|
9
|
+
var node_url_1 = require("node:url");
|
|
10
|
+
var node_module_1 = require("node:module");
|
|
11
|
+
var _require = (0, node_module_1.createRequire)(import.meta.url);
|
|
12
|
+
var __dirname = (0, node_path_1.dirname)((0, node_url_1.fileURLToPath)(import.meta.url));
|
|
13
|
+
var DEFAULT_PORT = parseInt((_a = process.env['MONOBROWSE_DASHBOARD_PORT']) !== null && _a !== void 0 ? _a : '4242', 10);
|
|
14
|
+
var MAX_RUN_HISTORY = 50;
|
|
15
|
+
var instance = null;
|
|
16
|
+
function startDashboard(port) {
|
|
17
|
+
var _a;
|
|
18
|
+
if (port === void 0) { port = DEFAULT_PORT; }
|
|
19
|
+
if (instance)
|
|
20
|
+
return instance;
|
|
21
|
+
var runHistory = [];
|
|
22
|
+
var stopRequests = new Set();
|
|
23
|
+
var clients = new Set(); // WebSocket or SSE response
|
|
24
|
+
// Try to load ws, fall back to SSE
|
|
25
|
+
var WebSocketServer = null;
|
|
26
|
+
try {
|
|
27
|
+
var wsModule = _require('ws');
|
|
28
|
+
WebSocketServer = (_a = wsModule.WebSocketServer) !== null && _a !== void 0 ? _a : wsModule.Server;
|
|
29
|
+
}
|
|
30
|
+
catch (_b) {
|
|
31
|
+
// ws not available — fall back to SSE
|
|
32
|
+
}
|
|
33
|
+
// ui.html must be copied to dist/ alongside server.js during build
|
|
34
|
+
var uiHtml;
|
|
35
|
+
try {
|
|
36
|
+
uiHtml = (0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, 'ui.html'), 'utf-8');
|
|
37
|
+
}
|
|
38
|
+
catch (_c) {
|
|
39
|
+
uiHtml = "<!DOCTYPE html><html><head><title>monobrowse dashboard</title></head><body style=\"background:#0f0f1a;color:#ccc;font-family:system-ui;padding:20px\"><h1>monobrowse dashboard</h1><p>Dashboard UI not found. Run the build to include ui.html.</p><script>const es=new EventSource('/events');es.onmessage=e=>console.log(JSON.parse(e.data));</script></body></html>";
|
|
40
|
+
}
|
|
41
|
+
var server = (0, node_http_1.createServer)(function (req, res) {
|
|
42
|
+
var _a;
|
|
43
|
+
var url = (_a = req.url) !== null && _a !== void 0 ? _a : '/';
|
|
44
|
+
if (url === '/' && req.method === 'GET') {
|
|
45
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
46
|
+
res.end(uiHtml);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (url === '/runs' && req.method === 'GET') {
|
|
50
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
51
|
+
res.end(JSON.stringify(runHistory));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (url.startsWith('/stop/') && req.method === 'POST') {
|
|
55
|
+
var runId = url.slice(6);
|
|
56
|
+
stopRequests.add(runId);
|
|
57
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
58
|
+
res.end(JSON.stringify({ ok: true, runId: runId }));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (url === '/events' && (req.method === 'GET' || req.method === 'HEAD') && !WebSocketServer) {
|
|
62
|
+
// SSE endpoint (fallback when ws not available).
|
|
63
|
+
// No CORS header — the dashboard is served from 127.0.0.1:4242 and no cross-origin
|
|
64
|
+
// access is needed. A wildcard ACAO would let any web page subscribe to workflow events.
|
|
65
|
+
res.writeHead(200, {
|
|
66
|
+
'Content-Type': 'text/event-stream',
|
|
67
|
+
'Cache-Control': 'no-cache',
|
|
68
|
+
'Connection': 'keep-alive',
|
|
69
|
+
});
|
|
70
|
+
res.write("data: ".concat(JSON.stringify({ type: 'connected' }), "\n\n"));
|
|
71
|
+
clients.add(res);
|
|
72
|
+
req.on('close', function () { return clients.delete(res); });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
res.writeHead(404);
|
|
76
|
+
res.end('Not found');
|
|
77
|
+
});
|
|
78
|
+
if (WebSocketServer) {
|
|
79
|
+
var wss = new WebSocketServer({ server: server });
|
|
80
|
+
wss.on('connection', function (ws) {
|
|
81
|
+
clients.add(ws);
|
|
82
|
+
ws.send(JSON.stringify({ type: 'history', runs: runHistory }));
|
|
83
|
+
ws.on('close', function () { return clients.delete(ws); });
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
server.on('error', function (err) {
|
|
87
|
+
if (err.code === 'EADDRINUSE') {
|
|
88
|
+
console.error("Dashboard port ".concat(port, " is already in use. Set MONOBROWSE_DASHBOARD_PORT to use a different port."));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.error("Dashboard server error: ".concat(err.message));
|
|
92
|
+
}
|
|
93
|
+
instance = null;
|
|
94
|
+
process.exit(1);
|
|
95
|
+
});
|
|
96
|
+
server.listen(port, '127.0.0.1');
|
|
97
|
+
function broadcast(event) {
|
|
98
|
+
var msg = JSON.stringify(event);
|
|
99
|
+
for (var _i = 0, clients_1 = clients; _i < clients_1.length; _i++) {
|
|
100
|
+
var client = clients_1[_i];
|
|
101
|
+
try {
|
|
102
|
+
if (typeof client.send === 'function') {
|
|
103
|
+
client.send(msg); // WebSocket
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
client.write("data: ".concat(msg, "\n\n")); // SSE
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (_a) {
|
|
110
|
+
clients.delete(client);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function addRunRecord(record) {
|
|
115
|
+
var idx = runHistory.findIndex(function (r) { return r.id === record.id; });
|
|
116
|
+
if (idx >= 0) {
|
|
117
|
+
runHistory[idx] = record;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
runHistory.unshift(record);
|
|
121
|
+
if (runHistory.length > MAX_RUN_HISTORY)
|
|
122
|
+
runHistory.pop();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function isStopRequested(runId) {
|
|
126
|
+
return stopRequests.has(runId);
|
|
127
|
+
}
|
|
128
|
+
function close() {
|
|
129
|
+
server.close();
|
|
130
|
+
instance = null;
|
|
131
|
+
}
|
|
132
|
+
instance = { broadcast: broadcast, addRunRecord: addRunRecord, isStopRequested: isStopRequested, close: close, port: port };
|
|
133
|
+
return instance;
|
|
134
|
+
}
|
|
135
|
+
function getDashboard() {
|
|
136
|
+
return instance;
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-adapters.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/browse-adapters.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/__tests__/browse-adapters.test.ts
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
+
import { getAdapter, adapters } from '@monoes/monobrowse';
|
|
4
|
+
function mockPage(isLoggedIn, username = 'testuser') {
|
|
5
|
+
return {
|
|
6
|
+
evaluate: vi.fn().mockImplementation((expr) => {
|
|
7
|
+
if (expr.includes('querySelector'))
|
|
8
|
+
return Promise.resolve(isLoggedIn ? true : false);
|
|
9
|
+
return Promise.resolve(username);
|
|
10
|
+
}),
|
|
11
|
+
url: vi.fn().mockResolvedValue('https://example.com'),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
describe('adapter registry', () => {
|
|
15
|
+
it('has all 6 platforms', () => {
|
|
16
|
+
expect(adapters.size).toBe(6);
|
|
17
|
+
for (const p of ['linkedin', 'instagram', 'x', 'gemini', 'google', 'microsoft']) {
|
|
18
|
+
expect(adapters.has(p)).toBe(true);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
it('getAdapter throws for unknown platform', () => {
|
|
22
|
+
expect(() => getAdapter('myspace')).toThrow('Unknown platform');
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe('each adapter', () => {
|
|
26
|
+
const platforms = ['linkedin', 'instagram', 'x', 'gemini', 'google', 'microsoft'];
|
|
27
|
+
for (const platform of platforms) {
|
|
28
|
+
describe(platform, () => {
|
|
29
|
+
const adapter = getAdapter(platform);
|
|
30
|
+
it('has required fields', () => {
|
|
31
|
+
expect(typeof adapter.platform).toBe('string');
|
|
32
|
+
expect(adapter.baseURL).toMatch(/^https?:\/\//);
|
|
33
|
+
expect(Array.isArray(adapter.reservedPaths)).toBe(true);
|
|
34
|
+
expect(adapter.reservedPaths.length).toBeGreaterThan(0);
|
|
35
|
+
expect(typeof adapter.loginURL()).toBe('string');
|
|
36
|
+
});
|
|
37
|
+
it('isLoggedIn returns boolean', async () => {
|
|
38
|
+
const page = mockPage(true);
|
|
39
|
+
const result = await adapter.isLoggedIn(page);
|
|
40
|
+
expect(typeof result).toBe('boolean');
|
|
41
|
+
});
|
|
42
|
+
it('extractUsername returns string', async () => {
|
|
43
|
+
const page = mockPage(true);
|
|
44
|
+
page.evaluate = vi.fn().mockResolvedValue('johndoe');
|
|
45
|
+
const username = await adapter.extractUsername(page);
|
|
46
|
+
expect(typeof username).toBe('string');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=browse-adapters.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-adapters.test.js","sourceRoot":"","sources":["../../../src/__tests__/browse-adapters.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-analyzer.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/browse-analyzer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
// Shared mock instance so tests can override `create` per-test
|
|
3
|
+
const mockCreate = vi.fn().mockResolvedValue({
|
|
4
|
+
content: [{
|
|
5
|
+
type: 'text',
|
|
6
|
+
text: JSON.stringify({
|
|
7
|
+
id: 'linkedin:comment_post',
|
|
8
|
+
platform: 'linkedin',
|
|
9
|
+
name: 'Comment on Post',
|
|
10
|
+
params: ['post_url', 'text'],
|
|
11
|
+
steps: [
|
|
12
|
+
{ type: 'navigate', url: '{{params.post_url}}' },
|
|
13
|
+
{ type: 'find', selectors: ['.comment-box'], as: 'box' },
|
|
14
|
+
{ type: 'click', target: '{{box}}' },
|
|
15
|
+
{ type: 'type', target: '{{box}}', text: '{{params.text}}', humanDelay: true },
|
|
16
|
+
{ type: 'wait', condition: 'network_idle', timeout: 3000 },
|
|
17
|
+
],
|
|
18
|
+
}),
|
|
19
|
+
}],
|
|
20
|
+
});
|
|
21
|
+
// Mock Anthropic SDK before importing analyzer
|
|
22
|
+
vi.mock('@anthropic-ai/sdk', () => {
|
|
23
|
+
const MockAnthropic = vi.fn(function () {
|
|
24
|
+
this.messages = { create: mockCreate };
|
|
25
|
+
});
|
|
26
|
+
return { default: MockAnthropic };
|
|
27
|
+
});
|
|
28
|
+
function mockPage(url = 'https://linkedin.com/feed', title = 'LinkedIn') {
|
|
29
|
+
return {
|
|
30
|
+
url: vi.fn().mockResolvedValue(url),
|
|
31
|
+
evaluate: vi.fn().mockImplementation((expr) => {
|
|
32
|
+
if (expr === 'document.title')
|
|
33
|
+
return Promise.resolve(title);
|
|
34
|
+
return Promise.resolve('[]'); // empty elements for DOM capture
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
describe('analyzePageForAction', () => {
|
|
39
|
+
let analyzePageForAction;
|
|
40
|
+
beforeEach(async () => {
|
|
41
|
+
mockCreate.mockClear();
|
|
42
|
+
const mod = await import('@monoes/monobrowse');
|
|
43
|
+
analyzePageForAction = mod.analyzePageForAction;
|
|
44
|
+
});
|
|
45
|
+
it('returns a valid ActionDef from mocked Claude response', async () => {
|
|
46
|
+
const page = mockPage();
|
|
47
|
+
// Pass a dummy key via options (Anthropic SDK is mocked — no real call is made)
|
|
48
|
+
const result = await analyzePageForAction(page, 'comment on a LinkedIn post', { apiKey: 'sk-test' });
|
|
49
|
+
expect(result.id).toBe('linkedin:comment_post');
|
|
50
|
+
expect(result.steps).toHaveLength(5);
|
|
51
|
+
expect(result.params).toContain('text');
|
|
52
|
+
});
|
|
53
|
+
it('throws on invalid JSON from Claude', async () => {
|
|
54
|
+
mockCreate.mockResolvedValueOnce({
|
|
55
|
+
content: [{ type: 'text', text: 'not json at all' }],
|
|
56
|
+
});
|
|
57
|
+
const page = mockPage();
|
|
58
|
+
await expect(analyzePageForAction(page, 'test', { apiKey: 'sk-test' })).rejects.toThrow('invalid JSON');
|
|
59
|
+
});
|
|
60
|
+
it('throws when ActionDef is missing id', async () => {
|
|
61
|
+
mockCreate.mockResolvedValueOnce({
|
|
62
|
+
content: [{ type: 'text', text: JSON.stringify({ steps: [] }) }],
|
|
63
|
+
});
|
|
64
|
+
const page = mockPage();
|
|
65
|
+
await expect(analyzePageForAction(page, 'test', { apiKey: 'sk-test' })).rejects.toThrow('invalid ActionDef');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=browse-analyzer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-analyzer.test.js","sourceRoot":"","sources":["../../../src/__tests__/browse-analyzer.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAG9D,+DAA+D;AAC/D,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;IAC3C,OAAO,EAAE,CAAC;YACR,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,EAAE,EAAE,uBAAuB;gBAC3B,QAAQ,EAAE,UAAU;gBACpB,IAAI,EAAE,iBAAiB;gBACvB,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;gBAC5B,KAAK,EAAE;oBACL,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,qBAAqB,EAAE;oBAChD,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE;oBACxD,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE;oBACpC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,EAAE,IAAI,EAAE;oBAC9E,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE;iBAC3D;aACF,CAAC;SACH,CAAC;CACH,CAAC,CAAC;AAEH,+CAA+C;AAC/C,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAChC,MAAM,aAAa,GAAG,EAAE,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;AACpC,CAAC,CAAC,CAAC;AAEH,SAAS,QAAQ,CAAC,GAAG,GAAG,2BAA2B,EAAE,KAAK,GAAG,UAAU;IACrE,OAAO;QACL,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC;QACnC,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,IAAY,EAAE,EAAE;YACpD,IAAI,IAAI,KAAK,gBAAgB;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC7D,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,iCAAiC;QACjE,CAAC,CAAC;KACH,CAAC;AACJ,CAAC;AAED,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,oBAAiF,CAAC;IAEtF,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,UAAU,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QAC/C,oBAAoB,GAAG,GAAG,CAAC,oBAAoB,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,gFAAgF;QAChF,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,4BAA4B,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACrG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,UAAU,CAAC,qBAAqB,CAAC;YAC/B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;SACrD,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,UAAU,CAAC,qBAAqB,CAAC;YAC/B,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;SACjE,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,MAAM,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC/G,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-builtin-handlers.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/browse-builtin-handlers.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
// Mock fs/promises before importing the module under test
|
|
3
|
+
vi.mock('node:fs/promises', () => ({
|
|
4
|
+
writeFile: vi.fn().mockResolvedValue(undefined),
|
|
5
|
+
readFile: vi.fn().mockRejectedValue(new Error('no file')),
|
|
6
|
+
mkdir: vi.fn().mockResolvedValue(undefined),
|
|
7
|
+
chmod: vi.fn().mockResolvedValue(undefined),
|
|
8
|
+
}));
|
|
9
|
+
vi.mock('node:fs', () => ({
|
|
10
|
+
existsSync: vi.fn().mockReturnValue(false),
|
|
11
|
+
}));
|
|
12
|
+
// Mock the browser module so gemini_image CDP path returns null immediately
|
|
13
|
+
vi.mock('../browser/index.js', () => ({
|
|
14
|
+
connectToTarget: vi.fn().mockRejectedValue(new Error('no browser')),
|
|
15
|
+
setCookies: vi.fn(),
|
|
16
|
+
openUrl: vi.fn(),
|
|
17
|
+
findByRole: vi.fn(),
|
|
18
|
+
findBySelector: vi.fn(),
|
|
19
|
+
clickElement: vi.fn(),
|
|
20
|
+
fillElement: vi.fn(),
|
|
21
|
+
pressKey: vi.fn(),
|
|
22
|
+
evaluateJs: vi.fn(),
|
|
23
|
+
getCookies: vi.fn().mockResolvedValue([]),
|
|
24
|
+
getCurrentUrl: vi.fn().mockResolvedValue(''),
|
|
25
|
+
captureScreenshot: vi.fn().mockResolvedValue(null),
|
|
26
|
+
}));
|
|
27
|
+
import { createBuiltinHandlers } from '@monoes/monobrowse';
|
|
28
|
+
import * as fsMock from 'node:fs/promises';
|
|
29
|
+
function makeItem(data = {}) {
|
|
30
|
+
return { data };
|
|
31
|
+
}
|
|
32
|
+
describe('createBuiltinHandlers', () => {
|
|
33
|
+
it('returns a Map with the expected handler keys', () => {
|
|
34
|
+
const handlers = createBuiltinHandlers();
|
|
35
|
+
expect(handlers).toBeInstanceOf(Map);
|
|
36
|
+
expect(handlers.has('action.http')).toBe(true);
|
|
37
|
+
expect(handlers.has('action.save_file')).toBe(true);
|
|
38
|
+
expect(handlers.has('action.log')).toBe(true);
|
|
39
|
+
expect(handlers.has('action.gemini_image')).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('action.save_file', () => {
|
|
43
|
+
let handlers;
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
vi.clearAllMocks();
|
|
46
|
+
// existsSync stays false — no sessions file
|
|
47
|
+
handlers = createBuiltinHandlers();
|
|
48
|
+
});
|
|
49
|
+
it('writes a file for a safe relative path', async () => {
|
|
50
|
+
const handler = handlers.get('action.save_file');
|
|
51
|
+
const items = [makeItem({ hello: 'world' })];
|
|
52
|
+
const result = await handler(items, { path: 'output.txt' });
|
|
53
|
+
expect(fsMock.writeFile).toHaveBeenCalled();
|
|
54
|
+
expect(result[0].data.savedPath).toMatch(/output\.txt$/);
|
|
55
|
+
});
|
|
56
|
+
it('throws "Path traversal blocked" for a path that escapes cwd', async () => {
|
|
57
|
+
const handler = handlers.get('action.save_file');
|
|
58
|
+
const items = [makeItem()];
|
|
59
|
+
await expect(handler(items, { path: '../../etc/passwd' })).rejects.toThrow('Path traversal blocked');
|
|
60
|
+
});
|
|
61
|
+
it('writes binary content when item.binaryBase64 is set', async () => {
|
|
62
|
+
const handler = handlers.get('action.save_file');
|
|
63
|
+
const binaryItem = { data: {}, binaryBase64: Buffer.from('abc').toString('base64') };
|
|
64
|
+
const result = await handler([binaryItem], { path: 'img.png' });
|
|
65
|
+
expect(fsMock.writeFile).toHaveBeenCalled();
|
|
66
|
+
const [, content] = vi.mocked(fsMock.writeFile).mock.calls[0];
|
|
67
|
+
expect(Buffer.isBuffer(content)).toBe(true);
|
|
68
|
+
expect(result[0].data.savedPath).toMatch(/img\.png$/);
|
|
69
|
+
});
|
|
70
|
+
it('uses config.content when no field is provided', async () => {
|
|
71
|
+
const handler = handlers.get('action.save_file');
|
|
72
|
+
const items = [makeItem()];
|
|
73
|
+
const result = await handler(items, { path: 'out.txt', content: 'hello content' });
|
|
74
|
+
const [, written] = vi.mocked(fsMock.writeFile).mock.calls[0];
|
|
75
|
+
expect(written).toBe('hello content');
|
|
76
|
+
expect(result[0].data.savedPath).toMatch(/out\.txt$/);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
describe('action.gemini_image', () => {
|
|
80
|
+
let handlers;
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
vi.clearAllMocks();
|
|
83
|
+
handlers = createBuiltinHandlers();
|
|
84
|
+
});
|
|
85
|
+
it('falls back to mock mode when browser and API key are unavailable', async () => {
|
|
86
|
+
const handler = handlers.get('action.gemini_image');
|
|
87
|
+
// No GEMINI_API_KEY set, browser import throws — mock mode
|
|
88
|
+
delete process.env['GEMINI_API_KEY'];
|
|
89
|
+
delete process.env['GOOGLE_API_KEY'];
|
|
90
|
+
const items = [makeItem({ prompt: 'a beautiful sunset' })];
|
|
91
|
+
const result = await handler(items, { prompt: 'a beautiful sunset', cdpPort: 19999 });
|
|
92
|
+
expect(result[0].data.mockMode).toBe(true);
|
|
93
|
+
expect(result[0].data.prompt).toBe('a beautiful sunset');
|
|
94
|
+
});
|
|
95
|
+
it('throws "Path traversal blocked" for outputPath outside cwd', async () => {
|
|
96
|
+
const handler = handlers.get('action.gemini_image');
|
|
97
|
+
delete process.env['GEMINI_API_KEY'];
|
|
98
|
+
delete process.env['GOOGLE_API_KEY'];
|
|
99
|
+
const items = [makeItem()];
|
|
100
|
+
await expect(handler(items, { prompt: 'test', outputPath: '../../evil.png', cdpPort: 19999 })).rejects.toThrow('Path traversal blocked');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe('action.http', () => {
|
|
104
|
+
let handlers;
|
|
105
|
+
const originalFetch = globalThis.fetch;
|
|
106
|
+
beforeEach(() => {
|
|
107
|
+
handlers = createBuiltinHandlers();
|
|
108
|
+
});
|
|
109
|
+
afterEach(() => {
|
|
110
|
+
globalThis.fetch = originalFetch;
|
|
111
|
+
});
|
|
112
|
+
it('fetches a URL and stores response in item.data.response', async () => {
|
|
113
|
+
const mockFetch = vi.fn().mockResolvedValue({
|
|
114
|
+
ok: true,
|
|
115
|
+
status: 200,
|
|
116
|
+
text: async () => JSON.stringify({ success: true }),
|
|
117
|
+
});
|
|
118
|
+
globalThis.fetch = mockFetch;
|
|
119
|
+
const handler = handlers.get('action.http');
|
|
120
|
+
const items = [makeItem()];
|
|
121
|
+
const result = await handler(items, { url: 'https://example.com/api', method: 'GET' });
|
|
122
|
+
expect(mockFetch).toHaveBeenCalledWith('https://example.com/api', expect.objectContaining({ method: 'GET' }));
|
|
123
|
+
expect(result[0].data.response.statusCode).toBe(200);
|
|
124
|
+
expect(result[0].data.response.json).toEqual({ success: true });
|
|
125
|
+
});
|
|
126
|
+
it('uses a custom responseField when specified', async () => {
|
|
127
|
+
globalThis.fetch = vi.fn().mockResolvedValue({
|
|
128
|
+
ok: true,
|
|
129
|
+
status: 201,
|
|
130
|
+
text: async () => 'created',
|
|
131
|
+
});
|
|
132
|
+
const handler = handlers.get('action.http');
|
|
133
|
+
const items = [makeItem()];
|
|
134
|
+
const result = await handler(items, { url: 'https://example.com', responseField: 'myResult' });
|
|
135
|
+
expect(result[0].data.myResult).toBeDefined();
|
|
136
|
+
expect(result[0].data.myResult.statusCode).toBe(201);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
//# sourceMappingURL=browse-builtin-handlers.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-builtin-handlers.test.js","sourceRoot":"","sources":["../../../src/__tests__/browse-builtin-handlers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-cdp.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/browse-cdp.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Fake WebSocket — mimics the Node.js EventEmitter-style API that 'ws' uses
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
class FakeWS {
|
|
6
|
+
readyState = 1; // OPEN
|
|
7
|
+
sent = [];
|
|
8
|
+
_handlers = {};
|
|
9
|
+
on(event, fn) {
|
|
10
|
+
if (!this._handlers[event])
|
|
11
|
+
this._handlers[event] = [];
|
|
12
|
+
this._handlers[event].push(fn);
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
send(data, cb) {
|
|
16
|
+
this.sent.push(data);
|
|
17
|
+
cb?.();
|
|
18
|
+
}
|
|
19
|
+
close() {
|
|
20
|
+
this.emit('close');
|
|
21
|
+
}
|
|
22
|
+
emit(event, ...args) {
|
|
23
|
+
for (const fn of this._handlers[event] ?? [])
|
|
24
|
+
fn(...args);
|
|
25
|
+
}
|
|
26
|
+
/** Simulate a message arriving from the browser */
|
|
27
|
+
simulateMessage(obj) {
|
|
28
|
+
this.emit('message', JSON.stringify(obj));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Module-level reference so test helpers can access the last FakeWS instance
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
let fakeWsInstance = null;
|
|
35
|
+
// We need WebSocket to be constructable. Use vi.fn() and expose a class-like
|
|
36
|
+
// constructor that captures the instance.
|
|
37
|
+
function FakeWebSocket(_url) {
|
|
38
|
+
fakeWsInstance = new FakeWS();
|
|
39
|
+
Object.assign(this, fakeWsInstance);
|
|
40
|
+
// Proxy the FakeWS methods onto `this`
|
|
41
|
+
for (const key of Object.getOwnPropertyNames(FakeWS.prototype)) {
|
|
42
|
+
if (key !== 'constructor') {
|
|
43
|
+
this[key] = fakeWsInstance[key].bind(fakeWsInstance);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Also expose sent and emit directly on `this`
|
|
47
|
+
Object.defineProperty(this, 'sent', {
|
|
48
|
+
get: () => fakeWsInstance.sent,
|
|
49
|
+
configurable: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
vi.mock('ws', () => ({
|
|
53
|
+
WebSocket: FakeWebSocket,
|
|
54
|
+
}));
|
|
55
|
+
import { CdpClient } from '@monoes/monobrowse';
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Helpers
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
function openClient() {
|
|
60
|
+
const client = new CdpClient();
|
|
61
|
+
client.connect('ws://localhost:9222/devtools/page/abc');
|
|
62
|
+
const ws = fakeWsInstance;
|
|
63
|
+
ws.emit('open');
|
|
64
|
+
return { client, ws };
|
|
65
|
+
}
|
|
66
|
+
async function connectedClient() {
|
|
67
|
+
const { client, ws } = openClient();
|
|
68
|
+
await Promise.resolve();
|
|
69
|
+
return { client, ws };
|
|
70
|
+
}
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Tests
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
describe('CdpClient', () => {
|
|
75
|
+
beforeEach(() => {
|
|
76
|
+
fakeWsInstance = null;
|
|
77
|
+
vi.clearAllMocks();
|
|
78
|
+
});
|
|
79
|
+
it('connects and resolves when the WebSocket opens', async () => {
|
|
80
|
+
const client = new CdpClient();
|
|
81
|
+
const p = client.connect('ws://localhost:9222/devtools/page/abc');
|
|
82
|
+
fakeWsInstance.emit('open');
|
|
83
|
+
await expect(p).resolves.toBeUndefined();
|
|
84
|
+
expect(client.isConnected()).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
it('rejects when the WebSocket emits an error before opening', async () => {
|
|
87
|
+
const client = new CdpClient();
|
|
88
|
+
const p = client.connect('ws://localhost:9222/devtools/page/abc');
|
|
89
|
+
const err = new Error('ECONNREFUSED');
|
|
90
|
+
fakeWsInstance.emit('error', err);
|
|
91
|
+
await expect(p).rejects.toThrow('ECONNREFUSED');
|
|
92
|
+
});
|
|
93
|
+
it('sends a command and resolves with the response result', async () => {
|
|
94
|
+
const { client, ws } = await connectedClient();
|
|
95
|
+
const sendPromise = client.send('Runtime.evaluate', { expression: '1+1' });
|
|
96
|
+
const sent = JSON.parse(ws.sent[0]);
|
|
97
|
+
expect(sent.method).toBe('Runtime.evaluate');
|
|
98
|
+
ws.simulateMessage({ id: sent.id, result: { value: 2 } });
|
|
99
|
+
const result = await sendPromise;
|
|
100
|
+
expect(result.value).toBe(2);
|
|
101
|
+
});
|
|
102
|
+
it('rejects a command when the response contains a CDP error', async () => {
|
|
103
|
+
const { client, ws } = await connectedClient();
|
|
104
|
+
const sendPromise = client.send('DOM.getDocument');
|
|
105
|
+
const sent = JSON.parse(ws.sent[0]);
|
|
106
|
+
ws.simulateMessage({ id: sent.id, error: { code: -32000, message: 'Not found' } });
|
|
107
|
+
await expect(sendPromise).rejects.toThrow('CDP error -32000: Not found');
|
|
108
|
+
});
|
|
109
|
+
it('rejects when not connected', async () => {
|
|
110
|
+
const client = new CdpClient();
|
|
111
|
+
await expect(client.send('Page.navigate')).rejects.toThrow('CDP not connected');
|
|
112
|
+
});
|
|
113
|
+
it('enforces 1000 in-flight command cap', async () => {
|
|
114
|
+
const { client, ws } = await connectedClient();
|
|
115
|
+
// Override send to avoid callbacks so commands stay pending
|
|
116
|
+
vi.spyOn(ws, 'send').mockImplementation((data) => {
|
|
117
|
+
ws.sent.push(data);
|
|
118
|
+
});
|
|
119
|
+
// Fill up to 1000 pending
|
|
120
|
+
for (let i = 0; i < 1000; i++) {
|
|
121
|
+
client.send('Page.dummy').catch(() => { });
|
|
122
|
+
}
|
|
123
|
+
// 1001st command should be rejected immediately
|
|
124
|
+
await expect(client.send('Page.overflow')).rejects.toThrow('queue full');
|
|
125
|
+
});
|
|
126
|
+
it('rejects all pending commands when the connection closes', async () => {
|
|
127
|
+
const { client, ws } = await connectedClient();
|
|
128
|
+
vi.spyOn(ws, 'send').mockImplementation((data) => {
|
|
129
|
+
ws.sent.push(data);
|
|
130
|
+
// no callback — keeps command in-flight
|
|
131
|
+
});
|
|
132
|
+
const pendingPromise = client.send('Page.navigate');
|
|
133
|
+
ws.emit('close');
|
|
134
|
+
await expect(pendingPromise).rejects.toThrow('CDP connection closed');
|
|
135
|
+
expect(client.isConnected()).toBe(false);
|
|
136
|
+
});
|
|
137
|
+
it('fires event listeners when a CDP event arrives', async () => {
|
|
138
|
+
const { client, ws } = await connectedClient();
|
|
139
|
+
const listener = vi.fn();
|
|
140
|
+
client.on('Page.loadEventFired', listener);
|
|
141
|
+
ws.simulateMessage({ method: 'Page.loadEventFired', params: { timestamp: 1.23 } });
|
|
142
|
+
expect(listener).toHaveBeenCalledWith({ timestamp: 1.23 }, undefined);
|
|
143
|
+
});
|
|
144
|
+
it('enforces 100 listener cap per event', async () => {
|
|
145
|
+
const { client } = await connectedClient();
|
|
146
|
+
for (let i = 0; i < 100; i++) {
|
|
147
|
+
client.on('Page.frameNavigated', vi.fn());
|
|
148
|
+
}
|
|
149
|
+
expect(() => client.on('Page.frameNavigated', vi.fn())).toThrow('CDP event listener limit reached');
|
|
150
|
+
});
|
|
151
|
+
it('close() rejects pending commands and disconnects', async () => {
|
|
152
|
+
const { client, ws } = await connectedClient();
|
|
153
|
+
vi.spyOn(ws, 'send').mockImplementation((data) => {
|
|
154
|
+
ws.sent.push(data);
|
|
155
|
+
});
|
|
156
|
+
const p = client.send('Network.enable');
|
|
157
|
+
client.close();
|
|
158
|
+
await expect(p).rejects.toThrow('CDP connection closed');
|
|
159
|
+
expect(client.isConnected()).toBe(false);
|
|
160
|
+
});
|
|
161
|
+
it('once() resolves on the first matching event', async () => {
|
|
162
|
+
const { client, ws } = await connectedClient();
|
|
163
|
+
const oncePromise = client.once('Page.loadEventFired');
|
|
164
|
+
ws.simulateMessage({ method: 'Page.loadEventFired', params: { timestamp: 99 } });
|
|
165
|
+
const params = await oncePromise;
|
|
166
|
+
expect(params).toEqual({ timestamp: 99 });
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=browse-cdp.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browse-cdp.test.js","sourceRoot":"","sources":["../../../src/__tests__/browse-cdp.test.ts"],"names":[],"mappings":"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"}
|