Menu
popagent
publicLatest 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();