AkurAI Build
Menu

popagent

public

Latest change 6edc7e928c57dab23c0973ed3f7ee70b3ebb72d5 - Initial popagent baseline by AkurAI Build

import { AgentBrowser } from "@mastra/agent-browser";
import type { Agent } from "@mastra/core/agent";
import { beforeAll, describe, expect, test } from "bun:test";
import { BrowserRuntime, BrowserSettingsStore } from "./browser-settings";
import type { AgentSettings, BrowserSettings } from "./api-types";

const store = new BrowserSettingsStore();

beforeAll(() => store.init());

describe("BrowserSettingsStore", () => {
  test("persists the complete browser runtime configuration", async () => {
    const original = await store.get();
    const { updatedAt: _updatedAt, ...originalInput } = original;
    const input = {
      ...originalInput,
      enabled: !original.enabled,
      scope: original.scope === "thread" ? "shared" as const : "thread" as const,
      viewportWidth: original.viewportWidth === 1280 ? 1440 : 1280,
      viewportHeight: original.viewportHeight === 720 ? 900 : 720,
      timeoutMs: original.timeoutMs === 30_000 ? 45_000 : 30_000,
      maxSessions: original.maxSessions === 4 ? 3 : 4,
      idleTimeoutMs: original.idleTimeoutMs === 900_000 ? 600_000 : 900_000,
      screencastEnabled: !original.screencastEnabled,
      screenshotsEnabled: !original.screenshotsEnabled,
      multiTabEnabled: !original.multiTabEnabled,
      formsEnabled: !original.formsEnabled,
      dialogsEnabled: !original.dialogsEnabled,
      dragEnabled: !original.dragEnabled,
      evaluateEnabled: !original.evaluateEnabled,
      recordingEnabled: !original.recordingEnabled,
      recordingRetentionDays: original.recordingRetentionDays === 7 ? 14 : 7,
      recordingMaxFiles: original.recordingMaxFiles === 25 ? 20 : 25,
      allowHosts: ["docs.example.com"],
      denyHosts: ["blocked.example.com"],
    };
    try {
      expect(await store.update(input)).toMatchObject(input);
      expect(await new BrowserSettingsStore().get()).toMatchObject(input);
    } finally {
      await store.update(originalInput);
    }
  });
});

describe("BrowserRuntime", () => {
  const runtimeSettings = (enabled: boolean): BrowserSettings => ({
    enabled,
    scope: "thread",
    viewportWidth: 1280,
    viewportHeight: 720,
    timeoutMs: 30_000,
    maxSessions: 4,
    idleTimeoutMs: 900_000,
    screencastEnabled: true,
    screenshotsEnabled: true,
    multiTabEnabled: true,
    formsEnabled: true,
    dialogsEnabled: true,
    dragEnabled: true,
    evaluateEnabled: false,
    recordingEnabled: false,
    recordingRetentionDays: 7,
    recordingMaxFiles: 25,
    allowHosts: [],
    denyHosts: [],
    updatedAt: "",
  });

  test("restricts read-only specialists to non-mutating browser tools", async () => {
    const applied = new Map<string, AgentBrowser | undefined>();
    const calls: string[] = [];
    const target = (id: string) => ({
      setBrowser: (browser?: AgentBrowser) => {
        calls.push(id);
        applied.set(id, browser);
      },
    });
    const specialists = {
      researcher: target("researcher"),
      implementer: target("implementer"),
      reviewer: target("reviewer"),
    };
    const profiles: AgentSettings[] = [
      ["popagent", "interactive"],
      ["researcher", "read-only"],
      ["implementer", "interactive"],
      ["reviewer", "read-only"],
    ].map(([id, browserAccess]) => ({
      id: id!,
      name: id!,
      description: `${id} role`,
      instructions: `${id} instructions`,
      workspaceAccess: id === "popagent" || id === "implementer" ? "read-write" : "read-only",
      browserAccess: browserAccess as AgentSettings["browserAccess"],
      delegationEnabled: id !== "popagent",
      tools: ["webSearch"],
      sourceUrls: [],
      createdAt: "",
      updatedAt: "",
    }));
    const supervisor = {
      id: "popagent",
      listAgents: async () => specialists,
      ...target("supervisor"),
    } as unknown as Agent;
    const runtime = new BrowserRuntime(
      {} as BrowserSettingsStore,
      { list: async () => profiles },
    );

    await runtime.apply(supervisor, runtimeSettings(true));
    await runtime.apply(supervisor, runtimeSettings(true));

    expect(calls).toEqual(["supervisor", "researcher", "implementer", "reviewer"]);
    expect(applied.get("supervisor")).toBe(applied.get("implementer"));
    expect(applied.get("researcher")).toBe(applied.get("reviewer"));
    expect(applied.get("researcher")).not.toBe(applied.get("supervisor"));
    expect(Object.keys(applied.get("supervisor")!.getTools())).toContain("browser_click");
    expect(Object.keys(applied.get("researcher")!.getTools())).not.toEqual(expect.arrayContaining([
      "browser_click",
      "browser_type",
      "browser_press",
      "browser_select",
      "browser_dialog",
      "browser_drag",
      "browser_evaluate",
    ]));

    await runtime.apply(supervisor, runtimeSettings(false));
    expect([...applied.values()].every((browser) => browser === undefined)).toBe(true);
  });
});