site-agent-pro 1.0.6 → 1.0.8

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
@@ -62,66 +62,34 @@ User submits URL + tasks
62
62
 
63
63
  ## Quick Start
64
64
 
65
- > **Using site-agent-pro in your own project?** Install it as a devDependency instead of cloning:
66
- > ```bash
67
- > npm install --save-dev site-agent-pro
68
- >
69
- > # Run a quick audit
70
- > site-agent-pro --url http://localhost:3000 --task "Check the homepage"
71
- >
72
- > # OR launch the web UI to enter tasks visually
73
- > site-agent-pro ui
74
- > ```
75
- > See [Programmatic API](#programmatic-api) for scripted and CI usage.
76
-
77
- ### 1. Install (self-hosted / contributor setup)
65
+ > **Site Agent Pro** is a zero-config AI visitor. Install it, initialize your identity, and run your first audit in seconds.
78
66
 
79
- ```bash
80
- npm install
81
- npm run browser:install
82
- ```
83
-
84
- ### 2. Configure
85
-
86
- ```bash
87
- cp .env.example .env
88
- ```
89
-
90
- Set your LLM provider in `.env`:
67
+ ### 1. Install & Initialize
91
68
 
92
69
  ```bash
93
- # Option A: OpenAI (recommended for production)
94
- LLM_PROVIDER=openai
95
- OPENAI_API_KEY=your_key_here
70
+ # Install globally
71
+ npm install -g site-agent-pro
96
72
 
97
- LLM_PROVIDER=ollama
98
- OLLAMA_MODEL=llama3.1:8b
73
+ # Set up your identity (OpenAI Key, Wallet, etc.)
74
+ site-agent-pro init
99
75
  ```
100
76
 
101
- #### Sensitive Data & CLI Overrides
102
- If you prefer not to save sensitive credentials in your `.env` file, you can pass them directly via the CLI:
77
+ ### 2. Run an Audit
103
78
 
104
- ```bash
105
- npx site-agent-pro --url https://example.com \
106
- --openai-api-key "sk-..." \
107
- --imap-password "your-app-password" \
108
- --auth-password "test-user-password" \
109
- --private-key "0x..."
110
- ```
111
- CLI flags always take precedence over values in `.env`.
112
-
113
- ### 3. Run
79
+ The agent handles everything else, including **automatically installing its own browser** on the first run.
114
80
 
115
81
  ```bash
116
- # Run the agent against a site
117
- npm run dev -- --url https://example.com \
118
- --task "Open pricing and compare the visible plans before signup"
82
+ # Run a quick audit
83
+ site-agent-pro --url https://google.com --task "Check the homepage"
119
84
 
120
- # Start the web dashboard
121
- npm run dashboard
122
- # → http://localhost:4173
85
+ # OR launch the web UI to enter tasks visually
86
+ site-agent-pro ui
123
87
  ```
124
88
 
89
+ ### 3. View Results
90
+
91
+ Artifacts are saved to `data/runs/<run-id>/` (or your current directory if using the local `.env`):
92
+
125
93
  ### 4. View Results
126
94
 
127
95
  Artifacts are saved to `runs/<run-id>/`:
@@ -264,7 +232,7 @@ For full control, import the lower-level API directly:
264
232
  import { runAuditJob, buildCustomTaskSuite, normalizeCustomTasks } from "site-agent-pro";
265
233
  ```
266
234
 
267
- > **Note:** site-agent-pro requires Playwright's Chromium browser. Run `npx playwright install chromium` once after installing the package.
235
+ > **Note:** site-agent-pro requires Playwright's Chromium browser. Run `` once after installing the package.
268
236
 
269
237
  ---
270
238
 
@@ -608,7 +576,7 @@ This repo now targets a standard Render web service deployment:
608
576
  The repo root includes a Render Blueprint with:
609
577
 
610
578
  - `runtime: node`
611
- - `buildCommand: npm ci && npm run build && npm run browser:install`
579
+ - `buildCommand: npm ci && npm run build && `
612
580
  - `startCommand: npm run render:start`
613
581
  - `healthCheckPath: /health`
614
582
  - a persistent disk mounted at `/opt/render/project/src/data`
package/dist/cli/run.js CHANGED
@@ -15,6 +15,25 @@ import { resolveRunDir } from "../utils/files.js";
15
15
  import { info, warn } from "../utils/log.js";
16
16
  import { startDashboard } from "../dashboard/server.js";
17
17
  import { updateWalletSettings } from "../wallet/wallet.js";
18
+ import fs from "node:fs";
19
+ import { fileURLToPath } from "node:url";
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
22
+ let pkgVersion = "1.0.0";
23
+ try {
24
+ let pkgDir = __dirname;
25
+ for (let i = 0; i < 5; i++) {
26
+ const pkgPath = path.join(pkgDir, "package.json");
27
+ if (fs.existsSync(pkgPath)) {
28
+ pkgVersion = JSON.parse(fs.readFileSync(pkgPath, "utf8")).version;
29
+ break;
30
+ }
31
+ pkgDir = path.dirname(pkgDir);
32
+ }
33
+ }
34
+ catch (e) {
35
+ // Ignored fallback
36
+ }
18
37
  const program = new Command();
19
38
  function summarizeCliPath(filePath) {
20
39
  const relativePath = path.relative(process.cwd(), filePath);
@@ -62,21 +81,8 @@ function openUrl(url) {
62
81
  }
63
82
  program
64
83
  .name("site-agent-pro")
65
- .description("AI-powered browser agent for website auditing and side-by-side development");
66
- program
67
- .command("install-browsers")
68
- .description("Download the necessary browser binaries (Playwright Chromium)")
69
- .action(async () => {
70
- const { execSync } = await import("node:child_process");
71
- console.log("Downloading browsers... this may take a minute.");
72
- try {
73
- execSync("npx playwright install chromium", { stdio: "inherit" });
74
- console.log("✅ Browsers installed successfully!");
75
- }
76
- catch (err) {
77
- console.error(`❌ Failed to install browsers: ${err.message}`);
78
- }
79
- });
84
+ .description("AI-powered browser agent for website auditing and side-by-side development")
85
+ .version(pkgVersion);
80
86
  program
81
87
  .command("init")
82
88
  .description("Initialize global configuration at ~/.site-agent-pro/.env")
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { chromium, devices } from "playwright";
3
+ import { devices } from "playwright";
4
4
  import { captureInboxCheckpoint, waitForVerificationEmail } from "../auth/inbox.js";
5
5
  import { getMailboxConfig, getPreferredAccessIdentity, isAuthBootstrapConfigured } from "../auth/profile.js";
6
6
  import { detectAuthWall, runAuthFlowInContext } from "../auth/runner.js";
@@ -1695,14 +1695,16 @@ export async function runTaskSuite(options) {
1695
1695
  ? `Launching MetaMask with persistent Chromium user data from '${summarizeLocalPath(userDataDir)}'.`
1696
1696
  : `Launching MetaMask with the default persistent Chromium user data at '${summarizeLocalPath(userDataDir)}'. Set WALLET_METAMASK_USER_DATA_DIR to reuse a specific unlocked MetaMask profile.`
1697
1697
  });
1698
- context = await chromium.launchPersistentContext(userDataDir, {
1698
+ const { launchPersistentWithSelfHealing } = await import("../utils/browser.js");
1699
+ context = await launchPersistentWithSelfHealing(userDataDir, {
1699
1700
  ...(await resolveLaunchOptions({ headed: options.headed })),
1700
1701
  ...contextOptions
1701
1702
  });
1702
1703
  browser = context.browser();
1703
1704
  }
1704
1705
  else {
1705
- browser = await chromium.launch(await resolveLaunchOptions({ headed: options.headed }));
1706
+ const { launchWithSelfHealing } = await import("../utils/browser.js");
1707
+ browser = await launchWithSelfHealing(await resolveLaunchOptions({ headed: options.headed }));
1706
1708
  context = await browser.newContext(contextOptions);
1707
1709
  }
1708
1710
  await installPlaywrightPageCompat(context);
@@ -34,6 +34,28 @@ function resolveDashboardHost() {
34
34
  }
35
35
  return process.env.RENDER === "true" ? RENDER_HOST : DEFAULT_HOST;
36
36
  }
37
+ function resolveDashboardDistDir() {
38
+ // __dirname may point to src/dashboard (tsx dev) or dist/dashboard (node prod).
39
+ // Walk up until we find the project root (contains package.json), then use dist/dashboard.
40
+ let dir = __dirname;
41
+ for (let i = 0; i < 5; i++) {
42
+ if (fs.existsSync(path.join(dir, "package.json"))) {
43
+ return path.join(dir, "dist", "dashboard");
44
+ }
45
+ dir = path.dirname(dir);
46
+ }
47
+ // Fallback: assume __dirname IS dist/dashboard already
48
+ return __dirname;
49
+ }
50
+ const DASHBOARD_DIST_DIR = resolveDashboardDistDir();
51
+ function readDashboardScript(fileName) {
52
+ const filePath = path.join(DASHBOARD_DIST_DIR, fileName);
53
+ if (fs.existsSync(filePath)) {
54
+ return fs.readFileSync(filePath, "utf8");
55
+ }
56
+ warn(`Dashboard script not found: ${filePath} — run 'npm run build' first.`);
57
+ return "";
58
+ }
37
59
  function renderDashboardHtml() {
38
60
  return `<!doctype html>
39
61
  <html lang="en">
@@ -198,7 +220,7 @@ async function handleRequest(req, res, args) {
198
220
  if (dashboardScripts.includes(pathParts[0] || "")) {
199
221
  const requestedName = pathParts[0];
200
222
  const diskName = requestedName === "app.js" ? "client.js" : requestedName;
201
- const distPath = path.join(__dirname, diskName);
223
+ const distPath = path.join(DASHBOARD_DIST_DIR, diskName);
202
224
  if (fs.existsSync(distPath)) {
203
225
  sendText(res, 200, fs.readFileSync(distPath, "utf8"), "application/javascript");
204
226
  return;
@@ -436,6 +458,22 @@ export async function startDashboard(options = {}) {
436
458
  // Patch appBaseUrl into the request handler closure via a shared ref
437
459
  server.__appBaseUrl = appBaseUrl;
438
460
  info(`Dashboard ready at ${url}`);
461
+ // Auto-open browser in non-CI environments
462
+ if (process.env.NODE_ENV !== "test" && process.env.CI !== "true" && options.open !== false) {
463
+ import("node:child_process").then(({ exec }) => {
464
+ const command = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
465
+ exec(`${command} ${url}`);
466
+ }).catch(() => {
467
+ // Ignore if opening fails
468
+ });
469
+ }
439
470
  submissionService.resumePendingSubmissions();
440
471
  return { server, port: boundPort, host, url };
441
472
  }
473
+ // Support standalone execution via 'tsx src/dashboard/server.ts' or 'node dist/dashboard/server.js'
474
+ if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("server.ts") || process.argv[1]?.endsWith("server.js")) {
475
+ startDashboard().catch((error) => {
476
+ console.error(`\n[ERROR] Dashboard failed to start: ${error instanceof Error ? error.message : String(error)}\n`);
477
+ process.exit(1);
478
+ });
479
+ }
@@ -0,0 +1,112 @@
1
+ import { execSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import { chromium } from "playwright";
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
+ }
50
+ /**
51
+ * Professional self-healing browser launcher.
52
+ * Tries system Chromium -> Playwright bundled -> Auto-installs if missing.
53
+ */
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
+ }
64
+ try {
65
+ return await chromium.launch(launchOptions);
66
+ }
67
+ catch (err) {
68
+ if (err.message.includes("Executable doesn't exist") || err.message.includes("playwright install")) {
69
+ info("🚀 Bundled Playwright browser missing. Automatically installing Chromium...");
70
+ try {
71
+ execSync("npx playwright install chromium", { stdio: "inherit" });
72
+ info("✅ Browser installed successfully! Retrying launch...");
73
+ return await chromium.launch(launchOptions);
74
+ }
75
+ catch (installErr) {
76
+ throw new Error(`Failed to auto-install Playwright browser: ${installErr.message}`);
77
+ }
78
+ }
79
+ throw err;
80
+ }
81
+ }
82
+ /**
83
+ * Self-healing launcher for persistent context (e.g. for MetaMask/Web3 flows).
84
+ */
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
+ }
95
+ try {
96
+ return await chromium.launchPersistentContext(userDataDir, options);
97
+ }
98
+ catch (err) {
99
+ if (err.message.includes("Executable doesn't exist") || err.message.includes("playwright install")) {
100
+ info("🚀 Bundled Playwright browser missing. Automatically installing Chromium...");
101
+ try {
102
+ execSync("npx playwright install chromium", { stdio: "inherit" });
103
+ info("✅ Browser installed successfully! Retrying launch...");
104
+ return await chromium.launchPersistentContext(userDataDir, options);
105
+ }
106
+ catch (installErr) {
107
+ throw new Error(`Failed to auto-install Playwright browser: ${installErr.message}`);
108
+ }
109
+ }
110
+ throw err;
111
+ }
112
+ }
@@ -1,134 +1,62 @@
1
1
  # 01 - Installation
2
2
 
3
- There are two ways to use site-agent-pro. Choose the one that fits your workflow.
3
+ **Site Agent Pro** is designed to be a zero-config experience. Choose the path that fits your workflow.
4
4
 
5
5
  ---
6
6
 
7
- ## Track A — devDependency (recommended for most developers)
7
+ ## Track A — Global CLI (Recommended for most users)
8
8
 
9
- This is the right choice if you want to audit your own product as you build it, run audits in CI, or call site-agent-pro from scripts and test files.
9
+ This is the fastest way to get started. Run it from any folder on your machine.
10
10
 
11
- ### 1. Prerequisites
12
-
13
- - Node.js 20.10 or newer
14
- - npm 10 or newer
11
+ ### 1. Install Globally
15
12
 
16
13
  ```bash
17
- node -v
18
- npm -v
14
+ npm install -g site-agent-pro
19
15
  ```
20
16
 
21
- ### 2. Install in your project
22
-
23
- ```bash
24
- npm install --save-dev site-agent-pro
25
- ```
17
+ ### 2. Initialize Your Identity
26
18
 
27
- ### 3. Install the Playwright browser
19
+ Run the `init` command to set up your global configuration (~/.site-agent-pro/.env). This includes your OpenAI API Key and optionally your Paystack and Wallet details.
28
20
 
29
21
  ```bash
30
- npx playwright install chromium
22
+ site-agent-pro init
31
23
  ```
32
24
 
33
- This only needs to be done once per machine or CI environment.
34
-
35
- ### 4. Set your API key
36
-
37
- Create a `.env` file (or set environment variables) in your project root:
38
-
39
- ```bash
40
- OPENAI_API_KEY=your_real_key_here
41
- ```
25
+ ### 3. Run Your First Audit
42
26
 
43
- Or use Ollama for local/offline development (no API key needed):
27
+ The agent handles everything else, including **automatically installing the required browser binaries** on the first run.
44
28
 
45
29
  ```bash
46
- LLM_PROVIDER=ollama
47
- OLLAMA_MODEL=llama3.1:8b
48
- ```
49
-
50
- ### 5. Run your first audit
51
-
52
- ```bash
53
- # Against your running dev server
54
- site-agent-pro --url http://localhost:3000 --task "Check the homepage CTA"
55
-
56
- # Or add it to your package.json scripts
57
- # "audit": "site-agent-pro --url http://localhost:3000 --task 'Check the homepage'"
58
- # npm run audit
59
- ```
60
-
61
- ### 6. Or use it programmatically
62
-
63
- ```ts
64
- import { runAudit } from "site-agent-pro";
65
-
66
- const result = await runAudit({
67
- url: "http://localhost:3000",
68
- tasks: ["Check the homepage CTA", "Try the signup flow"],
69
- });
70
-
71
- console.log(`Score: ${result.report.overall_score}/10`);
72
-
73
- if (result.report.overall_score < 7) {
74
- process.exit(1); // Fail CI
75
- }
30
+ site-agent-pro --url https://google.com --task "Verify the page loads correctly"
76
31
  ```
77
32
 
78
33
  ---
79
34
 
80
- ## Track B — Clone and run (for contributors and self-hosting)
81
-
82
- Use this if you want to run the full web dashboard, modify the source, or self-host the submission server.
83
-
84
- ### 1. Prerequisites
85
-
86
- - Node.js 20.10 or newer
87
- - npm 10 or newer
88
- - Git
89
-
90
- ```bash
91
- node -v
92
- npm -v
93
- ```
94
-
95
- ### 2. Clone the repository
35
+ ## Track B — devDependency (For CI/CD and scripted usage)
96
36
 
97
- ```bash
98
- git clone https://github.com/your-org/site-agent-pro.git
99
- cd site-agent-pro
100
- ```
37
+ Ideal for auditing your own products during development or as part of a build pipeline.
101
38
 
102
- ### 3. Install dependencies
39
+ ### 1. Install in your project
103
40
 
104
41
  ```bash
105
- npm install
42
+ npm install --save-dev site-agent-pro
106
43
  ```
107
44
 
108
- ### 4. Install the Playwright browser
45
+ ### 2. Run with npx
109
46
 
110
- ```bash
111
- npm run browser:install
112
- ```
113
-
114
- ### 5. Create your environment file
47
+ Since it's a local dependency, use `npx` to run it. It will still use your global identity if found, or a local `.env`.
115
48
 
116
49
  ```bash
117
- cp .env.example .env
50
+ npx site-agent-pro --url http://localhost:3000 --task "Check homepage"
118
51
  ```
119
52
 
120
- ### 6. Add your OpenAI API key
121
-
122
- Open `.env` and set:
53
+ ---
123
54
 
124
- ```bash
125
- OPENAI_API_KEY=your_real_key_here
126
- ```
55
+ ## Troubleshooting
127
56
 
128
- ### 7. Confirm TypeScript builds cleanly
57
+ ### "Executable doesn't exist"
58
+ If for any reason the automatic installation fails (e.g., restricted network), you can force a browser install manually:
129
59
 
130
60
  ```bash
131
- npm run check
61
+ npx playwright install chromium
132
62
  ```
133
-
134
- If this fails, do not keep going and pretend everything is fine. Fix the error first.
@@ -4,10 +4,13 @@
4
4
 
5
5
  | Setup | Command |
6
6
  |---|---|
7
- | Installed as npm devDependency | `site-agent-pro --url ... --task "..."` |
8
- | Cloned from source | `npm run dev -- --url ... --task "..."` |
7
+ | Global CLI (Installed via -g) | `site-agent-pro --url ... --task "..."` |
8
+ | devDependency (npx) | `npx site-agent-pro --url ... --task "..."` |
9
+ | Contributor (npm run dev) | `npm run dev -- --url ... --task "..."` |
9
10
 
10
- All examples below use the `site-agent-pro` command. If you cloned the repo, replace it with `npm run dev --`.
11
+ All examples below use the `site-agent-pro` command.
12
+
13
+ > **Important**: Before running your first audit, make sure you've run `site-agent-pro init` to set up your API keys globally.
11
14
 
12
15
  ---
13
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "site-agent-pro",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
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": {
@@ -23,9 +23,9 @@
23
23
  "dev": "tsx src/cli/run.ts",
24
24
  "trade:run": "tsx src/cli/trade.ts",
25
25
  "backfill:site-checks": "tsx src/cli/backfillSiteChecks.ts",
26
- "dashboard": "tsx src/dashboard/server.ts",
27
- "dashboard:start": "node dist/dashboard/server.js",
28
- "render:start": "node dist/dashboard/server.js",
26
+ "dashboard": "tsx src/cli/run.ts ui",
27
+ "dashboard:start": "node dist/cli/run.js ui",
28
+ "render:start": "node dist/cli/run.js ui",
29
29
  "format": "prettier --write .",
30
30
  "lint": "eslint .",
31
31
  "browser:install": "playwright install chromium",