AkurAI Build
Menu

popagent

public

Latest change 1ce5ab5f17eefb3cef070f9d98b28f2bb1e5c879 - Secure agent secrets behind origin-bound browser use by AkurAI Build

import { createTool } from "@mastra/core/tools";
import { z } from "zod";
import {
  agentSecrets,
  MAX_SECRET_NAME_CHARACTERS,
  normalizeSecretName,
  SECRET_NAME_PATTERN,
} from "../secrets";
import { browserRuntime } from "../browser-settings";

type BoundSecretRepository = Pick<typeof agentSecrets, "recallBound">;
type BoundSecretBrowser = Pick<typeof browserRuntime, "useBoundSecret">;

function resourceId(context: { requestContext?: { get(key: string): unknown } }): string {
  const id = context.requestContext?.get("popagent.resourceId");
  if (typeof id !== "string" || !id) throw new Error("Secret context is unavailable");
  return id;
}

export function createUseBrowserSecretTool(
  repository: BoundSecretRepository = agentSecrets,
  browser: BoundSecretBrowser = browserRuntime,
) {
  return createTool({
    id: "use-browser-secret",
    description: "Fill an origin-bound secret into a browser element without revealing its value.",
    inputSchema: z.object({
      name: z.string()
        .trim()
        .min(1)
        .max(MAX_SECRET_NAME_CHARACTERS)
        .regex(SECRET_NAME_PATTERN),
      ref: z.string().regex(/^@?e\d+$/, "Use an element ref from the current browser snapshot"),
    }).strict(),
    outputSchema: z.object({
      used: z.literal(true),
      name: z.string(),
      origin: z.string(),
    }),
    execute: async ({ name: rawName, ref }, context) => {
      context.abortSignal?.throwIfAborted();
      const name = normalizeSecretName(rawName);
      const secret = await repository.recallBound(resourceId(context), name);
      if (!secret) throw new Error(`Secret ${name} was not found or has no allowed origin`);
      const agentId = context.agent?.agentId;
      const threadId = context.agent?.threadId;
      if (!agentId || !threadId) throw new Error("Browser secret use requires an active agent thread");
      return browser.useBoundSecret({
        agentId,
        threadId,
        ref,
        ...secret,
        signal: context.abortSignal,
      });
    },
  });
}

export const useBrowserSecret = createUseBrowserSecretTool();