"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var pageAgent_exports = {};
__export(pageAgent_exports, {
  pageAgentExpect: () => pageAgentExpect,
  pageAgentExtract: () => pageAgentExtract,
  pageAgentPerform: () => pageAgentPerform
});
module.exports = __toCommonJS(pageAgent_exports);
var import_fs = __toESM(require("fs"));
var import_path = __toESM(require("path"));
var import_tool = require("./tool");
var import_utilsBundle = require("../../utilsBundle");
var import_mcpBundle = require("../../mcpBundle");
var import_actionRunner = require("./actionRunner");
var import_performTools = __toESM(require("./performTools"));
var import_expectTools = __toESM(require("./expectTools"));
var actions = __toESM(require("./actions"));
async function pageAgentPerform(progress, context, userTask, callParams) {
  const cacheKey = (callParams.cacheKey ?? userTask).trim();
  if (await cachedPerform(progress, context, cacheKey))
    return;
  const task = `
### Instructions
- Perform the following task on the page.
- Your reply should be a tool call that performs action the page.
- If you see text surrounded by <secret></secret>, it is a secret and you should preserve it as such. It will be replaced with the actual value before the tool call.

### Task
${userTask}
`;
  progress.disableTimeout();
  await runLoop(progress, context, import_performTools.default, task, void 0, callParams);
  await updateCache(context, cacheKey);
}
async function pageAgentExpect(progress, context, expectation, callParams) {
  const cacheKey = (callParams.cacheKey ?? expectation).trim();
  if (await cachedPerform(progress, context, cacheKey))
    return;
  const task = `
### Instructions
- Call one of the "browser_expect_*" tools to verify / assert the condition.
- If you see text surrounded by <secret></secret>, it is a secret and you should preserve it as such. It will be replaced with the actual value before the tool call.

### Expectation
${expectation}
`;
  progress.disableTimeout();
  await runLoop(progress, context, import_expectTools.default, task, void 0, callParams);
  await updateCache(context, cacheKey);
}
async function pageAgentExtract(progress, context, query, schema, callParams) {
  const task = `
### Instructions
Extract the following information from the page. Do not perform any actions, just extract the information.
If you see text surrounded by <secret></secret>, it is a secret and you should preserve it as such. It will be replaced with the actual value before the tool call.

### Query
${query}`;
  const { result } = await runLoop(progress, context, [], task, schema, callParams);
  return result;
}
async function runLoop(progress, context, toolDefinitions, userTask, resultSchema, params) {
  if (!context.agentParams.api || !context.agentParams.model)
    throw new Error(`This action requires the API and API key to be set on the page agent. Did you mean to --run-agents=missing?`);
  if (!context.agentParams.apiKey)
    throw new Error(`This action requires API key to be set on the page agent.`);
  if (context.agentParams.apiEndpoint && !URL.canParse(context.agentParams.apiEndpoint))
    throw new Error(`Agent API endpoint "${context.agentParams.apiEndpoint}" is not a valid URL.`);
  const snapshot = await context.takeSnapshot(progress);
  const { tools, callTool, reportedResult, refusedToPerformReason } = (0, import_tool.toolsForLoop)(progress, context, toolDefinitions, { resultSchema, refuseToPerform: "allow" });
  const apiCacheTextBefore = context.agentParams.apiCacheFile ? await import_fs.default.promises.readFile(context.agentParams.apiCacheFile, "utf-8").catch(() => "{}") : "{}";
  const apiCacheBefore = JSON.parse(apiCacheTextBefore || "{}");
  const loop = new import_mcpBundle.Loop({
    api: context.agentParams.api,
    apiEndpoint: context.agentParams.apiEndpoint,
    apiKey: context.agentParams.apiKey,
    apiTimeout: context.agentParams.apiTimeout ?? 0,
    model: context.agentParams.model,
    maxTokens: params.maxTokens ?? context.maxTokensRemaining(),
    maxToolCalls: params.maxActions ?? context.agentParams.maxActions ?? 10,
    maxToolCallRetries: params.maxActionRetries ?? context.agentParams.maxActionRetries ?? 3,
    summarize: true,
    debug: import_utilsBundle.debug,
    callTool,
    tools,
    cache: apiCacheBefore,
    ...context.events
  });
  const task = [];
  if (context.agentParams.systemPrompt) {
    task.push("### System");
    task.push(context.agentParams.systemPrompt);
    task.push("");
  }
  task.push("### Task");
  task.push(userTask);
  if (context.history().length) {
    task.push("### Context history");
    task.push(context.history().map((h) => `- ${h.type}: ${h.description}`).join("\n"));
    task.push("");
  }
  task.push("### Page snapshot");
  task.push(snapshot);
  task.push("");
  const { error, usage } = await loop.run(task.join("\n"), { signal: progress.signal });
  context.consumeTokens(usage.input + usage.output);
  if (context.agentParams.apiCacheFile) {
    const apiCacheAfter = { ...apiCacheBefore, ...loop.cache() };
    const sortedCache = Object.fromEntries(Object.entries(apiCacheAfter).sort(([a], [b]) => a.localeCompare(b)));
    const apiCacheTextAfter = JSON.stringify(sortedCache, void 0, 2);
    if (apiCacheTextAfter !== apiCacheTextBefore) {
      await import_fs.default.promises.mkdir(import_path.default.dirname(context.agentParams.apiCacheFile), { recursive: true });
      await import_fs.default.promises.writeFile(context.agentParams.apiCacheFile, apiCacheTextAfter);
    }
  }
  if (refusedToPerformReason())
    throw new Error(`Agent refused to perform action: ${refusedToPerformReason()}`);
  if (error)
    throw new Error(`Agentic loop failed: ${error}`);
  return { result: reportedResult ? reportedResult() : void 0 };
}
async function cachedPerform(progress, context, cacheKey) {
  if (!context.agentParams?.cacheFile)
    return;
  const cache = await cachedActions(context.agentParams?.cacheFile);
  const entry = cache.actions[cacheKey];
  if (!entry)
    return;
  for (const action of entry.actions)
    await (0, import_actionRunner.runAction)(progress, "run", context.page, action, context.agentParams.secrets ?? []);
  return entry.actions;
}
async function updateCache(context, cacheKey) {
  const cacheFile = context.agentParams?.cacheFile;
  const cacheOutFile = context.agentParams?.cacheOutFile;
  const cacheFileKey = cacheFile ?? cacheOutFile;
  const cache = cacheFileKey ? await cachedActions(cacheFileKey) : { actions: {}, newActions: {} };
  const newEntry = { actions: context.actions() };
  cache.actions[cacheKey] = newEntry;
  cache.newActions[cacheKey] = newEntry;
  if (cacheOutFile) {
    const entries = Object.entries(cache.newActions);
    entries.sort((e1, e2) => e1[0].localeCompare(e2[0]));
    await import_fs.default.promises.writeFile(cacheOutFile, JSON.stringify(Object.fromEntries(entries), void 0, 2));
  } else if (cacheFile) {
    const entries = Object.entries(cache.actions);
    entries.sort((e1, e2) => e1[0].localeCompare(e2[0]));
    await import_fs.default.promises.writeFile(cacheFile, JSON.stringify(Object.fromEntries(entries), void 0, 2));
  }
}
const allCaches = /* @__PURE__ */ new Map();
async function cachedActions(cacheFile) {
  let cache = allCaches.get(cacheFile);
  if (!cache) {
    const content = await import_fs.default.promises.readFile(cacheFile, "utf-8").catch(() => "");
    let json;
    try {
      json = JSON.parse(content.trim() || "{}");
    } catch (error) {
      throw new Error(`Failed to parse cache file ${cacheFile}:
${error.message}`);
    }
    const parsed = actions.cachedActionsSchema.safeParse(json);
    if (parsed.error)
      throw new Error(`Failed to parse cache file ${cacheFile}:
${import_mcpBundle.z.prettifyError(parsed.error)}`);
    cache = { actions: parsed.data, newActions: {} };
    allCaches.set(cacheFile, cache);
  }
  return cache;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  pageAgentExpect,
  pageAgentExtract,
  pageAgentPerform
});
