Commits merged: - chore(test-isolation): broaden runtime ignore list for live fusion app paths - feat(FN-3573): complete Step 2 — add plugin setup API client helpers - feat(FN-3573): complete Step 1 — backfill plugin setup routes Files changed: plugins/fusion-plugin-agent-browser/README.md | 26 ++++++ plugins/fusion-plugin-agent-browser/manifest.json | 15 ++++ plugins/fusion-plugin-agent-browser/package.json | 25 ++++++ .../src/__tests__/index.test.ts | 66 +++++++++++++++ .../src/__tests__/prompts.test.ts | 21 +++++ .../src/__tests__/setup.test.ts | 39 +++++++++ .../src/__tests__/skills.test.ts | 9 ++ .../src/__tests__/tools.test.ts | 55 ++++++++++++ .../src/__tests__/types.test.ts | 16 ++++ .../src/__tests__/workflow-steps.test.ts | 10 +++ plugins/fusion-plugin-agent-browser/src/index.ts | 67 +++++++++++++++ plugins/fusion-plugin-agent-browser/src/probe.ts | 98 ++++++++++++++++++++++ plugins/fusion-plugin-agent-browser/src/prompts.ts | 23 +++++ plugins/fusion-plugin-agent-browser/src/setup.ts | 31 +++++++ plugins/fusion-plugin-agent-browser/src/skills.ts | 12 +++ plugins/fusion-plugin-agent-browser/src/tools.ts | 34 ++++++++ plugins/fusion-plugin-agent-browser/src/types.ts | 56 +++++++++++++ .../src/workflow-steps.ts | 15 ++++ plugins/fusion-plugin-agent-browser/tsconfig.json | 9 ++ .../fusion-plugin-agent-browser/vitest.config.ts | 22 +++++ pnpm-lock.yaml | 16 ++++ pnpm-workspace.yaml | 1 + 22 files changed, 666 insertions(+) Fusion-Task-Id: FN-3573
56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { describe, expect, it, vi } from "vitest";
|
|
import { AGENT_BROWSER_TOOLS } from "../tools.js";
|
|
import type { PluginContext } from "@fusion/plugin-sdk";
|
|
|
|
const createContext = (settings: Record<string, unknown>): PluginContext => ({
|
|
pluginId: "fusion-plugin-agent-browser",
|
|
taskStore: {} as PluginContext["taskStore"],
|
|
settings,
|
|
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() },
|
|
emitEvent: vi.fn(),
|
|
});
|
|
|
|
describe("tools", () => {
|
|
it("blocks disallowed domains", async () => {
|
|
const tool = AGENT_BROWSER_TOOLS[0];
|
|
const result = await tool.execute(
|
|
{ url: "https://forbidden.example.com/path" },
|
|
createContext({ allowedDomains: ["allowed.example.com"] }),
|
|
);
|
|
expect(result.isError).toBe(true);
|
|
});
|
|
|
|
it("allows when allowlist is empty", async () => {
|
|
const tool = AGENT_BROWSER_TOOLS[0];
|
|
const result = await tool.execute(
|
|
{ url: "https://any.example.com/path" },
|
|
createContext({ allowedDomains: [], headlessMode: true }),
|
|
);
|
|
expect(result.isError).not.toBe(true);
|
|
});
|
|
|
|
it("allows matching domains", async () => {
|
|
const tool = AGENT_BROWSER_TOOLS[0];
|
|
const result = await tool.execute(
|
|
{ url: "https://docs.allowed.example.com/path" },
|
|
createContext({ allowedDomains: ["allowed.example.com"], headlessMode: true }),
|
|
);
|
|
expect(result.isError).not.toBe(true);
|
|
});
|
|
|
|
it("returns error for invalid URL", async () => {
|
|
const tool = AGENT_BROWSER_TOOLS[0];
|
|
const result = await tool.execute({ url: "not a url" }, createContext({ allowedDomains: [] }));
|
|
expect(result.isError).toBe(true);
|
|
});
|
|
|
|
it("blocks sibling domains that only share suffix text", async () => {
|
|
const tool = AGENT_BROWSER_TOOLS[0];
|
|
const result = await tool.execute(
|
|
{ url: "https://notexample.com/path" },
|
|
createContext({ allowedDomains: ["example.com"] }),
|
|
);
|
|
expect(result.isError).toBe(true);
|
|
});
|
|
});
|