site-agent-pro 1.0.2 → 1.0.4

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/dist/bin.js CHANGED
File without changes
@@ -0,0 +1,58 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import readline from "node:readline/promises";
5
+ import { info, warn } from "../utils/log.js";
6
+ const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".site-agent-pro");
7
+ const GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, ".env");
8
+ export async function runInitFlow() {
9
+ const rl = readline.createInterface({
10
+ input: process.stdin,
11
+ output: process.stdout
12
+ });
13
+ console.log("");
14
+ console.log("🚀 Site Agent Pro Initialization");
15
+ console.log("────────────────────────────────────────────────────────");
16
+ console.log("This will set up your global configuration at:");
17
+ console.log(` ${GLOBAL_CONFIG_PATH}`);
18
+ console.log("");
19
+ if (fs.existsSync(GLOBAL_CONFIG_PATH)) {
20
+ const overwrite = await rl.question("Global config already exists. Overwrite? (y/N): ");
21
+ if (overwrite.toLowerCase() !== 'y') {
22
+ console.log("Aborted.");
23
+ rl.close();
24
+ return;
25
+ }
26
+ }
27
+ const openaiKey = await rl.question("Enter your OpenAI API Key (or press enter to skip): ");
28
+ const paystackKey = await rl.question("Enter your Paystack Secret Key (or press enter to skip): ");
29
+ const agentPhone = await rl.question("Enter Agent Phone Number (for Paystack DVA, e.g. +234...): ");
30
+ const configContent = [
31
+ `# Site Agent Pro Global Configuration`,
32
+ `# Created on ${new Date().toISOString()}`,
33
+ "",
34
+ `LLM_PROVIDER=openai`,
35
+ `OPENAI_API_KEY=${openaiKey.trim()}`,
36
+ `PAYSTACK_SECRET_KEY=${paystackKey.trim()}`,
37
+ `PAYSTACK_AGENT_PHONE=${agentPhone.trim()}`,
38
+ `PAYSTACK_TRANSFER_ENABLED=false`,
39
+ `TRADE_DRY_RUN=true`,
40
+ "",
41
+ `# Default Wallet Configuration (Replace with your own or use as-is)`,
42
+ `WALLET_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY`,
43
+ `WALLET_CHAIN_ID=11155111`,
44
+ ].join("\n");
45
+ try {
46
+ if (!fs.existsSync(GLOBAL_CONFIG_DIR)) {
47
+ fs.mkdirSync(GLOBAL_CONFIG_DIR, { recursive: true });
48
+ }
49
+ fs.writeFileSync(GLOBAL_CONFIG_PATH, configContent, "utf8");
50
+ console.log("");
51
+ info(`✅ Global configuration saved to ${GLOBAL_CONFIG_PATH}`);
52
+ console.log("You can now run 'site-agent-pro' from any directory!");
53
+ }
54
+ catch (err) {
55
+ warn(`Failed to save config: ${err.message}`);
56
+ }
57
+ rl.close();
58
+ }
package/dist/cli/run.js CHANGED
@@ -63,6 +63,13 @@ function openUrl(url) {
63
63
  program
64
64
  .name("site-agent-pro")
65
65
  .description("AI-powered browser agent for website auditing and side-by-side development");
66
+ program
67
+ .command("init")
68
+ .description("Initialize global configuration at ~/.site-agent-pro/.env")
69
+ .action(async () => {
70
+ const { runInitFlow } = await import("./init.js");
71
+ await runInitFlow();
72
+ });
66
73
  program
67
74
  .command("run", { isDefault: true })
68
75
  .description("Run an audit against a target URL")
package/dist/config.js CHANGED
@@ -1,7 +1,16 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
1
3
  import dotenv from "dotenv";
2
4
  import { z } from "zod";
3
5
  import { TradePolicySchema } from "./trade/types.js";
4
- dotenv.config();
6
+ // Global config path (~/.site-agent-pro/.env)
7
+ const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".site-agent-pro");
8
+ const GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, ".env");
9
+ const LOCAL_CONFIG_PATH = path.join(process.cwd(), ".env");
10
+ // 1. Load global config (main fallback)
11
+ dotenv.config({ path: GLOBAL_CONFIG_PATH });
12
+ // 2. Load local config (overrides global)
13
+ dotenv.config({ path: LOCAL_CONFIG_PATH, override: true });
5
14
  export const MAX_TOTAL_RUN_DURATION_SECONDS = 600;
6
15
  export const MAX_TOTAL_RUN_DURATION_MS = MAX_TOTAL_RUN_DURATION_SECONDS * 1000;
7
16
  export const DEFAULT_TOTAL_RUN_DURATION_MS = MAX_TOTAL_RUN_DURATION_MS;
@@ -31,25 +31,6 @@ function resolveDashboardHost() {
31
31
  }
32
32
  return process.env.RENDER === "true" ? RENDER_HOST : DEFAULT_HOST;
33
33
  }
34
- function getClientScript() {
35
- // In production, we serve the pre-compiled .js file from the dist directory.
36
- // We look for it relative to the current file's location.
37
- const distPath = path.join(process.cwd(), "dist", "dashboard", "client.js");
38
- const srcPath = path.join(process.cwd(), "src", "dashboard", "client.ts");
39
- if (fs.existsSync(distPath)) {
40
- return fs.readFileSync(distPath, "utf8");
41
- }
42
- // Fallback for development if dist doesn't exist yet
43
- warn("Dashboard client.js not found in dist. Dashboard may not function correctly in production without a build.");
44
- return "// Dashboard client not found. Run 'npm run build' first.";
45
- }
46
- function getNarrativeScript() {
47
- const distPath = path.join(process.cwd(), "dist", "dashboard", "narrative.js");
48
- if (fs.existsSync(distPath)) {
49
- return fs.readFileSync(distPath, "utf8");
50
- }
51
- return "// Narrative script not found.";
52
- }
53
34
  function renderDashboardHtml() {
54
35
  return `<!doctype html>
55
36
  <html lang="en">
@@ -208,13 +189,17 @@ async function handleRequest(req, res, args) {
208
189
  sendText(res, 200, renderDashboardHtml(), "text/html");
209
190
  return;
210
191
  }
211
- if (requestUrl.pathname === "/app.js") {
212
- sendText(res, 200, getClientScript(), "application/javascript");
213
- return;
214
- }
215
- if (requestUrl.pathname === "/narrative.js") {
216
- sendText(res, 200, getNarrativeScript(), "application/javascript");
217
- return;
192
+ // Dynamic Static Asset Loader for Dashboard
193
+ // This allows the browser to fetch any .js files needed by the dashboard
194
+ const dashboardScripts = ["app.js", "narrative.js", "contracts.js", "theme.js"];
195
+ if (dashboardScripts.includes(pathParts[0] || "")) {
196
+ const requestedName = pathParts[0];
197
+ const diskName = requestedName === "app.js" ? "client.js" : requestedName;
198
+ const distPath = path.join(process.cwd(), "dist", "dashboard", diskName);
199
+ if (fs.existsSync(distPath)) {
200
+ sendText(res, 200, fs.readFileSync(distPath, "utf8"), "application/javascript");
201
+ return;
202
+ }
218
203
  }
219
204
  if (pathParts[0] === "submissions" && pathParts[1] && pathParts.length === 2) {
220
205
  const submission = await args.submissionService.getSubmission(decodeURIComponent(pathParts[1]));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "site-agent-pro",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
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": {