@inetafrica/open-claudia 2.2.19 → 2.2.20

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/Dockerfile CHANGED
@@ -1,6 +1,7 @@
1
1
  FROM node:20-slim
2
2
 
3
3
  # Install system dependencies
4
+ # chromium is the browser engine driven by agent-browser (apt pulls its headless libs).
4
5
  RUN apt-get update && apt-get install -y --no-install-recommends \
5
6
  curl \
6
7
  ffmpeg \
@@ -13,6 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
13
14
  sudo \
14
15
  openssh-client \
15
16
  rsync \
17
+ chromium \
16
18
  && rm -rf /var/lib/apt/lists/*
17
19
 
18
20
  # Install Claude Code CLI
@@ -22,6 +24,13 @@ RUN curl -fsSL https://claude.ai/install.sh | sh || \
22
24
  # Install OpenAI Codex CLI for the /codex backend
23
25
  RUN npm install -g @openai/codex
24
26
 
27
+ # Browser automation for the agent: vercel-labs agent-browser (Rust CLI, token-efficient,
28
+ # replaces Playwright MCP). Installed at build time as root so the non-root runtime user
29
+ # doesn't hit EACCES on `npm install -g`. Chrome is pinned to the apt chromium binary so it
30
+ # lives outside the /data VOLUME (build-time writes to /data are discarded at runtime).
31
+ RUN npm install -g agent-browser
32
+ ENV AGENT_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium
33
+
25
34
  # Create non-root user (Claude Code refuses --dangerously-skip-permissions as root)
26
35
  # node:20-slim already has uid/gid 1000 (node user). Create claudia with different IDs.
27
36
  RUN groupadd -g 1001 claudia && useradd -u 1001 -g 1001 -m -d /data claudia
@@ -182,6 +182,20 @@ Sub-agents (spawn a fresh throwaway Claude for focused research — output comes
182
182
  - Use when a side question would pollute this conversation, or to fan out independent lookups.
183
183
  - The sub-agent has Read/Glob/Grep/Bash but no access to your chat session or send-* tools.
184
184
 
185
+ ## Browser automation
186
+ You can drive a real web browser via the \`agent-browser\` CLI (vercel-labs). It is a plain command you run through Bash — NOT an MCP tool, so there is nothing to enable; just call it. Chrome is bundled in the image and runs headless (it auto-adds --no-sandbox in this container). Use it to read pages, fill forms, click through flows, scrape content, or capture screenshots of how something renders.
187
+
188
+ Core workflow — open, snapshot to get element refs, then act on those refs:
189
+ - \`agent-browser open <url>\` — navigate (also: \`goto\`, \`back\`, \`forward\`, \`reload\`).
190
+ - \`agent-browser snapshot -i\` — list interactive elements as @refs (e.g. @e1, @e2). Do this before clicking/filling so you target the right element. Add \`--json\` for machine-readable output.
191
+ - \`agent-browser click @e1\` / \`fill @e2 "text"\` / \`type\`, \`press\`, \`select\`, \`hover\`, \`check\`/\`uncheck\`, \`upload\` — interact.
192
+ - \`agent-browser get text @e3\` / \`get html\` / \`get url\` / \`get title\` / \`is visible @e4\` — read state.
193
+ - \`agent-browser screenshot <path.png>\` — capture; then deliver with \`open-claudia send-photo <path.png>\`.
194
+ - \`agent-browser eval "<js>"\` — run JS in the page when no command fits.
195
+ - \`agent-browser close\` — end the session when done.
196
+
197
+ Notes: a background daemon persists between commands, so navigation state carries across calls in a turn. Prefer \`snapshot -i\` refs over guessing selectors. Keep output lean by acting on refs rather than dumping full HTML. This replaced the old Playwright MCP — do not look for a playwright tool.
198
+
185
199
  If you tell the user "I'll check back in N minutes" or "I'll run this every morning", you MUST schedule it with one of the commands above in the same turn. Otherwise nothing happens.
186
200
 
187
201
  ## Guidelines
package/health.js CHANGED
@@ -336,32 +336,15 @@ async function runHealthChecks(options = {}) {
336
336
  results.warnings.push(`FFmpeg not found at: ${env.FFMPEG} (voice notes disabled)`);
337
337
  }
338
338
 
339
- // 12. Check Playwright MCP setup
340
- try {
341
- const root = execSync("npm root -g", { encoding: "utf-8", stdio: "pipe" }).trim();
342
- const pwMcpPkg = path.join(root, "@playwright", "mcp", "package.json");
343
- if (!fs.existsSync(pwMcpPkg)) {
344
- results.warnings.push("@playwright/mcp not installed globally (browser tools unavailable)");
345
- } else {
346
- results.checks.playwright_mcp = { ok: true };
347
- }
348
- } catch (e) {
349
- results.warnings.push("Could not check @playwright/mcp installation");
350
- }
351
-
352
- if (fs.existsSync(MCP_CONFIG_FILE)) {
353
- try {
354
- const mcpCfg = JSON.parse(fs.readFileSync(MCP_CONFIG_FILE, "utf-8"));
355
- if (!mcpCfg.mcpServers || !mcpCfg.mcpServers.playwright) {
356
- results.warnings.push("Playwright MCP not configured in ~/.claude/mcp.json");
357
- } else {
358
- results.checks.mcp_config = { ok: true };
359
- }
360
- } catch (e) {
361
- results.warnings.push("~/.claude/mcp.json is malformed");
362
- }
339
+ // 12. Check browser automation (agent-browser CLI + Chrome)
340
+ if (!binaryExists("agent-browser")) {
341
+ results.warnings.push("agent-browser CLI not found on PATH (browser tools unavailable)");
363
342
  } else {
364
- results.warnings.push("~/.claude/mcp.json not found (MCP tools unavailable)");
343
+ results.checks.agent_browser = { ok: true };
344
+ const chrome = env.AGENT_BROWSER_EXECUTABLE_PATH;
345
+ if (chrome && !fs.existsSync(chrome)) {
346
+ results.warnings.push(`Chrome not found at AGENT_BROWSER_EXECUTABLE_PATH=${chrome} (browser tools may fail)`);
347
+ }
365
348
  }
366
349
 
367
350
  return results;
@@ -406,99 +389,27 @@ function formatResults(results, verbose = false) {
406
389
 
407
390
  // ── Idempotent setup: ensures required tools and config are in place ──
408
391
 
409
- const MCP_CONFIG_FILE = path.join(process.env.HOME || require("os").homedir(), ".claude", "mcp.json");
410
-
411
- /**
412
- * Ensure @playwright/mcp is installed globally.
413
- * Returns { installed: bool, alreadyInstalled: bool, error?: string }
414
- */
415
- function ensurePlaywrightMcp() {
416
- // Check if already installed
417
- try {
418
- const root = execSync("npm root -g", { encoding: "utf-8", stdio: "pipe" }).trim();
419
- const pkgPath = path.join(root, "@playwright", "mcp", "package.json");
420
- if (fs.existsSync(pkgPath)) {
421
- return { installed: true, alreadyInstalled: true };
422
- }
423
- } catch (e) { /* not installed */ }
424
-
425
- // Install it
426
- try {
427
- execSync("npm install -g @playwright/mcp@latest 2>&1", {
428
- encoding: "utf-8",
429
- timeout: 120000,
430
- stdio: "pipe",
431
- env: { ...process.env, PATH: process.env.PATH },
432
- });
433
- return { installed: true, alreadyInstalled: false };
434
- } catch (e) {
435
- return { installed: false, error: (e.stderr || e.message || "").slice(-300) };
436
- }
437
- }
438
-
439
392
  /**
440
- * Ensure ~/.claude/mcp.json has the Playwright MCP server configured.
441
- * Idempotent won't duplicate if already present.
442
- * Returns { configured: bool, alreadyConfigured: bool, error?: string }
393
+ * Verify the agent-browser CLI is available for browser automation.
394
+ * The binary + Chrome are baked into the image at build time (see Dockerfile),
395
+ * so this is a presence check, not an installer — a non-root runtime user can't
396
+ * `npm install -g` anyway. Returns { installed, alreadyInstalled, error? }.
443
397
  */
444
- function ensureMcpConfig() {
445
- const claudeDir = path.dirname(MCP_CONFIG_FILE);
446
-
447
- // Ensure ~/.claude directory exists
448
- if (!fs.existsSync(claudeDir)) {
449
- try {
450
- fs.mkdirSync(claudeDir, { recursive: true });
451
- } catch (e) {
452
- return { configured: false, error: `Failed to create ${claudeDir}: ${e.message}` };
453
- }
454
- }
455
-
456
- // Load existing config or start fresh
457
- let mcpConfig = { mcpServers: {} };
458
- if (fs.existsSync(MCP_CONFIG_FILE)) {
459
- try {
460
- mcpConfig = JSON.parse(fs.readFileSync(MCP_CONFIG_FILE, "utf-8"));
461
- if (!mcpConfig.mcpServers) mcpConfig.mcpServers = {};
462
- } catch (e) {
463
- // Corrupted config — back up and start fresh
464
- const backup = MCP_CONFIG_FILE + ".bak." + Date.now();
465
- try { fs.copyFileSync(MCP_CONFIG_FILE, backup); } catch (e2) {}
466
- mcpConfig = { mcpServers: {} };
467
- }
468
- }
469
-
470
- // Check if Playwright MCP is already configured
471
- if (mcpConfig.mcpServers.playwright) {
472
- return { configured: true, alreadyConfigured: true };
473
- }
474
-
475
- // Find the installed binary
476
- let mcpBin = "playwright-mcp";
477
- try {
478
- const resolved = execSync("which playwright-mcp", { encoding: "utf-8", stdio: "pipe" }).trim();
479
- if (resolved) mcpBin = resolved;
480
- } catch (e) {
481
- // Try npx path
482
- try {
483
- const root = execSync("npm root -g", { encoding: "utf-8", stdio: "pipe" }).trim();
484
- const binPath = path.join(root, "@playwright", "mcp", "cli.js");
485
- if (fs.existsSync(binPath)) mcpBin = binPath;
486
- } catch (e2) {}
487
- }
488
-
489
- // Add Playwright MCP server config
490
- mcpConfig.mcpServers.playwright = {
491
- command: "npx",
492
- args: ["@playwright/mcp@latest", "--headless"],
493
- };
494
-
495
- // Write config
496
- try {
497
- fs.writeFileSync(MCP_CONFIG_FILE, JSON.stringify(mcpConfig, null, 2) + "\n", "utf-8");
498
- return { configured: true, alreadyConfigured: false };
499
- } catch (e) {
500
- return { configured: false, error: `Failed to write ${MCP_CONFIG_FILE}: ${e.message}` };
501
- }
398
+ function ensureAgentBrowser() {
399
+ if (!binaryExists("agent-browser")) {
400
+ return {
401
+ installed: false,
402
+ error: "agent-browser CLI not on PATH (expected from image build; browser tools unavailable)",
403
+ };
404
+ }
405
+ const chrome = process.env.AGENT_BROWSER_EXECUTABLE_PATH;
406
+ if (chrome && !fs.existsSync(chrome)) {
407
+ return {
408
+ installed: false,
409
+ error: `Chrome missing at AGENT_BROWSER_EXECUTABLE_PATH=${chrome}`,
410
+ };
411
+ }
412
+ return { installed: true, alreadyInstalled: true };
502
413
  }
503
414
 
504
415
  /**
@@ -509,15 +420,9 @@ function ensureMcpConfig() {
509
420
  function ensureSetup() {
510
421
  const results = { ok: true, steps: {} };
511
422
 
512
- // Step 1: Install Playwright MCP globally
513
- results.steps.playwright_mcp = ensurePlaywrightMcp();
514
- if (!results.steps.playwright_mcp.installed) {
515
- results.ok = false;
516
- }
517
-
518
- // Step 2: Configure MCP in Claude Code config
519
- results.steps.mcp_config = ensureMcpConfig();
520
- if (!results.steps.mcp_config.configured) {
423
+ // Browser automation: verify agent-browser CLI + Chrome are present.
424
+ results.steps.agent_browser = ensureAgentBrowser();
425
+ if (!results.steps.agent_browser.installed) {
521
426
  results.ok = false;
522
427
  }
523
428
 
@@ -554,8 +459,7 @@ module.exports = {
554
459
  binaryExists,
555
460
  ensureSetup,
556
461
  formatSetupResults,
557
- ensurePlaywrightMcp,
558
- ensureMcpConfig,
462
+ ensureAgentBrowser,
559
463
  REQUIRED_ENV_KEYS,
560
464
  OPTIONAL_ENV_KEYS,
561
465
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inetafrica/open-claudia",
3
- "version": "2.2.19",
3
+ "version": "2.2.20",
4
4
  "description": "Your always-on AI coding assistant — Claude Code, Cursor Agent, and OpenAI Codex via Telegram or Kazee Chat",
5
5
  "main": "bot.js",
6
6
  "bin": {