import { dispatchBrowserActionDetailed, } from "../browser/dispatch.js";
import { safeSliceHead, safeSliceTail } from "../utils/safe-slice.js";
/**
 * Run one browser tool call and return structured result + duration. The
 * caller decides what to put in tool-message text — usually `r.text`.
 *
 * Logging here is intentionally light: BrowserActions logs each underlying
 * action, so this layer only adds the dispatch-level aggregate (action
 * name, ok bit, duration) which is useful for the skill generator.
 */
export async function runBrowserTool(actions, args, logger) {
    const action = args.action ?? "";
    const start = Date.now();
    const r = await dispatchBrowserActionDetailed(actions, action, args);
    const durationMs = Date.now() - start;
    // The per-action log entry is emitted from inside BrowserActions methods
    // already. We only add a coarse "tool_call" entry so log readers can see
    // the agent-level timing and the structured ok bit without reconstructing
    // it from the result string.
    logger?.log("tool_call", {
        tool: "browser",
        action,
        ok: r.ok,
        ...(r.expectationFailed ? { expectationFailed: true } : {}),
        durationMs,
    }, r.ok);
    return { ...r, durationMs };
}
/**
 * Global ceiling for any single tool result before it lands in chat/task
 * history. This is the LAST line of defense: individual tools (browser
 * snapshot, evaluate, console, web_fetch, etc.) self-cap at their own
 * sensible thresholds, but if a new tool ever forgets to do that — or an
 * existing tool's cap regresses — this stops one freak return from
 * eating ~all of the message budget in a single shot.
 *
 * Picked at 50k chars (~12.5k tokens). Headroom over the largest normal
 * per-tool caps we ship today (scoped snapshot/evaluate 16k) so it never fires in
 * normal operation; small enough to keep one runaway tool from torching
 * the prompt-cache.
 */
const TOOL_RESULT_GLOBAL_CAP = 50_000;
/**
 * Apply the global cap to a tool result and emit a warning when triggered.
 * Returns the (possibly capped) string. Logging the trigger is important —
 * if you see this fire it means some tool's own cap is loose and that's
 * where the fix actually belongs.
 */
export function capToolResultText(toolName, text, logger) {
    if (text.length <= TOOL_RESULT_GLOBAL_CAP)
        return text;
    const headLen = Math.floor(TOOL_RESULT_GLOBAL_CAP * 0.7);
    const tailLen = TOOL_RESULT_GLOBAL_CAP - headLen;
    const head = safeSliceHead(text, headLen);
    const tail = safeSliceTail(text, tailLen);
    const omitted = text.length - head.length - tail.length;
    const capped = `${head}\n\n[...${omitted} chars omitted by global tool-result cap; ` +
        `${toolName} returned ${text.length} chars total, which exceeds the ` +
        `${TOOL_RESULT_GLOBAL_CAP}-char ceiling — the responsible tool should ` +
        `self-cap before reaching this hook]\n\n${tail}`;
    console.warn(`[tool-runner] global cap fired on tool="${toolName}" (` +
        `${text.length} chars → ${capped.length}); investigate the tool's ` +
        `own size limits.`);
    logger?.log("tool_result_capped", {
        tool: toolName,
        originalChars: text.length,
        cappedChars: capped.length,
        cap: TOOL_RESULT_GLOBAL_CAP,
    }, false);
    return capped;
}
//# sourceMappingURL=tool-runner.js.map