@@ -2,6 +2,7 @@ import { AGENT_TOOLS, AGENT_TOOL_NAMES, RESERVED_AGENT_TOOL_NAMES, getToolsForMo
22import { handleDoneJson } from './cloud-output.js';
33import { LoopDetector } from './loop-detector.js';
44import { parseToolCallsFromText } from './tool-call-parser.js';
5+ import { IMAGE_BUDGET, estimateImageTokens, fitImageDimensions } from './image-budget.js';
56import { BROWSER_MUTATION_TOOLS, STATE_CHANGE_TOOLS as SHARED_STATE_CHANGE_TOOLS } from './mutation-tools.js';
67import { isCredentialField, CREDENTIAL_NOTE_STRICT, STRICT_SECRET_SYSTEM_NOTE } from './credential-fields.js';
78import { detectProgressAction, formatLedgerRow, formatLedgerSummary, isBlockedLedgerDowngrade, isTerminalLedgerStatus, isValidLedgerStatus, ledgerDoneBlock, ledgerRowKey, normalizeLedgerStatus, progressCounts, selectLedgerRows, unresolvedLedgerRows, upsertLedgerItems } from './progress-ledger.js';
@@ -5747,23 +5748,15 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
57475748 // are tuned to Claude's native vision encoder and happen to be
57485749 // reasonable for most other endpoints too. Override per-capture if you
57495750 // need sharper (coord_aligned) or looser (full_page) constraints.
5750- static IMAGE_BUDGET = {
5751- pxPerToken: 28, // rough px² per vision token across providers
5752- maxTargetPx: 1568, // no dimension bigger than this
5753- maxTargetTokens: 1568, // total image tokens budget
5754- maxBase64Chars: 1398100, // ~1.4 MB base64, matches Anthropic's cap
5755- initialJpegQuality: 0.75,
5756- minJpegQuality: 0.10,
5757- jpegQualityStep: 0.05,
5758- };
5751+ static IMAGE_BUDGET = IMAGE_BUDGET;
57595752
57605753 /**
57615754 * Anthropic's token-cost approximation: ceil((w*h) / pxPerToken²).
57625755 * Good enough to compare two capture sizes under the same budget; not
57635756 * exact for any specific provider's tokenizer, but better than eyeballing.
57645757 */
57655758 static _estimateImageTokens(w, h, pxPerToken) {
5766- return Math.ceil((w / pxPerToken) * (h / pxPerToken) );
5759+ return estimateImageTokens(w, h, pxPerToken);
57675760 }
57685761
57695762 /**
@@ -5773,33 +5766,7 @@ Rules: no prose intro, no conclusion, no "this screenshot shows...", no layout d
57735766 * Claude-for-Chrome's `C(w, h, params)` (same algorithm, clearer names).
57745767 */
57755768 static _fitImageDimensions(origW, origH, budget = Agent.IMAGE_BUDGET) {
5776- const { pxPerToken, maxTargetPx, maxTargetTokens } = budget;
5777- // Already fits — no work.
5778- if (origW <= maxTargetPx && origH <= maxTargetPx &&
5779- Agent._estimateImageTokens(origW, origH, pxPerToken) <= maxTargetTokens) {
5780- return [origW, origH];
5781- }
5782- // Search the long side; the other follows from aspect ratio.
5783- if (origH > origW) {
5784- const [h, w] = Agent._fitImageDimensions(origH, origW, budget);
5785- return [w, h];
5786- }
5787- const aspect = origW / origH;
5788- let hi = origW, lo = 1;
5789- // eslint-disable-next-line no-constant-condition
5790- while (true) {
5791- if (lo + 1 >= hi) {
5792- return [lo, Math.max(Math.round(lo / aspect), 1)];
5793- }
5794- const mid = Math.floor((lo + hi) / 2);
5795- const midH = Math.max(Math.round(mid / aspect), 1);
5796- if (mid <= maxTargetPx &&
5797- Agent._estimateImageTokens(mid, midH, pxPerToken) <= maxTargetTokens) {
5798- lo = mid;
5799- } else {
5800- hi = mid;
5801- }
5802- }
5769+ return fitImageDimensions(origW, origH, budget);
58035770 }
58045771
58055772 /**
0 commit comments