site-agent-pro 1.0.7 → 1.0.9

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/README.md CHANGED
@@ -76,7 +76,7 @@ site-agent-pro init
76
76
 
77
77
  ### 2. Run an Audit
78
78
 
79
- The agent handles everything else, including **automatically installing its own browser** on the first run.
79
+ The agent handles everything else. It automatically uses your existing Google Chrome or Edge browser (saving disk space and time). If no system browser is found, it safely self-heals by downloading its own.
80
80
 
81
81
  ```bash
82
82
  # Run a quick audit
@@ -104,10 +104,8 @@ Artifacts are saved to `runs/<run-id>/`:
104
104
  | `accessibility.json` | axe-core violation list |
105
105
  | `site-checks.json` | SEO, performance, security, CRO, content, mobile checks |
106
106
  | `click-replay.webp` | Compact animated activity replay with click screenshots and overlays for all recorded actions |
107
- | `*.webm` | Full browser session video recording (enabled via `RECORD_VIDEO=true`) |
107
+ | `*.webm` | Full browser session video recording (enabled via `RECORD_VIDEO=true` in `.env`), now featuring a red mouse cursor tracking the agent's exact movements |
108
108
  | `inputs.json` | Run configuration and timing metadata |
109
- | `trade-executions.json` | Optional deterministic trade validation/execution records when trade mode is enabled |
110
- | `trade-instruction.json` | Optional standalone trade CLI input copy when `npm run trade:run` is used |
111
109
 
112
110
  ---
113
111
 
@@ -232,7 +230,7 @@ For full control, import the lower-level API directly:
232
230
  import { runAuditJob, buildCustomTaskSuite, normalizeCustomTasks } from "site-agent-pro";
233
231
  ```
234
232
 
235
- > **Note:** site-agent-pro requires Playwright's Chromium browser. Run `` once after installing the package.
233
+ > **Note:** site-agent-pro automatically uses your system's Google Chrome or Chromium. You do not need to manually install Playwright browsers.
236
234
 
237
235
  ---
238
236
 
@@ -244,7 +242,7 @@ npm run dashboard
244
242
 
245
243
  | URL | Purpose |
246
244
  |---|---|
247
- | `http://localhost:4173/` | Public submission form — enter URL, paste instructions, or upload text/JSON tasks |
245
+ | `http://localhost:4173/` | Public submission form — enter URL, paste instructions, and select the number of agents (1-5) |
248
246
  | `http://localhost:4173/dashboard` | Internal run dashboard — inspect all results |
249
247
  | `/submissions/<id>` | Submission progress tracking |
250
248
  | `/r/<token>` | Public shareable report link (valid 30 days) |
@@ -1751,6 +1751,39 @@ export async function runTaskSuite(options) {
1751
1751
  warn(`Web3 wallet injection failed: ${cleanErrorMessage(walletError)}`);
1752
1752
  }
1753
1753
  }
1754
+ if (config.recordVideo) {
1755
+ await context.addInitScript(() => {
1756
+ document.addEventListener("DOMContentLoaded", () => {
1757
+ const box = document.createElement("div");
1758
+ box.id = "playwright-mouse-pointer";
1759
+ box.style.position = "fixed";
1760
+ box.style.left = "0";
1761
+ box.style.top = "0";
1762
+ box.style.width = "20px";
1763
+ box.style.height = "20px";
1764
+ box.style.background = "rgba(255,0,0,0.4)";
1765
+ box.style.border = "2px solid red";
1766
+ box.style.borderRadius = "50%";
1767
+ box.style.pointerEvents = "none";
1768
+ box.style.zIndex = "2147483647";
1769
+ box.style.transform = "translate(-50%, -50%)";
1770
+ box.style.transition = "background 0.2s, transform 0.2s";
1771
+ document.documentElement.appendChild(box);
1772
+ document.addEventListener("mousemove", (event) => {
1773
+ box.style.left = event.clientX + "px";
1774
+ box.style.top = event.clientY + "px";
1775
+ }, true);
1776
+ document.addEventListener("mousedown", (event) => {
1777
+ box.style.background = "rgba(255,0,0,0.8)";
1778
+ box.style.transform = "translate(-50%, -50%) scale(0.7)";
1779
+ }, true);
1780
+ document.addEventListener("mouseup", (event) => {
1781
+ box.style.background = "rgba(255,0,0,0.4)";
1782
+ box.style.transform = "translate(-50%, -50%) scale(1)";
1783
+ }, true);
1784
+ });
1785
+ });
1786
+ }
1754
1787
  page = await context.newPage();
1755
1788
  page.setDefaultNavigationTimeout(config.navigationTimeoutMs);
1756
1789
  page.setDefaultTimeout(config.navigationTimeoutMs);
@@ -585,43 +585,13 @@ export function renderLandingPage(args) {
585
585
  <strong>Instructions</strong>
586
586
  <textarea name="instructions" placeholder="- Find the main signup path and explain whether it is clear&#10;- Check what a new user is supposed to do first&#10;- Try the pricing flow and stop before entering private details">${escapeHtml(args.submittedInstructions ?? "")}</textarea>
587
587
  </label>
588
- <label class="file-row">
589
- <strong>Instruction file (optional)</strong>
590
- <input type="file" name="instructions_file" accept=".txt,.md,.json,.csv,text/plain,application/json" />
591
- </label>
592
588
  <div class="config-row">
593
589
  <select class="config-select" name="agents">
594
590
  ${[1, 2, 3, 4, 5]
595
591
  .map((count) => `<option value="${count}" ${selectedAgentCount === count ? "selected" : ""}>${count} agent${count === 1 ? "" : "s"}</option>`)
596
592
  .join("")}
597
593
  </select>
598
- <label class="toggle-chip">
599
- <input type="checkbox" name="trade_enabled" ${selectedTradeOptions.enabled ? "checked" : ""} />
600
- <span>Enable onchain execution</span>
601
- </label>
602
- <label class="toggle-chip">
603
- <input type="checkbox" name="trade_dry_run" ${selectedTradeOptions.dryRun ? "checked" : ""} />
604
- <span>Dry run</span>
605
- </label>
606
- <select class="config-select" name="trade_strategy">
607
- ${[
608
- ["auto", "trade: auto"],
609
- ["deposit_only", "trade: deposit only"],
610
- ["dapp_only", "trade: dapp only"]
611
- ]
612
- .map(([value, label]) => `<option value="${value}" ${selectedTradeOptions.strategy === value ? "selected" : ""}>${label}</option>`)
613
- .join("")}
614
- </select>
615
- <select class="config-select" name="trade_confirmations">
616
- ${[0, 1, 2, 3]
617
- .map((count) => `<option value="${count}" ${selectedTradeOptions.confirmations === count ? "selected" : ""}>${count} conf${count === 1 ? "" : "s"}</option>`)
618
- .join("")}
619
- </select>
620
- <span class="tag on">tabs and links</span>
621
- <span class="tag on">mobile notes</span>
622
- <span class="tag on">honest feedback</span>
623
594
  </div>
624
- <p class="scope-note">Wallet secrets stay in <code>.env</code>. These controls only decide whether this run may use the configured wallet and whether it should broadcast or stay in dry-run mode.</p>
625
595
  </form>
626
596
  <p class="launch-note">${launchNote}</p>
627
597
  <div class="link-row">
@@ -1,17 +1,72 @@
1
1
  import { execSync } from "node:child_process";
2
+ import fs from "node:fs";
2
3
  import { chromium } from "playwright";
3
- import { info } from "./log.js";
4
+ import { info, warn } from "./log.js";
5
+ /**
6
+ * Discovers a system-installed Chrome/Chromium/Edge browser path.
7
+ */
8
+ export function findSystemChrome() {
9
+ const envPaths = [
10
+ process.env.CHROME_PATH,
11
+ process.env.PUPPETEER_EXECUTABLE_PATH,
12
+ process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
13
+ ];
14
+ for (const p of envPaths) {
15
+ if (p && fs.existsSync(p))
16
+ return p;
17
+ }
18
+ const isMac = process.platform === "darwin";
19
+ const isWin = process.platform === "win32";
20
+ const isLinux = process.platform === "linux";
21
+ let standardPaths = [];
22
+ if (isMac) {
23
+ standardPaths = [
24
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
25
+ "/Applications/Chromium.app/Contents/MacOS/Chromium",
26
+ "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
27
+ ];
28
+ }
29
+ else if (isWin) {
30
+ const prefixes = [
31
+ process.env.LOCALAPPDATA,
32
+ process.env.PROGRAMFILES,
33
+ process.env["PROGRAMFILES(X86)"]
34
+ ].filter(Boolean);
35
+ for (const prefix of prefixes) {
36
+ standardPaths.push(`${prefix}\\Google\\Chrome\\Application\\chrome.exe`, `${prefix}\\Chromium\\Application\\chrome.exe`, `${prefix}\\Microsoft\\Edge\\Application\\msedge.exe`);
37
+ }
38
+ }
39
+ else if (isLinux) {
40
+ standardPaths = [
41
+ "/usr/bin/google-chrome",
42
+ "/usr/bin/google-chrome-stable",
43
+ "/usr/bin/chromium-browser",
44
+ "/usr/bin/chromium",
45
+ "/usr/bin/microsoft-edge-stable"
46
+ ];
47
+ }
48
+ return standardPaths.find((p) => fs.existsSync(p));
49
+ }
4
50
  /**
5
51
  * Professional self-healing browser launcher.
6
- * If the Playwright browser is missing, it automatically installs it.
52
+ * Tries system Chromium -> Playwright bundled -> Auto-installs if missing.
7
53
  */
8
54
  export async function launchWithSelfHealing(launchOptions) {
55
+ const sysPath = findSystemChrome();
56
+ if (sysPath) {
57
+ try {
58
+ return await chromium.launch({ ...launchOptions, executablePath: sysPath });
59
+ }
60
+ catch (err) {
61
+ warn(`System browser at ${sysPath} failed to launch: ${err.message}. Falling back to bundled Chromium.`);
62
+ }
63
+ }
9
64
  try {
10
65
  return await chromium.launch(launchOptions);
11
66
  }
12
67
  catch (err) {
13
68
  if (err.message.includes("Executable doesn't exist") || err.message.includes("playwright install")) {
14
- info("🚀 Playwright browser missing. Automatically installing Chromium...");
69
+ info("🚀 Bundled Playwright browser missing. Automatically installing Chromium...");
15
70
  try {
16
71
  execSync("npx playwright install chromium", { stdio: "inherit" });
17
72
  info("✅ Browser installed successfully! Retrying launch...");
@@ -28,12 +83,21 @@ export async function launchWithSelfHealing(launchOptions) {
28
83
  * Self-healing launcher for persistent context (e.g. for MetaMask/Web3 flows).
29
84
  */
30
85
  export async function launchPersistentWithSelfHealing(userDataDir, options) {
86
+ const sysPath = findSystemChrome();
87
+ if (sysPath) {
88
+ try {
89
+ return await chromium.launchPersistentContext(userDataDir, { ...options, executablePath: sysPath });
90
+ }
91
+ catch (err) {
92
+ warn(`System browser at ${sysPath} failed to launch: ${err.message}. Falling back to bundled Chromium.`);
93
+ }
94
+ }
31
95
  try {
32
96
  return await chromium.launchPersistentContext(userDataDir, options);
33
97
  }
34
98
  catch (err) {
35
99
  if (err.message.includes("Executable doesn't exist") || err.message.includes("playwright install")) {
36
- info("🚀 Playwright browser missing. Automatically installing Chromium...");
100
+ info("🚀 Bundled Playwright browser missing. Automatically installing Chromium...");
37
101
  try {
38
102
  execSync("npx playwright install chromium", { stdio: "inherit" });
39
103
  info("✅ Browser installed successfully! Retrying launch...");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "site-agent-pro",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "type": "module",
5
5
  "description": "AI-powered browser agent that tests websites like a real user and produces evidence-based, scored reports.",
6
6
  "bin": {
@@ -29,7 +29,6 @@
29
29
  "format": "prettier --write .",
30
30
  "lint": "eslint .",
31
31
  "browser:install": "playwright install chromium",
32
- "postinstall": "playwright install chromium",
33
32
  "paystack:test": "tsx src/paystack/test-paystack.ts"
34
33
  },
35
34
  "dependencies": {